Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c21c4ab0 authored by Sowmini Varadhan's avatar Sowmini Varadhan Committed by David S. Miller
Browse files

sparc64: Move request_irq() from ldc_bind() to ldc_alloc()



The request_irq() needs to be done from ldc_alloc()
to avoid the following (caught by lockdep)

 [00000000004a0738] __might_sleep+0xf8/0x120
 [000000000058bea4] kmem_cache_alloc_trace+0x184/0x2c0
 [00000000004faf80] request_threaded_irq+0x80/0x160
 [000000000044f71c] ldc_bind+0x7c/0x220
 [0000000000452454] vio_port_up+0x54/0xe0
 [00000000101f6778] probe_disk+0x38/0x220 [sunvdc]
 [00000000101f6b8c] vdc_port_probe+0x22c/0x300 [sunvdc]
 [0000000000451a88] vio_device_probe+0x48/0x60
 [000000000074c56c] really_probe+0x6c/0x300
 [000000000074c83c] driver_probe_device+0x3c/0xa0
 [000000000074c92c] __driver_attach+0x8c/0xa0
 [000000000074a6ec] bus_for_each_dev+0x6c/0xa0
 [000000000074c1dc] driver_attach+0x1c/0x40
 [000000000074b0fc] bus_add_driver+0xbc/0x280

Signed-off-by: default avatarSowmini Varadhan <sowmini.varadhan@oracle.com>
Acked-by: default avatarDwight Engen <dwight.engen@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 05aa1651
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -53,13 +53,14 @@ struct ldc_channel;
/* Allocate state for a channel.  */
struct ldc_channel *ldc_alloc(unsigned long id,
			      const struct ldc_channel_config *cfgp,
			      void *event_arg);
			      void *event_arg,
			      const char *name);

/* Shut down and free state for a channel.  */
void ldc_free(struct ldc_channel *lp);

/* Register TX and RX queues of the link with the hypervisor.  */
int ldc_bind(struct ldc_channel *lp, const char *name);
int ldc_bind(struct ldc_channel *lp);

/* For non-RAW protocols we need to complete a handshake before
 * communication can proceed.  ldc_connect() does that, if the
+2 −2
Original line number Diff line number Diff line
@@ -1200,14 +1200,14 @@ static int ds_probe(struct vio_dev *vdev, const struct vio_device_id *id)
	ds_cfg.tx_irq = vdev->tx_irq;
	ds_cfg.rx_irq = vdev->rx_irq;

	lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp);
	lp = ldc_alloc(vdev->channel_id, &ds_cfg, dp, "DS");
	if (IS_ERR(lp)) {
		err = PTR_ERR(lp);
		goto out_free_ds_states;
	}
	dp->lp = lp;

	err = ldc_bind(lp, "DS");
	err = ldc_bind(lp);
	if (err)
		goto out_free_ldc;

+21 −20
Original line number Diff line number Diff line
@@ -1078,7 +1078,8 @@ static void ldc_iommu_release(struct ldc_channel *lp)

struct ldc_channel *ldc_alloc(unsigned long id,
			      const struct ldc_channel_config *cfgp,
			      void *event_arg)
			      void *event_arg,
			      const char *name)
{
	struct ldc_channel *lp;
	const struct ldc_mode_ops *mops;
@@ -1093,6 +1094,8 @@ struct ldc_channel *ldc_alloc(unsigned long id,
	err = -EINVAL;
	if (!cfgp)
		goto out_err;
	if (!name)
		goto out_err;

	switch (cfgp->mode) {
	case LDC_MODE_RAW:
@@ -1185,6 +1188,21 @@ struct ldc_channel *ldc_alloc(unsigned long id,

	INIT_HLIST_HEAD(&lp->mh_list);

	snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
	snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);

	err = request_irq(lp->cfg.rx_irq, ldc_rx, 0,
			  lp->rx_irq_name, lp);
	if (err)
		goto out_free_txq;

	err = request_irq(lp->cfg.tx_irq, ldc_tx, 0,
			  lp->tx_irq_name, lp);
	if (err) {
		free_irq(lp->cfg.rx_irq, lp);
		goto out_free_txq;
	}

	return lp;

out_free_txq:
@@ -1237,31 +1255,14 @@ EXPORT_SYMBOL(ldc_free);
 * state.  This does not initiate a handshake, ldc_connect() does
 * that.
 */
int ldc_bind(struct ldc_channel *lp, const char *name)
int ldc_bind(struct ldc_channel *lp)
{
	unsigned long hv_err, flags;
	int err = -EINVAL;

	if (!name ||
	    (lp->state != LDC_STATE_INIT))
	if (lp->state != LDC_STATE_INIT)
		return -EINVAL;

	snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
	snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);

	err = request_irq(lp->cfg.rx_irq, ldc_rx, 0,
			  lp->rx_irq_name, lp);
	if (err)
		return err;

	err = request_irq(lp->cfg.tx_irq, ldc_tx, 0,
			  lp->tx_irq_name, lp);
	if (err) {
		free_irq(lp->cfg.rx_irq, lp);
		return err;
	}


	spin_lock_irqsave(&lp->lock, flags);

	enable_irq(lp->cfg.rx_irq);
+2 −2
Original line number Diff line number Diff line
@@ -714,7 +714,7 @@ int vio_ldc_alloc(struct vio_driver_state *vio,
	cfg.tx_irq = vio->vdev->tx_irq;
	cfg.rx_irq = vio->vdev->rx_irq;

	lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg);
	lp = ldc_alloc(vio->vdev->channel_id, &cfg, event_arg, vio->name);
	if (IS_ERR(lp))
		return PTR_ERR(lp);

@@ -746,7 +746,7 @@ void vio_port_up(struct vio_driver_state *vio)

	err = 0;
	if (state == LDC_STATE_INIT) {
		err = ldc_bind(vio->lp, vio->name);
		err = ldc_bind(vio->lp);
		if (err)
			printk(KERN_WARNING "%s: Port %lu bind failed, "
			       "err=%d\n",