arch/sparc/kernel/viohs.c

Source file repositories/reference/linux-study-clean/arch/sparc/kernel/viohs.c

File Facts

System
Linux kernel
Corpus path
arch/sparc/kernel/viohs.c
Extension
.c
Size
19025 bytes
Lines
861
Domain
Architecture Layer
Bucket
arch/sparc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (vio->dev_class) {
		case VDEV_NETWORK:
		case VDEV_NETWORK_SWITCH:
			vio->dr_state = (VIO_DR_STATE_TXREQ |
					 VIO_DR_STATE_RXREQ);
			break;

		case VDEV_DISK:
			vio->dr_state = VIO_DR_STATE_TXREQ;
			break;
		case VDEV_DISK_SERVER:
			vio->dr_state = VIO_DR_STATE_RXREQ;
			break;
		}
		start_handshake(vio);
	} else if (event == LDC_EVENT_RESET) {
		vio->hs_state = VIO_HS_INVALID;

		if (vio->dr_state & VIO_DR_STATE_RXREG)
			flush_rx_dring(vio);

		vio->dr_state = 0x00;
		memset(&vio->ver, 0, sizeof(vio->ver));

		ldc_disconnect(vio->lp);
	}
}
EXPORT_SYMBOL(vio_link_state_change);

static int handshake_failure(struct vio_driver_state *vio)
{
	struct vio_dring_state *dr;

	/* XXX Put policy here...  Perhaps start a timer to fire
	 * XXX in 100 ms, which will bring the link up and retry
	 * XXX the handshake.
	 */

	viodbg(HS, "HANDSHAKE FAILURE\n");

	vio->dr_state &= ~(VIO_DR_STATE_TXREG |
			   VIO_DR_STATE_RXREG);

	dr = &vio->drings[VIO_DRIVER_RX_RING];
	memset(dr, 0, sizeof(*dr));

	kfree(vio->desc_buf);
	vio->desc_buf = NULL;
	vio->desc_buf_len = 0;

	vio->hs_state = VIO_HS_INVALID;

	return -ECONNRESET;
}

static int process_unknown(struct vio_driver_state *vio, void *arg)
{
	struct vio_msg_tag *pkt = arg;

	viodbg(HS, "UNKNOWN CONTROL [%02x:%02x:%04x:%08x]\n",
	       pkt->type, pkt->stype, pkt->stype_env, pkt->sid);

	printk(KERN_ERR "vio: ID[%lu] Resetting connection.\n",
	       vio->vdev->channel_id);

	ldc_disconnect(vio->lp);

	return -ECONNRESET;
}

static int send_dreg(struct vio_driver_state *vio)
{
	struct vio_dring_state *dr = &vio->drings[VIO_DRIVER_TX_RING];
	union {
		struct vio_dring_register pkt;
		char all[sizeof(struct vio_dring_register) +
			 (sizeof(struct ldc_trans_cookie) *
			  VIO_MAX_RING_COOKIES)];
	} u;
	size_t bytes = sizeof(struct vio_dring_register) +
		       (sizeof(struct ldc_trans_cookie) *
			dr->ncookies);
	int i;

	if (WARN_ON(bytes > sizeof(u)))
		return -EINVAL;

	memset(&u, 0, bytes);
	init_tag(&u.pkt.tag, VIO_TYPE_CTRL, VIO_SUBTYPE_INFO, VIO_DRING_REG);
	u.pkt.dring_ident = 0;

Annotation

Implementation Notes