diff options
Diffstat (limited to 'drivers/ps3/vuart.c')
| -rw-r--r-- | drivers/ps3/vuart.c | 817 |
1 files changed, 489 insertions, 328 deletions
diff --git a/drivers/ps3/vuart.c b/drivers/ps3/vuart.c index ec2d36a1bc67..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 | |||
| 77 | struct 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 | |||
| 93 | static 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 |
| @@ -83,31 +111,14 @@ struct ports_bmp { | |||
| 83 | } __attribute__ ((aligned (32))); | 111 | } __attribute__ ((aligned (32))); |
| 84 | 112 | ||
| 85 | #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__) | 113 | #define dump_ports_bmp(_b) _dump_ports_bmp(_b, __func__, __LINE__) |
| 86 | static void __attribute__ ((unused)) _dump_ports_bmp( | 114 | static void __maybe_unused _dump_ports_bmp( |
| 87 | const struct ports_bmp* bmp, const char* func, int line) | 115 | const struct ports_bmp* bmp, const char* func, int line) |
| 88 | { | 116 | { |
| 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 | ||
| 92 | static 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__) |
| 110 | static void __attribute__ ((unused)) _dump_port_params(unsigned int port_number, | 121 | static void __maybe_unused _dump_port_params(unsigned int port_number, |
| 111 | const char* func, int line) | 122 | const char* func, int line) |
| 112 | { | 123 | { |
| 113 | #if defined(DEBUG) | 124 | #if defined(DEBUG) |
| @@ -144,14 +155,14 @@ struct vuart_triggers { | |||
| 144 | unsigned long tx; | 155 | unsigned long tx; |
| 145 | }; | 156 | }; |
| 146 | 157 | ||
| 147 | int ps3_vuart_get_triggers(struct ps3_vuart_port_device *dev, | 158 | int 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 | ||
| 189 | int ps3_vuart_set_triggers(struct ps3_vuart_port_device *dev, unsigned int tx, | 200 | int 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 | ||
| 228 | static int ps3_vuart_get_rx_bytes_waiting(struct ps3_vuart_port_device *dev, | 239 | static 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 | ||
| 243 | static 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 | |||
| 262 | static 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 | ||
| 262 | static int ps3_vuart_get_interrupt_status(struct ps3_vuart_port_device *dev, | 282 | static 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 | ||
| 281 | int ps3_vuart_enable_interrupt_tx(struct ps3_vuart_port_device *dev) | 304 | int 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 | ||
| 288 | int ps3_vuart_enable_interrupt_rx(struct ps3_vuart_port_device *dev) | 313 | int 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 | ||
| 295 | int ps3_vuart_enable_interrupt_disconnect(struct ps3_vuart_port_device *dev) | 322 | int 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 | ||
| 302 | int ps3_vuart_disable_interrupt_tx(struct ps3_vuart_port_device *dev) | 331 | int 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 | ||
| 309 | int ps3_vuart_disable_interrupt_rx(struct ps3_vuart_port_device *dev) | 340 | int 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 | ||
| 316 | int ps3_vuart_disable_interrupt_disconnect(struct ps3_vuart_port_device *dev) | 349 | int 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 | ||
| 329 | static int ps3_vuart_raw_write(struct ps3_vuart_port_device *dev, | 365 | static 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 | ||
| 357 | static int ps3_vuart_raw_read(struct ps3_vuart_port_device *dev, void* buf, | 395 | static 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 | ||
| 388 | void ps3_vuart_clear_rx_bytes(struct ps3_vuart_port_device *dev, | 428 | void 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 | } |
| 464 | EXPORT_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 | ||
| 445 | int ps3_vuart_write(struct ps3_vuart_port_device *dev, const void* buf, | 488 | int 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 | } |
| 548 | EXPORT_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 | |||
| 558 | static 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 | ||
| 514 | int ps3_vuart_read(struct ps3_vuart_port_device *dev, void* buf, | 613 | int 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 | } |
| 670 | EXPORT_SYMBOL_GPL(ps3_vuart_read); | ||
| 562 | 671 | ||
| 563 | int 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 | |||
| 676 | static 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 | |||
| 687 | int 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 | } |
| 719 | EXPORT_SYMBOL_GPL(ps3_vuart_read_async); | ||
| 595 | 720 | ||
| 596 | void ps3_vuart_cancel_async(struct ps3_vuart_port_device *dev) | 721 | void 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 | } |
| 725 | EXPORT_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 | ||
| 609 | static int ps3_vuart_handle_interrupt_tx(struct ps3_vuart_port_device *dev) | 735 | static 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); |
| 653 | port_full: | 780 | port_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 | ||
| 668 | static int ps3_vuart_handle_interrupt_rx(struct ps3_vuart_port_device *dev) | 795 | static 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 | ||
| 720 | static int ps3_vuart_handle_interrupt_disconnect( | 824 | static 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 | ||
| 736 | static int ps3_vuart_handle_port_interrupt(struct ps3_vuart_port_device *dev) | 840 | static 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 | ||
| 773 | struct vuart_bus_priv { | 878 | struct 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 | ||
| 789 | static irqreturn_t ps3_vuart_irq_handler(int irq, void *_private) | 894 | static 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 | ||
| 815 | static int ps3_vuart_match(struct device *_dev, struct device_driver *_drv) | 919 | static 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 | |||
| 965 | fail_request_irq: | ||
| 966 | ps3_vuart_irq_destroy(vuart_bus_priv.virq); | ||
| 967 | vuart_bus_priv.virq = NO_IRQ; | ||
| 968 | fail_alloc_irq: | ||
| 969 | kfree(vuart_bus_priv.bmp); | ||
| 970 | vuart_bus_priv.bmp = NULL; | ||
| 971 | fail_bmp_malloc: | ||
| 972 | vuart_bus_priv.use_count--; | ||
| 973 | pr_debug(" <- %s:%d: failed\n", __func__, __LINE__); | ||
| 974 | return result; | ||
| 975 | } | ||
| 976 | |||
| 977 | static 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 | ||
| 830 | static int ps3_vuart_probe(struct device *_dev) | 1000 | static 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 | ||
| 937 | fail_probe: | 1085 | fail_probe: |
| 938 | ps3_vuart_set_interrupt_mask(dev, 0); | 1086 | ps3_vuart_set_interrupt_mask(dev, 0); |
| 939 | fail_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; | 1089 | fail_dev_malloc: |
| 942 | fail_alloc_irq: | 1090 | vuart_bus_priv.devices[dev->port_number] = NULL; |
| 943 | --vuart_bus_priv.use_count; | 1091 | fail_busy: |
| 944 | kfree(dev->priv); | 1092 | ps3_vuart_bus_interrupt_put(); |
| 945 | dev->priv = NULL; | 1093 | fail_setup_interrupt: |
| 946 | fail_alloc: | ||
| 947 | vuart_bus_priv.devices[port_number] = NULL; | ||
| 948 | fail_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 | ||
| 954 | static 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 | |||
| 1108 | static 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 | |||
| 1126 | static 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 | ||
| 989 | static 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 | ||
| 1011 | struct bus_type ps3_vuart_bus = { | 1178 | static 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 | |||
| 1019 | int __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 | ||
| 1035 | void __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 | ||
| 1041 | core_initcall(ps3_vuart_bus_init); | 1198 | BUG_ON(!drv); |
| 1042 | module_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 | ||
| 1048 | static 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 | /** | 1220 | static int __init ps3_vuart_bus_init(void) |
| 1061 | * ps3_vuart_port_device_register - Add a vuart port device. | ||
| 1062 | */ | ||
| 1063 | |||
| 1064 | int 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); | 1232 | static void __exit ps3_vuart_bus_exit(void) |
| 1233 | { | ||
| 1234 | pr_debug("%s:%d:\n", __func__, __LINE__); | ||
| 1080 | } | 1235 | } |
| 1081 | 1236 | ||
| 1082 | EXPORT_SYMBOL_GPL(ps3_vuart_port_device_register); | 1237 | core_initcall(ps3_vuart_bus_init); |
| 1238 | module_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 | |||
| 1098 | EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_register); | 1260 | EXPORT_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 | ||
| 1104 | void ps3_vuart_port_driver_unregister(struct ps3_vuart_port_driver *drv) | 1266 | void 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 | |||
| 1110 | EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister); | 1271 | EXPORT_SYMBOL_GPL(ps3_vuart_port_driver_unregister); |
