mirror of https://gitee.com/openkylin/linux.git
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: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
32bee77653
commit
3e23b7d3b5
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue