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