diff options
Diffstat (limited to 'drivers')
44 files changed, 787 insertions, 717 deletions
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index d568991ac6b3..8666171e187b 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/sched.h> | 57 | #include <linux/sched.h> |
58 | #include <linux/spinlock.h> | 58 | #include <linux/spinlock.h> |
59 | #include <linux/delay.h> | 59 | #include <linux/delay.h> |
60 | #include <linux/serial_8250.h> | ||
60 | #include "smapi.h" | 61 | #include "smapi.h" |
61 | #include "mwavedd.h" | 62 | #include "mwavedd.h" |
62 | #include "3780i.h" | 63 | #include "3780i.h" |
@@ -410,8 +411,8 @@ static ssize_t mwave_write(struct file *file, const char __user *buf, | |||
410 | 411 | ||
411 | static int register_serial_portandirq(unsigned int port, int irq) | 412 | static int register_serial_portandirq(unsigned int port, int irq) |
412 | { | 413 | { |
413 | struct serial_struct serial; | 414 | struct uart_port uart; |
414 | 415 | ||
415 | switch ( port ) { | 416 | switch ( port ) { |
416 | case 0x3f8: | 417 | case 0x3f8: |
417 | case 0x2f8: | 418 | case 0x2f8: |
@@ -442,12 +443,14 @@ static int register_serial_portandirq(unsigned int port, int irq) | |||
442 | } /* switch */ | 443 | } /* switch */ |
443 | /* irq is okay */ | 444 | /* irq is okay */ |
444 | 445 | ||
445 | memset(&serial, 0, sizeof(serial)); | 446 | memset(&uart, 0, sizeof(struct uart_port)); |
446 | serial.port = port; | 447 | |
447 | serial.irq = irq; | 448 | uart.uartclk = 1843200; |
448 | serial.flags = ASYNC_SHARE_IRQ; | 449 | uart.iobase = port; |
449 | 450 | uart.irq = irq; | |
450 | return register_serial(&serial); | 451 | uart.iotype = UPIO_PORT; |
452 | uart.flags = UPF_SHARE_IRQ; | ||
453 | return serial8250_register_port(&uart); | ||
451 | } | 454 | } |
452 | 455 | ||
453 | 456 | ||
@@ -523,7 +526,7 @@ static void mwave_exit(void) | |||
523 | #endif | 526 | #endif |
524 | 527 | ||
525 | if ( pDrvData->sLine >= 0 ) { | 528 | if ( pDrvData->sLine >= 0 ) { |
526 | unregister_serial(pDrvData->sLine); | 529 | serial8250_unregister_port(pDrvData->sLine); |
527 | } | 530 | } |
528 | if (pDrvData->bMwaveDevRegistered) { | 531 | if (pDrvData->bMwaveDevRegistered) { |
529 | misc_deregister(&mwave_misc_dev); | 532 | misc_deregister(&mwave_misc_dev); |
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c index d692af57213a..baaa365285fa 100644 --- a/drivers/char/snsc_event.c +++ b/drivers/char/snsc_event.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/byteorder/generic.h> | 20 | #include <linux/byteorder/generic.h> |
21 | #include <asm/sn/sn_sal.h> | 21 | #include <asm/sn/sn_sal.h> |
22 | #include <asm/unaligned.h> | ||
22 | #include "snsc.h" | 23 | #include "snsc.h" |
23 | 24 | ||
24 | static struct subch_data_s *event_sd; | 25 | static struct subch_data_s *event_sd; |
@@ -62,13 +63,16 @@ static int | |||
62 | scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc) | 63 | scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc) |
63 | { | 64 | { |
64 | char *desc_end; | 65 | char *desc_end; |
66 | __be32 from_buf; | ||
65 | 67 | ||
66 | /* record event source address */ | 68 | /* record event source address */ |
67 | *src = be32_to_cpup((__be32 *)event); | 69 | from_buf = get_unaligned((__be32 *)event); |
70 | *src = be32_to_cpup(&from_buf); | ||
68 | event += 4; /* move on to event code */ | 71 | event += 4; /* move on to event code */ |
69 | 72 | ||
70 | /* record the system controller's event code */ | 73 | /* record the system controller's event code */ |
71 | *code = be32_to_cpup((__be32 *)event); | 74 | from_buf = get_unaligned((__be32 *)event); |
75 | *code = be32_to_cpup(&from_buf); | ||
72 | event += 4; /* move on to event arguments */ | 76 | event += 4; /* move on to event arguments */ |
73 | 77 | ||
74 | /* how many arguments are in the packet? */ | 78 | /* how many arguments are in the packet? */ |
@@ -82,7 +86,8 @@ scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc) | |||
82 | /* not an integer argument, so give up */ | 86 | /* not an integer argument, so give up */ |
83 | return -1; | 87 | return -1; |
84 | } | 88 | } |
85 | *esp_code = be32_to_cpup((__be32 *)event); | 89 | from_buf = get_unaligned((__be32 *)event); |
90 | *esp_code = be32_to_cpup(&from_buf); | ||
86 | event += 4; | 91 | event += 4; |
87 | 92 | ||
88 | /* parse out the event description */ | 93 | /* parse out the event description */ |
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index bf3c011d2cfb..d8bf65877897 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
@@ -102,6 +102,9 @@ config DVB_BUDGET_AV | |||
102 | select VIDEO_DEV | 102 | select VIDEO_DEV |
103 | select VIDEO_SAA7146_VV | 103 | select VIDEO_SAA7146_VV |
104 | select DVB_STV0299 | 104 | select DVB_STV0299 |
105 | select DVB_TDA1004X | ||
106 | select DVB_TDA10021 | ||
107 | select FW_LOADER | ||
105 | help | 108 | help |
106 | Support for simple SAA7146 based DVB cards | 109 | Support for simple SAA7146 based DVB cards |
107 | (so called Budget- or Nova-PCI cards) without onboard | 110 | (so called Budget- or Nova-PCI cards) without onboard |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 7fc692a8f5b0..dea6589d1533 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -6,7 +6,7 @@ menu "Misc devices" | |||
6 | 6 | ||
7 | config IBM_ASM | 7 | config IBM_ASM |
8 | tristate "Device driver for IBM RSA service processor" | 8 | tristate "Device driver for IBM RSA service processor" |
9 | depends on X86 && PCI && EXPERIMENTAL | 9 | depends on X86 && PCI && EXPERIMENTAL && BROKEN |
10 | ---help--- | 10 | ---help--- |
11 | This option enables device driver support for in-band access to the | 11 | This option enables device driver support for in-band access to the |
12 | IBM RSA (Condor) service processor in eServer xSeries systems. | 12 | IBM RSA (Condor) service processor in eServer xSeries systems. |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e0239a10d325..7d8bcb38797a 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -447,7 +447,7 @@ config NET_SB1250_MAC | |||
447 | 447 | ||
448 | config SGI_IOC3_ETH | 448 | config SGI_IOC3_ETH |
449 | bool "SGI IOC3 Ethernet" | 449 | bool "SGI IOC3 Ethernet" |
450 | depends on NET_ETHERNET && PCI && SGI_IP27 | 450 | depends on NET_ETHERNET && PCI && SGI_IP27 && BROKEN |
451 | select CRC32 | 451 | select CRC32 |
452 | select MII | 452 | select MII |
453 | help | 453 | help |
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 183ba97785b0..dc5d089bf184 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c | |||
@@ -79,12 +79,55 @@ | |||
79 | #include <asm/iommu.h> | 79 | #include <asm/iommu.h> |
80 | #include <asm/vio.h> | 80 | #include <asm/vio.h> |
81 | 81 | ||
82 | #include "iseries_veth.h" | 82 | #undef DEBUG |
83 | 83 | ||
84 | MODULE_AUTHOR("Kyle Lucke <klucke@us.ibm.com>"); | 84 | MODULE_AUTHOR("Kyle Lucke <klucke@us.ibm.com>"); |
85 | MODULE_DESCRIPTION("iSeries Virtual ethernet driver"); | 85 | MODULE_DESCRIPTION("iSeries Virtual ethernet driver"); |
86 | MODULE_LICENSE("GPL"); | 86 | MODULE_LICENSE("GPL"); |
87 | 87 | ||
88 | #define VETH_EVENT_CAP (0) | ||
89 | #define VETH_EVENT_FRAMES (1) | ||
90 | #define VETH_EVENT_MONITOR (2) | ||
91 | #define VETH_EVENT_FRAMES_ACK (3) | ||
92 | |||
93 | #define VETH_MAX_ACKS_PER_MSG (20) | ||
94 | #define VETH_MAX_FRAMES_PER_MSG (6) | ||
95 | |||
96 | struct veth_frames_data { | ||
97 | u32 addr[VETH_MAX_FRAMES_PER_MSG]; | ||
98 | u16 len[VETH_MAX_FRAMES_PER_MSG]; | ||
99 | u32 eofmask; | ||
100 | }; | ||
101 | #define VETH_EOF_SHIFT (32-VETH_MAX_FRAMES_PER_MSG) | ||
102 | |||
103 | struct veth_frames_ack_data { | ||
104 | u16 token[VETH_MAX_ACKS_PER_MSG]; | ||
105 | }; | ||
106 | |||
107 | struct veth_cap_data { | ||
108 | u8 caps_version; | ||
109 | u8 rsvd1; | ||
110 | u16 num_buffers; | ||
111 | u16 ack_threshold; | ||
112 | u16 rsvd2; | ||
113 | u32 ack_timeout; | ||
114 | u32 rsvd3; | ||
115 | u64 rsvd4[3]; | ||
116 | }; | ||
117 | |||
118 | struct veth_lpevent { | ||
119 | struct HvLpEvent base_event; | ||
120 | union { | ||
121 | struct veth_cap_data caps_data; | ||
122 | struct veth_frames_data frames_data; | ||
123 | struct veth_frames_ack_data frames_ack_data; | ||
124 | } u; | ||
125 | |||
126 | }; | ||
127 | |||
128 | #define DRV_NAME "iseries_veth" | ||
129 | #define DRV_VERSION "2.0" | ||
130 | |||
88 | #define VETH_NUMBUFFERS (120) | 131 | #define VETH_NUMBUFFERS (120) |
89 | #define VETH_ACKTIMEOUT (1000000) /* microseconds */ | 132 | #define VETH_ACKTIMEOUT (1000000) /* microseconds */ |
90 | #define VETH_MAX_MCAST (12) | 133 | #define VETH_MAX_MCAST (12) |
@@ -113,9 +156,9 @@ MODULE_LICENSE("GPL"); | |||
113 | 156 | ||
114 | struct veth_msg { | 157 | struct veth_msg { |
115 | struct veth_msg *next; | 158 | struct veth_msg *next; |
116 | struct VethFramesData data; | 159 | struct veth_frames_data data; |
117 | int token; | 160 | int token; |
118 | unsigned long in_use; | 161 | int in_use; |
119 | struct sk_buff *skb; | 162 | struct sk_buff *skb; |
120 | struct device *dev; | 163 | struct device *dev; |
121 | }; | 164 | }; |
@@ -125,23 +168,28 @@ struct veth_lpar_connection { | |||
125 | struct work_struct statemachine_wq; | 168 | struct work_struct statemachine_wq; |
126 | struct veth_msg *msgs; | 169 | struct veth_msg *msgs; |
127 | int num_events; | 170 | int num_events; |
128 | struct VethCapData local_caps; | 171 | struct veth_cap_data local_caps; |
129 | 172 | ||
173 | struct kobject kobject; | ||
130 | struct timer_list ack_timer; | 174 | struct timer_list ack_timer; |
131 | 175 | ||
176 | struct timer_list reset_timer; | ||
177 | unsigned int reset_timeout; | ||
178 | unsigned long last_contact; | ||
179 | int outstanding_tx; | ||
180 | |||
132 | spinlock_t lock; | 181 | spinlock_t lock; |
133 | unsigned long state; | 182 | unsigned long state; |
134 | HvLpInstanceId src_inst; | 183 | HvLpInstanceId src_inst; |
135 | HvLpInstanceId dst_inst; | 184 | HvLpInstanceId dst_inst; |
136 | struct VethLpEvent cap_event, cap_ack_event; | 185 | struct veth_lpevent cap_event, cap_ack_event; |
137 | u16 pending_acks[VETH_MAX_ACKS_PER_MSG]; | 186 | u16 pending_acks[VETH_MAX_ACKS_PER_MSG]; |
138 | u32 num_pending_acks; | 187 | u32 num_pending_acks; |
139 | 188 | ||
140 | int num_ack_events; | 189 | int num_ack_events; |
141 | struct VethCapData remote_caps; | 190 | struct veth_cap_data remote_caps; |
142 | u32 ack_timeout; | 191 | u32 ack_timeout; |
143 | 192 | ||
144 | spinlock_t msg_stack_lock; | ||
145 | struct veth_msg *msg_stack_head; | 193 | struct veth_msg *msg_stack_head; |
146 | }; | 194 | }; |
147 | 195 | ||
@@ -151,15 +199,17 @@ struct veth_port { | |||
151 | u64 mac_addr; | 199 | u64 mac_addr; |
152 | HvLpIndexMap lpar_map; | 200 | HvLpIndexMap lpar_map; |
153 | 201 | ||
154 | spinlock_t pending_gate; | 202 | /* queue_lock protects the stopped_map and dev's queue. */ |
155 | struct sk_buff *pending_skb; | 203 | spinlock_t queue_lock; |
156 | HvLpIndexMap pending_lpmask; | 204 | HvLpIndexMap stopped_map; |
157 | 205 | ||
206 | /* mcast_gate protects promiscuous, num_mcast & mcast_addr. */ | ||
158 | rwlock_t mcast_gate; | 207 | rwlock_t mcast_gate; |
159 | int promiscuous; | 208 | int promiscuous; |
160 | int all_mcast; | ||
161 | int num_mcast; | 209 | int num_mcast; |
162 | u64 mcast_addr[VETH_MAX_MCAST]; | 210 | u64 mcast_addr[VETH_MAX_MCAST]; |
211 | |||
212 | struct kobject kobject; | ||
163 | }; | 213 | }; |
164 | 214 | ||
165 | static HvLpIndex this_lp; | 215 | static HvLpIndex this_lp; |
@@ -168,44 +218,56 @@ static struct net_device *veth_dev[HVMAXARCHITECTEDVIRTUALLANS]; /* = 0 */ | |||
168 | 218 | ||
169 | static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev); | 219 | static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev); |
170 | static void veth_recycle_msg(struct veth_lpar_connection *, struct veth_msg *); | 220 | static void veth_recycle_msg(struct veth_lpar_connection *, struct veth_msg *); |
171 | static void veth_flush_pending(struct veth_lpar_connection *cnx); | 221 | static void veth_wake_queues(struct veth_lpar_connection *cnx); |
172 | static void veth_receive(struct veth_lpar_connection *, struct VethLpEvent *); | 222 | static void veth_stop_queues(struct veth_lpar_connection *cnx); |
173 | static void veth_timed_ack(unsigned long connectionPtr); | 223 | static void veth_receive(struct veth_lpar_connection *, struct veth_lpevent *); |
224 | static void veth_release_connection(struct kobject *kobject); | ||
225 | static void veth_timed_ack(unsigned long ptr); | ||
226 | static void veth_timed_reset(unsigned long ptr); | ||
174 | 227 | ||
175 | /* | 228 | /* |
176 | * Utility functions | 229 | * Utility functions |
177 | */ | 230 | */ |
178 | 231 | ||
179 | #define veth_printk(prio, fmt, args...) \ | 232 | #define veth_info(fmt, args...) \ |
180 | printk(prio "%s: " fmt, __FILE__, ## args) | 233 | printk(KERN_INFO DRV_NAME ": " fmt, ## args) |
181 | 234 | ||
182 | #define veth_error(fmt, args...) \ | 235 | #define veth_error(fmt, args...) \ |
183 | printk(KERN_ERR "(%s:%3.3d) ERROR: " fmt, __FILE__, __LINE__ , ## args) | 236 | printk(KERN_ERR DRV_NAME ": Error: " fmt, ## args) |
237 | |||
238 | #ifdef DEBUG | ||
239 | #define veth_debug(fmt, args...) \ | ||
240 | printk(KERN_DEBUG DRV_NAME ": " fmt, ## args) | ||
241 | #else | ||
242 | #define veth_debug(fmt, args...) do {} while (0) | ||
243 | #endif | ||
184 | 244 | ||
245 | /* You must hold the connection's lock when you call this function. */ | ||
185 | static inline void veth_stack_push(struct veth_lpar_connection *cnx, | 246 | static inline void veth_stack_push(struct veth_lpar_connection *cnx, |
186 | struct veth_msg *msg) | 247 | struct veth_msg *msg) |
187 | { | 248 | { |
188 | unsigned long flags; | ||
189 | |||
190 | spin_lock_irqsave(&cnx->msg_stack_lock, flags); | ||
191 | msg->next = cnx->msg_stack_head; | 249 | msg->next = cnx->msg_stack_head; |
192 | cnx->msg_stack_head = msg; | 250 | cnx->msg_stack_head = msg; |
193 | spin_unlock_irqrestore(&cnx->msg_stack_lock, flags); | ||
194 | } | 251 | } |
195 | 252 | ||
253 | /* You must hold the connection's lock when you call this function. */ | ||
196 | static inline struct veth_msg *veth_stack_pop(struct veth_lpar_connection *cnx) | 254 | static inline struct veth_msg *veth_stack_pop(struct veth_lpar_connection *cnx) |
197 | { | 255 | { |
198 | unsigned long flags; | ||
199 | struct veth_msg *msg; | 256 | struct veth_msg *msg; |
200 | 257 | ||
201 | spin_lock_irqsave(&cnx->msg_stack_lock, flags); | ||
202 | msg = cnx->msg_stack_head; | 258 | msg = cnx->msg_stack_head; |
203 | if (msg) | 259 | if (msg) |
204 | cnx->msg_stack_head = cnx->msg_stack_head->next; | 260 | cnx->msg_stack_head = cnx->msg_stack_head->next; |
205 | spin_unlock_irqrestore(&cnx->msg_stack_lock, flags); | 261 | |
206 | return msg; | 262 | return msg; |
207 | } | 263 | } |
208 | 264 | ||
265 | /* You must hold the connection's lock when you call this function. */ | ||
266 | static inline int veth_stack_is_empty(struct veth_lpar_connection *cnx) | ||
267 | { | ||
268 | return cnx->msg_stack_head == NULL; | ||
269 | } | ||
270 | |||
209 | static inline HvLpEvent_Rc | 271 | static inline HvLpEvent_Rc |
210 | veth_signalevent(struct veth_lpar_connection *cnx, u16 subtype, | 272 | veth_signalevent(struct veth_lpar_connection *cnx, u16 subtype, |
211 | HvLpEvent_AckInd ackind, HvLpEvent_AckType acktype, | 273 | HvLpEvent_AckInd ackind, HvLpEvent_AckType acktype, |
@@ -249,7 +311,7 @@ static int veth_allocate_events(HvLpIndex rlp, int number) | |||
249 | struct veth_allocation vc = { COMPLETION_INITIALIZER(vc.c), 0 }; | 311 | struct veth_allocation vc = { COMPLETION_INITIALIZER(vc.c), 0 }; |
250 | 312 | ||
251 | mf_allocate_lp_events(rlp, HvLpEvent_Type_VirtualLan, | 313 | mf_allocate_lp_events(rlp, HvLpEvent_Type_VirtualLan, |
252 | sizeof(struct VethLpEvent), number, | 314 | sizeof(struct veth_lpevent), number, |
253 | &veth_complete_allocation, &vc); | 315 | &veth_complete_allocation, &vc); |
254 | wait_for_completion(&vc.c); | 316 | wait_for_completion(&vc.c); |
255 | 317 | ||
@@ -257,6 +319,137 @@ static int veth_allocate_events(HvLpIndex rlp, int number) | |||
257 | } | 319 | } |
258 | 320 | ||
259 | /* | 321 | /* |
322 | * sysfs support | ||
323 | */ | ||
324 | |||
325 | struct veth_cnx_attribute { | ||
326 | struct attribute attr; | ||
327 | ssize_t (*show)(struct veth_lpar_connection *, char *buf); | ||
328 | ssize_t (*store)(struct veth_lpar_connection *, const char *buf); | ||
329 | }; | ||
330 | |||
331 | static ssize_t veth_cnx_attribute_show(struct kobject *kobj, | ||
332 | struct attribute *attr, char *buf) | ||
333 | { | ||
334 | struct veth_cnx_attribute *cnx_attr; | ||
335 | struct veth_lpar_connection *cnx; | ||
336 | |||
337 | cnx_attr = container_of(attr, struct veth_cnx_attribute, attr); | ||
338 | cnx = container_of(kobj, struct veth_lpar_connection, kobject); | ||
339 | |||
340 | if (!cnx_attr->show) | ||
341 | return -EIO; | ||
342 | |||
343 | return cnx_attr->show(cnx, buf); | ||
344 | } | ||
345 | |||
346 | #define CUSTOM_CNX_ATTR(_name, _format, _expression) \ | ||
347 | static ssize_t _name##_show(struct veth_lpar_connection *cnx, char *buf)\ | ||
348 | { \ | ||
349 | return sprintf(buf, _format, _expression); \ | ||
350 | } \ | ||
351 | struct veth_cnx_attribute veth_cnx_attr_##_name = __ATTR_RO(_name) | ||
352 | |||
353 | #define SIMPLE_CNX_ATTR(_name) \ | ||
354 | CUSTOM_CNX_ATTR(_name, "%lu\n", (unsigned long)cnx->_name) | ||
355 | |||
356 | SIMPLE_CNX_ATTR(outstanding_tx); | ||
357 | SIMPLE_CNX_ATTR(remote_lp); | ||
358 | SIMPLE_CNX_ATTR(num_events); | ||
359 | SIMPLE_CNX_ATTR(src_inst); | ||
360 | SIMPLE_CNX_ATTR(dst_inst); | ||
361 | SIMPLE_CNX_ATTR(num_pending_acks); | ||
362 | SIMPLE_CNX_ATTR(num_ack_events); | ||
363 | CUSTOM_CNX_ATTR(ack_timeout, "%d\n", jiffies_to_msecs(cnx->ack_timeout)); | ||
364 | CUSTOM_CNX_ATTR(reset_timeout, "%d\n", jiffies_to_msecs(cnx->reset_timeout)); | ||
365 | CUSTOM_CNX_ATTR(state, "0x%.4lX\n", cnx->state); | ||
366 | CUSTOM_CNX_ATTR(last_contact, "%d\n", cnx->last_contact ? | ||
367 | jiffies_to_msecs(jiffies - cnx->last_contact) : 0); | ||
368 | |||
369 | #define GET_CNX_ATTR(_name) (&veth_cnx_attr_##_name.attr) | ||
370 | |||
371 | static struct attribute *veth_cnx_default_attrs[] = { | ||
372 | GET_CNX_ATTR(outstanding_tx), | ||
373 | GET_CNX_ATTR(remote_lp), | ||
374 | GET_CNX_ATTR(num_events), | ||
375 | GET_CNX_ATTR(reset_timeout), | ||
376 | GET_CNX_ATTR(last_contact), | ||
377 | GET_CNX_ATTR(state), | ||
378 | GET_CNX_ATTR(src_inst), | ||
379 | GET_CNX_ATTR(dst_inst), | ||
380 | GET_CNX_ATTR(num_pending_acks), | ||
381 | GET_CNX_ATTR(num_ack_events), | ||
382 | GET_CNX_ATTR(ack_timeout), | ||
383 | NULL | ||
384 | }; | ||
385 | |||
386 | static struct sysfs_ops veth_cnx_sysfs_ops = { | ||
387 | .show = veth_cnx_attribute_show | ||
388 | }; | ||
389 | |||
390 | static struct kobj_type veth_lpar_connection_ktype = { | ||
391 | .release = veth_release_connection, | ||
392 | .sysfs_ops = &veth_cnx_sysfs_ops, | ||
393 | .default_attrs = veth_cnx_default_attrs | ||
394 | }; | ||
395 | |||
396 | struct veth_port_attribute { | ||
397 | struct attribute attr; | ||
398 | ssize_t (*show)(struct veth_port *, char *buf); | ||
399 | ssize_t (*store)(struct veth_port *, const char *buf); | ||
400 | }; | ||
401 | |||
402 | static ssize_t veth_port_attribute_show(struct kobject *kobj, | ||
403 | struct attribute *attr, char *buf) | ||
404 | { | ||
405 | struct veth_port_attribute *port_attr; | ||
406 | struct veth_port *port; | ||
407 | |||
408 | port_attr = container_of(attr, struct veth_port_attribute, attr); | ||
409 | port = container_of(kobj, struct veth_port, kobject); | ||
410 | |||
411 | if (!port_attr->show) | ||
412 | return -EIO; | ||
413 | |||
414 | return port_attr->show(port, buf); | ||
415 | } | ||
416 | |||
417 | #define CUSTOM_PORT_ATTR(_name, _format, _expression) \ | ||
418 | static ssize_t _name##_show(struct veth_port *port, char *buf) \ | ||
419 | { \ | ||
420 | return sprintf(buf, _format, _expression); \ | ||
421 | } \ | ||
422 | struct veth_port_attribute veth_port_attr_##_name = __ATTR_RO(_name) | ||
423 | |||
424 | #define SIMPLE_PORT_ATTR(_name) \ | ||
425 | CUSTOM_PORT_ATTR(_name, "%lu\n", (unsigned long)port->_name) | ||
426 | |||
427 | SIMPLE_PORT_ATTR(promiscuous); | ||
428 | SIMPLE_PORT_ATTR(num_mcast); | ||
429 | CUSTOM_PORT_ATTR(lpar_map, "0x%X\n", port->lpar_map); | ||
430 | CUSTOM_PORT_ATTR(stopped_map, "0x%X\n", port->stopped_map); | ||
431 | CUSTOM_PORT_ATTR(mac_addr, "0x%lX\n", port->mac_addr); | ||
432 | |||
433 | #define GET_PORT_ATTR(_name) (&veth_port_attr_##_name.attr) | ||
434 | static struct attribute *veth_port_default_attrs[] = { | ||
435 | GET_PORT_ATTR(mac_addr), | ||
436 | GET_PORT_ATTR(lpar_map), | ||
437 | GET_PORT_ATTR(stopped_map), | ||
438 | GET_PORT_ATTR(promiscuous), | ||
439 | GET_PORT_ATTR(num_mcast), | ||
440 | NULL | ||
441 | }; | ||
442 | |||
443 | static struct sysfs_ops veth_port_sysfs_ops = { | ||
444 | .show = veth_port_attribute_show | ||
445 | }; | ||
446 | |||
447 | static struct kobj_type veth_port_ktype = { | ||
448 | .sysfs_ops = &veth_port_sysfs_ops, | ||
449 | .default_attrs = veth_port_default_attrs | ||
450 | }; | ||
451 | |||
452 | /* | ||
260 | * LPAR connection code | 453 | * LPAR connection code |
261 | */ | 454 | */ |
262 | 455 | ||
@@ -266,7 +459,7 @@ static inline void veth_kick_statemachine(struct veth_lpar_connection *cnx) | |||
266 | } | 459 | } |
267 | 460 | ||
268 | static void veth_take_cap(struct veth_lpar_connection *cnx, | 461 | static void veth_take_cap(struct veth_lpar_connection *cnx, |
269 | struct VethLpEvent *event) | 462 | struct veth_lpevent *event) |
270 | { | 463 | { |
271 | unsigned long flags; | 464 | unsigned long flags; |
272 | 465 | ||
@@ -278,7 +471,7 @@ static void veth_take_cap(struct veth_lpar_connection *cnx, | |||
278 | HvLpEvent_Type_VirtualLan); | 471 | HvLpEvent_Type_VirtualLan); |
279 | 472 | ||
280 | if (cnx->state & VETH_STATE_GOTCAPS) { | 473 | if (cnx->state & VETH_STATE_GOTCAPS) { |
281 | veth_error("Received a second capabilities from lpar %d\n", | 474 | veth_error("Received a second capabilities from LPAR %d.\n", |
282 | cnx->remote_lp); | 475 | cnx->remote_lp); |
283 | event->base_event.xRc = HvLpEvent_Rc_BufferNotAvailable; | 476 | event->base_event.xRc = HvLpEvent_Rc_BufferNotAvailable; |
284 | HvCallEvent_ackLpEvent((struct HvLpEvent *) event); | 477 | HvCallEvent_ackLpEvent((struct HvLpEvent *) event); |
@@ -291,13 +484,13 @@ static void veth_take_cap(struct veth_lpar_connection *cnx, | |||
291 | } | 484 | } |
292 | 485 | ||
293 | static void veth_take_cap_ack(struct veth_lpar_connection *cnx, | 486 | static void veth_take_cap_ack(struct veth_lpar_connection *cnx, |
294 | struct VethLpEvent *event) | 487 | struct veth_lpevent *event) |
295 | { | 488 | { |
296 | unsigned long flags; | 489 | unsigned long flags; |
297 | 490 | ||
298 | spin_lock_irqsave(&cnx->lock, flags); | 491 | spin_lock_irqsave(&cnx->lock, flags); |
299 | if (cnx->state & VETH_STATE_GOTCAPACK) { | 492 | if (cnx->state & VETH_STATE_GOTCAPACK) { |
300 | veth_error("Received a second capabilities ack from lpar %d\n", | 493 | veth_error("Received a second capabilities ack from LPAR %d.\n", |
301 | cnx->remote_lp); | 494 | cnx->remote_lp); |
302 | } else { | 495 | } else { |
303 | memcpy(&cnx->cap_ack_event, event, | 496 | memcpy(&cnx->cap_ack_event, event, |
@@ -309,19 +502,24 @@ static void veth_take_cap_ack(struct veth_lpar_connection *cnx, | |||
309 | } | 502 | } |
310 | 503 | ||
311 | static void veth_take_monitor_ack(struct veth_lpar_connection *cnx, | 504 | static void veth_take_monitor_ack(struct veth_lpar_connection *cnx, |
312 | struct VethLpEvent *event) | 505 | struct veth_lpevent *event) |
313 | { | 506 | { |
314 | unsigned long flags; | 507 | unsigned long flags; |
315 | 508 | ||
316 | spin_lock_irqsave(&cnx->lock, flags); | 509 | spin_lock_irqsave(&cnx->lock, flags); |
317 | veth_printk(KERN_DEBUG, "Monitor ack returned for lpar %d\n", | 510 | veth_debug("cnx %d: lost connection.\n", cnx->remote_lp); |
318 | cnx->remote_lp); | 511 | |
319 | cnx->state |= VETH_STATE_RESET; | 512 | /* Avoid kicking the statemachine once we're shutdown. |
320 | veth_kick_statemachine(cnx); | 513 | * It's unnecessary and it could break veth_stop_connection(). */ |
514 | |||
515 | if (! (cnx->state & VETH_STATE_SHUTDOWN)) { | ||
516 | cnx->state |= VETH_STATE_RESET; | ||
517 | veth_kick_statemachine(cnx); | ||
518 | } | ||
321 | spin_unlock_irqrestore(&cnx->lock, flags); | 519 | spin_unlock_irqrestore(&cnx->lock, flags); |
322 | } | 520 | } |
323 | 521 | ||
324 | static void veth_handle_ack(struct VethLpEvent *event) | 522 | static void veth_handle_ack(struct veth_lpevent *event) |
325 | { | 523 | { |
326 | HvLpIndex rlp = event->base_event.xTargetLp; | 524 | HvLpIndex rlp = event->base_event.xTargetLp; |
327 | struct veth_lpar_connection *cnx = veth_cnx[rlp]; | 525 | struct veth_lpar_connection *cnx = veth_cnx[rlp]; |
@@ -329,58 +527,67 @@ static void veth_handle_ack(struct VethLpEvent *event) | |||
329 | BUG_ON(! cnx); | 527 | BUG_ON(! cnx); |
330 | 528 | ||
331 | switch (event->base_event.xSubtype) { | 529 | switch (event->base_event.xSubtype) { |
332 | case VethEventTypeCap: | 530 | case VETH_EVENT_CAP: |
333 | veth_take_cap_ack(cnx, event); | 531 | veth_take_cap_ack(cnx, event); |
334 | break; | 532 | break; |
335 | case VethEventTypeMonitor: | 533 | case VETH_EVENT_MONITOR: |
336 | veth_take_monitor_ack(cnx, event); | 534 | veth_take_monitor_ack(cnx, event); |
337 | break; | 535 | break; |
338 | default: | 536 | default: |
339 | veth_error("Unknown ack type %d from lpar %d\n", | 537 | veth_error("Unknown ack type %d from LPAR %d.\n", |
340 | event->base_event.xSubtype, rlp); | 538 | event->base_event.xSubtype, rlp); |
341 | }; | 539 | }; |
342 | } | 540 | } |
343 | 541 | ||
344 | static void veth_handle_int(struct VethLpEvent *event) | 542 | static void veth_handle_int(struct veth_lpevent *event) |
345 | { | 543 | { |
346 | HvLpIndex rlp = event->base_event.xSourceLp; | 544 | HvLpIndex rlp = event->base_event.xSourceLp; |
347 | struct veth_lpar_connection *cnx = veth_cnx[rlp]; | 545 | struct veth_lpar_connection *cnx = veth_cnx[rlp]; |
348 | unsigned long flags; | 546 | unsigned long flags; |
349 | int i; | 547 | int i, acked = 0; |
350 | 548 | ||
351 | BUG_ON(! cnx); | 549 | BUG_ON(! cnx); |
352 | 550 | ||
353 | switch (event->base_event.xSubtype) { | 551 | switch (event->base_event.xSubtype) { |
354 | case VethEventTypeCap: | 552 | case VETH_EVENT_CAP: |
355 | veth_take_cap(cnx, event); | 553 | veth_take_cap(cnx, event); |
356 | break; | 554 | break; |
357 | case VethEventTypeMonitor: | 555 | case VETH_EVENT_MONITOR: |
358 | /* do nothing... this'll hang out here til we're dead, | 556 | /* do nothing... this'll hang out here til we're dead, |
359 | * and the hypervisor will return it for us. */ | 557 | * and the hypervisor will return it for us. */ |
360 | break; | 558 | break; |
361 | case VethEventTypeFramesAck: | 559 | case VETH_EVENT_FRAMES_ACK: |
362 | spin_lock_irqsave(&cnx->lock, flags); | 560 | spin_lock_irqsave(&cnx->lock, flags); |
561 | |||
363 | for (i = 0; i < VETH_MAX_ACKS_PER_MSG; ++i) { | 562 | for (i = 0; i < VETH_MAX_ACKS_PER_MSG; ++i) { |
364 | u16 msgnum = event->u.frames_ack_data.token[i]; | 563 | u16 msgnum = event->u.frames_ack_data.token[i]; |
365 | 564 | ||
366 | if (msgnum < VETH_NUMBUFFERS) | 565 | if (msgnum < VETH_NUMBUFFERS) { |
367 | veth_recycle_msg(cnx, cnx->msgs + msgnum); | 566 | veth_recycle_msg(cnx, cnx->msgs + msgnum); |
567 | cnx->outstanding_tx--; | ||
568 | acked++; | ||
569 | } | ||
570 | } | ||
571 | |||
572 | if (acked > 0) { | ||
573 | cnx->last_contact = jiffies; | ||
574 | veth_wake_queues(cnx); | ||
368 | } | 575 | } |
576 | |||
369 | spin_unlock_irqrestore(&cnx->lock, flags); | 577 | spin_unlock_irqrestore(&cnx->lock, flags); |
370 | veth_flush_pending(cnx); | ||
371 | break; | 578 | break; |
372 | case VethEventTypeFrames: | 579 | case VETH_EVENT_FRAMES: |
373 | veth_receive(cnx, event); | 580 | veth_receive(cnx, event); |
374 | break; | 581 | break; |
375 | default: | 582 | default: |
376 | veth_error("Unknown interrupt type %d from lpar %d\n", | 583 | veth_error("Unknown interrupt type %d from LPAR %d.\n", |
377 | event->base_event.xSubtype, rlp); | 584 | event->base_event.xSubtype, rlp); |
378 | }; | 585 | }; |
379 | } | 586 | } |
380 | 587 | ||
381 | static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs) | 588 | static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs) |
382 | { | 589 | { |
383 | struct VethLpEvent *veth_event = (struct VethLpEvent *)event; | 590 | struct veth_lpevent *veth_event = (struct veth_lpevent *)event; |
384 | 591 | ||
385 | if (event->xFlags.xFunction == HvLpEvent_Function_Ack) | 592 | if (event->xFlags.xFunction == HvLpEvent_Function_Ack) |
386 | veth_handle_ack(veth_event); | 593 | veth_handle_ack(veth_event); |
@@ -390,7 +597,7 @@ static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs) | |||
390 | 597 | ||
391 | static int veth_process_caps(struct veth_lpar_connection *cnx) | 598 | static int veth_process_caps(struct veth_lpar_connection *cnx) |
392 | { | 599 | { |
393 | struct VethCapData *remote_caps = &cnx->remote_caps; | 600 | struct veth_cap_data *remote_caps = &cnx->remote_caps; |
394 | int num_acks_needed; | 601 | int num_acks_needed; |
395 | 602 | ||
396 | /* Convert timer to jiffies */ | 603 | /* Convert timer to jiffies */ |
@@ -400,8 +607,8 @@ static int veth_process_caps(struct veth_lpar_connection *cnx) | |||
400 | || (remote_caps->ack_threshold > VETH_MAX_ACKS_PER_MSG) | 607 | || (remote_caps->ack_threshold > VETH_MAX_ACKS_PER_MSG) |
401 | || (remote_caps->ack_threshold == 0) | 608 | || (remote_caps->ack_threshold == 0) |
402 | || (cnx->ack_timeout == 0) ) { | 609 | || (cnx->ack_timeout == 0) ) { |
403 | veth_error("Received incompatible capabilities from lpar %d\n", | 610 | veth_error("Received incompatible capabilities from LPAR %d.\n", |
404 | cnx->remote_lp); | 611 | cnx->remote_lp); |
405 | return HvLpEvent_Rc_InvalidSubtypeData; | 612 | return HvLpEvent_Rc_InvalidSubtypeData; |
406 | } | 613 | } |
407 | 614 | ||
@@ -418,8 +625,8 @@ static int veth_process_caps(struct veth_lpar_connection *cnx) | |||
418 | cnx->num_ack_events += num; | 625 | cnx->num_ack_events += num; |
419 | 626 | ||
420 | if (cnx->num_ack_events < num_acks_needed) { | 627 | if (cnx->num_ack_events < num_acks_needed) { |
421 | veth_error("Couldn't allocate enough ack events for lpar %d\n", | 628 | veth_error("Couldn't allocate enough ack events " |
422 | cnx->remote_lp); | 629 | "for LPAR %d.\n", cnx->remote_lp); |
423 | 630 | ||
424 | return HvLpEvent_Rc_BufferNotAvailable; | 631 | return HvLpEvent_Rc_BufferNotAvailable; |
425 | } | 632 | } |
@@ -440,15 +647,15 @@ static void veth_statemachine(void *p) | |||
440 | 647 | ||
441 | restart: | 648 | restart: |
442 | if (cnx->state & VETH_STATE_RESET) { | 649 | if (cnx->state & VETH_STATE_RESET) { |
443 | int i; | ||
444 | |||
445 | del_timer(&cnx->ack_timer); | ||
446 | |||
447 | if (cnx->state & VETH_STATE_OPEN) | 650 | if (cnx->state & VETH_STATE_OPEN) |
448 | HvCallEvent_closeLpEventPath(cnx->remote_lp, | 651 | HvCallEvent_closeLpEventPath(cnx->remote_lp, |
449 | HvLpEvent_Type_VirtualLan); | 652 | HvLpEvent_Type_VirtualLan); |
450 | 653 | ||
451 | /* reset ack data */ | 654 | /* |
655 | * Reset ack data. This prevents the ack_timer actually | ||
656 | * doing anything, even if it runs one more time when | ||
657 | * we drop the lock below. | ||
658 | */ | ||
452 | memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks)); | 659 | memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks)); |
453 | cnx->num_pending_acks = 0; | 660 | cnx->num_pending_acks = 0; |
454 | 661 | ||
@@ -458,14 +665,32 @@ static void veth_statemachine(void *p) | |||
458 | | VETH_STATE_SENTCAPACK | VETH_STATE_READY); | 665 | | VETH_STATE_SENTCAPACK | VETH_STATE_READY); |
459 | 666 | ||
460 | /* Clean up any leftover messages */ | 667 | /* Clean up any leftover messages */ |
461 | if (cnx->msgs) | 668 | if (cnx->msgs) { |
669 | int i; | ||
462 | for (i = 0; i < VETH_NUMBUFFERS; ++i) | 670 | for (i = 0; i < VETH_NUMBUFFERS; ++i) |
463 | veth_recycle_msg(cnx, cnx->msgs + i); | 671 | veth_recycle_msg(cnx, cnx->msgs + i); |
672 | } | ||
673 | |||
674 | cnx->outstanding_tx = 0; | ||
675 | veth_wake_queues(cnx); | ||
676 | |||
677 | /* Drop the lock so we can do stuff that might sleep or | ||
678 | * take other locks. */ | ||
464 | spin_unlock_irq(&cnx->lock); | 679 | spin_unlock_irq(&cnx->lock); |
465 | veth_flush_pending(cnx); | 680 | |
681 | del_timer_sync(&cnx->ack_timer); | ||
682 | del_timer_sync(&cnx->reset_timer); | ||
683 | |||
466 | spin_lock_irq(&cnx->lock); | 684 | spin_lock_irq(&cnx->lock); |
685 | |||
467 | if (cnx->state & VETH_STATE_RESET) | 686 | if (cnx->state & VETH_STATE_RESET) |
468 | goto restart; | 687 | goto restart; |
688 | |||
689 | /* Hack, wait for the other end to reset itself. */ | ||
690 | if (! (cnx->state & VETH_STATE_SHUTDOWN)) { | ||
691 | schedule_delayed_work(&cnx->statemachine_wq, 5 * HZ); | ||
692 | goto out; | ||
693 | } | ||
469 | } | 694 | } |
470 | 695 | ||
471 | if (cnx->state & VETH_STATE_SHUTDOWN) | 696 | if (cnx->state & VETH_STATE_SHUTDOWN) |
@@ -488,7 +713,7 @@ static void veth_statemachine(void *p) | |||
488 | 713 | ||
489 | if ( (cnx->state & VETH_STATE_OPEN) | 714 | if ( (cnx->state & VETH_STATE_OPEN) |
490 | && !(cnx->state & VETH_STATE_SENTMON) ) { | 715 | && !(cnx->state & VETH_STATE_SENTMON) ) { |
491 | rc = veth_signalevent(cnx, VethEventTypeMonitor, | 716 | rc = veth_signalevent(cnx, VETH_EVENT_MONITOR, |
492 | HvLpEvent_AckInd_DoAck, | 717 | HvLpEvent_AckInd_DoAck, |
493 | HvLpEvent_AckType_DeferredAck, | 718 | HvLpEvent_AckType_DeferredAck, |
494 | 0, 0, 0, 0, 0, 0); | 719 | 0, 0, 0, 0, 0, 0); |
@@ -498,9 +723,8 @@ static void veth_statemachine(void *p) | |||
498 | } else { | 723 | } else { |
499 | if ( (rc != HvLpEvent_Rc_PartitionDead) | 724 | if ( (rc != HvLpEvent_Rc_PartitionDead) |
500 | && (rc != HvLpEvent_Rc_PathClosed) ) | 725 | && (rc != HvLpEvent_Rc_PathClosed) ) |
501 | veth_error("Error sending monitor to " | 726 | veth_error("Error sending monitor to LPAR %d, " |
502 | "lpar %d, rc=%x\n", | 727 | "rc = %d\n", rlp, rc); |
503 | rlp, (int) rc); | ||
504 | 728 | ||
505 | /* Oh well, hope we get a cap from the other | 729 | /* Oh well, hope we get a cap from the other |
506 | * end and do better when that kicks us */ | 730 | * end and do better when that kicks us */ |
@@ -512,7 +736,7 @@ static void veth_statemachine(void *p) | |||
512 | && !(cnx->state & VETH_STATE_SENTCAPS)) { | 736 | && !(cnx->state & VETH_STATE_SENTCAPS)) { |
513 | u64 *rawcap = (u64 *)&cnx->local_caps; | 737 | u64 *rawcap = (u64 *)&cnx->local_caps; |
514 | 738 | ||
515 | rc = veth_signalevent(cnx, VethEventTypeCap, | 739 | rc = veth_signalevent(cnx, VETH_EVENT_CAP, |
516 | HvLpEvent_AckInd_DoAck, | 740 | HvLpEvent_AckInd_DoAck, |
517 | HvLpEvent_AckType_ImmediateAck, | 741 | HvLpEvent_AckType_ImmediateAck, |
518 | 0, rawcap[0], rawcap[1], rawcap[2], | 742 | 0, rawcap[0], rawcap[1], rawcap[2], |
@@ -523,9 +747,9 @@ static void veth_statemachine(void *p) | |||
523 | } else { | 747 | } else { |
524 | if ( (rc != HvLpEvent_Rc_PartitionDead) | 748 | if ( (rc != HvLpEvent_Rc_PartitionDead) |
525 | && (rc != HvLpEvent_Rc_PathClosed) ) | 749 | && (rc != HvLpEvent_Rc_PathClosed) ) |
526 | veth_error("Error sending caps to " | 750 | veth_error("Error sending caps to LPAR %d, " |
527 | "lpar %d, rc=%x\n", | 751 | "rc = %d\n", rlp, rc); |
528 | rlp, (int) rc); | 752 | |
529 | /* Oh well, hope we get a cap from the other | 753 | /* Oh well, hope we get a cap from the other |
530 | * end and do better when that kicks us */ | 754 | * end and do better when that kicks us */ |
531 | goto out; | 755 | goto out; |
@@ -534,7 +758,7 @@ static void veth_statemachine(void *p) | |||
534 | 758 | ||
535 | if ((cnx->state & VETH_STATE_GOTCAPS) | 759 | if ((cnx->state & VETH_STATE_GOTCAPS) |
536 | && !(cnx->state & VETH_STATE_SENTCAPACK)) { | 760 | && !(cnx->state & VETH_STATE_SENTCAPACK)) { |
537 | struct VethCapData *remote_caps = &cnx->remote_caps; | 761 | struct veth_cap_data *remote_caps = &cnx->remote_caps; |
538 | 762 | ||
539 | memcpy(remote_caps, &cnx->cap_event.u.caps_data, | 763 | memcpy(remote_caps, &cnx->cap_event.u.caps_data, |
540 | sizeof(*remote_caps)); | 764 | sizeof(*remote_caps)); |
@@ -565,10 +789,8 @@ static void veth_statemachine(void *p) | |||
565 | add_timer(&cnx->ack_timer); | 789 | add_timer(&cnx->ack_timer); |
566 | cnx->state |= VETH_STATE_READY; | 790 | cnx->state |= VETH_STATE_READY; |
567 | } else { | 791 | } else { |
568 | veth_printk(KERN_ERR, "Caps rejected (rc=%d) by " | 792 | veth_error("Caps rejected by LPAR %d, rc = %d\n", |
569 | "lpar %d\n", | 793 | rlp, cnx->cap_ack_event.base_event.xRc); |
570 | cnx->cap_ack_event.base_event.xRc, | ||
571 | rlp); | ||
572 | goto cant_cope; | 794 | goto cant_cope; |
573 | } | 795 | } |
574 | } | 796 | } |
@@ -581,8 +803,8 @@ static void veth_statemachine(void *p) | |||
581 | /* FIXME: we get here if something happens we really can't | 803 | /* FIXME: we get here if something happens we really can't |
582 | * cope with. The link will never work once we get here, and | 804 | * cope with. The link will never work once we get here, and |
583 | * all we can do is not lock the rest of the system up */ | 805 | * all we can do is not lock the rest of the system up */ |
584 | veth_error("Badness on connection to lpar %d (state=%04lx) " | 806 | veth_error("Unrecoverable error on connection to LPAR %d, shutting down" |
585 | " - shutting down\n", rlp, cnx->state); | 807 | " (state = 0x%04lx)\n", rlp, cnx->state); |
586 | cnx->state |= VETH_STATE_SHUTDOWN; | 808 | cnx->state |= VETH_STATE_SHUTDOWN; |
587 | spin_unlock_irq(&cnx->lock); | 809 | spin_unlock_irq(&cnx->lock); |
588 | } | 810 | } |
@@ -591,7 +813,7 @@ static int veth_init_connection(u8 rlp) | |||
591 | { | 813 | { |
592 | struct veth_lpar_connection *cnx; | 814 | struct veth_lpar_connection *cnx; |
593 | struct veth_msg *msgs; | 815 | struct veth_msg *msgs; |
594 | int i; | 816 | int i, rc; |
595 | 817 | ||
596 | if ( (rlp == this_lp) | 818 | if ( (rlp == this_lp) |
597 | || ! HvLpConfig_doLpsCommunicateOnVirtualLan(this_lp, rlp) ) | 819 | || ! HvLpConfig_doLpsCommunicateOnVirtualLan(this_lp, rlp) ) |
@@ -605,22 +827,36 @@ static int veth_init_connection(u8 rlp) | |||
605 | cnx->remote_lp = rlp; | 827 | cnx->remote_lp = rlp; |
606 | spin_lock_init(&cnx->lock); | 828 | spin_lock_init(&cnx->lock); |
607 | INIT_WORK(&cnx->statemachine_wq, veth_statemachine, cnx); | 829 | INIT_WORK(&cnx->statemachine_wq, veth_statemachine, cnx); |
830 | |||
608 | init_timer(&cnx->ack_timer); | 831 | init_timer(&cnx->ack_timer); |
609 | cnx->ack_timer.function = veth_timed_ack; | 832 | cnx->ack_timer.function = veth_timed_ack; |
610 | cnx->ack_timer.data = (unsigned long) cnx; | 833 | cnx->ack_timer.data = (unsigned long) cnx; |
834 | |||
835 | init_timer(&cnx->reset_timer); | ||
836 | cnx->reset_timer.function = veth_timed_reset; | ||
837 | cnx->reset_timer.data = (unsigned long) cnx; | ||
838 | cnx->reset_timeout = 5 * HZ * (VETH_ACKTIMEOUT / 1000000); | ||
839 | |||
611 | memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks)); | 840 | memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks)); |
612 | 841 | ||
613 | veth_cnx[rlp] = cnx; | 842 | veth_cnx[rlp] = cnx; |
614 | 843 | ||
844 | /* This gets us 1 reference, which is held on behalf of the driver | ||
845 | * infrastructure. It's released at module unload. */ | ||
846 | kobject_init(&cnx->kobject); | ||
847 | cnx->kobject.ktype = &veth_lpar_connection_ktype; | ||
848 | rc = kobject_set_name(&cnx->kobject, "cnx%.2d", rlp); | ||
849 | if (rc != 0) | ||
850 | return rc; | ||
851 | |||
615 | msgs = kmalloc(VETH_NUMBUFFERS * sizeof(struct veth_msg), GFP_KERNEL); | 852 | msgs = kmalloc(VETH_NUMBUFFERS * sizeof(struct veth_msg), GFP_KERNEL); |
616 | if (! msgs) { | 853 | if (! msgs) { |
617 | veth_error("Can't allocate buffers for lpar %d\n", rlp); | 854 | veth_error("Can't allocate buffers for LPAR %d.\n", rlp); |
618 | return -ENOMEM; | 855 | return -ENOMEM; |
619 | } | 856 | } |
620 | 857 | ||
621 | cnx->msgs = msgs; | 858 | cnx->msgs = msgs; |
622 | memset(msgs, 0, VETH_NUMBUFFERS * sizeof(struct veth_msg)); | 859 | memset(msgs, 0, VETH_NUMBUFFERS * sizeof(struct veth_msg)); |
623 | spin_lock_init(&cnx->msg_stack_lock); | ||
624 | 860 | ||
625 | for (i = 0; i < VETH_NUMBUFFERS; i++) { | 861 | for (i = 0; i < VETH_NUMBUFFERS; i++) { |
626 | msgs[i].token = i; | 862 | msgs[i].token = i; |
@@ -630,8 +866,7 @@ static int veth_init_connection(u8 rlp) | |||
630 | cnx->num_events = veth_allocate_events(rlp, 2 + VETH_NUMBUFFERS); | 866 | cnx->num_events = veth_allocate_events(rlp, 2 + VETH_NUMBUFFERS); |
631 | 867 | ||
632 | if (cnx->num_events < (2 + VETH_NUMBUFFERS)) { | 868 | if (cnx->num_events < (2 + VETH_NUMBUFFERS)) { |
633 | veth_error("Can't allocate events for lpar %d, only got %d\n", | 869 | veth_error("Can't allocate enough events for LPAR %d.\n", rlp); |
634 | rlp, cnx->num_events); | ||
635 | return -ENOMEM; | 870 | return -ENOMEM; |
636 | } | 871 | } |
637 | 872 | ||
@@ -642,11 +877,9 @@ static int veth_init_connection(u8 rlp) | |||
642 | return 0; | 877 | return 0; |
643 | } | 878 | } |
644 | 879 | ||
645 | static void veth_stop_connection(u8 rlp) | 880 | static void veth_stop_connection(struct veth_lpar_connection *cnx) |
646 | { | 881 | { |
647 | struct veth_lpar_connection *cnx = veth_cnx[rlp]; | 882 | if (!cnx) |
648 | |||
649 | if (! cnx) | ||
650 | return; | 883 | return; |
651 | 884 | ||
652 | spin_lock_irq(&cnx->lock); | 885 | spin_lock_irq(&cnx->lock); |
@@ -654,12 +887,23 @@ static void veth_stop_connection(u8 rlp) | |||
654 | veth_kick_statemachine(cnx); | 887 | veth_kick_statemachine(cnx); |
655 | spin_unlock_irq(&cnx->lock); | 888 | spin_unlock_irq(&cnx->lock); |
656 | 889 | ||
890 | /* There's a slim chance the reset code has just queued the | ||
891 | * statemachine to run in five seconds. If so we need to cancel | ||
892 | * that and requeue the work to run now. */ | ||
893 | if (cancel_delayed_work(&cnx->statemachine_wq)) { | ||
894 | spin_lock_irq(&cnx->lock); | ||
895 | veth_kick_statemachine(cnx); | ||
896 | spin_unlock_irq(&cnx->lock); | ||
897 | } | ||
898 | |||
899 | /* Wait for the state machine to run. */ | ||
657 | flush_scheduled_work(); | 900 | flush_scheduled_work(); |
901 | } | ||
658 | 902 | ||
659 | /* FIXME: not sure if this is necessary - will already have | 903 | static void veth_destroy_connection(struct veth_lpar_connection *cnx) |
660 | * been deleted by the state machine, just want to make sure | 904 | { |
661 | * its not running any more */ | 905 | if (!cnx) |
662 | del_timer_sync(&cnx->ack_timer); | 906 | return; |
663 | 907 | ||
664 | if (cnx->num_events > 0) | 908 | if (cnx->num_events > 0) |
665 | mf_deallocate_lp_events(cnx->remote_lp, | 909 | mf_deallocate_lp_events(cnx->remote_lp, |
@@ -671,18 +915,18 @@ static void veth_stop_connection(u8 rlp) | |||
671 | HvLpEvent_Type_VirtualLan, | 915 | HvLpEvent_Type_VirtualLan, |
672 | cnx->num_ack_events, | 916 | cnx->num_ack_events, |
673 | NULL, NULL); | 917 | NULL, NULL); |
674 | } | ||
675 | |||
676 | static void veth_destroy_connection(u8 rlp) | ||
677 | { | ||
678 | struct veth_lpar_connection *cnx = veth_cnx[rlp]; | ||
679 | |||
680 | if (! cnx) | ||
681 | return; | ||
682 | 918 | ||
683 | kfree(cnx->msgs); | 919 | kfree(cnx->msgs); |
920 | veth_cnx[cnx->remote_lp] = NULL; | ||
684 | kfree(cnx); | 921 | kfree(cnx); |
685 | veth_cnx[rlp] = NULL; | 922 | } |
923 | |||
924 | static void veth_release_connection(struct kobject *kobj) | ||
925 | { | ||
926 | struct veth_lpar_connection *cnx; | ||
927 | cnx = container_of(kobj, struct veth_lpar_connection, kobject); | ||
928 | veth_stop_connection(cnx); | ||
929 | veth_destroy_connection(cnx); | ||
686 | } | 930 | } |
687 | 931 | ||
688 | /* | 932 | /* |
@@ -726,17 +970,15 @@ static void veth_set_multicast_list(struct net_device *dev) | |||
726 | 970 | ||
727 | write_lock_irqsave(&port->mcast_gate, flags); | 971 | write_lock_irqsave(&port->mcast_gate, flags); |
728 | 972 | ||
729 | if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ | 973 | if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || |
730 | printk(KERN_INFO "%s: Promiscuous mode enabled.\n", | 974 | (dev->mc_count > VETH_MAX_MCAST)) { |
731 | dev->name); | ||
732 | port->promiscuous = 1; | 975 | port->promiscuous = 1; |
733 | } else if ( (dev->flags & IFF_ALLMULTI) | ||
734 | || (dev->mc_count > VETH_MAX_MCAST) ) { | ||
735 | port->all_mcast = 1; | ||
736 | } else { | 976 | } else { |
737 | struct dev_mc_list *dmi = dev->mc_list; | 977 | struct dev_mc_list *dmi = dev->mc_list; |
738 | int i; | 978 | int i; |
739 | 979 | ||
980 | port->promiscuous = 0; | ||
981 | |||
740 | /* Update table */ | 982 | /* Update table */ |
741 | port->num_mcast = 0; | 983 | port->num_mcast = 0; |
742 | 984 | ||
@@ -758,9 +1000,10 @@ static void veth_set_multicast_list(struct net_device *dev) | |||
758 | 1000 | ||
759 | static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | 1001 | static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) |
760 | { | 1002 | { |
761 | strncpy(info->driver, "veth", sizeof(info->driver) - 1); | 1003 | strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1); |
762 | info->driver[sizeof(info->driver) - 1] = '\0'; | 1004 | info->driver[sizeof(info->driver) - 1] = '\0'; |
763 | strncpy(info->version, "1.0", sizeof(info->version) - 1); | 1005 | strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1); |
1006 | info->version[sizeof(info->version) - 1] = '\0'; | ||
764 | } | 1007 | } |
765 | 1008 | ||
766 | static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | 1009 | static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) |
@@ -791,49 +1034,6 @@ static struct ethtool_ops ops = { | |||
791 | .get_link = veth_get_link, | 1034 | .get_link = veth_get_link, |
792 | }; | 1035 | }; |
793 | 1036 | ||
794 | static void veth_tx_timeout(struct net_device *dev) | ||
795 | { | ||
796 | struct veth_port *port = (struct veth_port *)dev->priv; | ||
797 | struct net_device_stats *stats = &port->stats; | ||
798 | unsigned long flags; | ||
799 | int i; | ||
800 | |||
801 | stats->tx_errors++; | ||
802 | |||
803 | spin_lock_irqsave(&port->pending_gate, flags); | ||
804 | |||
805 | if (!port->pending_lpmask) { | ||
806 | spin_unlock_irqrestore(&port->pending_gate, flags); | ||
807 | return; | ||
808 | } | ||
809 | |||
810 | printk(KERN_WARNING "%s: Tx timeout! Resetting lp connections: %08x\n", | ||
811 | dev->name, port->pending_lpmask); | ||
812 | |||
813 | for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { | ||
814 | struct veth_lpar_connection *cnx = veth_cnx[i]; | ||
815 | |||
816 | if (! (port->pending_lpmask & (1<<i))) | ||
817 | continue; | ||
818 | |||
819 | /* If we're pending on it, we must be connected to it, | ||
820 | * so we should certainly have a structure for it. */ | ||
821 | BUG_ON(! cnx); | ||
822 | |||
823 | /* Theoretically we could be kicking a connection | ||
824 | * which doesn't deserve it, but in practice if we've | ||
825 | * had a Tx timeout, the pending_lpmask will have | ||
826 | * exactly one bit set - the connection causing the | ||
827 | * problem. */ | ||
828 | spin_lock(&cnx->lock); | ||
829 | cnx->state |= VETH_STATE_RESET; | ||
830 | veth_kick_statemachine(cnx); | ||
831 | spin_unlock(&cnx->lock); | ||
832 | } | ||
833 | |||
834 | spin_unlock_irqrestore(&port->pending_gate, flags); | ||
835 | } | ||
836 | |||
837 | static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) | 1037 | static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) |
838 | { | 1038 | { |
839 | struct net_device *dev; | 1039 | struct net_device *dev; |
@@ -848,8 +1048,9 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) | |||
848 | 1048 | ||
849 | port = (struct veth_port *) dev->priv; | 1049 | port = (struct veth_port *) dev->priv; |
850 | 1050 | ||
851 | spin_lock_init(&port->pending_gate); | 1051 | spin_lock_init(&port->queue_lock); |
852 | rwlock_init(&port->mcast_gate); | 1052 | rwlock_init(&port->mcast_gate); |
1053 | port->stopped_map = 0; | ||
853 | 1054 | ||
854 | for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { | 1055 | for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { |
855 | HvLpVirtualLanIndexMap map; | 1056 | HvLpVirtualLanIndexMap map; |
@@ -882,22 +1083,24 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) | |||
882 | dev->set_multicast_list = veth_set_multicast_list; | 1083 | dev->set_multicast_list = veth_set_multicast_list; |
883 | SET_ETHTOOL_OPS(dev, &ops); | 1084 | SET_ETHTOOL_OPS(dev, &ops); |
884 | 1085 | ||
885 | dev->watchdog_timeo = 2 * (VETH_ACKTIMEOUT * HZ / 1000000); | ||
886 | dev->tx_timeout = veth_tx_timeout; | ||
887 | |||
888 | SET_NETDEV_DEV(dev, vdev); | 1086 | SET_NETDEV_DEV(dev, vdev); |
889 | 1087 | ||
890 | rc = register_netdev(dev); | 1088 | rc = register_netdev(dev); |
891 | if (rc != 0) { | 1089 | if (rc != 0) { |
892 | veth_printk(KERN_ERR, | 1090 | veth_error("Failed registering net device for vlan%d.\n", vlan); |
893 | "Failed to register ethernet device for vlan %d\n", | ||
894 | vlan); | ||
895 | free_netdev(dev); | 1091 | free_netdev(dev); |
896 | return NULL; | 1092 | return NULL; |
897 | } | 1093 | } |
898 | 1094 | ||
899 | veth_printk(KERN_DEBUG, "%s attached to iSeries vlan %d (lpar_map=0x%04x)\n", | 1095 | kobject_init(&port->kobject); |
900 | dev->name, vlan, port->lpar_map); | 1096 | port->kobject.parent = &dev->class_dev.kobj; |
1097 | port->kobject.ktype = &veth_port_ktype; | ||
1098 | kobject_set_name(&port->kobject, "veth_port"); | ||
1099 | if (0 != kobject_add(&port->kobject)) | ||
1100 | veth_error("Failed adding port for %s to sysfs.\n", dev->name); | ||
1101 | |||
1102 | veth_info("%s attached to iSeries vlan %d (LPAR map = 0x%.4X)\n", | ||
1103 | dev->name, vlan, port->lpar_map); | ||
901 | 1104 | ||
902 | return dev; | 1105 | return dev; |
903 | } | 1106 | } |
@@ -912,98 +1115,95 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp, | |||
912 | struct veth_lpar_connection *cnx = veth_cnx[rlp]; | 1115 | struct veth_lpar_connection *cnx = veth_cnx[rlp]; |
913 | struct veth_port *port = (struct veth_port *) dev->priv; | 1116 | struct veth_port *port = (struct veth_port *) dev->priv; |
914 | HvLpEvent_Rc rc; | 1117 | HvLpEvent_Rc rc; |
915 | u32 dma_address, dma_length; | ||
916 | struct veth_msg *msg = NULL; | 1118 | struct veth_msg *msg = NULL; |
917 | int err = 0; | ||
918 | unsigned long flags; | 1119 | unsigned long flags; |
919 | 1120 | ||
920 | if (! cnx) { | 1121 | if (! cnx) |
921 | port->stats.tx_errors++; | ||
922 | dev_kfree_skb(skb); | ||
923 | return 0; | 1122 | return 0; |
924 | } | ||
925 | 1123 | ||
926 | spin_lock_irqsave(&cnx->lock, flags); | 1124 | spin_lock_irqsave(&cnx->lock, flags); |
927 | 1125 | ||
928 | if (! (cnx->state & VETH_STATE_READY)) | 1126 | if (! (cnx->state & VETH_STATE_READY)) |
929 | goto drop; | 1127 | goto no_error; |
930 | 1128 | ||
931 | if ((skb->len - 14) > VETH_MAX_MTU) | 1129 | if ((skb->len - ETH_HLEN) > VETH_MAX_MTU) |
932 | goto drop; | 1130 | goto drop; |
933 | 1131 | ||
934 | msg = veth_stack_pop(cnx); | 1132 | msg = veth_stack_pop(cnx); |
935 | 1133 | if (! msg) | |
936 | if (! msg) { | ||
937 | err = 1; | ||
938 | goto drop; | 1134 | goto drop; |
939 | } | ||
940 | 1135 | ||
941 | dma_length = skb->len; | 1136 | msg->in_use = 1; |
942 | dma_address = dma_map_single(port->dev, skb->data, | 1137 | msg->skb = skb_get(skb); |
943 | dma_length, DMA_TO_DEVICE); | 1138 | |
1139 | msg->data.addr[0] = dma_map_single(port->dev, skb->data, | ||
1140 | skb->len, DMA_TO_DEVICE); | ||
944 | 1141 | ||
945 | if (dma_mapping_error(dma_address)) | 1142 | if (dma_mapping_error(msg->data.addr[0])) |
946 | goto recycle_and_drop; | 1143 | goto recycle_and_drop; |
947 | 1144 | ||
948 | /* Is it really necessary to check the length and address | ||
949 | * fields of the first entry here? */ | ||
950 | msg->skb = skb; | ||
951 | msg->dev = port->dev; | 1145 | msg->dev = port->dev; |
952 | msg->data.addr[0] = dma_address; | 1146 | msg->data.len[0] = skb->len; |
953 | msg->data.len[0] = dma_length; | ||
954 | msg->data.eofmask = 1 << VETH_EOF_SHIFT; | 1147 | msg->data.eofmask = 1 << VETH_EOF_SHIFT; |
955 | set_bit(0, &(msg->in_use)); | 1148 | |
956 | rc = veth_signaldata(cnx, VethEventTypeFrames, msg->token, &msg->data); | 1149 | rc = veth_signaldata(cnx, VETH_EVENT_FRAMES, msg->token, &msg->data); |
957 | 1150 | ||
958 | if (rc != HvLpEvent_Rc_Good) | 1151 | if (rc != HvLpEvent_Rc_Good) |
959 | goto recycle_and_drop; | 1152 | goto recycle_and_drop; |
960 | 1153 | ||
1154 | /* If the timer's not already running, start it now. */ | ||
1155 | if (0 == cnx->outstanding_tx) | ||
1156 | mod_timer(&cnx->reset_timer, jiffies + cnx->reset_timeout); | ||
1157 | |||
1158 | cnx->last_contact = jiffies; | ||
1159 | cnx->outstanding_tx++; | ||
1160 | |||
1161 | if (veth_stack_is_empty(cnx)) | ||
1162 | veth_stop_queues(cnx); | ||
1163 | |||
1164 | no_error: | ||
961 | spin_unlock_irqrestore(&cnx->lock, flags); | 1165 | spin_unlock_irqrestore(&cnx->lock, flags); |
962 | return 0; | 1166 | return 0; |
963 | 1167 | ||
964 | recycle_and_drop: | 1168 | recycle_and_drop: |
965 | msg->skb = NULL; | ||
966 | /* need to set in use to make veth_recycle_msg in case this | ||
967 | * was a mapping failure */ | ||
968 | set_bit(0, &msg->in_use); | ||
969 | veth_recycle_msg(cnx, msg); | 1169 | veth_recycle_msg(cnx, msg); |
970 | drop: | 1170 | drop: |
971 | port->stats.tx_errors++; | ||
972 | dev_kfree_skb(skb); | ||
973 | spin_unlock_irqrestore(&cnx->lock, flags); | 1171 | spin_unlock_irqrestore(&cnx->lock, flags); |
974 | return err; | 1172 | return 1; |
975 | } | 1173 | } |
976 | 1174 | ||
977 | static HvLpIndexMap veth_transmit_to_many(struct sk_buff *skb, | 1175 | static void veth_transmit_to_many(struct sk_buff *skb, |
978 | HvLpIndexMap lpmask, | 1176 | HvLpIndexMap lpmask, |
979 | struct net_device *dev) | 1177 | struct net_device *dev) |
980 | { | 1178 | { |
981 | struct veth_port *port = (struct veth_port *) dev->priv; | 1179 | struct veth_port *port = (struct veth_port *) dev->priv; |
982 | int i; | 1180 | int i, success, error; |
983 | int rc; | 1181 | |
1182 | success = error = 0; | ||
984 | 1183 | ||
985 | for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { | 1184 | for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { |
986 | if ((lpmask & (1 << i)) == 0) | 1185 | if ((lpmask & (1 << i)) == 0) |
987 | continue; | 1186 | continue; |
988 | 1187 | ||
989 | rc = veth_transmit_to_one(skb_get(skb), i, dev); | 1188 | if (veth_transmit_to_one(skb, i, dev)) |
990 | if (! rc) | 1189 | error = 1; |
991 | lpmask &= ~(1<<i); | 1190 | else |
1191 | success = 1; | ||
992 | } | 1192 | } |
993 | 1193 | ||
994 | if (! lpmask) { | 1194 | if (error) |
1195 | port->stats.tx_errors++; | ||
1196 | |||
1197 | if (success) { | ||
995 | port->stats.tx_packets++; | 1198 | port->stats.tx_packets++; |
996 | port->stats.tx_bytes += skb->len; | 1199 | port->stats.tx_bytes += skb->len; |
997 | } | 1200 | } |
998 | |||
999 | return lpmask; | ||
1000 | } | 1201 | } |
1001 | 1202 | ||
1002 | static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev) | 1203 | static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev) |
1003 | { | 1204 | { |
1004 | unsigned char *frame = skb->data; | 1205 | unsigned char *frame = skb->data; |
1005 | struct veth_port *port = (struct veth_port *) dev->priv; | 1206 | struct veth_port *port = (struct veth_port *) dev->priv; |
1006 | unsigned long flags; | ||
1007 | HvLpIndexMap lpmask; | 1207 | HvLpIndexMap lpmask; |
1008 | 1208 | ||
1009 | if (! (frame[0] & 0x01)) { | 1209 | if (! (frame[0] & 0x01)) { |
@@ -1020,44 +1220,27 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1020 | lpmask = port->lpar_map; | 1220 | lpmask = port->lpar_map; |
1021 | } | 1221 | } |
1022 | 1222 | ||
1023 | spin_lock_irqsave(&port->pending_gate, flags); | 1223 | veth_transmit_to_many(skb, lpmask, dev); |
1024 | |||
1025 | lpmask = veth_transmit_to_many(skb, lpmask, dev); | ||
1026 | |||
1027 | dev->trans_start = jiffies; | ||
1028 | 1224 | ||
1029 | if (! lpmask) { | 1225 | dev_kfree_skb(skb); |
1030 | dev_kfree_skb(skb); | ||
1031 | } else { | ||
1032 | if (port->pending_skb) { | ||
1033 | veth_error("%s: Tx while skb was pending!\n", | ||
1034 | dev->name); | ||
1035 | dev_kfree_skb(skb); | ||
1036 | spin_unlock_irqrestore(&port->pending_gate, flags); | ||
1037 | return 1; | ||
1038 | } | ||
1039 | |||
1040 | port->pending_skb = skb; | ||
1041 | port->pending_lpmask = lpmask; | ||
1042 | netif_stop_queue(dev); | ||
1043 | } | ||
1044 | |||
1045 | spin_unlock_irqrestore(&port->pending_gate, flags); | ||
1046 | 1226 | ||
1047 | return 0; | 1227 | return 0; |
1048 | } | 1228 | } |
1049 | 1229 | ||
1230 | /* You must hold the connection's lock when you call this function. */ | ||
1050 | static void veth_recycle_msg(struct veth_lpar_connection *cnx, | 1231 | static void veth_recycle_msg(struct veth_lpar_connection *cnx, |
1051 | struct veth_msg *msg) | 1232 | struct veth_msg *msg) |
1052 | { | 1233 | { |
1053 | u32 dma_address, dma_length; | 1234 | u32 dma_address, dma_length; |
1054 | 1235 | ||
1055 | if (test_and_clear_bit(0, &msg->in_use)) { | 1236 | if (msg->in_use) { |
1237 | msg->in_use = 0; | ||
1056 | dma_address = msg->data.addr[0]; | 1238 | dma_address = msg->data.addr[0]; |
1057 | dma_length = msg->data.len[0]; | 1239 | dma_length = msg->data.len[0]; |
1058 | 1240 | ||
1059 | dma_unmap_single(msg->dev, dma_address, dma_length, | 1241 | if (!dma_mapping_error(dma_address)) |
1060 | DMA_TO_DEVICE); | 1242 | dma_unmap_single(msg->dev, dma_address, dma_length, |
1243 | DMA_TO_DEVICE); | ||
1061 | 1244 | ||
1062 | if (msg->skb) { | 1245 | if (msg->skb) { |
1063 | dev_kfree_skb_any(msg->skb); | 1246 | dev_kfree_skb_any(msg->skb); |
@@ -1066,15 +1249,16 @@ static void veth_recycle_msg(struct veth_lpar_connection *cnx, | |||
1066 | 1249 | ||
1067 | memset(&msg->data, 0, sizeof(msg->data)); | 1250 | memset(&msg->data, 0, sizeof(msg->data)); |
1068 | veth_stack_push(cnx, msg); | 1251 | veth_stack_push(cnx, msg); |
1069 | } else | 1252 | } else if (cnx->state & VETH_STATE_OPEN) { |
1070 | if (cnx->state & VETH_STATE_OPEN) | 1253 | veth_error("Non-pending frame (# %d) acked by LPAR %d.\n", |
1071 | veth_error("Bogus frames ack from lpar %d (#%d)\n", | 1254 | cnx->remote_lp, msg->token); |
1072 | cnx->remote_lp, msg->token); | 1255 | } |
1073 | } | 1256 | } |
1074 | 1257 | ||
1075 | static void veth_flush_pending(struct veth_lpar_connection *cnx) | 1258 | static void veth_wake_queues(struct veth_lpar_connection *cnx) |
1076 | { | 1259 | { |
1077 | int i; | 1260 | int i; |
1261 | |||
1078 | for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { | 1262 | for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { |
1079 | struct net_device *dev = veth_dev[i]; | 1263 | struct net_device *dev = veth_dev[i]; |
1080 | struct veth_port *port; | 1264 | struct veth_port *port; |
@@ -1088,20 +1272,77 @@ static void veth_flush_pending(struct veth_lpar_connection *cnx) | |||
1088 | if (! (port->lpar_map & (1<<cnx->remote_lp))) | 1272 | if (! (port->lpar_map & (1<<cnx->remote_lp))) |
1089 | continue; | 1273 | continue; |
1090 | 1274 | ||
1091 | spin_lock_irqsave(&port->pending_gate, flags); | 1275 | spin_lock_irqsave(&port->queue_lock, flags); |
1092 | if (port->pending_skb) { | 1276 | |
1093 | port->pending_lpmask = | 1277 | port->stopped_map &= ~(1 << cnx->remote_lp); |
1094 | veth_transmit_to_many(port->pending_skb, | 1278 | |
1095 | port->pending_lpmask, | 1279 | if (0 == port->stopped_map && netif_queue_stopped(dev)) { |
1096 | dev); | 1280 | veth_debug("cnx %d: woke queue for %s.\n", |
1097 | if (! port->pending_lpmask) { | 1281 | cnx->remote_lp, dev->name); |
1098 | dev_kfree_skb_any(port->pending_skb); | 1282 | netif_wake_queue(dev); |
1099 | port->pending_skb = NULL; | 1283 | } |
1100 | netif_wake_queue(dev); | 1284 | spin_unlock_irqrestore(&port->queue_lock, flags); |
1101 | } | 1285 | } |
1286 | } | ||
1287 | |||
1288 | static void veth_stop_queues(struct veth_lpar_connection *cnx) | ||
1289 | { | ||
1290 | int i; | ||
1291 | |||
1292 | for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { | ||
1293 | struct net_device *dev = veth_dev[i]; | ||
1294 | struct veth_port *port; | ||
1295 | |||
1296 | if (! dev) | ||
1297 | continue; | ||
1298 | |||
1299 | port = (struct veth_port *)dev->priv; | ||
1300 | |||
1301 | /* If this cnx is not on the vlan for this port, continue */ | ||
1302 | if (! (port->lpar_map & (1 << cnx->remote_lp))) | ||
1303 | continue; | ||
1304 | |||
1305 | spin_lock(&port->queue_lock); | ||
1306 | |||
1307 | netif_stop_queue(dev); | ||
1308 | port->stopped_map |= (1 << cnx->remote_lp); | ||
1309 | |||
1310 | veth_debug("cnx %d: stopped queue for %s, map = 0x%x.\n", | ||
1311 | cnx->remote_lp, dev->name, port->stopped_map); | ||
1312 | |||
1313 | spin_unlock(&port->queue_lock); | ||
1314 | } | ||
1315 | } | ||
1316 | |||
1317 | static void veth_timed_reset(unsigned long ptr) | ||
1318 | { | ||
1319 | struct veth_lpar_connection *cnx = (struct veth_lpar_connection *)ptr; | ||
1320 | unsigned long trigger_time, flags; | ||
1321 | |||
1322 | /* FIXME is it possible this fires after veth_stop_connection()? | ||
1323 | * That would reschedule the statemachine for 5 seconds and probably | ||
1324 | * execute it after the module's been unloaded. Hmm. */ | ||
1325 | |||
1326 | spin_lock_irqsave(&cnx->lock, flags); | ||
1327 | |||
1328 | if (cnx->outstanding_tx > 0) { | ||
1329 | trigger_time = cnx->last_contact + cnx->reset_timeout; | ||
1330 | |||
1331 | if (trigger_time < jiffies) { | ||
1332 | cnx->state |= VETH_STATE_RESET; | ||
1333 | veth_kick_statemachine(cnx); | ||
1334 | veth_error("%d packets not acked by LPAR %d within %d " | ||
1335 | "seconds, resetting.\n", | ||
1336 | cnx->outstanding_tx, cnx->remote_lp, | ||
1337 | cnx->reset_timeout / HZ); | ||
1338 | } else { | ||
1339 | /* Reschedule the timer */ | ||
1340 | trigger_time = jiffies + cnx->reset_timeout; | ||
1341 | mod_timer(&cnx->reset_timer, trigger_time); | ||
1102 | } | 1342 | } |
1103 | spin_unlock_irqrestore(&port->pending_gate, flags); | ||
1104 | } | 1343 | } |
1344 | |||
1345 | spin_unlock_irqrestore(&cnx->lock, flags); | ||
1105 | } | 1346 | } |
1106 | 1347 | ||
1107 | /* | 1348 | /* |
@@ -1117,12 +1358,9 @@ static inline int veth_frame_wanted(struct veth_port *port, u64 mac_addr) | |||
1117 | if ( (mac_addr == port->mac_addr) || (mac_addr == 0xffffffffffff0000) ) | 1358 | if ( (mac_addr == port->mac_addr) || (mac_addr == 0xffffffffffff0000) ) |
1118 | return 1; | 1359 | return 1; |
1119 | 1360 | ||
1120 | if (! (((char *) &mac_addr)[0] & 0x01)) | ||
1121 | return 0; | ||
1122 | |||
1123 | read_lock_irqsave(&port->mcast_gate, flags); | 1361 | read_lock_irqsave(&port->mcast_gate, flags); |
1124 | 1362 | ||
1125 | if (port->promiscuous || port->all_mcast) { | 1363 | if (port->promiscuous) { |
1126 | wanted = 1; | 1364 | wanted = 1; |
1127 | goto out; | 1365 | goto out; |
1128 | } | 1366 | } |
@@ -1175,21 +1413,21 @@ static void veth_flush_acks(struct veth_lpar_connection *cnx) | |||
1175 | { | 1413 | { |
1176 | HvLpEvent_Rc rc; | 1414 | HvLpEvent_Rc rc; |
1177 | 1415 | ||
1178 | rc = veth_signaldata(cnx, VethEventTypeFramesAck, | 1416 | rc = veth_signaldata(cnx, VETH_EVENT_FRAMES_ACK, |
1179 | 0, &cnx->pending_acks); | 1417 | 0, &cnx->pending_acks); |
1180 | 1418 | ||
1181 | if (rc != HvLpEvent_Rc_Good) | 1419 | if (rc != HvLpEvent_Rc_Good) |
1182 | veth_error("Error 0x%x acking frames from lpar %d!\n", | 1420 | veth_error("Failed acking frames from LPAR %d, rc = %d\n", |
1183 | (unsigned)rc, cnx->remote_lp); | 1421 | cnx->remote_lp, (int)rc); |
1184 | 1422 | ||
1185 | cnx->num_pending_acks = 0; | 1423 | cnx->num_pending_acks = 0; |
1186 | memset(&cnx->pending_acks, 0xff, sizeof(cnx->pending_acks)); | 1424 | memset(&cnx->pending_acks, 0xff, sizeof(cnx->pending_acks)); |
1187 | } | 1425 | } |
1188 | 1426 | ||
1189 | static void veth_receive(struct veth_lpar_connection *cnx, | 1427 | static void veth_receive(struct veth_lpar_connection *cnx, |
1190 | struct VethLpEvent *event) | 1428 | struct veth_lpevent *event) |
1191 | { | 1429 | { |
1192 | struct VethFramesData *senddata = &event->u.frames_data; | 1430 | struct veth_frames_data *senddata = &event->u.frames_data; |
1193 | int startchunk = 0; | 1431 | int startchunk = 0; |
1194 | int nchunks; | 1432 | int nchunks; |
1195 | unsigned long flags; | 1433 | unsigned long flags; |
@@ -1216,9 +1454,10 @@ static void veth_receive(struct veth_lpar_connection *cnx, | |||
1216 | /* make sure that we have at least 1 EOF entry in the | 1454 | /* make sure that we have at least 1 EOF entry in the |
1217 | * remaining entries */ | 1455 | * remaining entries */ |
1218 | if (! (senddata->eofmask >> (startchunk + VETH_EOF_SHIFT))) { | 1456 | if (! (senddata->eofmask >> (startchunk + VETH_EOF_SHIFT))) { |
1219 | veth_error("missing EOF frag in event " | 1457 | veth_error("Missing EOF fragment in event " |
1220 | "eofmask=0x%x startchunk=%d\n", | 1458 | "eofmask = 0x%x startchunk = %d\n", |
1221 | (unsigned) senddata->eofmask, startchunk); | 1459 | (unsigned)senddata->eofmask, |
1460 | startchunk); | ||
1222 | break; | 1461 | break; |
1223 | } | 1462 | } |
1224 | 1463 | ||
@@ -1237,8 +1476,9 @@ static void veth_receive(struct veth_lpar_connection *cnx, | |||
1237 | /* nchunks == # of chunks in this frame */ | 1476 | /* nchunks == # of chunks in this frame */ |
1238 | 1477 | ||
1239 | if ((length - ETH_HLEN) > VETH_MAX_MTU) { | 1478 | if ((length - ETH_HLEN) > VETH_MAX_MTU) { |
1240 | veth_error("Received oversize frame from lpar %d " | 1479 | veth_error("Received oversize frame from LPAR %d " |
1241 | "(length=%d)\n", cnx->remote_lp, length); | 1480 | "(length = %d)\n", |
1481 | cnx->remote_lp, length); | ||
1242 | continue; | 1482 | continue; |
1243 | } | 1483 | } |
1244 | 1484 | ||
@@ -1331,15 +1571,33 @@ static void veth_timed_ack(unsigned long ptr) | |||
1331 | 1571 | ||
1332 | static int veth_remove(struct vio_dev *vdev) | 1572 | static int veth_remove(struct vio_dev *vdev) |
1333 | { | 1573 | { |
1334 | int i = vdev->unit_address; | 1574 | struct veth_lpar_connection *cnx; |
1335 | struct net_device *dev; | 1575 | struct net_device *dev; |
1576 | struct veth_port *port; | ||
1577 | int i; | ||
1336 | 1578 | ||
1337 | dev = veth_dev[i]; | 1579 | dev = veth_dev[vdev->unit_address]; |
1338 | if (dev != NULL) { | 1580 | |
1339 | veth_dev[i] = NULL; | 1581 | if (! dev) |
1340 | unregister_netdev(dev); | 1582 | return 0; |
1341 | free_netdev(dev); | 1583 | |
1584 | port = netdev_priv(dev); | ||
1585 | |||
1586 | for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { | ||
1587 | cnx = veth_cnx[i]; | ||
1588 | |||
1589 | if (cnx && (port->lpar_map & (1 << i))) { | ||
1590 | /* Drop our reference to connections on our VLAN */ | ||
1591 | kobject_put(&cnx->kobject); | ||
1592 | } | ||
1342 | } | 1593 | } |
1594 | |||
1595 | veth_dev[vdev->unit_address] = NULL; | ||
1596 | kobject_del(&port->kobject); | ||
1597 | kobject_put(&port->kobject); | ||
1598 | unregister_netdev(dev); | ||
1599 | free_netdev(dev); | ||
1600 | |||
1343 | return 0; | 1601 | return 0; |
1344 | } | 1602 | } |
1345 | 1603 | ||
@@ -1347,6 +1605,7 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1347 | { | 1605 | { |
1348 | int i = vdev->unit_address; | 1606 | int i = vdev->unit_address; |
1349 | struct net_device *dev; | 1607 | struct net_device *dev; |
1608 | struct veth_port *port; | ||
1350 | 1609 | ||
1351 | dev = veth_probe_one(i, &vdev->dev); | 1610 | dev = veth_probe_one(i, &vdev->dev); |
1352 | if (dev == NULL) { | 1611 | if (dev == NULL) { |
@@ -1355,11 +1614,23 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id) | |||
1355 | } | 1614 | } |
1356 | veth_dev[i] = dev; | 1615 | veth_dev[i] = dev; |
1357 | 1616 | ||
1358 | /* Start the state machine on each connection, to commence | 1617 | port = (struct veth_port*)netdev_priv(dev); |
1359 | * link negotiation */ | 1618 | |
1360 | for (i = 0; i < HVMAXARCHITECTEDLPS; i++) | 1619 | /* Start the state machine on each connection on this vlan. If we're |
1361 | if (veth_cnx[i]) | 1620 | * the first dev to do so this will commence link negotiation */ |
1362 | veth_kick_statemachine(veth_cnx[i]); | 1621 | for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { |
1622 | struct veth_lpar_connection *cnx; | ||
1623 | |||
1624 | if (! (port->lpar_map & (1 << i))) | ||
1625 | continue; | ||
1626 | |||
1627 | cnx = veth_cnx[i]; | ||
1628 | if (!cnx) | ||
1629 | continue; | ||
1630 | |||
1631 | kobject_get(&cnx->kobject); | ||
1632 | veth_kick_statemachine(cnx); | ||
1633 | } | ||
1363 | 1634 | ||
1364 | return 0; | 1635 | return 0; |
1365 | } | 1636 | } |
@@ -1375,7 +1646,7 @@ static struct vio_device_id veth_device_table[] __devinitdata = { | |||
1375 | MODULE_DEVICE_TABLE(vio, veth_device_table); | 1646 | MODULE_DEVICE_TABLE(vio, veth_device_table); |
1376 | 1647 | ||
1377 | static struct vio_driver veth_driver = { | 1648 | static struct vio_driver veth_driver = { |
1378 | .name = "iseries_veth", | 1649 | .name = DRV_NAME, |
1379 | .id_table = veth_device_table, | 1650 | .id_table = veth_device_table, |
1380 | .probe = veth_probe, | 1651 | .probe = veth_probe, |
1381 | .remove = veth_remove | 1652 | .remove = veth_remove |
@@ -1388,29 +1659,29 @@ static struct vio_driver veth_driver = { | |||
1388 | void __exit veth_module_cleanup(void) | 1659 | void __exit veth_module_cleanup(void) |
1389 | { | 1660 | { |
1390 | int i; | 1661 | int i; |
1662 | struct veth_lpar_connection *cnx; | ||
1391 | 1663 | ||
1392 | /* Stop the queues first to stop any new packets being sent. */ | 1664 | /* Disconnect our "irq" to stop events coming from the Hypervisor. */ |
1393 | for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) | ||
1394 | if (veth_dev[i]) | ||
1395 | netif_stop_queue(veth_dev[i]); | ||
1396 | |||
1397 | /* Stop the connections before we unregister the driver. This | ||
1398 | * ensures there's no skbs lying around holding the device open. */ | ||
1399 | for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) | ||
1400 | veth_stop_connection(i); | ||
1401 | |||
1402 | HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan); | 1665 | HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan); |
1403 | 1666 | ||
1404 | /* Hypervisor callbacks may have scheduled more work while we | 1667 | /* Make sure any work queued from Hypervisor callbacks is finished. */ |
1405 | * were stoping connections. Now that we've disconnected from | ||
1406 | * the hypervisor make sure everything's finished. */ | ||
1407 | flush_scheduled_work(); | 1668 | flush_scheduled_work(); |
1408 | 1669 | ||
1409 | vio_unregister_driver(&veth_driver); | 1670 | for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { |
1671 | cnx = veth_cnx[i]; | ||
1672 | |||
1673 | if (!cnx) | ||
1674 | continue; | ||
1410 | 1675 | ||
1411 | for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) | 1676 | /* Remove the connection from sysfs */ |
1412 | veth_destroy_connection(i); | 1677 | kobject_del(&cnx->kobject); |
1678 | /* Drop the driver's reference to the connection */ | ||
1679 | kobject_put(&cnx->kobject); | ||
1680 | } | ||
1413 | 1681 | ||
1682 | /* Unregister the driver, which will close all the netdevs and stop | ||
1683 | * the connections when they're no longer referenced. */ | ||
1684 | vio_unregister_driver(&veth_driver); | ||
1414 | } | 1685 | } |
1415 | module_exit(veth_module_cleanup); | 1686 | module_exit(veth_module_cleanup); |
1416 | 1687 | ||
@@ -1423,15 +1694,37 @@ int __init veth_module_init(void) | |||
1423 | 1694 | ||
1424 | for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { | 1695 | for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { |
1425 | rc = veth_init_connection(i); | 1696 | rc = veth_init_connection(i); |
1426 | if (rc != 0) { | 1697 | if (rc != 0) |
1427 | veth_module_cleanup(); | 1698 | goto error; |
1428 | return rc; | ||
1429 | } | ||
1430 | } | 1699 | } |
1431 | 1700 | ||
1432 | HvLpEvent_registerHandler(HvLpEvent_Type_VirtualLan, | 1701 | HvLpEvent_registerHandler(HvLpEvent_Type_VirtualLan, |
1433 | &veth_handle_event); | 1702 | &veth_handle_event); |
1434 | 1703 | ||
1435 | return vio_register_driver(&veth_driver); | 1704 | rc = vio_register_driver(&veth_driver); |
1705 | if (rc != 0) | ||
1706 | goto error; | ||
1707 | |||
1708 | for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { | ||
1709 | struct kobject *kobj; | ||
1710 | |||
1711 | if (!veth_cnx[i]) | ||
1712 | continue; | ||
1713 | |||
1714 | kobj = &veth_cnx[i]->kobject; | ||
1715 | kobj->parent = &veth_driver.driver.kobj; | ||
1716 | /* If the add failes, complain but otherwise continue */ | ||
1717 | if (0 != kobject_add(kobj)) | ||
1718 | veth_error("cnx %d: Failed adding to sysfs.\n", i); | ||
1719 | } | ||
1720 | |||
1721 | return 0; | ||
1722 | |||
1723 | error: | ||
1724 | for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { | ||
1725 | veth_destroy_connection(veth_cnx[i]); | ||
1726 | } | ||
1727 | |||
1728 | return rc; | ||
1436 | } | 1729 | } |
1437 | module_init(veth_module_init); | 1730 | module_init(veth_module_init); |
diff --git a/drivers/net/iseries_veth.h b/drivers/net/iseries_veth.h deleted file mode 100644 index d9370f79b83e..000000000000 --- a/drivers/net/iseries_veth.h +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /* File veth.h created by Kyle A. Lucke on Mon Aug 7 2000. */ | ||
2 | |||
3 | #ifndef _ISERIES_VETH_H | ||
4 | #define _ISERIES_VETH_H | ||
5 | |||
6 | #define VethEventTypeCap (0) | ||
7 | #define VethEventTypeFrames (1) | ||
8 | #define VethEventTypeMonitor (2) | ||
9 | #define VethEventTypeFramesAck (3) | ||
10 | |||
11 | #define VETH_MAX_ACKS_PER_MSG (20) | ||
12 | #define VETH_MAX_FRAMES_PER_MSG (6) | ||
13 | |||
14 | struct VethFramesData { | ||
15 | u32 addr[VETH_MAX_FRAMES_PER_MSG]; | ||
16 | u16 len[VETH_MAX_FRAMES_PER_MSG]; | ||
17 | u32 eofmask; | ||
18 | }; | ||
19 | #define VETH_EOF_SHIFT (32-VETH_MAX_FRAMES_PER_MSG) | ||
20 | |||
21 | struct VethFramesAckData { | ||
22 | u16 token[VETH_MAX_ACKS_PER_MSG]; | ||
23 | }; | ||
24 | |||
25 | struct VethCapData { | ||
26 | u8 caps_version; | ||
27 | u8 rsvd1; | ||
28 | u16 num_buffers; | ||
29 | u16 ack_threshold; | ||
30 | u16 rsvd2; | ||
31 | u32 ack_timeout; | ||
32 | u32 rsvd3; | ||
33 | u64 rsvd4[3]; | ||
34 | }; | ||
35 | |||
36 | struct VethLpEvent { | ||
37 | struct HvLpEvent base_event; | ||
38 | union { | ||
39 | struct VethCapData caps_data; | ||
40 | struct VethFramesData frames_data; | ||
41 | struct VethFramesAckData frames_ack_data; | ||
42 | } u; | ||
43 | |||
44 | }; | ||
45 | |||
46 | #endif /* _ISERIES_VETH_H */ | ||
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index fc353e348f9a..a22d00198e4d 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c | |||
@@ -1934,7 +1934,7 @@ static int __init de_init_one (struct pci_dev *pdev, | |||
1934 | struct de_private *de; | 1934 | struct de_private *de; |
1935 | int rc; | 1935 | int rc; |
1936 | void __iomem *regs; | 1936 | void __iomem *regs; |
1937 | long pciaddr; | 1937 | unsigned long pciaddr; |
1938 | static int board_idx = -1; | 1938 | static int board_idx = -1; |
1939 | 1939 | ||
1940 | board_idx++; | 1940 | board_idx++; |
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 05da5bea564c..6266a9a7e6e3 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c | |||
@@ -238,6 +238,7 @@ static struct pci_device_id tulip_pci_tbl[] = { | |||
238 | { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, | 238 | { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, |
239 | { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */ | 239 | { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */ |
240 | { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */ | 240 | { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */ |
241 | { 0x1414, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, | ||
241 | { } /* terminate list */ | 242 | { } /* terminate list */ |
242 | }; | 243 | }; |
243 | MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); | 244 | MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); |
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 713c78f3a65d..49bd21702314 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c | |||
@@ -21,13 +21,21 @@ | |||
21 | * between the ROM and other resources, so enabling it may disable access | 21 | * between the ROM and other resources, so enabling it may disable access |
22 | * to MMIO registers or other card memory. | 22 | * to MMIO registers or other card memory. |
23 | */ | 23 | */ |
24 | static void pci_enable_rom(struct pci_dev *pdev) | 24 | static int pci_enable_rom(struct pci_dev *pdev) |
25 | { | 25 | { |
26 | struct resource *res = pdev->resource + PCI_ROM_RESOURCE; | ||
27 | struct pci_bus_region region; | ||
26 | u32 rom_addr; | 28 | u32 rom_addr; |
27 | 29 | ||
30 | if (!res->flags) | ||
31 | return -1; | ||
32 | |||
33 | pcibios_resource_to_bus(pdev, ®ion, res); | ||
28 | pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); | 34 | pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); |
29 | rom_addr |= PCI_ROM_ADDRESS_ENABLE; | 35 | rom_addr &= ~PCI_ROM_ADDRESS_MASK; |
36 | rom_addr |= region.start | PCI_ROM_ADDRESS_ENABLE; | ||
30 | pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr); | 37 | pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr); |
38 | return 0; | ||
31 | } | 39 | } |
32 | 40 | ||
33 | /** | 41 | /** |
@@ -71,19 +79,21 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) | |||
71 | } else { | 79 | } else { |
72 | if (res->flags & IORESOURCE_ROM_COPY) { | 80 | if (res->flags & IORESOURCE_ROM_COPY) { |
73 | *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); | 81 | *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); |
74 | return (void __iomem *)pci_resource_start(pdev, PCI_ROM_RESOURCE); | 82 | return (void __iomem *)pci_resource_start(pdev, |
83 | PCI_ROM_RESOURCE); | ||
75 | } else { | 84 | } else { |
76 | /* assign the ROM an address if it doesn't have one */ | 85 | /* assign the ROM an address if it doesn't have one */ |
77 | if (res->parent == NULL) | 86 | if (res->parent == NULL && |
78 | pci_assign_resource(pdev, PCI_ROM_RESOURCE); | 87 | pci_assign_resource(pdev,PCI_ROM_RESOURCE)) |
79 | 88 | return NULL; | |
80 | start = pci_resource_start(pdev, PCI_ROM_RESOURCE); | 89 | start = pci_resource_start(pdev, PCI_ROM_RESOURCE); |
81 | *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); | 90 | *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); |
82 | if (*size == 0) | 91 | if (*size == 0) |
83 | return NULL; | 92 | return NULL; |
84 | 93 | ||
85 | /* Enable ROM space decodes */ | 94 | /* Enable ROM space decodes */ |
86 | pci_enable_rom(pdev); | 95 | if (pci_enable_rom(pdev)) |
96 | return NULL; | ||
87 | } | 97 | } |
88 | } | 98 | } |
89 | 99 | ||
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 0b10169961eb..aec39fb261ca 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c | |||
@@ -58,8 +58,7 @@ static const char serial21285_name[] = "Footbridge UART"; | |||
58 | * int((BAUD_BASE - (baud >> 1)) / baud) | 58 | * int((BAUD_BASE - (baud >> 1)) / baud) |
59 | */ | 59 | */ |
60 | 60 | ||
61 | static void | 61 | static void serial21285_stop_tx(struct uart_port *port) |
62 | serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop) | ||
63 | { | 62 | { |
64 | if (tx_enabled(port)) { | 63 | if (tx_enabled(port)) { |
65 | disable_irq(IRQ_CONTX); | 64 | disable_irq(IRQ_CONTX); |
@@ -67,8 +66,7 @@ serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
67 | } | 66 | } |
68 | } | 67 | } |
69 | 68 | ||
70 | static void | 69 | static void serial21285_start_tx(struct uart_port *port) |
71 | serial21285_start_tx(struct uart_port *port, unsigned int tty_start) | ||
72 | { | 70 | { |
73 | if (!tx_enabled(port)) { | 71 | if (!tx_enabled(port)) { |
74 | enable_irq(IRQ_CONTX); | 72 | enable_irq(IRQ_CONTX); |
@@ -148,7 +146,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r | |||
148 | goto out; | 146 | goto out; |
149 | } | 147 | } |
150 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 148 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
151 | serial21285_stop_tx(port, 0); | 149 | serial21285_stop_tx(port); |
152 | goto out; | 150 | goto out; |
153 | } | 151 | } |
154 | 152 | ||
@@ -164,7 +162,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r | |||
164 | uart_write_wakeup(port); | 162 | uart_write_wakeup(port); |
165 | 163 | ||
166 | if (uart_circ_empty(xmit)) | 164 | if (uart_circ_empty(xmit)) |
167 | serial21285_stop_tx(port, 0); | 165 | serial21285_stop_tx(port); |
168 | 166 | ||
169 | out: | 167 | out: |
170 | return IRQ_HANDLED; | 168 | return IRQ_HANDLED; |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 7e8fc7c1d4cc..30a0a3d10145 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -1001,7 +1001,7 @@ static inline void __stop_tx(struct uart_8250_port *p) | |||
1001 | } | 1001 | } |
1002 | } | 1002 | } |
1003 | 1003 | ||
1004 | static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) | 1004 | static void serial8250_stop_tx(struct uart_port *port) |
1005 | { | 1005 | { |
1006 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 1006 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
1007 | 1007 | ||
@@ -1018,7 +1018,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
1018 | 1018 | ||
1019 | static void transmit_chars(struct uart_8250_port *up); | 1019 | static void transmit_chars(struct uart_8250_port *up); |
1020 | 1020 | ||
1021 | static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start) | 1021 | static void serial8250_start_tx(struct uart_port *port) |
1022 | { | 1022 | { |
1023 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 1023 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
1024 | 1024 | ||
@@ -1158,7 +1158,11 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up) | |||
1158 | up->port.x_char = 0; | 1158 | up->port.x_char = 0; |
1159 | return; | 1159 | return; |
1160 | } | 1160 | } |
1161 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | 1161 | if (uart_tx_stopped(&up->port)) { |
1162 | serial8250_stop_tx(&up->port); | ||
1163 | return; | ||
1164 | } | ||
1165 | if (uart_circ_empty(xmit)) { | ||
1162 | __stop_tx(up); | 1166 | __stop_tx(up); |
1163 | return; | 1167 | return; |
1164 | } | 1168 | } |
@@ -2586,82 +2590,3 @@ module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444); | |||
2586 | MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); | 2590 | MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); |
2587 | #endif | 2591 | #endif |
2588 | MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); | 2592 | MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); |
2589 | |||
2590 | /** | ||
2591 | * register_serial - configure a 16x50 serial port at runtime | ||
2592 | * @req: request structure | ||
2593 | * | ||
2594 | * Configure the serial port specified by the request. If the | ||
2595 | * port exists and is in use an error is returned. If the port | ||
2596 | * is not currently in the table it is added. | ||
2597 | * | ||
2598 | * The port is then probed and if necessary the IRQ is autodetected | ||
2599 | * If this fails an error is returned. | ||
2600 | * | ||
2601 | * On success the port is ready to use and the line number is returned. | ||
2602 | * | ||
2603 | * Note: this function is deprecated - use serial8250_register_port | ||
2604 | * instead. | ||
2605 | */ | ||
2606 | int register_serial(struct serial_struct *req) | ||
2607 | { | ||
2608 | struct uart_port port; | ||
2609 | |||
2610 | port.iobase = req->port; | ||
2611 | port.membase = req->iomem_base; | ||
2612 | port.irq = req->irq; | ||
2613 | port.uartclk = req->baud_base * 16; | ||
2614 | port.fifosize = req->xmit_fifo_size; | ||
2615 | port.regshift = req->iomem_reg_shift; | ||
2616 | port.iotype = req->io_type; | ||
2617 | port.flags = req->flags | UPF_BOOT_AUTOCONF; | ||
2618 | port.mapbase = req->iomap_base; | ||
2619 | port.dev = NULL; | ||
2620 | |||
2621 | if (share_irqs) | ||
2622 | port.flags |= UPF_SHARE_IRQ; | ||
2623 | |||
2624 | if (HIGH_BITS_OFFSET) | ||
2625 | port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET; | ||
2626 | |||
2627 | /* | ||
2628 | * If a clock rate wasn't specified by the low level driver, then | ||
2629 | * default to the standard clock rate. This should be 115200 (*16) | ||
2630 | * and should not depend on the architecture's BASE_BAUD definition. | ||
2631 | * However, since this API will be deprecated, it's probably a | ||
2632 | * better idea to convert the drivers to use the new API | ||
2633 | * (serial8250_register_port and serial8250_unregister_port). | ||
2634 | */ | ||
2635 | if (port.uartclk == 0) { | ||
2636 | printk(KERN_WARNING | ||
2637 | "Serial: registering port at [%08x,%08lx,%p] irq %d with zero baud_base\n", | ||
2638 | port.iobase, port.mapbase, port.membase, port.irq); | ||
2639 | printk(KERN_WARNING "Serial: see %s:%d for more information\n", | ||
2640 | __FILE__, __LINE__); | ||
2641 | dump_stack(); | ||
2642 | |||
2643 | /* | ||
2644 | * Fix it up for now, but this is only a temporary measure. | ||
2645 | */ | ||
2646 | port.uartclk = BASE_BAUD * 16; | ||
2647 | } | ||
2648 | |||
2649 | return serial8250_register_port(&port); | ||
2650 | } | ||
2651 | EXPORT_SYMBOL(register_serial); | ||
2652 | |||
2653 | /** | ||
2654 | * unregister_serial - remove a 16x50 serial port at runtime | ||
2655 | * @line: serial line number | ||
2656 | * | ||
2657 | * Remove one serial port. This may not be called from interrupt | ||
2658 | * context. We hand the port back to our local PM control. | ||
2659 | * | ||
2660 | * Note: this function is deprecated - use serial8250_unregister_port | ||
2661 | * instead. | ||
2662 | */ | ||
2663 | void unregister_serial(int line) | ||
2664 | { | ||
2665 | serial8250_unregister_port(line); | ||
2666 | } | ||
2667 | EXPORT_SYMBOL(unregister_serial); | ||
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index 9225c82faeb8..b1b459efda52 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h | |||
@@ -16,11 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/config.h> | 18 | #include <linux/config.h> |
19 | 19 | #include <linux/serial_8250.h> | |
20 | int serial8250_register_port(struct uart_port *); | ||
21 | void serial8250_unregister_port(int line); | ||
22 | void serial8250_suspend_port(int line); | ||
23 | void serial8250_resume_port(int line); | ||
24 | 20 | ||
25 | struct old_serial_port { | 21 | struct old_serial_port { |
26 | unsigned int uart; | 22 | unsigned int uart; |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index d5797618a3b9..74b80f7c062d 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -830,7 +830,7 @@ config SERIAL_M32R_PLDSIO | |||
830 | 830 | ||
831 | config SERIAL_TXX9 | 831 | config SERIAL_TXX9 |
832 | bool "TMPTX39XX/49XX SIO support" | 832 | bool "TMPTX39XX/49XX SIO support" |
833 | depends HAS_TXX9_SERIAL | 833 | depends HAS_TXX9_SERIAL && BROKEN |
834 | select SERIAL_CORE | 834 | select SERIAL_CORE |
835 | default y | 835 | default y |
836 | 836 | ||
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 2884b310e54d..978e12437e61 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
@@ -105,7 +105,7 @@ struct uart_amba_port { | |||
105 | unsigned int old_status; | 105 | unsigned int old_status; |
106 | }; | 106 | }; |
107 | 107 | ||
108 | static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop) | 108 | static void pl010_stop_tx(struct uart_port *port) |
109 | { | 109 | { |
110 | unsigned int cr; | 110 | unsigned int cr; |
111 | 111 | ||
@@ -114,7 +114,7 @@ static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
114 | UART_PUT_CR(port, cr); | 114 | UART_PUT_CR(port, cr); |
115 | } | 115 | } |
116 | 116 | ||
117 | static void pl010_start_tx(struct uart_port *port, unsigned int tty_start) | 117 | static void pl010_start_tx(struct uart_port *port) |
118 | { | 118 | { |
119 | unsigned int cr; | 119 | unsigned int cr; |
120 | 120 | ||
@@ -219,7 +219,7 @@ static void pl010_tx_chars(struct uart_port *port) | |||
219 | return; | 219 | return; |
220 | } | 220 | } |
221 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 221 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
222 | pl010_stop_tx(port, 0); | 222 | pl010_stop_tx(port); |
223 | return; | 223 | return; |
224 | } | 224 | } |
225 | 225 | ||
@@ -236,7 +236,7 @@ static void pl010_tx_chars(struct uart_port *port) | |||
236 | uart_write_wakeup(port); | 236 | uart_write_wakeup(port); |
237 | 237 | ||
238 | if (uart_circ_empty(xmit)) | 238 | if (uart_circ_empty(xmit)) |
239 | pl010_stop_tx(port, 0); | 239 | pl010_stop_tx(port); |
240 | } | 240 | } |
241 | 241 | ||
242 | static void pl010_modem_status(struct uart_port *port) | 242 | static void pl010_modem_status(struct uart_port *port) |
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 7db88ee18f75..56071309744c 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c | |||
@@ -74,7 +74,7 @@ struct uart_amba_port { | |||
74 | unsigned int old_status; | 74 | unsigned int old_status; |
75 | }; | 75 | }; |
76 | 76 | ||
77 | static void pl011_stop_tx(struct uart_port *port, unsigned int tty_stop) | 77 | static void pl011_stop_tx(struct uart_port *port) |
78 | { | 78 | { |
79 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 79 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
80 | 80 | ||
@@ -82,7 +82,7 @@ static void pl011_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
82 | writew(uap->im, uap->port.membase + UART011_IMSC); | 82 | writew(uap->im, uap->port.membase + UART011_IMSC); |
83 | } | 83 | } |
84 | 84 | ||
85 | static void pl011_start_tx(struct uart_port *port, unsigned int tty_start) | 85 | static void pl011_start_tx(struct uart_port *port) |
86 | { | 86 | { |
87 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 87 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
88 | 88 | ||
@@ -184,7 +184,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap) | |||
184 | return; | 184 | return; |
185 | } | 185 | } |
186 | if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { | 186 | if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { |
187 | pl011_stop_tx(&uap->port, 0); | 187 | pl011_stop_tx(&uap->port); |
188 | return; | 188 | return; |
189 | } | 189 | } |
190 | 190 | ||
@@ -201,7 +201,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap) | |||
201 | uart_write_wakeup(&uap->port); | 201 | uart_write_wakeup(&uap->port); |
202 | 202 | ||
203 | if (uart_circ_empty(xmit)) | 203 | if (uart_circ_empty(xmit)) |
204 | pl011_stop_tx(&uap->port, 0); | 204 | pl011_stop_tx(&uap->port); |
205 | } | 205 | } |
206 | 206 | ||
207 | static void pl011_modem_status(struct uart_amba_port *uap) | 207 | static void pl011_modem_status(struct uart_amba_port *uap) |
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index 6104aeef1243..a274ebf256a1 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c | |||
@@ -200,7 +200,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
200 | DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); | 200 | DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); |
201 | } | 201 | } |
202 | 202 | ||
203 | static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) | 203 | static void serial8250_stop_tx(struct uart_port *port) |
204 | { | 204 | { |
205 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 205 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
206 | 206 | ||
@@ -210,7 +210,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
210 | } | 210 | } |
211 | } | 211 | } |
212 | 212 | ||
213 | static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start) | 213 | static void serial8250_start_tx(struct uart_port *port) |
214 | { | 214 | { |
215 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 215 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
216 | 216 | ||
@@ -337,7 +337,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up) | |||
337 | return; | 337 | return; |
338 | } | 338 | } |
339 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | 339 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { |
340 | serial8250_stop_tx(&up->port, 0); | 340 | serial8250_stop_tx(&up->port); |
341 | return; | 341 | return; |
342 | } | 342 | } |
343 | 343 | ||
@@ -356,7 +356,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up) | |||
356 | DEBUG_INTR("THRE..."); | 356 | DEBUG_INTR("THRE..."); |
357 | 357 | ||
358 | if (uart_circ_empty(xmit)) | 358 | if (uart_circ_empty(xmit)) |
359 | serial8250_stop_tx(&up->port, 0); | 359 | serial8250_stop_tx(&up->port); |
360 | } | 360 | } |
361 | 361 | ||
362 | static _INLINE_ void check_modem_status(struct uart_8250_port *up) | 362 | static _INLINE_ void check_modem_status(struct uart_8250_port *up) |
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index e92522b33c48..d822896b488c 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c | |||
@@ -69,8 +69,7 @@ | |||
69 | 69 | ||
70 | #define tx_enabled(port) ((port)->unused[0]) | 70 | #define tx_enabled(port) ((port)->unused[0]) |
71 | 71 | ||
72 | static void | 72 | static void clps711xuart_stop_tx(struct uart_port *port) |
73 | clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop) | ||
74 | { | 73 | { |
75 | if (tx_enabled(port)) { | 74 | if (tx_enabled(port)) { |
76 | disable_irq(TX_IRQ(port)); | 75 | disable_irq(TX_IRQ(port)); |
@@ -78,8 +77,7 @@ clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
78 | } | 77 | } |
79 | } | 78 | } |
80 | 79 | ||
81 | static void | 80 | static void clps711xuart_start_tx(struct uart_port *port) |
82 | clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start) | ||
83 | { | 81 | { |
84 | if (!tx_enabled(port)) { | 82 | if (!tx_enabled(port)) { |
85 | enable_irq(TX_IRQ(port)); | 83 | enable_irq(TX_IRQ(port)); |
@@ -165,7 +163,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re | |||
165 | return IRQ_HANDLED; | 163 | return IRQ_HANDLED; |
166 | } | 164 | } |
167 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 165 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
168 | clps711xuart_stop_tx(port, 0); | 166 | clps711xuart_stop_tx(port); |
169 | return IRQ_HANDLED; | 167 | return IRQ_HANDLED; |
170 | } | 168 | } |
171 | 169 | ||
@@ -182,7 +180,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re | |||
182 | uart_write_wakeup(port); | 180 | uart_write_wakeup(port); |
183 | 181 | ||
184 | if (uart_circ_empty(xmit)) | 182 | if (uart_circ_empty(xmit)) |
185 | clps711xuart_stop_tx(port, 0); | 183 | clps711xuart_stop_tx(port); |
186 | 184 | ||
187 | return IRQ_HANDLED; | 185 | return IRQ_HANDLED; |
188 | } | 186 | } |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index d639ac92a117..282b32351d8e 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -124,7 +124,7 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port) | |||
124 | /* | 124 | /* |
125 | * Stop transmitter | 125 | * Stop transmitter |
126 | */ | 126 | */ |
127 | static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop) | 127 | static void cpm_uart_stop_tx(struct uart_port *port) |
128 | { | 128 | { |
129 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | 129 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; |
130 | volatile smc_t *smcp = pinfo->smcp; | 130 | volatile smc_t *smcp = pinfo->smcp; |
@@ -141,7 +141,7 @@ static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
141 | /* | 141 | /* |
142 | * Start transmitter | 142 | * Start transmitter |
143 | */ | 143 | */ |
144 | static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start) | 144 | static void cpm_uart_start_tx(struct uart_port *port) |
145 | { | 145 | { |
146 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | 146 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; |
147 | volatile smc_t *smcp = pinfo->smcp; | 147 | volatile smc_t *smcp = pinfo->smcp; |
@@ -623,7 +623,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
623 | } | 623 | } |
624 | 624 | ||
625 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 625 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
626 | cpm_uart_stop_tx(port, 0); | 626 | cpm_uart_stop_tx(port); |
627 | return 0; | 627 | return 0; |
628 | } | 628 | } |
629 | 629 | ||
@@ -656,7 +656,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) | |||
656 | uart_write_wakeup(port); | 656 | uart_write_wakeup(port); |
657 | 657 | ||
658 | if (uart_circ_empty(xmit)) { | 658 | if (uart_circ_empty(xmit)) { |
659 | cpm_uart_stop_tx(port, 0); | 659 | cpm_uart_stop_tx(port); |
660 | return 0; | 660 | return 0; |
661 | } | 661 | } |
662 | 662 | ||
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index 97824eeeafae..e63b9dffc8d7 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c | |||
@@ -112,7 +112,7 @@ static inline void dz_out(struct dz_port *dport, unsigned offset, | |||
112 | * ------------------------------------------------------------ | 112 | * ------------------------------------------------------------ |
113 | */ | 113 | */ |
114 | 114 | ||
115 | static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop) | 115 | static void dz_stop_tx(struct uart_port *uport) |
116 | { | 116 | { |
117 | struct dz_port *dport = (struct dz_port *)uport; | 117 | struct dz_port *dport = (struct dz_port *)uport; |
118 | unsigned short tmp, mask = 1 << dport->port.line; | 118 | unsigned short tmp, mask = 1 << dport->port.line; |
@@ -125,7 +125,7 @@ static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop) | |||
125 | spin_unlock_irqrestore(&dport->port.lock, flags); | 125 | spin_unlock_irqrestore(&dport->port.lock, flags); |
126 | } | 126 | } |
127 | 127 | ||
128 | static void dz_start_tx(struct uart_port *uport, unsigned int tty_start) | 128 | static void dz_start_tx(struct uart_port *uport) |
129 | { | 129 | { |
130 | struct dz_port *dport = (struct dz_port *)uport; | 130 | struct dz_port *dport = (struct dz_port *)uport; |
131 | unsigned short tmp, mask = 1 << dport->port.line; | 131 | unsigned short tmp, mask = 1 << dport->port.line; |
@@ -290,7 +290,7 @@ static inline void dz_transmit_chars(struct dz_port *dport) | |||
290 | } | 290 | } |
291 | /* if nothing to do or stopped or hardware stopped */ | 291 | /* if nothing to do or stopped or hardware stopped */ |
292 | if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { | 292 | if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { |
293 | dz_stop_tx(&dport->port, 0); | 293 | dz_stop_tx(&dport->port); |
294 | return; | 294 | return; |
295 | } | 295 | } |
296 | 296 | ||
@@ -308,7 +308,7 @@ static inline void dz_transmit_chars(struct dz_port *dport) | |||
308 | 308 | ||
309 | /* Are we done */ | 309 | /* Are we done */ |
310 | if (uart_circ_empty(xmit)) | 310 | if (uart_circ_empty(xmit)) |
311 | dz_stop_tx(&dport->port, 0); | 311 | dz_stop_tx(&dport->port); |
312 | } | 312 | } |
313 | 313 | ||
314 | /* | 314 | /* |
@@ -440,7 +440,7 @@ static int dz_startup(struct uart_port *uport) | |||
440 | */ | 440 | */ |
441 | static void dz_shutdown(struct uart_port *uport) | 441 | static void dz_shutdown(struct uart_port *uport) |
442 | { | 442 | { |
443 | dz_stop_tx(uport, 0); | 443 | dz_stop_tx(uport); |
444 | } | 444 | } |
445 | 445 | ||
446 | /* | 446 | /* |
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index c112b32764e8..79f8df4d66b7 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c | |||
@@ -989,18 +989,16 @@ static unsigned int icom_get_mctrl(struct uart_port *port) | |||
989 | return result; | 989 | return result; |
990 | } | 990 | } |
991 | 991 | ||
992 | static void icom_stop_tx(struct uart_port *port, unsigned int tty_stop) | 992 | static void icom_stop_tx(struct uart_port *port) |
993 | { | 993 | { |
994 | unsigned char cmdReg; | 994 | unsigned char cmdReg; |
995 | 995 | ||
996 | if (tty_stop) { | 996 | trace(ICOM_PORT, "STOP", 0); |
997 | trace(ICOM_PORT, "STOP", 0); | 997 | cmdReg = readb(&ICOM_PORT->dram->CmdReg); |
998 | cmdReg = readb(&ICOM_PORT->dram->CmdReg); | 998 | writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg); |
999 | writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg); | ||
1000 | } | ||
1001 | } | 999 | } |
1002 | 1000 | ||
1003 | static void icom_start_tx(struct uart_port *port, unsigned int tty_start) | 1001 | static void icom_start_tx(struct uart_port *port) |
1004 | { | 1002 | { |
1005 | unsigned char cmdReg; | 1003 | unsigned char cmdReg; |
1006 | 1004 | ||
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 01a8726a3f97..4c985e6b3784 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -124,7 +124,7 @@ static void imx_timeout(unsigned long data) | |||
124 | /* | 124 | /* |
125 | * interrupts disabled on entry | 125 | * interrupts disabled on entry |
126 | */ | 126 | */ |
127 | static void imx_stop_tx(struct uart_port *port, unsigned int tty_stop) | 127 | static void imx_stop_tx(struct uart_port *port) |
128 | { | 128 | { |
129 | struct imx_port *sport = (struct imx_port *)port; | 129 | struct imx_port *sport = (struct imx_port *)port; |
130 | UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN; | 130 | UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN; |
@@ -165,13 +165,13 @@ static inline void imx_transmit_buffer(struct imx_port *sport) | |||
165 | } while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)); | 165 | } while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)); |
166 | 166 | ||
167 | if (uart_circ_empty(xmit)) | 167 | if (uart_circ_empty(xmit)) |
168 | imx_stop_tx(&sport->port, 0); | 168 | imx_stop_tx(&sport->port); |
169 | } | 169 | } |
170 | 170 | ||
171 | /* | 171 | /* |
172 | * interrupts disabled on entry | 172 | * interrupts disabled on entry |
173 | */ | 173 | */ |
174 | static void imx_start_tx(struct uart_port *port, unsigned int tty_start) | 174 | static void imx_start_tx(struct uart_port *port) |
175 | { | 175 | { |
176 | struct imx_port *sport = (struct imx_port *)port; | 176 | struct imx_port *sport = (struct imx_port *)port; |
177 | 177 | ||
@@ -196,7 +196,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs) | |||
196 | } | 196 | } |
197 | 197 | ||
198 | if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { | 198 | if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { |
199 | imx_stop_tx(&sport->port, 0); | 199 | imx_stop_tx(&sport->port); |
200 | goto out; | 200 | goto out; |
201 | } | 201 | } |
202 | 202 | ||
@@ -291,13 +291,31 @@ static unsigned int imx_tx_empty(struct uart_port *port) | |||
291 | return USR2((u32)sport->port.membase) & USR2_TXDC ? TIOCSER_TEMT : 0; | 291 | return USR2((u32)sport->port.membase) & USR2_TXDC ? TIOCSER_TEMT : 0; |
292 | } | 292 | } |
293 | 293 | ||
294 | /* | ||
295 | * We have a modem side uart, so the meanings of RTS and CTS are inverted. | ||
296 | */ | ||
294 | static unsigned int imx_get_mctrl(struct uart_port *port) | 297 | static unsigned int imx_get_mctrl(struct uart_port *port) |
295 | { | 298 | { |
296 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | 299 | struct imx_port *sport = (struct imx_port *)port; |
300 | unsigned int tmp = TIOCM_DSR | TIOCM_CAR; | ||
301 | |||
302 | if (USR1((u32)sport->port.membase) & USR1_RTSS) | ||
303 | tmp |= TIOCM_CTS; | ||
304 | |||
305 | if (UCR2((u32)sport->port.membase) & UCR2_CTS) | ||
306 | tmp |= TIOCM_RTS; | ||
307 | |||
308 | return tmp; | ||
297 | } | 309 | } |
298 | 310 | ||
299 | static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) | 311 | static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) |
300 | { | 312 | { |
313 | struct imx_port *sport = (struct imx_port *)port; | ||
314 | |||
315 | if (mctrl & TIOCM_RTS) | ||
316 | UCR2((u32)sport->port.membase) |= UCR2_CTS; | ||
317 | else | ||
318 | UCR2((u32)sport->port.membase) &= ~UCR2_CTS; | ||
301 | } | 319 | } |
302 | 320 | ||
303 | /* | 321 | /* |
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 793c3a7cbe47..0c5c96a582b3 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c | |||
@@ -2373,10 +2373,9 @@ static unsigned int ic4_tx_empty(struct uart_port *the_port) | |||
2373 | /** | 2373 | /** |
2374 | * ic4_stop_tx - stop the transmitter | 2374 | * ic4_stop_tx - stop the transmitter |
2375 | * @port: Port to operate on | 2375 | * @port: Port to operate on |
2376 | * @tty_stop: Set to 1 if called via uart_stop | ||
2377 | * | 2376 | * |
2378 | */ | 2377 | */ |
2379 | static void ic4_stop_tx(struct uart_port *the_port, unsigned int tty_stop) | 2378 | static void ic4_stop_tx(struct uart_port *the_port) |
2380 | { | 2379 | { |
2381 | } | 2380 | } |
2382 | 2381 | ||
@@ -2471,10 +2470,9 @@ static unsigned int ic4_get_mctrl(struct uart_port *the_port) | |||
2471 | /** | 2470 | /** |
2472 | * ic4_start_tx - Start transmitter, flush any output | 2471 | * ic4_start_tx - Start transmitter, flush any output |
2473 | * @port: Port to operate on | 2472 | * @port: Port to operate on |
2474 | * @tty_stop: Set to 1 if called via uart_start | ||
2475 | * | 2473 | * |
2476 | */ | 2474 | */ |
2477 | static void ic4_start_tx(struct uart_port *the_port, unsigned int tty_stop) | 2475 | static void ic4_start_tx(struct uart_port *the_port) |
2478 | { | 2476 | { |
2479 | struct ioc4_port *port = get_ioc4_port(the_port); | 2477 | struct ioc4_port *port = get_ioc4_port(the_port); |
2480 | unsigned long flags; | 2478 | unsigned long flags; |
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index ea5bf4d4daa3..ef132349f310 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c | |||
@@ -592,7 +592,7 @@ static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
592 | } | 592 | } |
593 | 593 | ||
594 | /* The port lock is held and interrupts are disabled. */ | 594 | /* The port lock is held and interrupts are disabled. */ |
595 | static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop) | 595 | static void ip22zilog_stop_tx(struct uart_port *port) |
596 | { | 596 | { |
597 | struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; | 597 | struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; |
598 | 598 | ||
@@ -600,7 +600,7 @@ static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
600 | } | 600 | } |
601 | 601 | ||
602 | /* The port lock is held and interrupts are disabled. */ | 602 | /* The port lock is held and interrupts are disabled. */ |
603 | static void ip22zilog_start_tx(struct uart_port *port, unsigned int tty_start) | 603 | static void ip22zilog_start_tx(struct uart_port *port) |
604 | { | 604 | { |
605 | struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; | 605 | struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; |
606 | struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); | 606 | struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); |
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 98de2258fd06..6fa0d62d6f68 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
@@ -113,7 +113,7 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
113 | udelay(10); | 113 | udelay(10); |
114 | } | 114 | } |
115 | 115 | ||
116 | static void jsm_tty_start_tx(struct uart_port *port, unsigned int tty_start) | 116 | static void jsm_tty_start_tx(struct uart_port *port) |
117 | { | 117 | { |
118 | struct jsm_channel *channel = (struct jsm_channel *)port; | 118 | struct jsm_channel *channel = (struct jsm_channel *)port; |
119 | 119 | ||
@@ -125,7 +125,7 @@ static void jsm_tty_start_tx(struct uart_port *port, unsigned int tty_start) | |||
125 | jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n"); | 125 | jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n"); |
126 | } | 126 | } |
127 | 127 | ||
128 | static void jsm_tty_stop_tx(struct uart_port *port, unsigned int tty_stop) | 128 | static void jsm_tty_stop_tx(struct uart_port *port) |
129 | { | 129 | { |
130 | struct jsm_channel *channel = (struct jsm_channel *)port; | 130 | struct jsm_channel *channel = (struct jsm_channel *)port; |
131 | 131 | ||
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 9b50560b9d16..b0ecc7537ce5 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c | |||
@@ -275,7 +275,7 @@ serial_out(struct uart_sio_port *up, int offset, int value) | |||
275 | __sio_out(value, offset); | 275 | __sio_out(value, offset); |
276 | } | 276 | } |
277 | 277 | ||
278 | static void m32r_sio_stop_tx(struct uart_port *port, unsigned int tty_stop) | 278 | static void m32r_sio_stop_tx(struct uart_port *port) |
279 | { | 279 | { |
280 | struct uart_sio_port *up = (struct uart_sio_port *)port; | 280 | struct uart_sio_port *up = (struct uart_sio_port *)port; |
281 | 281 | ||
@@ -285,7 +285,7 @@ static void m32r_sio_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
285 | } | 285 | } |
286 | } | 286 | } |
287 | 287 | ||
288 | static void m32r_sio_start_tx(struct uart_port *port, unsigned int tty_start) | 288 | static void m32r_sio_start_tx(struct uart_port *port) |
289 | { | 289 | { |
290 | #ifdef CONFIG_SERIAL_M32R_PLDSIO | 290 | #ifdef CONFIG_SERIAL_M32R_PLDSIO |
291 | struct uart_sio_port *up = (struct uart_sio_port *)port; | 291 | struct uart_sio_port *up = (struct uart_sio_port *)port; |
@@ -425,7 +425,7 @@ static _INLINE_ void transmit_chars(struct uart_sio_port *up) | |||
425 | return; | 425 | return; |
426 | } | 426 | } |
427 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | 427 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { |
428 | m32r_sio_stop_tx(&up->port, 0); | 428 | m32r_sio_stop_tx(&up->port); |
429 | return; | 429 | return; |
430 | } | 430 | } |
431 | 431 | ||
@@ -446,7 +446,7 @@ static _INLINE_ void transmit_chars(struct uart_sio_port *up) | |||
446 | DEBUG_INTR("THRE..."); | 446 | DEBUG_INTR("THRE..."); |
447 | 447 | ||
448 | if (uart_circ_empty(xmit)) | 448 | if (uart_circ_empty(xmit)) |
449 | m32r_sio_stop_tx(&up->port, 0); | 449 | m32r_sio_stop_tx(&up->port); |
450 | } | 450 | } |
451 | 451 | ||
452 | /* | 452 | /* |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 2a5cf174ca30..a3cd0ee8486d 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -119,7 +119,7 @@ mpc52xx_uart_get_mctrl(struct uart_port *port) | |||
119 | } | 119 | } |
120 | 120 | ||
121 | static void | 121 | static void |
122 | mpc52xx_uart_stop_tx(struct uart_port *port, unsigned int tty_stop) | 122 | mpc52xx_uart_stop_tx(struct uart_port *port) |
123 | { | 123 | { |
124 | /* port->lock taken by caller */ | 124 | /* port->lock taken by caller */ |
125 | port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY; | 125 | port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY; |
@@ -127,7 +127,7 @@ mpc52xx_uart_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
127 | } | 127 | } |
128 | 128 | ||
129 | static void | 129 | static void |
130 | mpc52xx_uart_start_tx(struct uart_port *port, unsigned int tty_start) | 130 | mpc52xx_uart_start_tx(struct uart_port *port) |
131 | { | 131 | { |
132 | /* port->lock taken by caller */ | 132 | /* port->lock taken by caller */ |
133 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; | 133 | port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; |
@@ -485,7 +485,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) | |||
485 | 485 | ||
486 | /* Nothing to do ? */ | 486 | /* Nothing to do ? */ |
487 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 487 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
488 | mpc52xx_uart_stop_tx(port,0); | 488 | mpc52xx_uart_stop_tx(port); |
489 | return 0; | 489 | return 0; |
490 | } | 490 | } |
491 | 491 | ||
@@ -504,7 +504,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) | |||
504 | 504 | ||
505 | /* Maybe we're done after all */ | 505 | /* Maybe we're done after all */ |
506 | if (uart_circ_empty(xmit)) { | 506 | if (uart_circ_empty(xmit)) { |
507 | mpc52xx_uart_stop_tx(port,0); | 507 | mpc52xx_uart_stop_tx(port); |
508 | return 0; | 508 | return 0; |
509 | } | 509 | } |
510 | 510 | ||
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index e43276c6a954..efe79b1fd431 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c | |||
@@ -1072,18 +1072,18 @@ mpsc_get_mctrl(struct uart_port *port) | |||
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | static void | 1074 | static void |
1075 | mpsc_stop_tx(struct uart_port *port, uint tty_start) | 1075 | mpsc_stop_tx(struct uart_port *port) |
1076 | { | 1076 | { |
1077 | struct mpsc_port_info *pi = (struct mpsc_port_info *)port; | 1077 | struct mpsc_port_info *pi = (struct mpsc_port_info *)port; |
1078 | 1078 | ||
1079 | pr_debug("mpsc_stop_tx[%d]: tty_start: %d\n", port->line, tty_start); | 1079 | pr_debug("mpsc_stop_tx[%d]\n", port->line); |
1080 | 1080 | ||
1081 | mpsc_freeze(pi); | 1081 | mpsc_freeze(pi); |
1082 | return; | 1082 | return; |
1083 | } | 1083 | } |
1084 | 1084 | ||
1085 | static void | 1085 | static void |
1086 | mpsc_start_tx(struct uart_port *port, uint tty_start) | 1086 | mpsc_start_tx(struct uart_port *port) |
1087 | { | 1087 | { |
1088 | struct mpsc_port_info *pi = (struct mpsc_port_info *)port; | 1088 | struct mpsc_port_info *pi = (struct mpsc_port_info *)port; |
1089 | 1089 | ||
@@ -1091,7 +1091,7 @@ mpsc_start_tx(struct uart_port *port, uint tty_start) | |||
1091 | mpsc_copy_tx_data(pi); | 1091 | mpsc_copy_tx_data(pi); |
1092 | mpsc_sdma_start_tx(pi); | 1092 | mpsc_sdma_start_tx(pi); |
1093 | 1093 | ||
1094 | pr_debug("mpsc_start_tx[%d]: tty_start: %d\n", port->line, tty_start); | 1094 | pr_debug("mpsc_start_tx[%d]\n", port->line); |
1095 | return; | 1095 | return; |
1096 | } | 1096 | } |
1097 | 1097 | ||
diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index dadd7e19714e..189064607709 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c | |||
@@ -111,22 +111,20 @@ static unsigned int mux_get_mctrl(struct uart_port *port) | |||
111 | /** | 111 | /** |
112 | * mux_stop_tx - Stop transmitting characters. | 112 | * mux_stop_tx - Stop transmitting characters. |
113 | * @port: Ptr to the uart_port. | 113 | * @port: Ptr to the uart_port. |
114 | * @tty_stop: tty layer issue this command? | ||
115 | * | 114 | * |
116 | * The Serial MUX does not support this function. | 115 | * The Serial MUX does not support this function. |
117 | */ | 116 | */ |
118 | static void mux_stop_tx(struct uart_port *port, unsigned int tty_stop) | 117 | static void mux_stop_tx(struct uart_port *port) |
119 | { | 118 | { |
120 | } | 119 | } |
121 | 120 | ||
122 | /** | 121 | /** |
123 | * mux_start_tx - Start transmitting characters. | 122 | * mux_start_tx - Start transmitting characters. |
124 | * @port: Ptr to the uart_port. | 123 | * @port: Ptr to the uart_port. |
125 | * @tty_start: tty layer issue this command? | ||
126 | * | 124 | * |
127 | * The Serial Mux does not support this function. | 125 | * The Serial Mux does not support this function. |
128 | */ | 126 | */ |
129 | static void mux_start_tx(struct uart_port *port, unsigned int tty_start) | 127 | static void mux_start_tx(struct uart_port *port) |
130 | { | 128 | { |
131 | } | 129 | } |
132 | 130 | ||
@@ -181,7 +179,7 @@ static void mux_write(struct uart_port *port) | |||
181 | } | 179 | } |
182 | 180 | ||
183 | if(uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 181 | if(uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
184 | mux_stop_tx(port, 0); | 182 | mux_stop_tx(port); |
185 | return; | 183 | return; |
186 | } | 184 | } |
187 | 185 | ||
@@ -202,7 +200,7 @@ static void mux_write(struct uart_port *port) | |||
202 | uart_write_wakeup(port); | 200 | uart_write_wakeup(port); |
203 | 201 | ||
204 | if (uart_circ_empty(xmit)) | 202 | if (uart_circ_empty(xmit)) |
205 | mux_stop_tx(port, 0); | 203 | mux_stop_tx(port); |
206 | } | 204 | } |
207 | 205 | ||
208 | /** | 206 | /** |
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 7db2f37532cf..5bfde99e245e 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c | |||
@@ -630,11 +630,10 @@ static unsigned int pmz_get_mctrl(struct uart_port *port) | |||
630 | 630 | ||
631 | /* | 631 | /* |
632 | * Stop TX side. Dealt like sunzilog at next Tx interrupt, | 632 | * Stop TX side. Dealt like sunzilog at next Tx interrupt, |
633 | * though for DMA, we will have to do a bit more. What is | 633 | * though for DMA, we will have to do a bit more. |
634 | * the meaning of the tty_stop bit ? XXX | ||
635 | * The port lock is held and interrupts are disabled. | 634 | * The port lock is held and interrupts are disabled. |
636 | */ | 635 | */ |
637 | static void pmz_stop_tx(struct uart_port *port, unsigned int tty_stop) | 636 | static void pmz_stop_tx(struct uart_port *port) |
638 | { | 637 | { |
639 | to_pmz(port)->flags |= PMACZILOG_FLAG_TX_STOPPED; | 638 | to_pmz(port)->flags |= PMACZILOG_FLAG_TX_STOPPED; |
640 | } | 639 | } |
@@ -643,7 +642,7 @@ static void pmz_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
643 | * Kick the Tx side. | 642 | * Kick the Tx side. |
644 | * The port lock is held and interrupts are disabled. | 643 | * The port lock is held and interrupts are disabled. |
645 | */ | 644 | */ |
646 | static void pmz_start_tx(struct uart_port *port, unsigned int tty_start) | 645 | static void pmz_start_tx(struct uart_port *port) |
647 | { | 646 | { |
648 | struct uart_pmac_port *uap = to_pmz(port); | 647 | struct uart_pmac_port *uap = to_pmz(port); |
649 | unsigned char status; | 648 | unsigned char status; |
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 461c81c93207..eaa0af835290 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c | |||
@@ -80,7 +80,7 @@ static void serial_pxa_enable_ms(struct uart_port *port) | |||
80 | serial_out(up, UART_IER, up->ier); | 80 | serial_out(up, UART_IER, up->ier); |
81 | } | 81 | } |
82 | 82 | ||
83 | static void serial_pxa_stop_tx(struct uart_port *port, unsigned int tty_stop) | 83 | static void serial_pxa_stop_tx(struct uart_port *port) |
84 | { | 84 | { |
85 | struct uart_pxa_port *up = (struct uart_pxa_port *)port; | 85 | struct uart_pxa_port *up = (struct uart_pxa_port *)port; |
86 | 86 | ||
@@ -185,7 +185,7 @@ static void transmit_chars(struct uart_pxa_port *up) | |||
185 | return; | 185 | return; |
186 | } | 186 | } |
187 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | 187 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { |
188 | serial_pxa_stop_tx(&up->port, 0); | 188 | serial_pxa_stop_tx(&up->port); |
189 | return; | 189 | return; |
190 | } | 190 | } |
191 | 191 | ||
@@ -203,10 +203,10 @@ static void transmit_chars(struct uart_pxa_port *up) | |||
203 | 203 | ||
204 | 204 | ||
205 | if (uart_circ_empty(xmit)) | 205 | if (uart_circ_empty(xmit)) |
206 | serial_pxa_stop_tx(&up->port, 0); | 206 | serial_pxa_stop_tx(&up->port); |
207 | } | 207 | } |
208 | 208 | ||
209 | static void serial_pxa_start_tx(struct uart_port *port, unsigned int tty_start) | 209 | static void serial_pxa_start_tx(struct uart_port *port) |
210 | { | 210 | { |
211 | struct uart_pxa_port *up = (struct uart_pxa_port *)port; | 211 | struct uart_pxa_port *up = (struct uart_pxa_port *)port; |
212 | 212 | ||
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 7365d4b50b95..c361c6fb0809 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c | |||
@@ -246,8 +246,7 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port) | |||
246 | spin_unlock_irqrestore(&port->lock, flags); | 246 | spin_unlock_irqrestore(&port->lock, flags); |
247 | } | 247 | } |
248 | 248 | ||
249 | static void | 249 | static void s3c24xx_serial_stop_tx(struct uart_port *port) |
250 | s3c24xx_serial_stop_tx(struct uart_port *port, unsigned int tty_stop) | ||
251 | { | 250 | { |
252 | if (tx_enabled(port)) { | 251 | if (tx_enabled(port)) { |
253 | disable_irq(TX_IRQ(port)); | 252 | disable_irq(TX_IRQ(port)); |
@@ -257,8 +256,7 @@ s3c24xx_serial_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
257 | } | 256 | } |
258 | } | 257 | } |
259 | 258 | ||
260 | static void | 259 | static void s3c24xx_serial_start_tx(struct uart_port *port) |
261 | s3c24xx_serial_start_tx(struct uart_port *port, unsigned int tty_start) | ||
262 | { | 260 | { |
263 | if (!tx_enabled(port)) { | 261 | if (!tx_enabled(port)) { |
264 | if (port->flags & UPF_CONS_FLOW) | 262 | if (port->flags & UPF_CONS_FLOW) |
@@ -424,7 +422,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *re | |||
424 | */ | 422 | */ |
425 | 423 | ||
426 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 424 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
427 | s3c24xx_serial_stop_tx(port, 0); | 425 | s3c24xx_serial_stop_tx(port); |
428 | goto out; | 426 | goto out; |
429 | } | 427 | } |
430 | 428 | ||
@@ -443,7 +441,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *re | |||
443 | uart_write_wakeup(port); | 441 | uart_write_wakeup(port); |
444 | 442 | ||
445 | if (uart_circ_empty(xmit)) | 443 | if (uart_circ_empty(xmit)) |
446 | s3c24xx_serial_stop_tx(port, 0); | 444 | s3c24xx_serial_stop_tx(port); |
447 | 445 | ||
448 | out: | 446 | out: |
449 | return IRQ_HANDLED; | 447 | return IRQ_HANDLED; |
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 98641c3f5ab9..1225b14f6e9d 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c | |||
@@ -145,7 +145,7 @@ static void sa1100_timeout(unsigned long data) | |||
145 | /* | 145 | /* |
146 | * interrupts disabled on entry | 146 | * interrupts disabled on entry |
147 | */ | 147 | */ |
148 | static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop) | 148 | static void sa1100_stop_tx(struct uart_port *port) |
149 | { | 149 | { |
150 | struct sa1100_port *sport = (struct sa1100_port *)port; | 150 | struct sa1100_port *sport = (struct sa1100_port *)port; |
151 | u32 utcr3; | 151 | u32 utcr3; |
@@ -158,7 +158,7 @@ static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
158 | /* | 158 | /* |
159 | * interrupts may not be disabled on entry | 159 | * interrupts may not be disabled on entry |
160 | */ | 160 | */ |
161 | static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start) | 161 | static void sa1100_start_tx(struct uart_port *port) |
162 | { | 162 | { |
163 | struct sa1100_port *sport = (struct sa1100_port *)port; | 163 | struct sa1100_port *sport = (struct sa1100_port *)port; |
164 | unsigned long flags; | 164 | unsigned long flags; |
@@ -264,7 +264,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport) | |||
264 | sa1100_mctrl_check(sport); | 264 | sa1100_mctrl_check(sport); |
265 | 265 | ||
266 | if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { | 266 | if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { |
267 | sa1100_stop_tx(&sport->port, 0); | 267 | sa1100_stop_tx(&sport->port); |
268 | return; | 268 | return; |
269 | } | 269 | } |
270 | 270 | ||
@@ -284,7 +284,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport) | |||
284 | uart_write_wakeup(&sport->port); | 284 | uart_write_wakeup(&sport->port); |
285 | 285 | ||
286 | if (uart_circ_empty(xmit)) | 286 | if (uart_circ_empty(xmit)) |
287 | sa1100_stop_tx(&sport->port, 0); | 287 | sa1100_stop_tx(&sport->port); |
288 | } | 288 | } |
289 | 289 | ||
290 | static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs) | 290 | static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs) |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 54699c3a00ab..dea156a62d0a 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -80,7 +80,7 @@ static void uart_stop(struct tty_struct *tty) | |||
80 | unsigned long flags; | 80 | unsigned long flags; |
81 | 81 | ||
82 | spin_lock_irqsave(&port->lock, flags); | 82 | spin_lock_irqsave(&port->lock, flags); |
83 | port->ops->stop_tx(port, 1); | 83 | port->ops->stop_tx(port); |
84 | spin_unlock_irqrestore(&port->lock, flags); | 84 | spin_unlock_irqrestore(&port->lock, flags); |
85 | } | 85 | } |
86 | 86 | ||
@@ -91,7 +91,7 @@ static void __uart_start(struct tty_struct *tty) | |||
91 | 91 | ||
92 | if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf && | 92 | if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf && |
93 | !tty->stopped && !tty->hw_stopped) | 93 | !tty->stopped && !tty->hw_stopped) |
94 | port->ops->start_tx(port, 1); | 94 | port->ops->start_tx(port); |
95 | } | 95 | } |
96 | 96 | ||
97 | static void uart_start(struct tty_struct *tty) | 97 | static void uart_start(struct tty_struct *tty) |
@@ -542,7 +542,7 @@ static void uart_send_xchar(struct tty_struct *tty, char ch) | |||
542 | port->x_char = ch; | 542 | port->x_char = ch; |
543 | if (ch) { | 543 | if (ch) { |
544 | spin_lock_irqsave(&port->lock, flags); | 544 | spin_lock_irqsave(&port->lock, flags); |
545 | port->ops->start_tx(port, 0); | 545 | port->ops->start_tx(port); |
546 | spin_unlock_irqrestore(&port->lock, flags); | 546 | spin_unlock_irqrestore(&port->lock, flags); |
547 | } | 547 | } |
548 | } | 548 | } |
@@ -1146,7 +1146,7 @@ static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios | |||
1146 | spin_lock_irqsave(&state->port->lock, flags); | 1146 | spin_lock_irqsave(&state->port->lock, flags); |
1147 | if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) { | 1147 | if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) { |
1148 | tty->hw_stopped = 1; | 1148 | tty->hw_stopped = 1; |
1149 | state->port->ops->stop_tx(state->port, 0); | 1149 | state->port->ops->stop_tx(state->port); |
1150 | } | 1150 | } |
1151 | spin_unlock_irqrestore(&state->port->lock, flags); | 1151 | spin_unlock_irqrestore(&state->port->lock, flags); |
1152 | } | 1152 | } |
@@ -1869,7 +1869,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) | |||
1869 | struct uart_ops *ops = port->ops; | 1869 | struct uart_ops *ops = port->ops; |
1870 | 1870 | ||
1871 | spin_lock_irq(&port->lock); | 1871 | spin_lock_irq(&port->lock); |
1872 | ops->stop_tx(port, 0); | 1872 | ops->stop_tx(port); |
1873 | ops->set_mctrl(port, 0); | 1873 | ops->set_mctrl(port, 0); |
1874 | ops->stop_rx(port); | 1874 | ops->stop_rx(port); |
1875 | spin_unlock_irq(&port->lock); | 1875 | spin_unlock_irq(&port->lock); |
@@ -1935,7 +1935,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) | |||
1935 | uart_change_speed(state, NULL); | 1935 | uart_change_speed(state, NULL); |
1936 | spin_lock_irq(&port->lock); | 1936 | spin_lock_irq(&port->lock); |
1937 | ops->set_mctrl(port, port->mctrl); | 1937 | ops->set_mctrl(port, port->mctrl); |
1938 | ops->start_tx(port, 0); | 1938 | ops->start_tx(port); |
1939 | spin_unlock_irq(&port->lock); | 1939 | spin_unlock_irq(&port->lock); |
1940 | } | 1940 | } |
1941 | 1941 | ||
@@ -2289,143 +2289,11 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2) | |||
2289 | } | 2289 | } |
2290 | EXPORT_SYMBOL(uart_match_port); | 2290 | EXPORT_SYMBOL(uart_match_port); |
2291 | 2291 | ||
2292 | /* | ||
2293 | * Try to find an unused uart_state slot for a port. | ||
2294 | */ | ||
2295 | static struct uart_state * | ||
2296 | uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port) | ||
2297 | { | ||
2298 | int i; | ||
2299 | |||
2300 | /* | ||
2301 | * First, find a port entry which matches. Note: if we do | ||
2302 | * find a matching entry, and it has a non-zero use count, | ||
2303 | * then we can't register the port. | ||
2304 | */ | ||
2305 | for (i = 0; i < drv->nr; i++) | ||
2306 | if (uart_match_port(drv->state[i].port, port)) | ||
2307 | return &drv->state[i]; | ||
2308 | |||
2309 | /* | ||
2310 | * We didn't find a matching entry, so look for the first | ||
2311 | * free entry. We look for one which hasn't been previously | ||
2312 | * used (indicated by zero iobase). | ||
2313 | */ | ||
2314 | for (i = 0; i < drv->nr; i++) | ||
2315 | if (drv->state[i].port->type == PORT_UNKNOWN && | ||
2316 | drv->state[i].port->iobase == 0 && | ||
2317 | drv->state[i].count == 0) | ||
2318 | return &drv->state[i]; | ||
2319 | |||
2320 | /* | ||
2321 | * That also failed. Last resort is to find any currently | ||
2322 | * entry which doesn't have a real port associated with it. | ||
2323 | */ | ||
2324 | for (i = 0; i < drv->nr; i++) | ||
2325 | if (drv->state[i].port->type == PORT_UNKNOWN && | ||
2326 | drv->state[i].count == 0) | ||
2327 | return &drv->state[i]; | ||
2328 | |||
2329 | return NULL; | ||
2330 | } | ||
2331 | |||
2332 | /** | ||
2333 | * uart_register_port: register uart settings with a port | ||
2334 | * @drv: pointer to the uart low level driver structure for this port | ||
2335 | * @port: uart port structure describing the port | ||
2336 | * | ||
2337 | * Register UART settings with the specified low level driver. Detect | ||
2338 | * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the | ||
2339 | * IRQ if UPF_AUTO_IRQ is set. | ||
2340 | * | ||
2341 | * We try to pick the same port for the same IO base address, so that | ||
2342 | * when a modem is plugged in, unplugged and plugged back in, it gets | ||
2343 | * allocated the same port. | ||
2344 | * | ||
2345 | * Returns negative error, or positive line number. | ||
2346 | */ | ||
2347 | int uart_register_port(struct uart_driver *drv, struct uart_port *port) | ||
2348 | { | ||
2349 | struct uart_state *state; | ||
2350 | int ret; | ||
2351 | |||
2352 | down(&port_sem); | ||
2353 | |||
2354 | state = uart_find_match_or_unused(drv, port); | ||
2355 | |||
2356 | if (state) { | ||
2357 | /* | ||
2358 | * Ok, we've found a line that we can use. | ||
2359 | * | ||
2360 | * If we find a port that matches this one, and it appears | ||
2361 | * to be in-use (even if it doesn't have a type) we shouldn't | ||
2362 | * alter it underneath itself - the port may be open and | ||
2363 | * trying to do useful work. | ||
2364 | */ | ||
2365 | if (uart_users(state) != 0) { | ||
2366 | ret = -EBUSY; | ||
2367 | goto out; | ||
2368 | } | ||
2369 | |||
2370 | /* | ||
2371 | * If the port is already initialised, don't touch it. | ||
2372 | */ | ||
2373 | if (state->port->type == PORT_UNKNOWN) { | ||
2374 | state->port->iobase = port->iobase; | ||
2375 | state->port->membase = port->membase; | ||
2376 | state->port->irq = port->irq; | ||
2377 | state->port->uartclk = port->uartclk; | ||
2378 | state->port->fifosize = port->fifosize; | ||
2379 | state->port->regshift = port->regshift; | ||
2380 | state->port->iotype = port->iotype; | ||
2381 | state->port->flags = port->flags; | ||
2382 | state->port->line = state - drv->state; | ||
2383 | state->port->mapbase = port->mapbase; | ||
2384 | |||
2385 | uart_configure_port(drv, state, state->port); | ||
2386 | } | ||
2387 | |||
2388 | ret = state->port->line; | ||
2389 | } else | ||
2390 | ret = -ENOSPC; | ||
2391 | out: | ||
2392 | up(&port_sem); | ||
2393 | return ret; | ||
2394 | } | ||
2395 | |||
2396 | /** | ||
2397 | * uart_unregister_port - de-allocate a port | ||
2398 | * @drv: pointer to the uart low level driver structure for this port | ||
2399 | * @line: line index previously returned from uart_register_port() | ||
2400 | * | ||
2401 | * Hang up the specified line associated with the low level driver, | ||
2402 | * and mark the port as unused. | ||
2403 | */ | ||
2404 | void uart_unregister_port(struct uart_driver *drv, int line) | ||
2405 | { | ||
2406 | struct uart_state *state; | ||
2407 | |||
2408 | if (line < 0 || line >= drv->nr) { | ||
2409 | printk(KERN_ERR "Attempt to unregister "); | ||
2410 | printk("%s%d", drv->dev_name, line); | ||
2411 | printk("\n"); | ||
2412 | return; | ||
2413 | } | ||
2414 | |||
2415 | state = drv->state + line; | ||
2416 | |||
2417 | down(&port_sem); | ||
2418 | uart_unconfigure_port(drv, state); | ||
2419 | up(&port_sem); | ||
2420 | } | ||
2421 | |||
2422 | EXPORT_SYMBOL(uart_write_wakeup); | 2292 | EXPORT_SYMBOL(uart_write_wakeup); |
2423 | EXPORT_SYMBOL(uart_register_driver); | 2293 | EXPORT_SYMBOL(uart_register_driver); |
2424 | EXPORT_SYMBOL(uart_unregister_driver); | 2294 | EXPORT_SYMBOL(uart_unregister_driver); |
2425 | EXPORT_SYMBOL(uart_suspend_port); | 2295 | EXPORT_SYMBOL(uart_suspend_port); |
2426 | EXPORT_SYMBOL(uart_resume_port); | 2296 | EXPORT_SYMBOL(uart_resume_port); |
2427 | EXPORT_SYMBOL(uart_register_port); | ||
2428 | EXPORT_SYMBOL(uart_unregister_port); | ||
2429 | EXPORT_SYMBOL(uart_add_one_port); | 2297 | EXPORT_SYMBOL(uart_add_one_port); |
2430 | EXPORT_SYMBOL(uart_remove_one_port); | 2298 | EXPORT_SYMBOL(uart_remove_one_port); |
2431 | 2299 | ||
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 56f269b6bfb1..32f808d157a1 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c | |||
@@ -112,13 +112,12 @@ struct uart_port_lh7a40x { | |||
112 | unsigned int statusPrev; /* Most recently read modem status */ | 112 | unsigned int statusPrev; /* Most recently read modem status */ |
113 | }; | 113 | }; |
114 | 114 | ||
115 | static void lh7a40xuart_stop_tx (struct uart_port* port, unsigned int tty_stop) | 115 | static void lh7a40xuart_stop_tx (struct uart_port* port) |
116 | { | 116 | { |
117 | BIT_CLR (port, UART_R_INTEN, TxInt); | 117 | BIT_CLR (port, UART_R_INTEN, TxInt); |
118 | } | 118 | } |
119 | 119 | ||
120 | static void lh7a40xuart_start_tx (struct uart_port* port, | 120 | static void lh7a40xuart_start_tx (struct uart_port* port) |
121 | unsigned int tty_start) | ||
122 | { | 121 | { |
123 | BIT_SET (port, UART_R_INTEN, TxInt); | 122 | BIT_SET (port, UART_R_INTEN, TxInt); |
124 | 123 | ||
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index d085030df70b..49afadbe461b 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c | |||
@@ -253,7 +253,7 @@ sio_quot_set(struct uart_txx9_port *up, int quot) | |||
253 | sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6); | 253 | sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6); |
254 | } | 254 | } |
255 | 255 | ||
256 | static void serial_txx9_stop_tx(struct uart_port *port, unsigned int tty_stop) | 256 | static void serial_txx9_stop_tx(struct uart_port *port) |
257 | { | 257 | { |
258 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | 258 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; |
259 | unsigned long flags; | 259 | unsigned long flags; |
@@ -263,7 +263,7 @@ static void serial_txx9_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
263 | spin_unlock_irqrestore(&up->port.lock, flags); | 263 | spin_unlock_irqrestore(&up->port.lock, flags); |
264 | } | 264 | } |
265 | 265 | ||
266 | static void serial_txx9_start_tx(struct uart_port *port, unsigned int tty_start) | 266 | static void serial_txx9_start_tx(struct uart_port *port) |
267 | { | 267 | { |
268 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; | 268 | struct uart_txx9_port *up = (struct uart_txx9_port *)port; |
269 | unsigned long flags; | 269 | unsigned long flags; |
@@ -372,7 +372,7 @@ static inline void transmit_chars(struct uart_txx9_port *up) | |||
372 | return; | 372 | return; |
373 | } | 373 | } |
374 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | 374 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { |
375 | serial_txx9_stop_tx(&up->port, 0); | 375 | serial_txx9_stop_tx(&up->port); |
376 | return; | 376 | return; |
377 | } | 377 | } |
378 | 378 | ||
@@ -389,7 +389,7 @@ static inline void transmit_chars(struct uart_txx9_port *up) | |||
389 | uart_write_wakeup(&up->port); | 389 | uart_write_wakeup(&up->port); |
390 | 390 | ||
391 | if (uart_circ_empty(xmit)) | 391 | if (uart_circ_empty(xmit)) |
392 | serial_txx9_stop_tx(&up->port, 0); | 392 | serial_txx9_stop_tx(&up->port); |
393 | } | 393 | } |
394 | 394 | ||
395 | static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 395 | static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index ad5b776d779b..512266307866 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -79,8 +79,8 @@ static struct sci_port *serial_console_port = 0; | |||
79 | #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ | 79 | #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ |
80 | 80 | ||
81 | /* Function prototypes */ | 81 | /* Function prototypes */ |
82 | static void sci_stop_tx(struct uart_port *port, unsigned int tty_stop); | 82 | static void sci_stop_tx(struct uart_port *port); |
83 | static void sci_start_tx(struct uart_port *port, unsigned int tty_start); | 83 | static void sci_start_tx(struct uart_port *port); |
84 | static void sci_start_rx(struct uart_port *port, unsigned int tty_start); | 84 | static void sci_start_rx(struct uart_port *port, unsigned int tty_start); |
85 | static void sci_stop_rx(struct uart_port *port); | 85 | static void sci_stop_rx(struct uart_port *port); |
86 | static int sci_request_irq(struct sci_port *port); | 86 | static int sci_request_irq(struct sci_port *port); |
@@ -455,7 +455,7 @@ static void sci_transmit_chars(struct uart_port *port) | |||
455 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 455 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
456 | uart_write_wakeup(port); | 456 | uart_write_wakeup(port); |
457 | if (uart_circ_empty(xmit)) { | 457 | if (uart_circ_empty(xmit)) { |
458 | sci_stop_tx(port, 0); | 458 | sci_stop_tx(port); |
459 | } else { | 459 | } else { |
460 | local_irq_save(flags); | 460 | local_irq_save(flags); |
461 | ctrl = sci_in(port, SCSCR); | 461 | ctrl = sci_in(port, SCSCR); |
@@ -900,7 +900,7 @@ static unsigned int sci_get_mctrl(struct uart_port *port) | |||
900 | return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR; | 900 | return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR; |
901 | } | 901 | } |
902 | 902 | ||
903 | static void sci_start_tx(struct uart_port *port, unsigned int tty_start) | 903 | static void sci_start_tx(struct uart_port *port) |
904 | { | 904 | { |
905 | struct sci_port *s = &sci_ports[port->line]; | 905 | struct sci_port *s = &sci_ports[port->line]; |
906 | 906 | ||
@@ -909,7 +909,7 @@ static void sci_start_tx(struct uart_port *port, unsigned int tty_start) | |||
909 | enable_irq(s->irqs[SCIx_TXI_IRQ]); | 909 | enable_irq(s->irqs[SCIx_TXI_IRQ]); |
910 | } | 910 | } |
911 | 911 | ||
912 | static void sci_stop_tx(struct uart_port *port, unsigned int tty_stop) | 912 | static void sci_stop_tx(struct uart_port *port) |
913 | { | 913 | { |
914 | unsigned long flags; | 914 | unsigned long flags; |
915 | unsigned short ctrl; | 915 | unsigned short ctrl; |
@@ -978,7 +978,7 @@ static void sci_shutdown(struct uart_port *port) | |||
978 | struct sci_port *s = &sci_ports[port->line]; | 978 | struct sci_port *s = &sci_ports[port->line]; |
979 | 979 | ||
980 | sci_stop_rx(port); | 980 | sci_stop_rx(port); |
981 | sci_stop_tx(port, 1); | 981 | sci_stop_tx(port); |
982 | sci_free_irq(s); | 982 | sci_free_irq(s); |
983 | 983 | ||
984 | #if defined(__H8300S__) | 984 | #if defined(__H8300S__) |
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 12d1f14e78ce..313f9df24a2d 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c | |||
@@ -259,10 +259,9 @@ static unsigned int snp_tx_empty(struct uart_port *port) | |||
259 | /** | 259 | /** |
260 | * snp_stop_tx - stop the transmitter - no-op for us | 260 | * snp_stop_tx - stop the transmitter - no-op for us |
261 | * @port: Port to operat eon - we ignore - no-op function | 261 | * @port: Port to operat eon - we ignore - no-op function |
262 | * @tty_stop: Set to 1 if called via uart_stop | ||
263 | * | 262 | * |
264 | */ | 263 | */ |
265 | static void snp_stop_tx(struct uart_port *port, unsigned int tty_stop) | 264 | static void snp_stop_tx(struct uart_port *port) |
266 | { | 265 | { |
267 | } | 266 | } |
268 | 267 | ||
@@ -325,10 +324,9 @@ static void snp_stop_rx(struct uart_port *port) | |||
325 | /** | 324 | /** |
326 | * snp_start_tx - Start transmitter | 325 | * snp_start_tx - Start transmitter |
327 | * @port: Port to operate on | 326 | * @port: Port to operate on |
328 | * @tty_stop: Set to 1 if called via uart_start | ||
329 | * | 327 | * |
330 | */ | 328 | */ |
331 | static void snp_start_tx(struct uart_port *port, unsigned int tty_stop) | 329 | static void snp_start_tx(struct uart_port *port) |
332 | { | 330 | { |
333 | if (sal_console_port.sc_ops->sal_wakeup_transmit) | 331 | if (sal_console_port.sc_ops->sal_wakeup_transmit) |
334 | sal_console_port.sc_ops->sal_wakeup_transmit(&sal_console_port, | 332 | sal_console_port.sc_ops->sal_wakeup_transmit(&sal_console_port, |
@@ -615,7 +613,7 @@ static void sn_transmit_chars(struct sn_cons_port *port, int raw) | |||
615 | uart_write_wakeup(&port->sc_port); | 613 | uart_write_wakeup(&port->sc_port); |
616 | 614 | ||
617 | if (uart_circ_empty(xmit)) | 615 | if (uart_circ_empty(xmit)) |
618 | snp_stop_tx(&port->sc_port, 0); /* no-op for us */ | 616 | snp_stop_tx(&port->sc_port); /* no-op for us */ |
619 | } | 617 | } |
620 | 618 | ||
621 | /** | 619 | /** |
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 8d198880756a..e971156daa60 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
@@ -245,7 +245,7 @@ receive_chars(struct uart_sunsab_port *up, | |||
245 | return tty; | 245 | return tty; |
246 | } | 246 | } |
247 | 247 | ||
248 | static void sunsab_stop_tx(struct uart_port *, unsigned int); | 248 | static void sunsab_stop_tx(struct uart_port *); |
249 | static void sunsab_tx_idle(struct uart_sunsab_port *); | 249 | static void sunsab_tx_idle(struct uart_sunsab_port *); |
250 | 250 | ||
251 | static void transmit_chars(struct uart_sunsab_port *up, | 251 | static void transmit_chars(struct uart_sunsab_port *up, |
@@ -301,7 +301,7 @@ static void transmit_chars(struct uart_sunsab_port *up, | |||
301 | uart_write_wakeup(&up->port); | 301 | uart_write_wakeup(&up->port); |
302 | 302 | ||
303 | if (uart_circ_empty(xmit)) | 303 | if (uart_circ_empty(xmit)) |
304 | sunsab_stop_tx(&up->port, 0); | 304 | sunsab_stop_tx(&up->port); |
305 | } | 305 | } |
306 | 306 | ||
307 | static void check_status(struct uart_sunsab_port *up, | 307 | static void check_status(struct uart_sunsab_port *up, |
@@ -448,7 +448,7 @@ static unsigned int sunsab_get_mctrl(struct uart_port *port) | |||
448 | } | 448 | } |
449 | 449 | ||
450 | /* port->lock held by caller. */ | 450 | /* port->lock held by caller. */ |
451 | static void sunsab_stop_tx(struct uart_port *port, unsigned int tty_stop) | 451 | static void sunsab_stop_tx(struct uart_port *port) |
452 | { | 452 | { |
453 | struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; | 453 | struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; |
454 | 454 | ||
@@ -476,7 +476,7 @@ static void sunsab_tx_idle(struct uart_sunsab_port *up) | |||
476 | } | 476 | } |
477 | 477 | ||
478 | /* port->lock held by caller. */ | 478 | /* port->lock held by caller. */ |
479 | static void sunsab_start_tx(struct uart_port *port, unsigned int tty_start) | 479 | static void sunsab_start_tx(struct uart_port *port) |
480 | { | 480 | { |
481 | struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; | 481 | struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; |
482 | struct circ_buf *xmit = &up->port.info->xmit; | 482 | struct circ_buf *xmit = &up->port.info->xmit; |
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index d57a3553aea3..0cc879eb1c02 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
@@ -255,21 +255,27 @@ static void disable_rsa(struct uart_sunsu_port *up) | |||
255 | } | 255 | } |
256 | #endif /* CONFIG_SERIAL_8250_RSA */ | 256 | #endif /* CONFIG_SERIAL_8250_RSA */ |
257 | 257 | ||
258 | static void sunsu_stop_tx(struct uart_port *port, unsigned int tty_stop) | 258 | static inline void __stop_tx(struct uart_sunsu_port *p) |
259 | { | ||
260 | if (p->ier & UART_IER_THRI) { | ||
261 | p->ier &= ~UART_IER_THRI; | ||
262 | serial_out(p, UART_IER, p->ier); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | static void sunsu_stop_tx(struct uart_port *port) | ||
259 | { | 267 | { |
260 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 268 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
261 | 269 | ||
262 | if (up->ier & UART_IER_THRI) { | 270 | __stop_tx(up); |
263 | up->ier &= ~UART_IER_THRI; | 271 | |
264 | serial_out(up, UART_IER, up->ier); | 272 | if (up->port.type == PORT_16C950 && tty_stop /*FIXME*/) { |
265 | } | ||
266 | if (up->port.type == PORT_16C950 && tty_stop) { | ||
267 | up->acr |= UART_ACR_TXDIS; | 273 | up->acr |= UART_ACR_TXDIS; |
268 | serial_icr_write(up, UART_ACR, up->acr); | 274 | serial_icr_write(up, UART_ACR, up->acr); |
269 | } | 275 | } |
270 | } | 276 | } |
271 | 277 | ||
272 | static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start) | 278 | static void sunsu_start_tx(struct uart_port *port) |
273 | { | 279 | { |
274 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; | 280 | struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; |
275 | 281 | ||
@@ -280,7 +286,7 @@ static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start) | |||
280 | /* | 286 | /* |
281 | * We only do this from uart_start | 287 | * We only do this from uart_start |
282 | */ | 288 | */ |
283 | if (tty_start && up->port.type == PORT_16C950) { | 289 | if (tty_start && up->port.type == PORT_16C950 /*FIXME*/) { |
284 | up->acr &= ~UART_ACR_TXDIS; | 290 | up->acr &= ~UART_ACR_TXDIS; |
285 | serial_icr_write(up, UART_ACR, up->acr); | 291 | serial_icr_write(up, UART_ACR, up->acr); |
286 | } | 292 | } |
@@ -413,8 +419,12 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up) | |||
413 | up->port.x_char = 0; | 419 | up->port.x_char = 0; |
414 | return; | 420 | return; |
415 | } | 421 | } |
416 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | 422 | if (uart_tx_stopped(&up->port)) { |
417 | sunsu_stop_tx(&up->port, 0); | 423 | sunsu_stop_tx(&up->port); |
424 | return; | ||
425 | } | ||
426 | if (uart_circ_empty(xmit)) { | ||
427 | __stop_tx(up); | ||
418 | return; | 428 | return; |
419 | } | 429 | } |
420 | 430 | ||
@@ -431,7 +441,7 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up) | |||
431 | uart_write_wakeup(&up->port); | 441 | uart_write_wakeup(&up->port); |
432 | 442 | ||
433 | if (uart_circ_empty(xmit)) | 443 | if (uart_circ_empty(xmit)) |
434 | sunsu_stop_tx(&up->port, 0); | 444 | __stop_tx(up); |
435 | } | 445 | } |
436 | 446 | ||
437 | static _INLINE_ void check_modem_status(struct uart_sunsu_port *up) | 447 | static _INLINE_ void check_modem_status(struct uart_sunsu_port *up) |
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index bff42a7b89d0..d75445738c88 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
@@ -684,7 +684,7 @@ static void sunzilog_set_mctrl(struct uart_port *port, unsigned int mctrl) | |||
684 | } | 684 | } |
685 | 685 | ||
686 | /* The port lock is held and interrupts are disabled. */ | 686 | /* The port lock is held and interrupts are disabled. */ |
687 | static void sunzilog_stop_tx(struct uart_port *port, unsigned int tty_stop) | 687 | static void sunzilog_stop_tx(struct uart_port *port) |
688 | { | 688 | { |
689 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; | 689 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; |
690 | 690 | ||
@@ -692,7 +692,7 @@ static void sunzilog_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
692 | } | 692 | } |
693 | 693 | ||
694 | /* The port lock is held and interrupts are disabled. */ | 694 | /* The port lock is held and interrupts are disabled. */ |
695 | static void sunzilog_start_tx(struct uart_port *port, unsigned int tty_start) | 695 | static void sunzilog_start_tx(struct uart_port *port) |
696 | { | 696 | { |
697 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; | 697 | struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; |
698 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); | 698 | struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); |
diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c index 186f1300cead..47b504ff38b2 100644 --- a/drivers/serial/uart00.c +++ b/drivers/serial/uart00.c | |||
@@ -87,7 +87,7 @@ | |||
87 | #define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15) | 87 | #define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15) |
88 | //#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0) | 88 | //#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0) |
89 | 89 | ||
90 | static void uart00_stop_tx(struct uart_port *port, unsigned int tty_stop) | 90 | static void uart00_stop_tx(struct uart_port *port) |
91 | { | 91 | { |
92 | UART_PUT_IEC(port, UART_IEC_TIE_MSK); | 92 | UART_PUT_IEC(port, UART_IEC_TIE_MSK); |
93 | } | 93 | } |
@@ -199,7 +199,7 @@ static void uart00_tx_chars(struct uart_port *port) | |||
199 | return; | 199 | return; |
200 | } | 200 | } |
201 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 201 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
202 | uart00_stop_tx(port, 0); | 202 | uart00_stop_tx(port); |
203 | return; | 203 | return; |
204 | } | 204 | } |
205 | 205 | ||
@@ -218,10 +218,10 @@ static void uart00_tx_chars(struct uart_port *port) | |||
218 | uart_write_wakeup(port); | 218 | uart_write_wakeup(port); |
219 | 219 | ||
220 | if (uart_circ_empty(xmit)) | 220 | if (uart_circ_empty(xmit)) |
221 | uart00_stop_tx(port, 0); | 221 | uart00_stop_tx(port); |
222 | } | 222 | } |
223 | 223 | ||
224 | static void uart00_start_tx(struct uart_port *port, unsigned int tty_start) | 224 | static void uart00_start_tx(struct uart_port *port) |
225 | { | 225 | { |
226 | UART_PUT_IES(port, UART_IES_TIE_MSK); | 226 | UART_PUT_IES(port, UART_IES_TIE_MSK); |
227 | uart00_tx_chars(port); | 227 | uart00_tx_chars(port); |
diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c index bb482780a41d..9378895a8d56 100644 --- a/drivers/serial/v850e_uart.c +++ b/drivers/serial/v850e_uart.c | |||
@@ -240,7 +240,7 @@ console_initcall(v850e_uart_console_init); | |||
240 | 240 | ||
241 | /* TX/RX interrupt handlers. */ | 241 | /* TX/RX interrupt handlers. */ |
242 | 242 | ||
243 | static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop); | 243 | static void v850e_uart_stop_tx (struct uart_port *port); |
244 | 244 | ||
245 | void v850e_uart_tx (struct uart_port *port) | 245 | void v850e_uart_tx (struct uart_port *port) |
246 | { | 246 | { |
@@ -339,14 +339,14 @@ static unsigned v850e_uart_get_mctrl (struct uart_port *port) | |||
339 | return mctrl; | 339 | return mctrl; |
340 | } | 340 | } |
341 | 341 | ||
342 | static void v850e_uart_start_tx (struct uart_port *port, unsigned tty_start) | 342 | static void v850e_uart_start_tx (struct uart_port *port) |
343 | { | 343 | { |
344 | v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line)); | 344 | v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line)); |
345 | v850e_uart_tx (port); | 345 | v850e_uart_tx (port); |
346 | v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line)); | 346 | v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line)); |
347 | } | 347 | } |
348 | 348 | ||
349 | static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop) | 349 | static void v850e_uart_stop_tx (struct uart_port *port) |
350 | { | 350 | { |
351 | v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line)); | 351 | v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line)); |
352 | } | 352 | } |
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 1f985327b0d4..0c5d65a08f6e 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c | |||
@@ -284,7 +284,7 @@ static unsigned int siu_get_mctrl(struct uart_port *port) | |||
284 | return mctrl; | 284 | return mctrl; |
285 | } | 285 | } |
286 | 286 | ||
287 | static void siu_stop_tx(struct uart_port *port, unsigned int tty_stop) | 287 | static void siu_stop_tx(struct uart_port *port) |
288 | { | 288 | { |
289 | unsigned long flags; | 289 | unsigned long flags; |
290 | uint8_t ier; | 290 | uint8_t ier; |
@@ -298,7 +298,7 @@ static void siu_stop_tx(struct uart_port *port, unsigned int tty_stop) | |||
298 | spin_unlock_irqrestore(&port->lock, flags); | 298 | spin_unlock_irqrestore(&port->lock, flags); |
299 | } | 299 | } |
300 | 300 | ||
301 | static void siu_start_tx(struct uart_port *port, unsigned int tty_start) | 301 | static void siu_start_tx(struct uart_port *port) |
302 | { | 302 | { |
303 | unsigned long flags; | 303 | unsigned long flags; |
304 | uint8_t ier; | 304 | uint8_t ier; |
@@ -458,7 +458,7 @@ static inline void transmit_chars(struct uart_port *port) | |||
458 | } | 458 | } |
459 | 459 | ||
460 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | 460 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { |
461 | siu_stop_tx(port, 0); | 461 | siu_stop_tx(port); |
462 | return; | 462 | return; |
463 | } | 463 | } |
464 | 464 | ||
@@ -474,7 +474,7 @@ static inline void transmit_chars(struct uart_port *port) | |||
474 | uart_write_wakeup(port); | 474 | uart_write_wakeup(port); |
475 | 475 | ||
476 | if (uart_circ_empty(xmit)) | 476 | if (uart_circ_empty(xmit)) |
477 | siu_stop_tx(port, 0); | 477 | siu_stop_tx(port); |
478 | } | 478 | } |
479 | 479 | ||
480 | static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 480 | static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs) |