aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGeoff Levand <geoffrey.levand@am.sony.com>2007-06-15 18:01:06 -0400
committerPaul Mackerras <paulus@samba.org>2007-06-28 05:16:40 -0400
commit7626e78d29651d3075e88f233c0632867ea6a35c (patch)
tree0f1d4b26d6597b9a81af2e2009ce2dae6aaabbc7 /drivers
parenta3323d1a52ec5b70821590e4beaaf13c466fd396 (diff)
[POWERPC] PS3: Vuart rework
PS3 vuart updates to reflect the new PS3 unified device support. - Move vuart devices to the PS3 system bus. - Replace use of ps3_vuart_port_device with ps3_system_bus_device. - Make the PS3 vuart bus driver a loadable module. - Add remove() and shutdown() routines. - Move ps3_vuart_work into ps3_vuart_port_priv.tx_list. - Remove redundant spinlock ps3_vuart_work.lock. - No longer free ps3_vuart_port_device.priv on shutdown. - Cleanup Kconfig defs. - Export symbols needed for modular port drivers. - Arrange to use port numbers found in repository. - Fix bugs in ps3_vuart_read_async() and polled reading - Cleanup handling of shared interrupt with ps3_vuart_bus_interrupt_get() and ps3_vuart_bus_interrupt_put() - Add more comments to vuart.c. Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ps3/vuart.c813
-rw-r--r--drivers/ps3/vuart.h71
2 files changed, 510 insertions, 374 deletions
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c
index 5333fb2f0d86..bea25a1391ee 100644
--- a/drivers/ps3/vuart.c
+++ b/drivers/ps3/vuart.c
@@ -71,6 +71,34 @@ enum vuart_interrupt_mask {
71}; 71};
72 72
73/** 73/**
74 * struct ps3_vuart_port_priv - private vuart device data.
75 */
76
77struct ps3_vuart_port_priv {
78 u64 interrupt_mask;
79
80 struct {
81 spinlock_t lock;
82 struct list_head head;
83 } tx_list;
84 struct {
85 struct ps3_vuart_work work;
86 unsigned long bytes_held;
87 spinlock_t lock;
88 struct list_head head;
89 } rx_list;
90 struct ps3_vuart_stats stats;
91};
92
93static struct ps3_vuart_port_priv *to_port_priv(
94 struct ps3_system_bus_device *dev)
95{
96 BUG_ON(!dev);
97 BUG_ON(!dev->driver_priv);
98 return (struct ps3_vuart_port_priv *)dev->driver_priv;
99}
100
101/**
74 * struct ports_bmp - bitmap indicating ports needing service. 102 * struct ports_bmp - bitmap indicating ports needing service.
75 * 103 *
76 * A 256 bit read only bitmap indicating ports needing service. Do not write 104 * A 256 bit read only bitmap indicating ports needing service. Do not write
@@ -89,23 +117,6 @@ static void __maybe_unused _dump_ports_bmp(
89 pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status); 117 pr_debug("%s:%d: ports_bmp: %016lxh\n", func, line, bmp->status);
90} 118}
91 119
92static int ps3_vuart_match_id_to_port(enum ps3_match_id match_id,
93 unsigned int *port_number)
94{
95 switch(match_id) {
96 case PS3_MATCH_ID_AV_SETTINGS:
97 *port_number = 0;
98 return 0;
99 case PS3_MATCH_ID_SYSTEM_MANAGER:
100 *port_number = 2;
101 return 0;
102 default:
103 WARN_ON(1);
104 *port_number = UINT_MAX;
105 return -EINVAL;
106 };
107}
108
109#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__) 120#define dump_port_params(_b) _dump_port_params(_b, __func__, __LINE__)
110static void __maybe_unused _dump_port_params(unsigned int port_number, 121static void __maybe_unused _dump_port_params(unsigned int port_number,
111 const char* func, int line) 122 const char* func, int line)
@@ -144,14 +155,14 @@ struct vuart_triggers {
144 unsigned long tx; 155 unsigned long tx;
145}; 156};
146 157
147int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, 158int ps3_vuart_get_triggers(struct ps3_system_bus_device *dev,
148 struct vuart_triggers *trig) 159 struct vuart_triggers *trig)
149{ 160{
150 int result; 161 int result;
151 unsigned long size; 162 unsigned long size;
152 unsigned long val; 163 unsigned long val;
153 164
154 result = lv1_get_virtual_uart_param(dev->priv->port_number, 165 result = lv1_get_virtual_uart_param(dev->port_number,
155 PARAM_TX_TRIGGER, &trig->tx); 166 PARAM_TX_TRIGGER, &trig->tx);
156 167
157 if (result) { 168 if (result) {
@@ -160,7 +171,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
160 return result; 171 return result;
161 } 172 }
162 173
163 result = lv1_get_virtual_uart_param(dev->priv->port_number, 174 result = lv1_get_virtual_uart_param(dev->port_number,
164 PARAM_RX_BUF_SIZE, &size); 175 PARAM_RX_BUF_SIZE, &size);
165 176
166 if (result) { 177 if (result) {
@@ -169,7 +180,7 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
169 return result; 180 return result;
170 } 181 }
171 182
172 result = lv1_get_virtual_uart_param(dev->priv->port_number, 183 result = lv1_get_virtual_uart_param(dev->port_number,
173 PARAM_RX_TRIGGER, &val); 184 PARAM_RX_TRIGGER, &val);
174 185
175 if (result) { 186 if (result) {
@@ -186,13 +197,13 @@ int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev,
186 return result; 197 return result;
187} 198}
188 199
189int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, 200int ps3_vuart_set_triggers(struct ps3_system_bus_device *dev, unsigned int tx,
190 unsigned int rx) 201 unsigned int rx)
191{ 202{
192 int result; 203 int result;
193 unsigned long size; 204 unsigned long size;
194 205
195 result = lv1_set_virtual_uart_param(dev->priv->port_number, 206 result = lv1_set_virtual_uart_param(dev->port_number,
196 PARAM_TX_TRIGGER, tx); 207 PARAM_TX_TRIGGER, tx);
197 208
198 if (result) { 209 if (result) {
@@ -201,7 +212,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
201 return result; 212 return result;
202 } 213 }
203 214
204 result = lv1_get_virtual_uart_param(dev->priv->port_number, 215 result = lv1_get_virtual_uart_param(dev->port_number,
205 PARAM_RX_BUF_SIZE, &size); 216 PARAM_RX_BUF_SIZE, &size);
206 217
207 if (result) { 218 if (result) {
@@ -210,7 +221,7 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
210 return result; 221 return result;
211 } 222 }
212 223
213 result = lv1_set_virtual_uart_param(dev->priv->port_number, 224 result = lv1_set_virtual_uart_param(dev->port_number,
214 PARAM_RX_TRIGGER, size - rx); 225 PARAM_RX_TRIGGER, size - rx);
215 226
216 if (result) { 227 if (result) {
@@ -225,10 +236,12 @@ int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx,
225 return result; 236 return result;
226} 237}
227 238
228static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev, 239static int ps3_vuart_get_rx_bytes_waiting(struct ps3_system_bus_device *dev,
229 u64 *bytes_waiting) 240 u64 *bytes_waiting)
230{ 241{
231 int result = lv1_get_virtual_uart_param(dev->priv->port_number, 242 int result;
243
244 result = lv1_get_virtual_uart_param(dev->port_number,
232 PARAM_RX_BYTES, bytes_waiting); 245 PARAM_RX_BYTES, bytes_waiting);
233 246
234 if (result) 247 if (result)
@@ -240,17 +253,24 @@ static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev,
240 return result; 253 return result;
241} 254}
242 255
243static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev, 256/**
257 * ps3_vuart_set_interrupt_mask - Enable/disable the port interrupt sources.
258 * @dev: The struct ps3_system_bus_device instance.
259 * @bmp: Logical OR of enum vuart_interrupt_mask values. A zero bit disables.
260 */
261
262static int ps3_vuart_set_interrupt_mask(struct ps3_system_bus_device *dev,
244 unsigned long mask) 263 unsigned long mask)
245{ 264{
246 int result; 265 int result;
266 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
247 267
248 dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask); 268 dev_dbg(&dev->core, "%s:%d: %lxh\n", __func__, __LINE__, mask);
249 269
250 dev->priv->interrupt_mask = mask; 270 priv->interrupt_mask = mask;
251 271
252 result = lv1_set_virtual_uart_param(dev->priv->port_number, 272 result = lv1_set_virtual_uart_param(dev->port_number,
253 PARAM_INTERRUPT_MASK, dev->priv->interrupt_mask); 273 PARAM_INTERRUPT_MASK, priv->interrupt_mask);
254 274
255 if (result) 275 if (result)
256 dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n", 276 dev_dbg(&dev->core, "%s:%d: interrupt_mask failed: %s\n",
@@ -259,79 +279,96 @@ static int ps3_vuart_set_interrupt_mask(struct ps3_vuart_port_device *dev,
259 return result; 279 return result;
260} 280}
261 281
262static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev, 282static int ps3_vuart_get_interrupt_status(struct ps3_system_bus_device *dev,
263 unsigned long *status) 283 unsigned long *status)
264{ 284{
285 int result;
286 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
265 u64 tmp; 287 u64 tmp;
266 int result = lv1_get_virtual_uart_param(dev->priv->port_number, 288
289 result = lv1_get_virtual_uart_param(dev->port_number,
267 PARAM_INTERRUPT_STATUS, &tmp); 290 PARAM_INTERRUPT_STATUS, &tmp);
268 291
269 if (result) 292 if (result)
270 dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n", 293 dev_dbg(&dev->core, "%s:%d: interrupt_status failed: %s\n",
271 __func__, __LINE__, ps3_result(result)); 294 __func__, __LINE__, ps3_result(result));
272 295
273 *status = tmp & dev->priv->interrupt_mask; 296 *status = tmp & priv->interrupt_mask;
274 297
275 dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n", 298 dev_dbg(&dev->core, "%s:%d: m %lxh, s %lxh, m&s %lxh\n",
276 __func__, __LINE__, dev->priv->interrupt_mask, tmp, *status); 299 __func__, __LINE__, priv->interrupt_mask, tmp, *status);
277 300
278 return result; 301 return result;
279} 302}
280 303
281int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev) 304int ps3_vuart_enable_interrupt_tx(struct ps3_system_bus_device *dev)
282{ 305{
283 return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0 306 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
284 : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 307
308 return (priv->interrupt_mask & INTERRUPT_MASK_TX) ? 0
309 : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
285 | INTERRUPT_MASK_TX); 310 | INTERRUPT_MASK_TX);
286} 311}
287 312
288int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev) 313int ps3_vuart_enable_interrupt_rx(struct ps3_system_bus_device *dev)
289{ 314{
290 return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0 315 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
291 : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 316
317 return (priv->interrupt_mask & INTERRUPT_MASK_RX) ? 0
318 : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
292 | INTERRUPT_MASK_RX); 319 | INTERRUPT_MASK_RX);
293} 320}
294 321
295int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev) 322int ps3_vuart_enable_interrupt_disconnect(struct ps3_system_bus_device *dev)
296{ 323{
297 return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0 324 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
298 : ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 325
326 return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) ? 0
327 : ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
299 | INTERRUPT_MASK_DISCONNECT); 328 | INTERRUPT_MASK_DISCONNECT);
300} 329}
301 330
302int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev) 331int ps3_vuart_disable_interrupt_tx(struct ps3_system_bus_device *dev)
303{ 332{
304 return (dev->priv->interrupt_mask & INTERRUPT_MASK_TX) 333 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
305 ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 334
335 return (priv->interrupt_mask & INTERRUPT_MASK_TX)
336 ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
306 & ~INTERRUPT_MASK_TX) : 0; 337 & ~INTERRUPT_MASK_TX) : 0;
307} 338}
308 339
309int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev) 340int ps3_vuart_disable_interrupt_rx(struct ps3_system_bus_device *dev)
310{ 341{
311 return (dev->priv->interrupt_mask & INTERRUPT_MASK_RX) 342 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
312 ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 343
344 return (priv->interrupt_mask & INTERRUPT_MASK_RX)
345 ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
313 & ~INTERRUPT_MASK_RX) : 0; 346 & ~INTERRUPT_MASK_RX) : 0;
314} 347}
315 348
316int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev) 349int ps3_vuart_disable_interrupt_disconnect(struct ps3_system_bus_device *dev)
317{ 350{
318 return (dev->priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT) 351 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
319 ? ps3_vuart_set_interrupt_mask(dev, dev->priv->interrupt_mask 352
353 return (priv->interrupt_mask & INTERRUPT_MASK_DISCONNECT)
354 ? ps3_vuart_set_interrupt_mask(dev, priv->interrupt_mask
320 & ~INTERRUPT_MASK_DISCONNECT) : 0; 355 & ~INTERRUPT_MASK_DISCONNECT) : 0;
321} 356}
322 357
323/** 358/**
324 * ps3_vuart_raw_write - Low level write helper. 359 * ps3_vuart_raw_write - Low level write helper.
360 * @dev: The struct ps3_system_bus_device instance.
325 * 361 *
326 * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write. 362 * Do not call ps3_vuart_raw_write directly, use ps3_vuart_write.
327 */ 363 */
328 364
329static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev, 365static int ps3_vuart_raw_write(struct ps3_system_bus_device *dev,
330 const void* buf, unsigned int bytes, unsigned long *bytes_written) 366 const void* buf, unsigned int bytes, unsigned long *bytes_written)
331{ 367{
332 int result; 368 int result;
369 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
333 370
334 result = lv1_write_virtual_uart(dev->priv->port_number, 371 result = lv1_write_virtual_uart(dev->port_number,
335 ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written); 372 ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_written);
336 373
337 if (result) { 374 if (result) {
@@ -340,28 +377,30 @@ static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev,
340 return result; 377 return result;
341 } 378 }
342 379
343 dev->priv->stats.bytes_written += *bytes_written; 380 priv->stats.bytes_written += *bytes_written;
344 381
345 dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__, 382 dev_dbg(&dev->core, "%s:%d: wrote %lxh/%xh=>%lxh\n", __func__, __LINE__,
346 *bytes_written, bytes, dev->priv->stats.bytes_written); 383 *bytes_written, bytes, priv->stats.bytes_written);
347 384
348 return result; 385 return result;
349} 386}
350 387
351/** 388/**
352 * ps3_vuart_raw_read - Low level read helper. 389 * ps3_vuart_raw_read - Low level read helper.
390 * @dev: The struct ps3_system_bus_device instance.
353 * 391 *
354 * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read. 392 * Do not call ps3_vuart_raw_read directly, use ps3_vuart_read.
355 */ 393 */
356 394
357static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf, 395static int ps3_vuart_raw_read(struct ps3_system_bus_device *dev, void *buf,
358 unsigned int bytes, unsigned long *bytes_read) 396 unsigned int bytes, unsigned long *bytes_read)
359{ 397{
360 int result; 398 int result;
399 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
361 400
362 dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes); 401 dev_dbg(&dev->core, "%s:%d: %xh\n", __func__, __LINE__, bytes);
363 402
364 result = lv1_read_virtual_uart(dev->priv->port_number, 403 result = lv1_read_virtual_uart(dev->port_number,
365 ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read); 404 ps3_mm_phys_to_lpar(__pa(buf)), bytes, bytes_read);
366 405
367 if (result) { 406 if (result) {
@@ -370,25 +409,27 @@ static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf,
370 return result; 409 return result;
371 } 410 }
372 411
373 dev->priv->stats.bytes_read += *bytes_read; 412 priv->stats.bytes_read += *bytes_read;
374 413
375 dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__, 414 dev_dbg(&dev->core, "%s:%d: read %lxh/%xh=>%lxh\n", __func__, __LINE__,
376 *bytes_read, bytes, dev->priv->stats.bytes_read); 415 *bytes_read, bytes, priv->stats.bytes_read);
377 416
378 return result; 417 return result;
379} 418}
380 419
381/** 420/**
382 * ps3_vuart_clear_rx_bytes - Discard bytes received. 421 * ps3_vuart_clear_rx_bytes - Discard bytes received.
422 * @dev: The struct ps3_system_bus_device instance.
383 * @bytes: Max byte count to discard, zero = all pending. 423 * @bytes: Max byte count to discard, zero = all pending.
384 * 424 *
385 * Used to clear pending rx interrupt source. Will not block. 425 * Used to clear pending rx interrupt source. Will not block.
386 */ 426 */
387 427
388void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, 428void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
389 unsigned int bytes) 429 unsigned int bytes)
390{ 430{
391 int result; 431 int result;
432 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
392 u64 bytes_waiting; 433 u64 bytes_waiting;
393 void* tmp; 434 void* tmp;
394 435
@@ -418,8 +459,9 @@ void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev,
418 459
419 /* Don't include these bytes in the stats. */ 460 /* Don't include these bytes in the stats. */
420 461
421 dev->priv->stats.bytes_read -= bytes_waiting; 462 priv->stats.bytes_read -= bytes_waiting;
422} 463}
464EXPORT_SYMBOL_GPL(ps3_vuart_clear_rx_bytes);
423 465
424/** 466/**
425 * struct list_buffer - An element for a port device fifo buffer list. 467 * struct list_buffer - An element for a port device fifo buffer list.
@@ -435,6 +477,7 @@ struct list_buffer {
435 477
436/** 478/**
437 * ps3_vuart_write - the entry point for writing data to a port 479 * ps3_vuart_write - the entry point for writing data to a port
480 * @dev: The struct ps3_system_bus_device instance.
438 * 481 *
439 * If the port is idle on entry as much of the incoming data is written to 482 * If the port is idle on entry as much of the incoming data is written to
440 * the port as the port will accept. Otherwise a list buffer is created 483 * the port as the port will accept. Otherwise a list buffer is created
@@ -442,25 +485,26 @@ struct list_buffer {
442 * then enqueued for transmision via the transmit interrupt. 485 * then enqueued for transmision via the transmit interrupt.
443 */ 486 */
444 487
445int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, 488int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
446 unsigned int bytes) 489 unsigned int bytes)
447{ 490{
448 static unsigned long dbg_number; 491 static unsigned long dbg_number;
449 int result; 492 int result;
493 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
450 unsigned long flags; 494 unsigned long flags;
451 struct list_buffer *lb; 495 struct list_buffer *lb;
452 496
453 dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, 497 dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
454 bytes, bytes); 498 bytes, bytes);
455 499
456 spin_lock_irqsave(&dev->priv->tx_list.lock, flags); 500 spin_lock_irqsave(&priv->tx_list.lock, flags);
457 501
458 if (list_empty(&dev->priv->tx_list.head)) { 502 if (list_empty(&priv->tx_list.head)) {
459 unsigned long bytes_written; 503 unsigned long bytes_written;
460 504
461 result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written); 505 result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);
462 506
463 spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); 507 spin_unlock_irqrestore(&priv->tx_list.lock, flags);
464 508
465 if (result) { 509 if (result) {
466 dev_dbg(&dev->core, 510 dev_dbg(&dev->core,
@@ -478,7 +522,7 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
478 bytes -= bytes_written; 522 bytes -= bytes_written;
479 buf += bytes_written; 523 buf += bytes_written;
480 } else 524 } else
481 spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); 525 spin_unlock_irqrestore(&priv->tx_list.lock, flags);
482 526
483 lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL); 527 lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);
484 528
@@ -491,29 +535,86 @@ int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf,
491 lb->tail = lb->data + bytes; 535 lb->tail = lb->data + bytes;
492 lb->dbg_number = ++dbg_number; 536 lb->dbg_number = ++dbg_number;
493 537
494 spin_lock_irqsave(&dev->priv->tx_list.lock, flags); 538 spin_lock_irqsave(&priv->tx_list.lock, flags);
495 list_add_tail(&lb->link, &dev->priv->tx_list.head); 539 list_add_tail(&lb->link, &priv->tx_list.head);
496 ps3_vuart_enable_interrupt_tx(dev); 540 ps3_vuart_enable_interrupt_tx(dev);
497 spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); 541 spin_unlock_irqrestore(&priv->tx_list.lock, flags);
498 542
499 dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n", 543 dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
500 __func__, __LINE__, lb->dbg_number, bytes); 544 __func__, __LINE__, lb->dbg_number, bytes);
501 545
502 return 0; 546 return 0;
503} 547}
548EXPORT_SYMBOL_GPL(ps3_vuart_write);
549
550/**
551 * ps3_vuart_queue_rx_bytes - Queue waiting bytes into the buffer list.
552 * @dev: The struct ps3_system_bus_device instance.
553 * @bytes_queued: Number of bytes queued to the buffer list.
554 *
555 * Must be called with priv->rx_list.lock held.
556 */
557
558static int ps3_vuart_queue_rx_bytes(struct ps3_system_bus_device *dev,
559 u64 *bytes_queued)
560{
561 static unsigned long dbg_number;
562 int result;
563 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
564 struct list_buffer *lb;
565 u64 bytes;
566
567 *bytes_queued = 0;
568
569 result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes);
570 BUG_ON(result);
571
572 if (result)
573 return -EIO;
574
575 if (!bytes)
576 return 0;
577
578 /* Add some extra space for recently arrived data. */
579
580 bytes += 128;
581
582 lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
583
584 if (!lb)
585 return -ENOMEM;
586
587 ps3_vuart_raw_read(dev, lb->data, bytes, &bytes);
588
589 lb->head = lb->data;
590 lb->tail = lb->data + bytes;
591 lb->dbg_number = ++dbg_number;
592
593 list_add_tail(&lb->link, &priv->rx_list.head);
594 priv->rx_list.bytes_held += bytes;
595
596 dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
597 __func__, __LINE__, lb->dbg_number, bytes);
598
599 *bytes_queued = bytes;
600
601 return 0;
602}
504 603
505/** 604/**
506 * ps3_vuart_read - the entry point for reading data from a port 605 * ps3_vuart_read - The entry point for reading data from a port.
507 * 606 *
508 * If enough bytes to satisfy the request are held in the buffer list those 607 * Queue data waiting at the port, and if enough bytes to satisfy the request
509 * bytes are dequeued and copied to the caller's buffer. Emptied list buffers 608 * are held in the buffer list those bytes are dequeued and copied to the
510 * are retiered. If the request cannot be statified by bytes held in the list 609 * caller's buffer. Emptied list buffers are retiered. If the request cannot
511 * buffers -EAGAIN is returned. 610 * be statified by bytes held in the list buffers -EAGAIN is returned.
512 */ 611 */
513 612
514int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, 613int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
515 unsigned int bytes) 614 unsigned int bytes)
516{ 615{
616 int result;
617 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
517 unsigned long flags; 618 unsigned long flags;
518 struct list_buffer *lb, *n; 619 struct list_buffer *lb, *n;
519 unsigned long bytes_read; 620 unsigned long bytes_read;
@@ -521,30 +622,37 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
521 dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__, 622 dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
522 bytes, bytes); 623 bytes, bytes);
523 624
524 spin_lock_irqsave(&dev->priv->rx_list.lock, flags); 625 spin_lock_irqsave(&priv->rx_list.lock, flags);
525 626
526 if (dev->priv->rx_list.bytes_held < bytes) { 627 /* Queue rx bytes here for polled reads. */
527 spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); 628
528 dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n", 629 while (priv->rx_list.bytes_held < bytes) {
529 __func__, __LINE__, 630 u64 tmp;
530 bytes - dev->priv->rx_list.bytes_held); 631
531 return -EAGAIN; 632 result = ps3_vuart_queue_rx_bytes(dev, &tmp);
633 if (result || !tmp) {
634 dev_dbg(&dev->core, "%s:%d: starved for %lxh bytes\n",
635 __func__, __LINE__,
636 bytes - priv->rx_list.bytes_held);
637 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
638 return -EAGAIN;
639 }
532 } 640 }
533 641
534 list_for_each_entry_safe(lb, n, &dev->priv->rx_list.head, link) { 642 list_for_each_entry_safe(lb, n, &priv->rx_list.head, link) {
535 bytes_read = min((unsigned int)(lb->tail - lb->head), bytes); 643 bytes_read = min((unsigned int)(lb->tail - lb->head), bytes);
536 644
537 memcpy(buf, lb->head, bytes_read); 645 memcpy(buf, lb->head, bytes_read);
538 buf += bytes_read; 646 buf += bytes_read;
539 bytes -= bytes_read; 647 bytes -= bytes_read;
540 dev->priv->rx_list.bytes_held -= bytes_read; 648 priv->rx_list.bytes_held -= bytes_read;
541 649
542 if (bytes_read < lb->tail - lb->head) { 650 if (bytes_read < lb->tail - lb->head) {
543 lb->head += bytes_read; 651 lb->head += bytes_read;
544 dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh " 652 dev_dbg(&dev->core, "%s:%d: buf_%lu: dequeued %lxh "
545 "bytes\n", __func__, __LINE__, lb->dbg_number, 653 "bytes\n", __func__, __LINE__, lb->dbg_number,
546 bytes_read); 654 bytes_read);
547 spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); 655 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
548 return 0; 656 return 0;
549 } 657 }
550 658
@@ -556,16 +664,32 @@ int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
556 kfree(lb); 664 kfree(lb);
557 } 665 }
558 666
559 spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags); 667 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
560 return 0; 668 return 0;
561} 669}
670EXPORT_SYMBOL_GPL(ps3_vuart_read);
562 671
563int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func, 672/**
564 unsigned int bytes) 673 * ps3_vuart_work - Asynchronous read handler.
674 */
675
676static void ps3_vuart_work(struct work_struct *work)
677{
678 struct ps3_system_bus_device *dev =
679 ps3_vuart_work_to_system_bus_dev(work);
680 struct ps3_vuart_port_driver *drv =
681 ps3_system_bus_dev_to_vuart_drv(dev);
682
683 BUG_ON(!drv);
684 drv->work(dev);
685}
686
687int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes)
565{ 688{
689 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
566 unsigned long flags; 690 unsigned long flags;
567 691
568 if(dev->priv->work.trigger) { 692 if (priv->rx_list.work.trigger) {
569 dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n", 693 dev_dbg(&dev->core, "%s:%d: warning, multiple calls\n",
570 __func__, __LINE__); 694 __func__, __LINE__);
571 return -EAGAIN; 695 return -EAGAIN;
@@ -573,30 +697,32 @@ int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func,
573 697
574 BUG_ON(!bytes); 698 BUG_ON(!bytes);
575 699
576 PREPARE_WORK(&dev->priv->work.work, func); 700 PREPARE_WORK(&priv->rx_list.work.work, ps3_vuart_work);
577 701
578 spin_lock_irqsave(&dev->priv->work.lock, flags); 702 spin_lock_irqsave(&priv->rx_list.lock, flags);
579 if(dev->priv->rx_list.bytes_held >= bytes) { 703 if (priv->rx_list.bytes_held >= bytes) {
580 dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n", 704 dev_dbg(&dev->core, "%s:%d: schedule_work %xh bytes\n",
581 __func__, __LINE__, bytes); 705 __func__, __LINE__, bytes);
582 schedule_work(&dev->priv->work.work); 706 schedule_work(&priv->rx_list.work.work);
583 spin_unlock_irqrestore(&dev->priv->work.lock, flags); 707 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
584 return 0; 708 return 0;
585 } 709 }
586 710
587 dev->priv->work.trigger = bytes; 711 priv->rx_list.work.trigger = bytes;
588 spin_unlock_irqrestore(&dev->priv->work.lock, flags); 712 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
589 713
590 dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__, 714 dev_dbg(&dev->core, "%s:%d: waiting for %u(%xh) bytes\n", __func__,
591 __LINE__, bytes, bytes); 715 __LINE__, bytes, bytes);
592 716
593 return 0; 717 return 0;
594} 718}
719EXPORT_SYMBOL_GPL(ps3_vuart_read_async);
595 720
596void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev) 721void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev)
597{ 722{
598 dev->priv->work.trigger = 0; 723 to_port_priv(dev)->rx_list.work.trigger = 0;
599} 724}
725EXPORT_SYMBOL_GPL(ps3_vuart_cancel_async);
600 726
601/** 727/**
602 * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler 728 * ps3_vuart_handle_interrupt_tx - third stage transmit interrupt handler
@@ -606,18 +732,19 @@ void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev)
606 * adjusts the final list buffer state for a partial write. 732 * adjusts the final list buffer state for a partial write.
607 */ 733 */
608 734
609static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev) 735static int ps3_vuart_handle_interrupt_tx(struct ps3_system_bus_device *dev)
610{ 736{
611 int result = 0; 737 int result = 0;
738 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
612 unsigned long flags; 739 unsigned long flags;
613 struct list_buffer *lb, *n; 740 struct list_buffer *lb, *n;
614 unsigned long bytes_total = 0; 741 unsigned long bytes_total = 0;
615 742
616 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 743 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
617 744
618 spin_lock_irqsave(&dev->priv->tx_list.lock, flags); 745 spin_lock_irqsave(&priv->tx_list.lock, flags);
619 746
620 list_for_each_entry_safe(lb, n, &dev->priv->tx_list.head, link) { 747 list_for_each_entry_safe(lb, n, &priv->tx_list.head, link) {
621 748
622 unsigned long bytes_written; 749 unsigned long bytes_written;
623 750
@@ -651,7 +778,7 @@ static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev)
651 778
652 ps3_vuart_disable_interrupt_tx(dev); 779 ps3_vuart_disable_interrupt_tx(dev);
653port_full: 780port_full:
654 spin_unlock_irqrestore(&dev->priv->tx_list.lock, flags); 781 spin_unlock_irqrestore(&priv->tx_list.lock, flags);
655 dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n", 782 dev_dbg(&dev->core, "%s:%d wrote %lxh bytes total\n",
656 __func__, __LINE__, bytes_total); 783 __func__, __LINE__, bytes_total);
657 return result; 784 return result;
@@ -665,60 +792,37 @@ port_full:
665 * buffer list. Buffer list data is dequeued via ps3_vuart_read. 792 * buffer list. Buffer list data is dequeued via ps3_vuart_read.
666 */ 793 */
667 794
668static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev) 795static int ps3_vuart_handle_interrupt_rx(struct ps3_system_bus_device *dev)
669{ 796{
670 static unsigned long dbg_number; 797 int result;
671 int result = 0; 798 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
672 unsigned long flags; 799 unsigned long flags;
673 struct list_buffer *lb; 800 u64 bytes;
674 unsigned long bytes;
675 801
676 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 802 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
677 803
678 result = ps3_vuart_get_rx_bytes_waiting(dev, &bytes); 804 spin_lock_irqsave(&priv->rx_list.lock, flags);
679 805 result = ps3_vuart_queue_rx_bytes(dev, &bytes);
680 if (result)
681 return -EIO;
682
683 BUG_ON(!bytes);
684
685 /* Add some extra space for recently arrived data. */
686
687 bytes += 128;
688
689 lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_ATOMIC);
690 806
691 if (!lb) 807 if (result) {
692 return -ENOMEM; 808 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
693 809 return result;
694 ps3_vuart_raw_read(dev, lb->data, bytes, &bytes); 810 }
695
696 lb->head = lb->data;
697 lb->tail = lb->data + bytes;
698 lb->dbg_number = ++dbg_number;
699
700 spin_lock_irqsave(&dev->priv->rx_list.lock, flags);
701 list_add_tail(&lb->link, &dev->priv->rx_list.head);
702 dev->priv->rx_list.bytes_held += bytes;
703 spin_unlock_irqrestore(&dev->priv->rx_list.lock, flags);
704
705 dev_dbg(&dev->core, "%s:%d: buf_%lu: queued %lxh bytes\n",
706 __func__, __LINE__, lb->dbg_number, bytes);
707 811
708 spin_lock_irqsave(&dev->priv->work.lock, flags); 812 if (priv->rx_list.work.trigger && priv->rx_list.bytes_held
709 if(dev->priv->work.trigger 813 >= priv->rx_list.work.trigger) {
710 && dev->priv->rx_list.bytes_held >= dev->priv->work.trigger) {
711 dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n", 814 dev_dbg(&dev->core, "%s:%d: schedule_work %lxh bytes\n",
712 __func__, __LINE__, dev->priv->work.trigger); 815 __func__, __LINE__, priv->rx_list.work.trigger);
713 dev->priv->work.trigger = 0; 816 priv->rx_list.work.trigger = 0;
714 schedule_work(&dev->priv->work.work); 817 schedule_work(&priv->rx_list.work.work);
715 } 818 }
716 spin_unlock_irqrestore(&dev->priv->work.lock, flags); 819
717 return 0; 820 spin_unlock_irqrestore(&priv->rx_list.lock, flags);
821 return result;
718} 822}
719 823
720static int ps3_vuart_handle_interrupt_disconnect( 824static int ps3_vuart_handle_interrupt_disconnect(
721 struct ps3_vuart_port_device *dev) 825 struct ps3_system_bus_device *dev)
722{ 826{
723 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 827 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
724 BUG_ON("no support"); 828 BUG_ON("no support");
@@ -733,9 +837,10 @@ static int ps3_vuart_handle_interrupt_disconnect(
733 * stage handler after one iteration. 837 * stage handler after one iteration.
734 */ 838 */
735 839
736static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) 840static int ps3_vuart_handle_port_interrupt(struct ps3_system_bus_device *dev)
737{ 841{
738 int result; 842 int result;
843 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
739 unsigned long status; 844 unsigned long status;
740 845
741 result = ps3_vuart_get_interrupt_status(dev, &status); 846 result = ps3_vuart_get_interrupt_status(dev, &status);
@@ -747,21 +852,21 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
747 status); 852 status);
748 853
749 if (status & INTERRUPT_MASK_DISCONNECT) { 854 if (status & INTERRUPT_MASK_DISCONNECT) {
750 dev->priv->stats.disconnect_interrupts++; 855 priv->stats.disconnect_interrupts++;
751 result = ps3_vuart_handle_interrupt_disconnect(dev); 856 result = ps3_vuart_handle_interrupt_disconnect(dev);
752 if (result) 857 if (result)
753 ps3_vuart_disable_interrupt_disconnect(dev); 858 ps3_vuart_disable_interrupt_disconnect(dev);
754 } 859 }
755 860
756 if (status & INTERRUPT_MASK_TX) { 861 if (status & INTERRUPT_MASK_TX) {
757 dev->priv->stats.tx_interrupts++; 862 priv->stats.tx_interrupts++;
758 result = ps3_vuart_handle_interrupt_tx(dev); 863 result = ps3_vuart_handle_interrupt_tx(dev);
759 if (result) 864 if (result)
760 ps3_vuart_disable_interrupt_tx(dev); 865 ps3_vuart_disable_interrupt_tx(dev);
761 } 866 }
762 867
763 if (status & INTERRUPT_MASK_RX) { 868 if (status & INTERRUPT_MASK_RX) {
764 dev->priv->stats.rx_interrupts++; 869 priv->stats.rx_interrupts++;
765 result = ps3_vuart_handle_interrupt_rx(dev); 870 result = ps3_vuart_handle_interrupt_rx(dev);
766 if (result) 871 if (result)
767 ps3_vuart_disable_interrupt_rx(dev); 872 ps3_vuart_disable_interrupt_rx(dev);
@@ -771,11 +876,11 @@ static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev)
771} 876}
772 877
773struct vuart_bus_priv { 878struct vuart_bus_priv {
774 const struct ports_bmp bmp; 879 struct ports_bmp *bmp;
775 unsigned int virq; 880 unsigned int virq;
776 struct semaphore probe_mutex; 881 struct semaphore probe_mutex;
777 int use_count; 882 int use_count;
778 struct ps3_vuart_port_device *devices[PORT_COUNT]; 883 struct ps3_system_bus_device *devices[PORT_COUNT];
779} static vuart_bus_priv; 884} static vuart_bus_priv;
780 885
781/** 886/**
@@ -788,17 +893,16 @@ struct vuart_bus_priv {
788 893
789static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) 894static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
790{ 895{
791 struct vuart_bus_priv *bus_priv; 896 struct vuart_bus_priv *bus_priv = _private;
792 897
793 BUG_ON(!_private); 898 BUG_ON(!bus_priv);
794 bus_priv = (struct vuart_bus_priv *)_private;
795 899
796 while (1) { 900 while (1) {
797 unsigned int port; 901 unsigned int port;
798 902
799 dump_ports_bmp(&bus_priv->bmp); 903 dump_ports_bmp(bus_priv->bmp);
800 904
801 port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp.status); 905 port = (BITS_PER_LONG - 1) - __ilog2(bus_priv->bmp->status);
802 906
803 if (port == BITS_PER_LONG) 907 if (port == BITS_PER_LONG)
804 break; 908 break;
@@ -812,100 +916,144 @@ static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private)
812 return IRQ_HANDLED; 916 return IRQ_HANDLED;
813} 917}
814 918
815static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv) 919static int ps3_vuart_bus_interrupt_get(void)
816{ 920{
817 int result; 921 int result;
818 struct ps3_vuart_port_driver *drv = to_ps3_vuart_port_driver(_drv);
819 struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
820 922
821 result = dev->match_id == drv->match_id; 923 pr_debug(" -> %s:%d\n", __func__, __LINE__);
924
925 vuart_bus_priv.use_count++;
926
927 BUG_ON(vuart_bus_priv.use_count > 2);
928
929 if (vuart_bus_priv.use_count != 1) {
930 return 0;
931 }
932
933 BUG_ON(vuart_bus_priv.bmp);
934
935 vuart_bus_priv.bmp = kzalloc(sizeof(struct ports_bmp), GFP_KERNEL);
936
937 if (!vuart_bus_priv.bmp) {
938 pr_debug("%s:%d: kzalloc failed.\n", __func__, __LINE__);
939 result = -ENOMEM;
940 goto fail_bmp_malloc;
941 }
942
943 result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, vuart_bus_priv.bmp,
944 &vuart_bus_priv.virq);
945
946 if (result) {
947 pr_debug("%s:%d: ps3_vuart_irq_setup failed (%d)\n",
948 __func__, __LINE__, result);
949 result = -EPERM;
950 goto fail_alloc_irq;
951 }
952
953 result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
954 IRQF_DISABLED, "vuart", &vuart_bus_priv);
822 955
823 dev_info(&dev->core, "%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, 956 if (result) {
824 __LINE__, dev->match_id, dev->core.bus_id, drv->match_id, 957 pr_debug("%s:%d: request_irq failed (%d)\n",
825 drv->core.name, (result ? "match" : "miss")); 958 __func__, __LINE__, result);
959 goto fail_request_irq;
960 }
826 961
962 pr_debug(" <- %s:%d: ok\n", __func__, __LINE__);
827 return result; 963 return result;
964
965fail_request_irq:
966 ps3_vuart_irq_destroy(vuart_bus_priv.virq);
967 vuart_bus_priv.virq = NO_IRQ;
968fail_alloc_irq:
969 kfree(vuart_bus_priv.bmp);
970 vuart_bus_priv.bmp = NULL;
971fail_bmp_malloc:
972 vuart_bus_priv.use_count--;
973 pr_debug(" <- %s:%d: failed\n", __func__, __LINE__);
974 return result;
975}
976
977static int ps3_vuart_bus_interrupt_put(void)
978{
979 pr_debug(" -> %s:%d\n", __func__, __LINE__);
980
981 vuart_bus_priv.use_count--;
982
983 BUG_ON(vuart_bus_priv.use_count < 0);
984
985 if (vuart_bus_priv.use_count != 0)
986 return 0;
987
988 free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
989
990 ps3_vuart_irq_destroy(vuart_bus_priv.virq);
991 vuart_bus_priv.virq = NO_IRQ;
992
993 kfree(vuart_bus_priv.bmp);
994 vuart_bus_priv.bmp = NULL;
995
996 pr_debug(" <- %s:%d\n", __func__, __LINE__);
997 return 0;
828} 998}
829 999
830static int ps3_vuart_probe(struct device *_dev) 1000static int ps3_vuart_probe(struct ps3_system_bus_device *dev)
831{ 1001{
832 int result; 1002 int result;
833 unsigned int port_number; 1003 struct ps3_vuart_port_driver *drv;
834 struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); 1004 struct ps3_vuart_port_priv *priv = NULL;
835 struct ps3_vuart_port_driver *drv =
836 to_ps3_vuart_port_driver(_dev->driver);
837 1005
838 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 1006 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
839 1007
1008 drv = ps3_system_bus_dev_to_vuart_drv(dev);
1009
1010 dev_dbg(&dev->core, "%s:%d: (%s)\n", __func__, __LINE__,
1011 drv->core.core.name);
1012
840 BUG_ON(!drv); 1013 BUG_ON(!drv);
841 1014
842 down(&vuart_bus_priv.probe_mutex); 1015 if (dev->port_number >= PORT_COUNT) {
1016 BUG();
1017 return -EINVAL;
1018 }
843 1019
844 /* Setup vuart_bus_priv.devices[]. */ 1020 down(&vuart_bus_priv.probe_mutex);
845 1021
846 result = ps3_vuart_match_id_to_port(dev->match_id, 1022 result = ps3_vuart_bus_interrupt_get();
847 &port_number);
848 1023
849 if (result) { 1024 if (result)
850 dev_dbg(&dev->core, "%s:%d: unknown match_id (%d)\n", 1025 goto fail_setup_interrupt;
851 __func__, __LINE__, dev->match_id);
852 result = -EINVAL;
853 goto fail_match;
854 }
855 1026
856 if (vuart_bus_priv.devices[port_number]) { 1027 if (vuart_bus_priv.devices[dev->port_number]) {
857 dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__, 1028 dev_dbg(&dev->core, "%s:%d: port busy (%d)\n", __func__,
858 __LINE__, port_number); 1029 __LINE__, dev->port_number);
859 result = -EBUSY; 1030 result = -EBUSY;
860 goto fail_match; 1031 goto fail_busy;
861 } 1032 }
862 1033
863 vuart_bus_priv.devices[port_number] = dev; 1034 vuart_bus_priv.devices[dev->port_number] = dev;
864 1035
865 /* Setup dev->priv. */ 1036 /* Setup dev->driver_priv. */
866 1037
867 dev->priv = kzalloc(sizeof(struct ps3_vuart_port_priv), GFP_KERNEL); 1038 dev->driver_priv = kzalloc(sizeof(struct ps3_vuart_port_priv),
1039 GFP_KERNEL);
868 1040
869 if (!dev->priv) { 1041 if (!dev->driver_priv) {
870 result = -ENOMEM; 1042 result = -ENOMEM;
871 goto fail_alloc; 1043 goto fail_dev_malloc;
872 } 1044 }
873 1045
874 dev->priv->port_number = port_number; 1046 priv = to_port_priv(dev);
875
876 INIT_LIST_HEAD(&dev->priv->tx_list.head);
877 spin_lock_init(&dev->priv->tx_list.lock);
878 1047
879 INIT_LIST_HEAD(&dev->priv->rx_list.head); 1048 INIT_LIST_HEAD(&priv->tx_list.head);
880 spin_lock_init(&dev->priv->rx_list.lock); 1049 spin_lock_init(&priv->tx_list.lock);
881 1050
882 INIT_WORK(&dev->priv->work.work, NULL); 1051 INIT_LIST_HEAD(&priv->rx_list.head);
883 spin_lock_init(&dev->priv->work.lock); 1052 spin_lock_init(&priv->rx_list.lock);
884 dev->priv->work.trigger = 0;
885 dev->priv->work.dev = dev;
886 1053
887 if (++vuart_bus_priv.use_count == 1) { 1054 INIT_WORK(&priv->rx_list.work.work, NULL);
888 1055 priv->rx_list.work.trigger = 0;
889 result = ps3_vuart_irq_setup(PS3_BINDING_CPU_ANY, 1056 priv->rx_list.work.dev = dev;
890 (void*)&vuart_bus_priv.bmp.status, &vuart_bus_priv.virq);
891
892 if (result) {
893 dev_dbg(&dev->core,
894 "%s:%d: ps3_vuart_irq_setup failed (%d)\n",
895 __func__, __LINE__, result);
896 result = -EPERM;
897 goto fail_alloc_irq;
898 }
899
900 result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
901 IRQF_DISABLED, "vuart", &vuart_bus_priv);
902
903 if (result) {
904 dev_info(&dev->core, "%s:%d: request_irq failed (%d)\n",
905 __func__, __LINE__, result);
906 goto fail_request_irq;
907 }
908 }
909 1057
910 /* clear stale pending interrupts */ 1058 /* clear stale pending interrupts */
911 1059
@@ -936,150 +1084,158 @@ static int ps3_vuart_probe(struct device *_dev)
936 1084
937fail_probe: 1085fail_probe:
938 ps3_vuart_set_interrupt_mask(dev, 0); 1086 ps3_vuart_set_interrupt_mask(dev, 0);
939fail_request_irq: 1087 kfree(dev->driver_priv);
940 ps3_vuart_irq_destroy(vuart_bus_priv.virq); 1088 dev->driver_priv = NULL;
941 vuart_bus_priv.virq = NO_IRQ; 1089fail_dev_malloc:
942fail_alloc_irq: 1090 vuart_bus_priv.devices[dev->port_number] = NULL;
943 --vuart_bus_priv.use_count; 1091fail_busy:
944 kfree(dev->priv); 1092 ps3_vuart_bus_interrupt_put();
945 dev->priv = NULL; 1093fail_setup_interrupt:
946fail_alloc:
947 vuart_bus_priv.devices[port_number] = NULL;
948fail_match:
949 up(&vuart_bus_priv.probe_mutex); 1094 up(&vuart_bus_priv.probe_mutex);
950 dev_dbg(&dev->core, "%s:%d failed\n", __func__, __LINE__); 1095 dev_dbg(&dev->core, "%s:%d: failed\n", __func__, __LINE__);
951 return result; 1096 return result;
952} 1097}
953 1098
954static int ps3_vuart_remove(struct device *_dev) 1099/**
1100 * ps3_vuart_cleanup - common cleanup helper.
1101 * @dev: The struct ps3_system_bus_device instance.
1102 *
1103 * Cleans interrupts and HV resources. Must be called with
1104 * vuart_bus_priv.probe_mutex held. Used by ps3_vuart_remove and
1105 * ps3_vuart_shutdown. After this call, polled reading will still work.
1106 */
1107
1108static int ps3_vuart_cleanup(struct ps3_system_bus_device *dev)
955{ 1109{
956 struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev); 1110 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__);
957 struct ps3_vuart_port_driver *drv = 1111
958 to_ps3_vuart_port_driver(_dev->driver); 1112 ps3_vuart_cancel_async(dev);
1113 ps3_vuart_set_interrupt_mask(dev, 0);
1114 ps3_vuart_bus_interrupt_put();
1115 return 0;
1116}
1117
1118/**
1119 * ps3_vuart_remove - Completely clean the device instance.
1120 * @dev: The struct ps3_system_bus_device instance.
1121 *
1122 * Cleans all memory, interrupts and HV resources. After this call the
1123 * device can no longer be used.
1124 */
1125
1126static int ps3_vuart_remove(struct ps3_system_bus_device *dev)
1127{
1128 struct ps3_vuart_port_priv *priv = to_port_priv(dev);
1129 struct ps3_vuart_port_driver *drv;
1130
1131 BUG_ON(!dev);
959 1132
960 down(&vuart_bus_priv.probe_mutex); 1133 down(&vuart_bus_priv.probe_mutex);
961 1134
962 dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__, 1135 dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
963 dev->core.bus_id); 1136 dev->match_id);
964 1137
965 BUG_ON(vuart_bus_priv.use_count < 1); 1138 if (!dev->core.driver) {
1139 dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
1140 __LINE__);
1141 up(&vuart_bus_priv.probe_mutex);
1142 return 0;
1143 }
966 1144
967 if (drv->remove) 1145 drv = ps3_system_bus_dev_to_vuart_drv(dev);
968 drv->remove(dev);
969 else
970 dev_dbg(&dev->core, "%s:%d: %s no remove method\n", __func__,
971 __LINE__, dev->core.bus_id);
972 1146
973 vuart_bus_priv.devices[dev->priv->port_number] = NULL; 1147 BUG_ON(!drv);
974 1148
975 if (--vuart_bus_priv.use_count == 0) { 1149 if (drv->remove) {
1150 drv->remove(dev);
1151 } else {
1152 dev_dbg(&dev->core, "%s:%d: no remove method\n", __func__,
1153 __LINE__);
976 BUG(); 1154 BUG();
977 free_irq(vuart_bus_priv.virq, &vuart_bus_priv);
978 ps3_vuart_irq_destroy(vuart_bus_priv.virq);
979 vuart_bus_priv.virq = NO_IRQ;
980 } 1155 }
981 1156
982 kfree(dev->priv); 1157 ps3_vuart_cleanup(dev);
983 dev->priv = NULL; 1158
1159 vuart_bus_priv.devices[dev->port_number] = NULL;
1160 kfree(priv);
1161 priv = NULL;
984 1162
1163 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
985 up(&vuart_bus_priv.probe_mutex); 1164 up(&vuart_bus_priv.probe_mutex);
986 return 0; 1165 return 0;
987} 1166}
988 1167
989static void ps3_vuart_shutdown(struct device *_dev)
990{
991 struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
992 struct ps3_vuart_port_driver *drv =
993 to_ps3_vuart_port_driver(_dev->driver);
994
995 dev_dbg(&dev->core, "%s:%d: %s\n", __func__, __LINE__,
996 dev->core.bus_id);
997
998 if (drv->shutdown)
999 drv->shutdown(dev);
1000 else
1001 dev_dbg(&dev->core, "%s:%d: %s no shutdown method\n", __func__,
1002 __LINE__, dev->core.bus_id);
1003}
1004
1005/** 1168/**
1006 * ps3_vuart_bus - The vuart bus instance. 1169 * ps3_vuart_shutdown - Cleans interrupts and HV resources.
1170 * @dev: The struct ps3_system_bus_device instance.
1007 * 1171 *
1008 * The vuart is managed as a bus that port devices connect to. 1172 * Cleans interrupts and HV resources. After this call the
1173 * device can still be used in polling mode. This behavior required
1174 * by sys-manager to be able to complete the device power operation
1175 * sequence.
1009 */ 1176 */
1010 1177
1011struct bus_type ps3_vuart_bus = { 1178static int ps3_vuart_shutdown(struct ps3_system_bus_device *dev)
1012 .name = "ps3_vuart",
1013 .match = ps3_vuart_match,
1014 .probe = ps3_vuart_probe,
1015 .remove = ps3_vuart_remove,
1016 .shutdown = ps3_vuart_shutdown,
1017};
1018
1019int __init ps3_vuart_bus_init(void)
1020{ 1179{
1021 int result; 1180 struct ps3_vuart_port_driver *drv;
1022 1181
1023 pr_debug("%s:%d:\n", __func__, __LINE__); 1182 BUG_ON(!dev);
1024 1183
1025 if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) 1184 down(&vuart_bus_priv.probe_mutex);
1026 return -ENODEV;
1027 1185
1028 init_MUTEX(&vuart_bus_priv.probe_mutex); 1186 dev_dbg(&dev->core, " -> %s:%d: match_id %d\n", __func__, __LINE__,
1029 result = bus_register(&ps3_vuart_bus); 1187 dev->match_id);
1030 BUG_ON(result);
1031 1188
1032 return result; 1189 if (!dev->core.driver) {
1033} 1190 dev_dbg(&dev->core, "%s:%d: no driver bound\n", __func__,
1191 __LINE__);
1192 up(&vuart_bus_priv.probe_mutex);
1193 return 0;
1194 }
1034 1195
1035void __exit ps3_vuart_bus_exit(void) 1196 drv = ps3_system_bus_dev_to_vuart_drv(dev);
1036{
1037 pr_debug("%s:%d:\n", __func__, __LINE__);
1038 bus_unregister(&ps3_vuart_bus);
1039}
1040 1197
1041core_initcall(ps3_vuart_bus_init); 1198 BUG_ON(!drv);
1042module_exit(ps3_vuart_bus_exit);
1043 1199
1044/** 1200 if (drv->shutdown)
1045 * ps3_vuart_port_release_device - Remove a vuart port device. 1201 drv->shutdown(dev);
1046 */ 1202 else if (drv->remove) {
1203 dev_dbg(&dev->core, "%s:%d: no shutdown, calling remove\n",
1204 __func__, __LINE__);
1205 drv->remove(dev);
1206 } else {
1207 dev_dbg(&dev->core, "%s:%d: no shutdown method\n", __func__,
1208 __LINE__);
1209 BUG();
1210 }
1047 1211
1048static void ps3_vuart_port_release_device(struct device *_dev) 1212 ps3_vuart_cleanup(dev);
1049{
1050#if defined(DEBUG)
1051 struct ps3_vuart_port_device *dev = to_ps3_vuart_port_device(_dev);
1052 1213
1053 dev_dbg(&dev->core, "%s:%d\n", __func__, __LINE__); 1214 dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__);
1054 1215
1055 BUG_ON(dev->priv && "forgot to free"); 1216 up(&vuart_bus_priv.probe_mutex);
1056 memset(&dev->core, 0, sizeof(dev->core)); 1217 return 0;
1057#endif
1058} 1218}
1059 1219
1060/** 1220static int __init ps3_vuart_bus_init(void)
1061 * ps3_vuart_port_device_register - Add a vuart port device.
1062 */
1063
1064int ps3_vuart_port_device_register(struct ps3_vuart_port_device *dev)
1065{ 1221{
1066 static unsigned int dev_count = 1; 1222 pr_debug("%s:%d:\n", __func__, __LINE__);
1067
1068 BUG_ON(dev->priv && "forgot to free");
1069 1223
1070 dev->core.parent = NULL; 1224 if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
1071 dev->core.bus = &ps3_vuart_bus; 1225 return -ENODEV;
1072 dev->core.release = ps3_vuart_port_release_device;
1073 1226
1074 snprintf(dev->core.bus_id, sizeof(dev->core.bus_id), "vuart_%02x", 1227 init_MUTEX(&vuart_bus_priv.probe_mutex);
1075 dev_count++);
1076 1228
1077 dev_dbg(&dev->core, "%s:%d register\n", __func__, __LINE__); 1229 return 0;
1230}
1078 1231
1079 return device_register(&dev->core); 1232static void __exit ps3_vuart_bus_exit(void)
1233{
1234 pr_debug("%s:%d:\n", __func__, __LINE__);
1080} 1235}
1081 1236
1082EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register); 1237core_initcall(ps3_vuart_bus_init);
1238module_exit(ps3_vuart_bus_exit);
1083 1239
1084/** 1240/**
1085 * ps3_vuart_port_driver_register - Add a vuart port device driver. 1241 * ps3_vuart_port_driver_register - Add a vuart port device driver.
@@ -1089,12 +1245,18 @@ int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv)
1089{ 1245{
1090 int result; 1246 int result;
1091 1247
1092 pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); 1248 pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
1093 drv->core.bus = &ps3_vuart_bus; 1249
1094 result = driver_register(&drv->core); 1250 BUG_ON(!drv->core.match_id);
1251 BUG_ON(!drv->core.core.name);
1252
1253 drv->core.probe = ps3_vuart_probe;
1254 drv->core.remove = ps3_vuart_remove;
1255 drv->core.shutdown = ps3_vuart_shutdown;
1256
1257 result = ps3_system_bus_driver_register(&drv->core);
1095 return result; 1258 return result;
1096} 1259}
1097
1098EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); 1260EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
1099 1261
1100/** 1262/**
@@ -1103,8 +1265,7 @@ EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register);
1103 1265
1104void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv) 1266void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv)
1105{ 1267{
1106 pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.name); 1268 pr_debug("%s:%d: (%s)\n", __func__, __LINE__, drv->core.core.name);
1107 driver_unregister(&drv->core); 1269 ps3_system_bus_driver_unregister(&drv->core);
1108} 1270}
1109
1110EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister); 1271EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister);
diff --git a/drivers/ps3/vuart.h b/drivers/ps3/vuart.h
index 1be992d568c8..eb7f6d94a890 100644
--- a/drivers/ps3/vuart.h
+++ b/drivers/ps3/vuart.h
@@ -34,29 +34,7 @@ struct ps3_vuart_stats {
34struct ps3_vuart_work { 34struct ps3_vuart_work {
35 struct work_struct work; 35 struct work_struct work;
36 unsigned long trigger; 36 unsigned long trigger;
37 spinlock_t lock; 37 struct ps3_system_bus_device *dev; /* to convert work to device */
38 struct ps3_vuart_port_device* dev; /* to convert work to device */
39};
40
41/**
42 * struct ps3_vuart_port_priv - private vuart device data.
43 */
44
45struct ps3_vuart_port_priv {
46 unsigned int port_number;
47 u64 interrupt_mask;
48
49 struct {
50 spinlock_t lock;
51 struct list_head head;
52 } tx_list;
53 struct {
54 unsigned long bytes_held;
55 spinlock_t lock;
56 struct list_head head;
57 } rx_list;
58 struct ps3_vuart_stats stats;
59 struct ps3_vuart_work work;
60}; 38};
61 39
62/** 40/**
@@ -64,32 +42,30 @@ struct ps3_vuart_port_priv {
64 */ 42 */
65 43
66struct ps3_vuart_port_driver { 44struct ps3_vuart_port_driver {
67 enum ps3_match_id match_id; 45 struct ps3_system_bus_driver core;
68 struct device_driver core; 46 int (*probe)(struct ps3_system_bus_device *);
69 int (*probe)(struct ps3_vuart_port_device *); 47 int (*remove)(struct ps3_system_bus_device *);
70 int (*remove)(struct ps3_vuart_port_device *); 48 void (*shutdown)(struct ps3_system_bus_device *);
71 void (*shutdown)(struct ps3_vuart_port_device *); 49 void (*work)(struct ps3_system_bus_device *);
72 int (*tx_event)(struct ps3_vuart_port_device *dev); 50 /* int (*tx_event)(struct ps3_system_bus_device *dev); */
73 int (*rx_event)(struct ps3_vuart_port_device *dev); 51 /* int (*rx_event)(struct ps3_system_bus_device *dev); */
74 int (*disconnect_event)(struct ps3_vuart_port_device *dev); 52 /* int (*disconnect_event)(struct ps3_system_bus_device *dev); */
75 /* int (*suspend)(struct ps3_vuart_port_device *, pm_message_t); */ 53 /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */
76 /* int (*resume)(struct ps3_vuart_port_device *); */ 54 /* int (*resume)(struct ps3_system_bus_device *); */
77}; 55};
78 56
79int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv); 57int ps3_vuart_port_driver_register(struct ps3_vuart_port_driver *drv);
80void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv); 58void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv);
81 59
82static inline struct ps3_vuart_port_driver *to_ps3_vuart_port_driver( 60static inline struct ps3_vuart_port_driver *
83 struct device_driver *_drv) 61 ps3_system_bus_dev_to_vuart_drv(struct ps3_system_bus_device *_dev)
84{
85 return container_of(_drv, struct ps3_vuart_port_driver, core);
86}
87static inline struct ps3_vuart_port_device *to_ps3_vuart_port_device(
88 struct device *_dev)
89{ 62{
90 return container_of(_dev, struct ps3_vuart_port_device, core); 63 struct ps3_system_bus_driver *sbd =
64 ps3_system_bus_dev_to_system_bus_drv(_dev);
65 BUG_ON(!sbd);
66 return container_of(sbd, struct ps3_vuart_port_driver, core);
91} 67}
92static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device( 68static inline struct ps3_system_bus_device *ps3_vuart_work_to_system_bus_dev(
93 struct work_struct *_work) 69 struct work_struct *_work)
94{ 70{
95 struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work, 71 struct ps3_vuart_work *vw = container_of(_work, struct ps3_vuart_work,
@@ -97,14 +73,13 @@ static inline struct ps3_vuart_port_device *ps3_vuart_work_to_port_device(
97 return vw->dev; 73 return vw->dev;
98} 74}
99 75
100int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, 76int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
101 unsigned int bytes);
102int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf,
103 unsigned int bytes); 77 unsigned int bytes);
104int ps3_vuart_read_async(struct ps3_vuart_port_device *dev, work_func_t func, 78int ps3_vuart_read(struct ps3_system_bus_device *dev, void *buf,
105 unsigned int bytes); 79 unsigned int bytes);
106void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev); 80int ps3_vuart_read_async(struct ps3_system_bus_device *dev, unsigned int bytes);
107void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, 81void ps3_vuart_cancel_async(struct ps3_system_bus_device *dev);
82void ps3_vuart_clear_rx_bytes(struct ps3_system_bus_device *dev,
108 unsigned int bytes); 83 unsigned int bytes);
109 84
110#endif 85#endif