0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/export.h>
0009 #include <linux/string.h>
0010 #include <linux/delay.h>
0011 #include <linux/sched.h>
0012 #include <linux/sched/clock.h>
0013 #include <linux/slab.h>
0014
0015 #include <asm/ldc.h>
0016 #include <asm/vio.h>
0017
0018 int vio_ldc_send(struct vio_driver_state *vio, void *data, int len)
0019 {
0020 int err, limit = 1000;
0021
0022 err = -EINVAL;
0023 while (limit-- > 0) {
0024 err = ldc_write(vio->lp, data, len);
0025 if (!err || (err != -EAGAIN))
0026 break;
0027 udelay(1);
0028 }
0029
0030 return err;
0031 }
0032 EXPORT_SYMBOL(vio_ldc_send);
0033
0034 static int send_ctrl(struct vio_driver_state *vio,
0035 struct vio_msg_tag *tag, int len)
0036 {
0037 tag->sid = vio_send_sid(vio);
0038 return vio_ldc_send(vio, tag, len);
0039 }
0040
0041 static void init_tag(struct vio_msg_tag *tag, u8 type, u8 stype, u16 stype_env)
0042 {
0043 tag->type = type;
0044 tag->stype = stype;
0045 tag->stype_env = stype_env;
0046 }
0047
0048 static int send_version(struct vio_driver_state *vio, u16 major, u16 minor)
0049 {
0050 struct vio_ver_info pkt;
0051
0052 vio->_local_sid = (u32) sched_clock();
0053
0054 memset(&pkt, 0, sizeof(pkt));
0055 init_tag(&pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_VER_INFO);
0056 pkt.major = major;
0057 pkt.minor = minor;
0058 pkt.dev_class = vio->dev_class;
0059
0060 viodbg(HS, "SEND VERSION INFO maj[%u] min[%u] devclass[%u]\n",
0061 major, minor, vio->dev_class);
0062
0063 return send_ctrl(vio, &pkt.tag, sizeof(pkt));
0064 }
0065
0066 static int start_handshake(struct vio_driver_state *vio)
0067 {
0068 int err;
0069
0070 viodbg(HS, "START HANDSHAKE\n");
0071
0072 vio->hs_state = VIO_HS_INVALID;
0073
0074 err = send_version(vio,
0075 vio->ver_table[0].major,
0076 vio->ver_table[0].minor);
0077 if (err < 0)
0078 return err;
0079
0080 return 0;
0081 }
0082
0083 static void flush_rx_dring(struct vio_driver_state *vio)
0084 {
0085 struct vio_dring_state *dr;
0086 u64 ident;
0087
0088 BUG_ON(!(vio->dr_state & VIO_DR_STATE_RXREG));
0089
0090 dr = &vio->drings[VIO_DRIVER_RX_RING];
0091 ident = dr->ident;
0092
0093 BUG_ON(!vio->desc_buf);
0094 kfree(vio->desc_buf);
0095 vio->desc_buf = NULL;
0096
0097 memset(dr, 0, sizeof(*dr));
0098 dr->ident = ident;
0099 }
0100
0101 void vio_link_state_change(struct vio_driver_state *vio, int event)
0102 {
0103 if (event == LDC_EVENT_UP) {
0104 vio->hs_state = VIO_HS_INVALID;
0105
0106 switch (vio->dev_class) {
0107 case VDEV_NETWORK:
0108 case VDEV_NETWORK_SWITCH:
0109 vio->dr_state = (VIO_DR_STATE_TXREQ |
0110 VIO_DR_STATE_RXREQ);
0111 break;
0112
0113 case VDEV_DISK:
0114 vio->dr_state = VIO_DR_STATE_TXREQ;
0115 break;
0116 case VDEV_DISK_SERVER:
0117 vio->dr_state = VIO_DR_STATE_RXREQ;
0118 break;
0119 }
0120 start_handshake(vio);
0121 } else if (event == LDC_EVENT_RESET) {
0122 vio->hs_state = VIO_HS_INVALID;
0123
0124 if (vio->dr_state & VIO_DR_STATE_RXREG)
0125 flush_rx_dring(vio);
0126
0127 vio->dr_state = 0x00;
0128 memset(&vio->ver, 0, sizeof(vio->ver));
0129
0130 ldc_disconnect(vio->lp);
0131 }
0132 }
0133 EXPORT_SYMBOL(vio_link_state_change);
0134
0135 static int handshake_failure(struct vio_driver_state *vio)
0136 {
0137 struct vio_dring_state *dr;
0138
0139
0140
0141
0142
0143
0144 viodbg(HS, "HANDSHAKE FAILURE\n");
0145
0146 vio->dr_state &= ~(VIO_DR_STATE_TXREG |
0147 VIO_DR_STATE_RXREG);
0148
0149 dr = &vio->drings[VIO_DRIVER_RX_RING];
0150 memset(dr, 0, sizeof(*dr));
0151
0152 kfree(vio->desc_buf);
0153 vio->desc_buf = NULL;
0154 vio->desc_buf_len = 0;
0155
0156 vio->hs_state = VIO_HS_INVALID;
0157
0158 return -ECONNRESET;
0159 }
0160
0161 static int process_unknown(struct vio_driver_state *vio, void *arg)
0162 {
0163 struct vio_msg_tag *pkt = arg;
0164
0165 viodbg(HS, "UNKNOWN CONTROL [%02x:%02x:%04x:%08x]\n",
0166 pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
0167
0168 printk(KERN_ERR "vio: ID[%lu] Resetting connection.\n",
0169 vio->vdev->channel_id);
0170
0171 ldc_disconnect(vio->lp);
0172
0173 return -ECONNRESET;
0174 }
0175
0176 static int send_dreg(struct vio_driver_state *vio)
0177 {
0178 struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_TX_RING];
0179 union {
0180 struct vio_dring_register pkt;
0181 char all[sizeof(struct vio_dring_register) +
0182 (sizeof(struct ldc_trans_cookie) *
0183 VIO_MAX_RING_COOKIES)];
0184 } u;
0185 size_t bytes = sizeof(struct vio_dring_register) +
0186 (sizeof(struct ldc_trans_cookie) *
0187 dr->ncookies);
0188 int i;
0189
0190 if (WARN_ON(bytes > sizeof(u)))
0191 return -EINVAL;
0192
0193 memset(&u, 0, bytes);
0194 init_tag(&u.pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_DRING_REG);
0195 u.pkt.dring_ident = 0;
0196 u.pkt.num_descr = dr->num_entries;
0197 u.pkt.descr_size = dr->entry_size;
0198 u.pkt.options = VIO_TX_DRING;
0199 u.pkt.num_cookies = dr->ncookies;
0200
0201 viodbg(HS, "SEND DRING_REG INFO ndesc[%u] dsz[%u] opt[0x%x] "
0202 "ncookies[%u]\n",
0203 u.pkt.num_descr, u.pkt.descr_size, u.pkt.options,
0204 u.pkt.num_cookies);
0205
0206 for (i = 0; i < dr->ncookies; i++) {
0207 u.pkt.cookies[i] = dr->cookies[i];
0208
0209 viodbg(HS, "DRING COOKIE(%d) [%016llx:%016llx]\n",
0210 i,
0211 (unsigned long long) u.pkt.cookies[i].cookie_addr,
0212 (unsigned long long) u.pkt.cookies[i].cookie_size);
0213 }
0214
0215 return send_ctrl(vio, &u.pkt.tag, bytes);
0216 }
0217
0218 static int send_rdx(struct vio_driver_state *vio)
0219 {
0220 struct vio_rdx pkt;
0221
0222 memset(&pkt, 0, sizeof(pkt));
0223
0224 init_tag(&pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_RDX);
0225
0226 viodbg(HS, "SEND RDX INFO\n");
0227
0228 return send_ctrl(vio, &pkt.tag, sizeof(pkt));
0229 }
0230
0231 static int send_attr(struct vio_driver_state *vio)
0232 {
0233 if (!vio->ops)
0234 return -EINVAL;
0235
0236 return vio->ops->send_attr(vio);
0237 }
0238
0239 static struct vio_version *find_by_major(struct vio_driver_state *vio,
0240 u16 major)
0241 {
0242 struct vio_version *ret = NULL;
0243 int i;
0244
0245 for (i = 0; i < vio->ver_table_entries; i++) {
0246 struct vio_version *v = &vio->ver_table[i];
0247 if (v->major <= major) {
0248 ret = v;
0249 break;
0250 }
0251 }
0252 return ret;
0253 }
0254
0255 static int process_ver_info(struct vio_driver_state *vio,
0256 struct vio_ver_info *pkt)
0257 {
0258 struct vio_version *vap;
0259 int err;
0260
0261 viodbg(HS, "GOT VERSION INFO maj[%u] min[%u] devclass[%u]\n",
0262 pkt->major, pkt->minor, pkt->dev_class);
0263
0264 if (vio->hs_state != VIO_HS_INVALID) {
0265
0266 memset(&vio->ver, 0, sizeof(vio->ver));
0267 vio->hs_state = VIO_HS_INVALID;
0268 }
0269
0270 vap = find_by_major(vio, pkt->major);
0271
0272 vio->_peer_sid = pkt->tag.sid;
0273
0274 if (!vap) {
0275 pkt->tag.stype = VIO_SUBTYPE_NACK;
0276 pkt->major = 0;
0277 pkt->minor = 0;
0278 viodbg(HS, "SEND VERSION NACK maj[0] min[0]\n");
0279 err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
0280 } else if (vap->major != pkt->major) {
0281 pkt->tag.stype = VIO_SUBTYPE_NACK;
0282 pkt->major = vap->major;
0283 pkt->minor = vap->minor;
0284 viodbg(HS, "SEND VERSION NACK maj[%u] min[%u]\n",
0285 pkt->major, pkt->minor);
0286 err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
0287 } else {
0288 struct vio_version ver = {
0289 .major = pkt->major,
0290 .minor = pkt->minor,
0291 };
0292 if (ver.minor > vap->minor)
0293 ver.minor = vap->minor;
0294 pkt->minor = ver.minor;
0295 pkt->tag.stype = VIO_SUBTYPE_ACK;
0296 pkt->dev_class = vio->dev_class;
0297 viodbg(HS, "SEND VERSION ACK maj[%u] min[%u]\n",
0298 pkt->major, pkt->minor);
0299 err = send_ctrl(vio, &pkt->tag, sizeof(*pkt));
0300 if (err > 0) {
0301 vio->ver = ver;
0302 vio->hs_state = VIO_HS_GOTVERS;
0303 }
0304 }
0305 if (err < 0)
0306 return handshake_failure(vio);
0307
0308 return 0;
0309 }
0310
0311 static int process_ver_ack(struct vio_driver_state *vio,
0312 struct vio_ver_info *pkt)
0313 {
0314 viodbg(HS, "GOT VERSION ACK maj[%u] min[%u] devclass[%u]\n",
0315 pkt->major, pkt->minor, pkt->dev_class);
0316
0317 if (vio->hs_state & VIO_HS_GOTVERS) {
0318 if (vio->ver.major != pkt->major ||
0319 vio->ver.minor != pkt->minor) {
0320 pkt->tag.stype = VIO_SUBTYPE_NACK;
0321 (void) send_ctrl(vio, &pkt->tag, sizeof(*pkt));
0322 return handshake_failure(vio);
0323 }
0324 } else {
0325 vio->ver.major = pkt->major;
0326 vio->ver.minor = pkt->minor;
0327 vio->hs_state = VIO_HS_GOTVERS;
0328 }
0329
0330 switch (vio->dev_class) {
0331 case VDEV_NETWORK:
0332 case VDEV_DISK:
0333 if (send_attr(vio) < 0)
0334 return handshake_failure(vio);
0335 break;
0336
0337 default:
0338 break;
0339 }
0340
0341 return 0;
0342 }
0343
0344 static int process_ver_nack(struct vio_driver_state *vio,
0345 struct vio_ver_info *pkt)
0346 {
0347 struct vio_version *nver;
0348
0349 viodbg(HS, "GOT VERSION NACK maj[%u] min[%u] devclass[%u]\n",
0350 pkt->major, pkt->minor, pkt->dev_class);
0351
0352 if (pkt->major == 0 && pkt->minor == 0)
0353 return handshake_failure(vio);
0354 nver = find_by_major(vio, pkt->major);
0355 if (!nver)
0356 return handshake_failure(vio);
0357
0358 if (send_version(vio, nver->major, nver->minor) < 0)
0359 return handshake_failure(vio);
0360
0361 return 0;
0362 }
0363
0364 static int process_ver(struct vio_driver_state *vio, struct vio_ver_info *pkt)
0365 {
0366 switch (pkt->tag.stype) {
0367 case VIO_SUBTYPE_INFO:
0368 return process_ver_info(vio, pkt);
0369
0370 case VIO_SUBTYPE_ACK:
0371 return process_ver_ack(vio, pkt);
0372
0373 case VIO_SUBTYPE_NACK:
0374 return process_ver_nack(vio, pkt);
0375
0376 default:
0377 return handshake_failure(vio);
0378 }
0379 }
0380
0381 static int process_attr(struct vio_driver_state *vio, void *pkt)
0382 {
0383 int err;
0384
0385 if (!(vio->hs_state & VIO_HS_GOTVERS))
0386 return handshake_failure(vio);
0387
0388 if (!vio->ops)
0389 return 0;
0390
0391 err = vio->ops->handle_attr(vio, pkt);
0392 if (err < 0) {
0393 return handshake_failure(vio);
0394 } else {
0395 vio->hs_state |= VIO_HS_GOT_ATTR;
0396
0397 if ((vio->dr_state & VIO_DR_STATE_TXREQ) &&
0398 !(vio->hs_state & VIO_HS_SENT_DREG)) {
0399 if (send_dreg(vio) < 0)
0400 return handshake_failure(vio);
0401
0402 vio->hs_state |= VIO_HS_SENT_DREG;
0403 }
0404 }
0405
0406 return 0;
0407 }
0408
0409 static int all_drings_registered(struct vio_driver_state *vio)
0410 {
0411 int need_rx, need_tx;
0412
0413 need_rx = (vio->dr_state & VIO_DR_STATE_RXREQ);
0414 need_tx = (vio->dr_state & VIO_DR_STATE_TXREQ);
0415
0416 if (need_rx &&
0417 !(vio->dr_state & VIO_DR_STATE_RXREG))
0418 return 0;
0419
0420 if (need_tx &&
0421 !(vio->dr_state & VIO_DR_STATE_TXREG))
0422 return 0;
0423
0424 return 1;
0425 }
0426
0427 static int process_dreg_info(struct vio_driver_state *vio,
0428 struct vio_dring_register *pkt)
0429 {
0430 struct vio_dring_state *dr;
0431 int i;
0432
0433 viodbg(HS, "GOT DRING_REG INFO ident[%llx] "
0434 "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
0435 (unsigned long long) pkt->dring_ident,
0436 pkt->num_descr, pkt->descr_size, pkt->options,
0437 pkt->num_cookies);
0438
0439 if (!(vio->dr_state & VIO_DR_STATE_RXREQ))
0440 goto send_nack;
0441
0442 if (vio->dr_state & VIO_DR_STATE_RXREG)
0443 goto send_nack;
0444
0445
0446 if (vio_version_after_eq(vio, 1, 6)) {
0447 if (!(pkt->options & VIO_TX_DRING))
0448 goto send_nack;
0449 pkt->options = VIO_TX_DRING;
0450 }
0451
0452 BUG_ON(vio->desc_buf);
0453
0454 vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC);
0455 if (!vio->desc_buf)
0456 goto send_nack;
0457
0458 vio->desc_buf_len = pkt->descr_size;
0459
0460 dr = &vio->drings[VIO_DRIVER_RX_RING];
0461
0462 dr->num_entries = pkt->num_descr;
0463 dr->entry_size = pkt->descr_size;
0464 dr->ncookies = pkt->num_cookies;
0465 for (i = 0; i < dr->ncookies; i++) {
0466 dr->cookies[i] = pkt->cookies[i];
0467
0468 viodbg(HS, "DRING COOKIE(%d) [%016llx:%016llx]\n",
0469 i,
0470 (unsigned long long)
0471 pkt->cookies[i].cookie_addr,
0472 (unsigned long long)
0473 pkt->cookies[i].cookie_size);
0474 }
0475
0476 pkt->tag.stype = VIO_SUBTYPE_ACK;
0477 pkt->dring_ident = ++dr->ident;
0478
0479 viodbg(HS, "SEND DRING_REG ACK ident[%llx] "
0480 "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
0481 (unsigned long long) pkt->dring_ident,
0482 pkt->num_descr, pkt->descr_size, pkt->options,
0483 pkt->num_cookies);
0484
0485 if (send_ctrl(vio, &pkt->tag, struct_size(pkt, cookies, dr->ncookies)) < 0)
0486 goto send_nack;
0487
0488 vio->dr_state |= VIO_DR_STATE_RXREG;
0489
0490 return 0;
0491
0492 send_nack:
0493 pkt->tag.stype = VIO_SUBTYPE_NACK;
0494 viodbg(HS, "SEND DRING_REG NACK\n");
0495 (void) send_ctrl(vio, &pkt->tag, sizeof(*pkt));
0496
0497 return handshake_failure(vio);
0498 }
0499
0500 static int process_dreg_ack(struct vio_driver_state *vio,
0501 struct vio_dring_register *pkt)
0502 {
0503 struct vio_dring_state *dr;
0504
0505 viodbg(HS, "GOT DRING_REG ACK ident[%llx] "
0506 "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
0507 (unsigned long long) pkt->dring_ident,
0508 pkt->num_descr, pkt->descr_size, pkt->options,
0509 pkt->num_cookies);
0510
0511 dr = &vio->drings[VIO_DRIVER_TX_RING];
0512
0513 if (!(vio->dr_state & VIO_DR_STATE_TXREQ))
0514 return handshake_failure(vio);
0515
0516 dr->ident = pkt->dring_ident;
0517 vio->dr_state |= VIO_DR_STATE_TXREG;
0518
0519 if (all_drings_registered(vio)) {
0520 if (send_rdx(vio) < 0)
0521 return handshake_failure(vio);
0522 vio->hs_state = VIO_HS_SENT_RDX;
0523 }
0524 return 0;
0525 }
0526
0527 static int process_dreg_nack(struct vio_driver_state *vio,
0528 struct vio_dring_register *pkt)
0529 {
0530 viodbg(HS, "GOT DRING_REG NACK ident[%llx] "
0531 "ndesc[%u] dsz[%u] opt[0x%x] ncookies[%u]\n",
0532 (unsigned long long) pkt->dring_ident,
0533 pkt->num_descr, pkt->descr_size, pkt->options,
0534 pkt->num_cookies);
0535
0536 return handshake_failure(vio);
0537 }
0538
0539 static int process_dreg(struct vio_driver_state *vio,
0540 struct vio_dring_register *pkt)
0541 {
0542 if (!(vio->hs_state & VIO_HS_GOTVERS))
0543 return handshake_failure(vio);
0544
0545 switch (pkt->tag.stype) {
0546 case VIO_SUBTYPE_INFO:
0547 return process_dreg_info(vio, pkt);
0548
0549 case VIO_SUBTYPE_ACK:
0550 return process_dreg_ack(vio, pkt);
0551
0552 case VIO_SUBTYPE_NACK:
0553 return process_dreg_nack(vio, pkt);
0554
0555 default:
0556 return handshake_failure(vio);
0557 }
0558 }
0559
0560 static int process_dunreg(struct vio_driver_state *vio,
0561 struct vio_dring_unregister *pkt)
0562 {
0563 struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_RX_RING];
0564
0565 viodbg(HS, "GOT DRING_UNREG\n");
0566
0567 if (pkt->dring_ident != dr->ident)
0568 return 0;
0569
0570 vio->dr_state &= ~VIO_DR_STATE_RXREG;
0571
0572 memset(dr, 0, sizeof(*dr));
0573
0574 kfree(vio->desc_buf);
0575 vio->desc_buf = NULL;
0576 vio->desc_buf_len = 0;
0577
0578 return 0;
0579 }
0580
0581 static int process_rdx_info(struct vio_driver_state *vio, struct vio_rdx *pkt)
0582 {
0583 viodbg(HS, "GOT RDX INFO\n");
0584
0585 pkt->tag.stype = VIO_SUBTYPE_ACK;
0586 viodbg(HS, "SEND RDX ACK\n");
0587 if (send_ctrl(vio, &pkt->tag, sizeof(*pkt)) < 0)
0588 return handshake_failure(vio);
0589
0590 vio->hs_state |= VIO_HS_SENT_RDX_ACK;
0591 return 0;
0592 }
0593
0594 static int process_rdx_ack(struct vio_driver_state *vio, struct vio_rdx *pkt)
0595 {
0596 viodbg(HS, "GOT RDX ACK\n");
0597
0598 if (!(vio->hs_state & VIO_HS_SENT_RDX))
0599 return handshake_failure(vio);
0600
0601 vio->hs_state |= VIO_HS_GOT_RDX_ACK;
0602 return 0;
0603 }
0604
0605 static int process_rdx_nack(struct vio_driver_state *vio, struct vio_rdx *pkt)
0606 {
0607 viodbg(HS, "GOT RDX NACK\n");
0608
0609 return handshake_failure(vio);
0610 }
0611
0612 static int process_rdx(struct vio_driver_state *vio, struct vio_rdx *pkt)
0613 {
0614 if (!all_drings_registered(vio))
0615 handshake_failure(vio);
0616
0617 switch (pkt->tag.stype) {
0618 case VIO_SUBTYPE_INFO:
0619 return process_rdx_info(vio, pkt);
0620
0621 case VIO_SUBTYPE_ACK:
0622 return process_rdx_ack(vio, pkt);
0623
0624 case VIO_SUBTYPE_NACK:
0625 return process_rdx_nack(vio, pkt);
0626
0627 default:
0628 return handshake_failure(vio);
0629 }
0630 }
0631
0632 int vio_control_pkt_engine(struct vio_driver_state *vio, void *pkt)
0633 {
0634 struct vio_msg_tag *tag = pkt;
0635 u8 prev_state = vio->hs_state;
0636 int err;
0637
0638 switch (tag->stype_env) {
0639 case VIO_VER_INFO:
0640 err = process_ver(vio, pkt);
0641 break;
0642
0643 case VIO_ATTR_INFO:
0644 err = process_attr(vio, pkt);
0645 break;
0646
0647 case VIO_DRING_REG:
0648 err = process_dreg(vio, pkt);
0649 break;
0650
0651 case VIO_DRING_UNREG:
0652 err = process_dunreg(vio, pkt);
0653 break;
0654
0655 case VIO_RDX:
0656 err = process_rdx(vio, pkt);
0657 break;
0658
0659 default:
0660 err = process_unknown(vio, pkt);
0661 break;
0662 }
0663
0664 if (!err &&
0665 vio->hs_state != prev_state &&
0666 (vio->hs_state & VIO_HS_COMPLETE)) {
0667 if (vio->ops)
0668 vio->ops->handshake_complete(vio);
0669 }
0670
0671 return err;
0672 }
0673 EXPORT_SYMBOL(vio_control_pkt_engine);
0674
0675 void vio_conn_reset(struct vio_driver_state *vio)
0676 {
0677 }
0678 EXPORT_SYMBOL(vio_conn_reset);
0679
0680
0681
0682
0683
0684
0685 int vio_validate_sid(struct vio_driver_state *vio, struct vio_msg_tag *tp)
0686 {
0687 u32 sid;
0688
0689
0690
0691
0692 if (tp->type == VIO_TYPE_CTRL &&
0693 tp->stype == VIO_SUBTYPE_INFO &&
0694 tp->stype_env == VIO_VER_INFO)
0695 return 0;
0696
0697
0698 switch (vio->dev_class) {
0699 case VDEV_NETWORK:
0700 case VDEV_NETWORK_SWITCH:
0701 case VDEV_DISK_SERVER:
0702 default:
0703 sid = vio->_peer_sid;
0704 break;
0705
0706 case VDEV_DISK:
0707 sid = vio->_local_sid;
0708 break;
0709 }
0710
0711 if (sid == tp->sid)
0712 return 0;
0713 viodbg(DATA, "BAD SID tag->sid[%08x] peer_sid[%08x] local_sid[%08x]\n",
0714 tp->sid, vio->_peer_sid, vio->_local_sid);
0715 return -EINVAL;
0716 }
0717 EXPORT_SYMBOL(vio_validate_sid);
0718
0719 u32 vio_send_sid(struct vio_driver_state *vio)
0720 {
0721 switch (vio->dev_class) {
0722 case VDEV_NETWORK:
0723 case VDEV_NETWORK_SWITCH:
0724 case VDEV_DISK:
0725 default:
0726 return vio->_local_sid;
0727
0728 case VDEV_DISK_SERVER:
0729 return vio->_peer_sid;
0730 }
0731 }
0732 EXPORT_SYMBOL(vio_send_sid);
0733
0734 int vio_ldc_alloc(struct vio_driver_state *vio,
0735 struct ldc_channel_config *base_cfg,
0736 void *event_arg)
0737 {
0738 struct ldc_channel_config cfg = *base_cfg;
0739 struct ldc_channel *lp;
0740
0741 cfg.tx_irq = vio->vdev->tx_irq;
0742 cfg.rx_irq = vio->vdev->rx_irq;
0743
0744 lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg, vio->name);
0745 if (IS_ERR(lp))
0746 return PTR_ERR(lp);
0747
0748 vio->lp = lp;
0749
0750 return 0;
0751 }
0752 EXPORT_SYMBOL(vio_ldc_alloc);
0753
0754 void vio_ldc_free(struct vio_driver_state *vio)
0755 {
0756 ldc_free(vio->lp);
0757 vio->lp = NULL;
0758
0759 kfree(vio->desc_buf);
0760 vio->desc_buf = NULL;
0761 vio->desc_buf_len = 0;
0762 }
0763 EXPORT_SYMBOL(vio_ldc_free);
0764
0765 void vio_port_up(struct vio_driver_state *vio)
0766 {
0767 unsigned long flags;
0768 int err, state;
0769
0770 spin_lock_irqsave(&vio->lock, flags);
0771
0772 state = ldc_state(vio->lp);
0773
0774 err = 0;
0775 if (state == LDC_STATE_INIT) {
0776 err = ldc_bind(vio->lp);
0777 if (err)
0778 printk(KERN_WARNING "%s: Port %lu bind failed, "
0779 "err=%d\n",
0780 vio->name, vio->vdev->channel_id, err);
0781 }
0782
0783 if (!err) {
0784 if (ldc_mode(vio->lp) == LDC_MODE_RAW)
0785 ldc_set_state(vio->lp, LDC_STATE_CONNECTED);
0786 else
0787 err = ldc_connect(vio->lp);
0788
0789 if (err)
0790 printk(KERN_WARNING "%s: Port %lu connect failed, "
0791 "err=%d\n",
0792 vio->name, vio->vdev->channel_id, err);
0793 }
0794 if (err) {
0795 unsigned long expires = jiffies + HZ;
0796
0797 expires = round_jiffies(expires);
0798 mod_timer(&vio->timer, expires);
0799 }
0800
0801 spin_unlock_irqrestore(&vio->lock, flags);
0802 }
0803 EXPORT_SYMBOL(vio_port_up);
0804
0805 static void vio_port_timer(struct timer_list *t)
0806 {
0807 struct vio_driver_state *vio = from_timer(vio, t, timer);
0808
0809 vio_port_up(vio);
0810 }
0811
0812 int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
0813 u8 dev_class, struct vio_version *ver_table,
0814 int ver_table_size, struct vio_driver_ops *ops,
0815 char *name)
0816 {
0817 switch (dev_class) {
0818 case VDEV_NETWORK:
0819 case VDEV_NETWORK_SWITCH:
0820 case VDEV_DISK:
0821 case VDEV_DISK_SERVER:
0822 case VDEV_CONSOLE_CON:
0823 break;
0824
0825 default:
0826 return -EINVAL;
0827 }
0828
0829 if (dev_class == VDEV_NETWORK ||
0830 dev_class == VDEV_NETWORK_SWITCH ||
0831 dev_class == VDEV_DISK ||
0832 dev_class == VDEV_DISK_SERVER) {
0833 if (!ops || !ops->send_attr || !ops->handle_attr ||
0834 !ops->handshake_complete)
0835 return -EINVAL;
0836 }
0837
0838 if (!ver_table || ver_table_size < 0)
0839 return -EINVAL;
0840
0841 if (!name)
0842 return -EINVAL;
0843
0844 spin_lock_init(&vio->lock);
0845
0846 vio->name = name;
0847
0848 vio->dev_class = dev_class;
0849 vio->vdev = vdev;
0850
0851 vio->ver_table = ver_table;
0852 vio->ver_table_entries = ver_table_size;
0853
0854 vio->ops = ops;
0855
0856 timer_setup(&vio->timer, vio_port_timer, 0);
0857
0858 return 0;
0859 }
0860 EXPORT_SYMBOL(vio_driver_init);