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

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
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment