return 0;
}
+static void flush_rx_dring(struct vio_driver_state *vio)
+{
+ struct vio_dring_state *dr;
+ u64 ident;
+
+ BUG_ON(!(vio->dr_state & VIO_DR_STATE_RXREG));
+
+ dr = &vio->drings[VIO_DRIVER_RX_RING];
+ ident = dr->ident;
+
+ BUG_ON(!vio->desc_buf);
+ kfree(vio->desc_buf);
+ vio->desc_buf = NULL;
+
+ memset(dr, 0, sizeof(*dr));
+ dr->ident = ident;
+}
+
void vio_link_state_change(struct vio_driver_state *vio, int event)
{
if (event == LDC_EVENT_UP) {
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);
pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
printk(KERN_ERR "vio: ID[%lu] Resetting connection.\n",
- vio->channel_id);
+ vio->vdev->channel_id);
ldc_disconnect(vio->lp);
if (vio->dr_state & VIO_DR_STATE_RXREG)
goto send_nack;
+ BUG_ON(vio->desc_buf);
+
vio->desc_buf = kzalloc(pkt->descr_size, GFP_ATOMIC);
if (!vio->desc_buf)
goto send_nack;
}
EXPORT_SYMBOL(vio_send_sid);
-extern int vio_ldc_alloc(struct vio_driver_state *vio,
+int vio_ldc_alloc(struct vio_driver_state *vio,
struct ldc_channel_config *base_cfg,
void *event_arg)
{
struct ldc_channel_config cfg = *base_cfg;
struct ldc_channel *lp;
- const u64 *id;
- id = md_get_property(vio->endpoint, "id", NULL);
- if (!id) {
- printk(KERN_ERR "%s: Channel lacks id property.\n",
- vio->name);
- return -ENODEV;
- }
-
- vio->channel_id = *id;
-
- cfg.rx_irq = vio->rx_irq;
- cfg.tx_irq = vio->tx_irq;
+ cfg.tx_irq = vio->vdev->tx_irq;
+ cfg.rx_irq = vio->vdev->rx_irq;
- lp = ldc_alloc(vio->channel_id, &cfg, event_arg);
+ lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg);
if (IS_ERR(lp))
return PTR_ERR(lp);
err = 0;
if (state == LDC_STATE_INIT) {
- err = ldc_bind(vio->lp);
+ err = ldc_bind(vio->lp, vio->name);
if (err)
printk(KERN_WARNING "%s: Port %lu bind failed, "
"err=%d\n",
- vio->name, vio->channel_id, err);
+ vio->name, vio->vdev->channel_id, err);
}
if (!err) {
if (err)
printk(KERN_WARNING "%s: Port %lu connect failed, "
"err=%d\n",
- vio->name, vio->channel_id, err);
+ vio->name, vio->vdev->channel_id, err);
}
if (err) {
unsigned long expires = jiffies + HZ;
}
int vio_driver_init(struct vio_driver_state *vio, struct vio_dev *vdev,
- u8 dev_class, struct mdesc_node *channel_endpoint,
- struct vio_version *ver_table, int ver_table_size,
- struct vio_driver_ops *ops, char *name)
+ u8 dev_class, struct vio_version *ver_table,
+ int ver_table_size, struct vio_driver_ops *ops,
+ char *name)
{
switch (dev_class) {
case VDEV_NETWORK:
!ops->handshake_complete)
return -EINVAL;
- if (!channel_endpoint)
- return -EINVAL;
-
if (!ver_table || ver_table_size < 0)
return -EINVAL;
vio->dev_class = dev_class;
vio->vdev = vdev;
- vio->endpoint = channel_endpoint;
- vio->tx_irq = channel_endpoint->irqs[0];
- vio->rx_irq = channel_endpoint->irqs[1];
-
vio->ver_table = ver_table;
vio->ver_table_entries = ver_table_size;