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

Commit 3e23b7d3 authored by Ron Mercer's avatar Ron Mercer Committed by Jeff Garzik
Browse files

qla3xxx: bugfix: Move link state machine into a worker thread



The link state machine requires access to some resources that
are shared with the iSCSI function on the chip.  (See iSCSI
driver at drivers/scsi/qla4xxx)  If the interface is being
up/downed at a rapid pace this driver may need to sleep
waiting to get access to the common resources. For this we
are moving the state machine to run as a work thread.

Signed-off-by: default avatarRon Mercer <ron.mercer@qlogic.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 32bee776
Loading
Loading
Loading
Loading
+13 −14
Original line number Diff line number Diff line
@@ -1645,8 +1645,11 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev)
	return 0;
}

static void ql_link_state_machine(struct ql3_adapter *qdev)
static void ql_link_state_machine_work(struct work_struct *work)
{
	struct ql3_adapter *qdev =
		container_of(work, struct ql3_adapter, link_state_work.work);

	u32 curr_link_state;
	unsigned long hw_flags;

@@ -1661,6 +1664,10 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
			       "state.\n", qdev->ndev->name);

		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);

		/* Restart timer on 2 second interval. */
		mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);\

		return;
	}

@@ -1705,6 +1712,9 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
		break;
	}
	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);

	/* Restart timer on 2 second interval. */
	mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
}

/*
@@ -3941,19 +3951,7 @@ static void ql_get_board_info(struct ql3_adapter *qdev)
static void ql3xxx_timer(unsigned long ptr)
{
	struct ql3_adapter *qdev = (struct ql3_adapter *)ptr;

	if (test_bit(QL_RESET_ACTIVE,&qdev->flags)) {
		printk(KERN_DEBUG PFX
		       "%s: Reset in progress.\n",
		       qdev->ndev->name);
		goto end;
	}

	ql_link_state_machine(qdev);

	/* Restart timer on 2 second interval. */
end:
	mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
	queue_delayed_work(qdev->workqueue, &qdev->link_state_work, 0);
}

static int __devinit ql3xxx_probe(struct pci_dev *pdev,
@@ -4103,6 +4101,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
	qdev->workqueue = create_singlethread_workqueue(ndev->name);
	INIT_DELAYED_WORK(&qdev->reset_work, ql_reset_work);
	INIT_DELAYED_WORK(&qdev->tx_timeout_work, ql_tx_timeout_work);
	INIT_DELAYED_WORK(&qdev->link_state_work, ql_link_state_machine_work);

	init_timer(&qdev->adapter_timer);
	qdev->adapter_timer.function = ql3xxx_timer;
+1 −0
Original line number Diff line number Diff line
@@ -1286,6 +1286,7 @@ struct ql3_adapter {
	struct workqueue_struct *workqueue;
	struct delayed_work reset_work;
	struct delayed_work tx_timeout_work;
	struct delayed_work link_state_work;
	u32 max_frame_size;
	u32 device_id;
	u16 phyType;