root/arch/sparc/kernel/viohs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vio_ldc_send
  2. send_ctrl
  3. init_tag
  4. send_version
  5. start_handshake
  6. flush_rx_dring
  7. vio_link_state_change
  8. handshake_failure
  9. process_unknown
  10. send_dreg
  11. send_rdx
  12. send_attr
  13. find_by_major
  14. process_ver_info
  15. process_ver_ack
  16. process_ver_nack
  17. process_ver
  18. process_attr
  19. all_drings_registered
  20. process_dreg_info
  21. process_dreg_ack
  22. process_dreg_nack
  23. process_dreg
  24. process_dunreg
  25. process_rdx_info
  26. process_rdx_ack
  27. process_rdx_nack
  28. process_rdx
  29. vio_control_pkt_engine
  30. vio_conn_reset
  31. vio_validate_sid
  32. vio_send_sid
  33. vio_ldc_alloc
  34. vio_ldc_free
  35. vio_port_up
  36. vio_port_timer
  37. vio_driver_init

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

/* [<][>][^][v][top][bottom][index][help] */