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