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