1/* viohs.c: LDOM Virtual I/O handshake helper layer. 2 * 3 * Copyright (C) 2007 David S. Miller <davem@davemloft.net> 4 */ 5 6#include <linux/kernel.h> 7#include <linux/module.h> 8#include <linux/string.h> 9#include <linux/delay.h> 10#include <linux/sched.h> 11#include <linux/slab.h> 12 13#include <asm/ldc.h> 14#include <asm/vio.h> 15 16int vio_ldc_send(struct vio_driver_state *vio, void *data, int len) 17{ 18 int err, limit = 1000; 19 20 err = -EINVAL; 21 while (limit-- > 0) { 22 err = ldc_write(vio->lp, data, len); 23 if (!err || (err != -EAGAIN)) 24 break; 25 udelay(1); 26 } 27 28 return err; 29} 30EXPORT_SYMBOL(vio_ldc_send); 31 32static int send_ctrl(struct vio_driver_state *vio, 33 struct vio_msg_tag *tag, int len) 34{ 35 tag->sid = vio_send_sid(vio); 36 return vio_ldc_send(vio, tag, len); 37} 38 39static void init_tag(struct vio_msg_tag *tag, u8 type, u8 stype, u16 stype_env) 40{ 41 tag->type = type; 42 tag->stype = stype; 43 tag->stype_env = stype_env; 44} 45 46static int send_version(struct vio_driver_state *vio, u16 major, u16 minor) 47{ 48 struct vio_ver_info pkt; 49 50 vio->_local_sid = (u32) sched_clock(); 51 52 memset(&pkt, 0, sizeof(pkt)); 53 init_tag(&pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_VER_INFO); 54 pkt.major = major; 55 pkt.minor = minor; 56 pkt.dev_class = vio->dev_class; 57 58 viodbg(HS, "SEND VERSION INFO maj[%u] min[%u] devclass[%u]\n", 59 major, minor, vio->dev_class); 60 61 return send_ctrl(vio, &pkt.tag, sizeof(pkt)); 62} 63 64static int start_handshake(struct vio_driver_state *vio) 65{ 66 int err; 67 68 viodbg(HS, "START HANDSHAKE\n"); 69 70 vio->hs_state = VIO_HS_INVALID; 71 72 err = send_version(vio, 73 vio->ver_table[0].major, 74 vio->ver_table[0].minor); 75 if (err < 0) 76 return err; 77 78 return 0; 79} 80 81static void flush_rx_dring(struct vio_driver_state *vio) 82{ 83 struct vio_dring_state *dr; 84 u64 ident; 85 86 BUG_ON(!(vio->dr_state & VIO_DR_STATE_RXREG)); 87 88 dr = &vio->drings[VIO_DRIVER_RX_RING]; 89 ident = dr->ident; 90 91 BUG_ON(!vio->desc_buf); 92 kfree(vio->desc_buf); 93 vio->desc_buf = NULL; 94 95 memset(dr, 0, sizeof(*dr)); 96 dr->ident = ident; 97} 98 99void vio_link_state_change(struct vio_driver_state *vio, int event) 100{ 101 if (event == LDC_EVENT_UP) { 102 vio->hs_state = VIO_HS_INVALID; 103 104 switch (vio->dev_class) { 105 case VDEV_NETWORK: 106 case VDEV_NETWORK_SWITCH: 107 vio->dr_state = (VIO_DR_STATE_TXREQ | 108 VIO_DR_STATE_RXREQ); 109 break; 110 111 case VDEV_DISK: 112 vio->dr_state = VIO_DR_STATE_TXREQ; 113 break; 114 case VDEV_DISK_SERVER: 115 vio->dr_state = VIO_DR_STATE_RXREQ; 116 break; 117 } 118 start_handshake(vio); 119 } else if (event == LDC_EVENT_RESET) { 120 vio->hs_state = VIO_HS_INVALID; 121 122 if (vio->dr_state & VIO_DR_STATE_RXREG) 123 flush_rx_dring(vio); 124 125 vio->dr_state = 0x00; 126 memset(&vio->ver, 0, sizeof(vio->ver)); 127 128 ldc_disconnect(vio->lp); 129 } 130} 131EXPORT_SYMBOL(vio_link_state_change); 132 133static int handshake_failure(struct vio_driver_state *vio) 134{ 135 struct vio_dring_state *dr; 136 137 138 viodbg(HS, "HANDSHAKE FAILURE\n"); 139 140 vio->dr_state &= ~(VIO_DR_STATE_TXREG | 141 VIO_DR_STATE_RXREG); 142 143 dr = &vio->drings[VIO_DRIVER_RX_RING]; 144 memset(dr, 0, sizeof(*dr)); 145 146 kfree(vio->desc_buf); 147 vio->desc_buf = NULL; 148 vio->desc_buf_len = 0; 149 150 vio->hs_state = VIO_HS_INVALID; 151 152 return -ECONNRESET; 153} 154 155static int process_unknown(struct vio_driver_state *vio, void *arg) 156{ 157 struct vio_msg_tag *pkt = arg; 158 159 viodbg(HS, "UNKNOWN CONTROL [%02x:%02x:%04x:%08x]\n", 160 pkt->type, pkt->stype, pkt->stype_env, pkt->sid); 161 162 printk(KERN_ERR "vio: ID[%lu] Resetting connection.\n", 163 vio->vdev->channel_id); 164 165 ldc_disconnect(vio->lp); 166 167 return -ECONNRESET; 168} 169 170static int send_dreg(struct vio_driver_state *vio) 171{ 172 struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_TX_RING]; 173 union { 174 struct vio_dring_register pkt; 175 char all[sizeof(struct vio_dring_register) + 176 (sizeof(struct ldc_trans_cookie) * 177 dr->ncookies)]; 178 } u; 179 int i; 180 181 memset(&u, 0, sizeof(u)); 182 init_tag(&u.pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_DRING_REG); 183 u.pkt.dring_ident = 0; 184 u.pkt.num_descr = dr->num_entries; 185 u.pkt.descr_size = dr->entry_size; 186 u.pkt.options = VIO_TX_DRING; 187 u.pkt.num_cookies = dr->ncookies; 188 189 viodbg(HS, "SEND DRING_REG INFO ndesc[%u] dsz[%u] opt[0x%x] " 190 "ncookies[%u]\n", 191 u.pkt.num_descr, u.pkt.descr_size, u.pkt.options, 192 u.pkt.num_cookies); 193 194 for (i = 0; i < dr->ncookies; i++) { 195 u.pkt.cookies[i] = dr->cookies[i]; 196 197 viodbg(HS, "DRING COOKIE(%d) [%016llx:%016llx]\n", 198 i, 199 (unsigned long long) u.pkt.cookies[i].cookie_addr, 200 (unsigned long long) u.pkt.cookies[i].cookie_size); 201 } 202 203 return send_ctrl(vio, &u.pkt.tag, sizeof(u)); 204} 205 206static int send_rdx(struct vio_driver_state *vio) 207{ 208 struct vio_rdx pkt; 209 210 memset(&pkt, 0, sizeof(pkt)); 211 212 init_tag(&pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_RDX); 213 214 viodbg(HS, "SEND RDX INFO\n"); 215 216 return send_ctrl(vio, &pkt.tag, sizeof(pkt)); 217} 218 219static int send_attr(struct vio_driver_state *vio) 220{ 221 return vio->ops->send_attr(vio); 222} 223 224static struct vio_version *find_by_major(struct vio_driver_state *vio, 225 u16 major) 226{ 227 struct vio_version *ret = NULL; 228 int i; 229 230 for (i = 0; i < vio->ver_table_entries; i++) { 231 struct vio_version *v = &vio->ver_table[i]; 232 if (v->major <= major) { 233 ret = v; 234 break; 235 } 236 } 237 return ret; 238} 239 240static int process_ver_info(struct vio_driver_state *vio, 241 struct vio_ver_info *pkt) 242{ 243 struct vio_version *vap; 244 int err; 245 246 viodbg(HS, "GOT VERSION INFO maj[%u] min[%u] devclass[%u]\n", 247 pkt->major, pkt->minor, pkt->dev_class); 248 249 if (vio->hs_state != VIO_HS_INVALID) { 250 memset(&vio->ver, 0, sizeof(vio->ver)); 251 vio->hs_state = VIO_HS_INVALID; 252 } 253 254 vap = find_by_major(vio, pkt->major); 255 256 vio->_peer_sid = pkt->tag.sid; 257 258 if (!vap) { 259 pkt->tag.stype = VIO_SUBTYPE_NACK; 260 pkt->major = 0; 261 pkt->minor = 0; 262 viodbg(HS, "SEND VERSION NACK maj[0] min[0]\n"); 263 err = send_ctrl(vio, &pkt->tag, sizeof(*pkt)); 264 } else if (vap->major != pkt->major) { 265 pkt->tag.stype = VIO_SUBTYPE_NACK; 266 pkt->major = vap->major; 267 pkt->minor = vap->minor; 268 viodbg(HS, "SEND VERSION NACK maj[%u] min[%u]\n", 269 pkt->major, pkt->minor); 270 err = send_ctrl(vio, &pkt->tag, sizeof(*pkt)); 271 } else { 272 struct vio_version ver = { 273 .major = pkt->major, 274 .minor = pkt->minor, 275 }; 276 if (ver.minor > vap->minor) 277 ver.minor = vap->minor; 278 pkt->minor = ver.minor; 279 pkt->tag.stype = VIO_SUBTYPE_ACK; 280 viodbg(HS, "SEND VERSION ACK maj[%u] min[%u]\n", 281 pkt->major, pkt->minor); 282 err = send_ctrl(vio, &pkt->tag, sizeof(*pkt)); 283 if (err > 0) { 284 vio->ver = ver; 285 vio->hs_state = VIO_HS_GOTVERS; 286 } 287 } 288 if (err < 0) 289 return handshake_failure(vio); 290 291 return 0; 292} 293 294static int process_ver_ack(struct vio_driver_state *vio, 295 struct vio_ver_info *pkt) 296{ 297 viodbg(HS, "GOT VERSION ACK maj[%u] min[%u] devclass[%u]\n", 298 pkt->major, pkt->minor, pkt->dev_class); 299 300 if (vio->hs_state & VIO_HS_GOTVERS) { 301 if (vio->ver.major != pkt->major || 302 vio->ver.minor != pkt->minor) { 303 pkt->tag.stype = VIO_SUBTYPE_NACK; 304 (void) send_ctrl(vio, &pkt->tag, sizeof(*pkt)); 305 return handshake_failure(vio); 306 } 307 } else { 308 vio->ver.major = pkt->major; 309 vio->ver.minor = pkt->minor; 310 vio->hs_state = VIO_HS_GOTVERS; 311 } 312 313 switch (vio->dev_class) { 314 case VDEV_NETWORK: 315 case VDEV_DISK: 316 if (send_attr(vio) < 0) 317 return handshake_failure(vio); 318 break; 319 320 default: 321 break; 322 } 323 324 return 0; 325} 326 327static int process_ver_nack(struct vio_driver_state *vio, 328 struct vio_ver_info *pkt) 329{ 330 struct vio_version *nver; 331 332 viodbg(HS, "GOT VERSION NACK maj[%u] min[%u] devclass[%u]\n", 333 pkt->major, pkt->minor, pkt->dev_class); 334 335 if (pkt->major == 0 && pkt->minor == 0) 336 return handshake_failure(vio); 337 nver = find_by_major(vio, pkt->major); 338 if (!nver) 339 return handshake_failure(vio); 340 341 if (send_version(vio, nver->major, nver->minor) < 0) 342 return handshake_failure(vio); 343 344 return 0; 345} 346 347static int process_ver(struct vio_driver_state *vio, struct vio_ver_info *pkt) 348{ 349 switch (pkt->tag.stype) { 350 case VIO_SUBTYPE_INFO: 351 return process_ver_info(vio, pkt); 352 353 case VIO_SUBTYPE_ACK: 354 return process_ver_ack(vio, pkt); 355 356 case VIO_SUBTYPE_NACK: 357 return process_ver_nack(vio, pkt); 358 359 default: 360 return handshake_failure(vio); 361 }; 362} 363 364static int process_attr(struct vio_driver_state *vio, void *pkt) 365{ 366 int err; 367 368 if (!(vio->hs_state & VIO_HS_GOTVERS)) 369 return handshake_failure(vio); 370 371 err = vio->ops->handle_attr(vio, pkt); 372 if (err < 0) { 373 return handshake_failure(vio); 374 } else { 375 vio->hs_state |= VIO_HS_GOT_ATTR; 376 377 if ((vio->dr_state & VIO_DR_STATE_TXREQ) && 378 !(vio->hs_state & VIO_HS_SENT_DREG)) { 379 if (send_dreg(vio) < 0) 380 return handshake_failure(vio); 381 382 vio->hs_state |= VIO_HS_SENT_DREG; 383 } 384 } 385 return 0; 386} 387 388static int all_drings_registered(struct vio_driver_state *vio) 389{ 390 int need_rx, need_tx; 391 392 need_rx = (vio->dr_state & VIO_DR_STATE_RXREQ); 393 need_tx = (vio->dr_state & VIO_DR_STATE_TXREQ); 394 395 if (need_rx && 396 !(vio->dr_state & VIO_DR_STATE_RXREG)) 397 return 0; 398 399 if (need_tx && 400 !(vio->dr_state & VIO_DR_STATE_TXREG)) 401 return 0; 402 403 return 1; 404} 405 406static int process_dreg_info(struct vio_driver_state *vio, 407 struct vio_dring_register *pkt) 408{ 409 struct vio_dring_state *dr; 410 int i, len; 411 412 viodbg(HS, "GOT DRING_REG INFO ident[%llx] " 413 "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n", 414 (unsigned long long) pkt->dring_ident, 415 pkt->num_descr, pkt->descr_size, pkt->options, 416 pkt->num_cookies); 417 418 if (!(vio->dr_state & VIO_DR_STATE_RXREQ)) 419 goto send_nack; 420 421 if (vio->dr_state & VIO_DR_STATE_RXREG) 422 goto send_nack; 423 424 BUG_ON(vio->desc_buf); 425 426 vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC); 427 if (!vio->desc_buf) 428 goto send_nack; 429 430 vio->desc_buf_len = pkt->descr_size; 431 432 dr = &vio->drings[VIO_DRIVER_RX_RING]; 433 434 dr->num_entries = pkt->num_descr; 435 dr->entry_size = pkt->descr_size; 436 dr->ncookies = pkt->num_cookies; 437 for (i = 0; i < dr->ncookies; i++) { 438 dr->cookies[i] = pkt->cookies[i]; 439 440 viodbg(HS, "DRING COOKIE(%d) [%016llx:%016llx]\n", 441 i, 442 (unsigned long long) 443 pkt->cookies[i].cookie_addr, 444 (unsigned long long) 445 pkt->cookies[i].cookie_size); 446 } 447 448 pkt->tag.stype = VIO_SUBTYPE_ACK; 449 pkt->dring_ident = ++dr->ident; 450 451 viodbg(HS, "SEND DRING_REG ACK ident[%llx]\n", 452 (unsigned long long) pkt->dring_ident); 453 454 len = (sizeof(*pkt) + 455 (dr->ncookies * sizeof(struct ldc_trans_cookie))); 456 if (send_ctrl(vio, &pkt->tag, len) < 0) 457 goto send_nack; 458 459 vio->dr_state |= VIO_DR_STATE_RXREG; 460 461 return 0; 462 463send_nack: 464 pkt->tag.stype = VIO_SUBTYPE_NACK; 465 viodbg(HS, "SEND DRING_REG NACK\n"); 466 (void) send_ctrl(vio, &pkt->tag, sizeof(*pkt)); 467 468 return handshake_failure(vio); 469} 470 471static int process_dreg_ack(struct vio_driver_state *vio, 472 struct vio_dring_register *pkt) 473{ 474 struct vio_dring_state *dr; 475 476 viodbg(HS, "GOT DRING_REG ACK ident[%llx] " 477 "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n", 478 (unsigned long long) pkt->dring_ident, 479 pkt->num_descr, pkt->descr_size, pkt->options, 480 pkt->num_cookies); 481 482 dr = &vio->drings[VIO_DRIVER_TX_RING]; 483 484 if (!(vio->dr_state & VIO_DR_STATE_TXREQ)) 485 return handshake_failure(vio); 486 487 dr->ident = pkt->dring_ident; 488 vio->dr_state |= VIO_DR_STATE_TXREG; 489 490 if (all_drings_registered(vio)) { 491 if (send_rdx(vio) < 0) 492 return handshake_failure(vio); 493 vio->hs_state = VIO_HS_SENT_RDX; 494 } 495 return 0; 496} 497 498static int process_dreg_nack(struct vio_driver_state *vio, 499 struct vio_dring_register *pkt) 500{ 501 viodbg(HS, "GOT DRING_REG NACK ident[%llx] " 502 "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n", 503 (unsigned long long) pkt->dring_ident, 504 pkt->num_descr, pkt->descr_size, pkt->options, 505 pkt->num_cookies); 506 507 return handshake_failure(vio); 508} 509 510static int process_dreg(struct vio_driver_state *vio, 511 struct vio_dring_register *pkt) 512{ 513 if (!(vio->hs_state & VIO_HS_GOTVERS)) 514 return handshake_failure(vio); 515 516 switch (pkt->tag.stype) { 517 case VIO_SUBTYPE_INFO: 518 return process_dreg_info(vio, pkt); 519 520 case VIO_SUBTYPE_ACK: 521 return process_dreg_ack(vio, pkt); 522 523 case VIO_SUBTYPE_NACK: 524 return process_dreg_nack(vio, pkt); 525 526 default: 527 return handshake_failure(vio); 528 } 529} 530 531static int process_dunreg(struct vio_driver_state *vio, 532 struct vio_dring_unregister *pkt) 533{ 534 struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_RX_RING]; 535 536 viodbg(HS, "GOT DRING_UNREG\n"); 537 538 if (pkt->dring_ident != dr->ident) 539 return 0; 540 541 vio->dr_state &= ~VIO_DR_STATE_RXREG; 542 543 memset(dr, 0, sizeof(*dr)); 544 545 kfree(vio->desc_buf); 546 vio->desc_buf = NULL; 547 vio->desc_buf_len = 0; 548 549 return 0; 550} 551 552static int process_rdx_info(struct vio_driver_state *vio, struct vio_rdx *pkt) 553{ 554 viodbg(HS, "GOT RDX INFO\n"); 555 556 pkt->tag.stype = VIO_SUBTYPE_ACK; 557 viodbg(HS, "SEND RDX ACK\n"); 558 if (send_ctrl(vio, &pkt->tag, sizeof(*pkt)) < 0) 559 return handshake_failure(vio); 560 561 vio->hs_state |= VIO_HS_SENT_RDX_ACK; 562 return 0; 563} 564 565static int process_rdx_ack(struct vio_driver_state *vio, struct vio_rdx *pkt) 566{ 567 viodbg(HS, "GOT RDX ACK\n"); 568 569 if (!(vio->hs_state & VIO_HS_SENT_RDX)) 570 return handshake_failure(vio); 571 572 vio->hs_state |= VIO_HS_GOT_RDX_ACK; 573 return 0; 574} 575 576static int process_rdx_nack(struct vio_driver_state *vio, struct vio_rdx *pkt) 577{ 578 viodbg(HS, "GOT RDX NACK\n"); 579 580 return handshake_failure(vio); 581} 582 583static int process_rdx(struct vio_driver_state *vio, struct vio_rdx *pkt) 584{ 585 if (!all_drings_registered(vio)) 586 handshake_failure(vio); 587 588 switch (pkt->tag.stype) { 589 case VIO_SUBTYPE_INFO: 590 return process_rdx_info(vio, pkt); 591 592 case VIO_SUBTYPE_ACK: 593 return process_rdx_ack(vio, pkt); 594 595 case VIO_SUBTYPE_NACK: 596 return process_rdx_nack(vio, pkt); 597 598 default: 599 return handshake_failure(vio); 600 } 601} 602 603int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt) 604{ 605 struct vio_msg_tag *tag = pkt; 606 u8 prev_state = vio->hs_state; 607 int err; 608 609 switch (tag->stype_env) { 610 case VIO_VER_INFO: 611 err = process_ver(vio, pkt); 612 break; 613 614 case VIO_ATTR_INFO: 615 err = process_attr(vio, pkt); 616 break; 617 618 case VIO_DRING_REG: 619 err = process_dreg(vio, pkt); 620 break; 621 622 case VIO_DRING_UNREG: 623 err = process_dunreg(vio, pkt); 624 break; 625 626 case VIO_RDX: 627 err = process_rdx(vio, pkt); 628 break; 629 630 default: 631 err = process_unknown(vio, pkt); 632 break; 633 } 634 if (!err && 635 vio->hs_state != prev_state && 636 (vio->hs_state & VIO_HS_COMPLETE)) 637 vio->ops->handshake_complete(vio); 638 639 return err; 640} 641EXPORT_SYMBOL(vio_control_pkt_engine); 642 643void vio_conn_reset(struct vio_driver_state *vio) 644{ 645} 646EXPORT_SYMBOL(vio_conn_reset); 647 648int vio_validate_sid(struct vio_driver_state *vio, struct vio_msg_tag *tp) 649{ 650 u32 sid; 651 652 /* Always let VERSION+INFO packets through unchecked, they 653 * define the new SID. 654 */ 655 if (tp->type == VIO_TYPE_CTRL && 656 tp->stype == VIO_SUBTYPE_INFO && 657 tp->stype_env == VIO_VER_INFO) 658 return 0; 659 660 /* Ok, now figure out which SID to use. */ 661 switch (vio->dev_class) { 662 case VDEV_NETWORK: 663 case VDEV_NETWORK_SWITCH: 664 case VDEV_DISK_SERVER: 665 default: 666 sid = vio->_peer_sid; 667 break; 668 669 case VDEV_DISK: 670 sid = vio->_local_sid; 671 break; 672 } 673 674 if (sid == tp->sid) 675 return 0; 676 viodbg(DATA, "BAD SID tag->sid[%08x] peer_sid[%08x] local_sid[%08x]\n", 677 tp->sid, vio->_peer_sid, vio->_local_sid); 678 return -EINVAL; 679} 680EXPORT_SYMBOL(vio_validate_sid); 681 682u32 vio_send_sid(struct vio_driver_state *vio) 683{ 684 switch (vio->dev_class) { 685 case VDEV_NETWORK: 686 case VDEV_NETWORK_SWITCH: 687 case VDEV_DISK: 688 default: 689 return vio->_local_sid; 690 691 case VDEV_DISK_SERVER: 692 return vio->_peer_sid; 693 } 694} 695EXPORT_SYMBOL(vio_send_sid); 696 697int vio_ldc_alloc(struct vio_driver_state *vio, 698 struct ldc_channel_config *base_cfg, 699 void *event_arg) 700{ 701 struct ldc_channel_config cfg = *base_cfg; 702 struct ldc_channel *lp; 703 704 cfg.tx_irq = vio->vdev->tx_irq; 705 cfg.rx_irq = vio->vdev->rx_irq; 706 707 lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg); 708 if (IS_ERR(lp)) 709 return PTR_ERR(lp); 710 711 vio->lp = lp; 712 713 return 0; 714} 715EXPORT_SYMBOL(vio_ldc_alloc); 716 717void vio_ldc_free(struct vio_driver_state *vio) 718{ 719 ldc_free(vio->lp); 720 vio->lp = NULL; 721 722 kfree(vio->desc_buf); 723 vio->desc_buf = NULL; 724 vio->desc_buf_len = 0; 725} 726EXPORT_SYMBOL(vio_ldc_free); 727 728void vio_port_up(struct vio_driver_state *vio) 729{ 730 unsigned long flags; 731 int err, state; 732 733 spin_lock_irqsave(&vio->lock, flags); 734 735 state = ldc_state(vio->lp); 736 737 err = 0; 738 if (state == LDC_STATE_INIT) { 739 err = ldc_bind(vio->lp, vio->name); 740 if (err) 741 printk(KERN_WARNING "%s: Port %lu bind failed, " 742 "err=%d\n", 743 vio->name, vio->vdev->channel_id, err); 744 } 745 746 if (!err) { 747 err = ldc_connect(vio->lp); 748 if (err) 749 printk(KERN_WARNING "%s: Port %lu connect failed, " 750 "err=%d\n", 751 vio->name, vio->vdev->channel_id, err); 752 } 753 if (err) { 754 unsigned long expires = jiffies + HZ; 755 756 expires = round_jiffies(expires); 757 mod_timer(&vio->timer, expires); 758 } 759 760 spin_unlock_irqrestore(&vio->lock, flags); 761} 762EXPORT_SYMBOL(vio_port_up); 763 764static void vio_port_timer(unsigned long _arg) 765{ 766 struct vio_driver_state *vio = (struct vio_driver_state *) _arg; 767 768 vio_port_up(vio); 769} 770 771int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev, 772 u8 dev_class, struct vio_version *ver_table, 773 int ver_table_size, struct vio_driver_ops *ops, 774 char *name) 775{ 776 switch (dev_class) { 777 case VDEV_NETWORK: 778 case VDEV_NETWORK_SWITCH: 779 case VDEV_DISK: 780 case VDEV_DISK_SERVER: 781 break; 782 783 default: 784 return -EINVAL; 785 } 786 787 if (!ops->send_attr || 788 !ops->handle_attr || 789 !ops->handshake_complete) 790 return -EINVAL; 791 792 if (!ver_table || ver_table_size < 0) 793 return -EINVAL; 794 795 if (!name) 796 return -EINVAL; 797 798 spin_lock_init(&vio->lock); 799 800 vio->name = name; 801 802 vio->dev_class = dev_class; 803 vio->vdev = vdev; 804 805 vio->ver_table = ver_table; 806 vio->ver_table_entries = ver_table_size; 807 808 vio->ops = ops; 809 810 setup_timer(&vio->timer, vio_port_timer, (unsigned long) vio); 811 812 return 0; 813} 814EXPORT_SYMBOL(vio_driver_init); 815