aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_os.c
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2009-06-03 12:55:28 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-06-08 15:46:57 -0400
commitf999f4c1961fe5399fd66c95860cc2d5d67e591e (patch)
treeaa1b4389021f1676f04aa3a79e8b7f00ecfbb2c7 /drivers/scsi/qla2xxx/qla_os.c
parent6805c1504eb4cfd4a31c05ed88fdeb56228eb3ba (diff)
[SCSI] qla2xxx: Reduce lock-contention during do-work processing.
Queued work processing will now be serialized with its own lower-priority spinlock. This also simplifies the work-queue interface for future work-queue consumers. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c45
1 files changed, 22 insertions, 23 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 128b3d5c9663..dcf011679c8b 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2533,6 +2533,8 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
2533 INIT_LIST_HEAD(&vha->work_list); 2533 INIT_LIST_HEAD(&vha->work_list);
2534 INIT_LIST_HEAD(&vha->list); 2534 INIT_LIST_HEAD(&vha->list);
2535 2535
2536 spin_lock_init(&vha->work_lock);
2537
2536 sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no); 2538 sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
2537 return vha; 2539 return vha;
2538 2540
@@ -2541,13 +2543,11 @@ fail:
2541} 2543}
2542 2544
2543static struct qla_work_evt * 2545static struct qla_work_evt *
2544qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type, 2546qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type)
2545 int locked)
2546{ 2547{
2547 struct qla_work_evt *e; 2548 struct qla_work_evt *e;
2548 2549
2549 e = kzalloc(sizeof(struct qla_work_evt), locked ? GFP_ATOMIC: 2550 e = kzalloc(sizeof(struct qla_work_evt), GFP_ATOMIC);
2550 GFP_KERNEL);
2551 if (!e) 2551 if (!e)
2552 return NULL; 2552 return NULL;
2553 2553
@@ -2558,17 +2558,15 @@ qla2x00_alloc_work(struct scsi_qla_host *vha, enum qla_work_type type,
2558} 2558}
2559 2559
2560static int 2560static int
2561qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e, int locked) 2561qla2x00_post_work(struct scsi_qla_host *vha, struct qla_work_evt *e)
2562{ 2562{
2563 unsigned long uninitialized_var(flags); 2563 unsigned long flags;
2564 struct qla_hw_data *ha = vha->hw;
2565 2564
2566 if (!locked) 2565 spin_lock_irqsave(&vha->work_lock, flags);
2567 spin_lock_irqsave(&ha->hardware_lock, flags);
2568 list_add_tail(&e->list, &vha->work_list); 2566 list_add_tail(&e->list, &vha->work_list);
2567 spin_unlock_irqrestore(&vha->work_lock, flags);
2569 qla2xxx_wake_dpc(vha); 2568 qla2xxx_wake_dpc(vha);
2570 if (!locked) 2569
2571 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2572 return QLA_SUCCESS; 2570 return QLA_SUCCESS;
2573} 2571}
2574 2572
@@ -2578,13 +2576,13 @@ qla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code,
2578{ 2576{
2579 struct qla_work_evt *e; 2577 struct qla_work_evt *e;
2580 2578
2581 e = qla2x00_alloc_work(vha, QLA_EVT_AEN, 1); 2579 e = qla2x00_alloc_work(vha, QLA_EVT_AEN);
2582 if (!e) 2580 if (!e)
2583 return QLA_FUNCTION_FAILED; 2581 return QLA_FUNCTION_FAILED;
2584 2582
2585 e->u.aen.code = code; 2583 e->u.aen.code = code;
2586 e->u.aen.data = data; 2584 e->u.aen.data = data;
2587 return qla2x00_post_work(vha, e, 1); 2585 return qla2x00_post_work(vha, e);
2588} 2586}
2589 2587
2590int 2588int
@@ -2592,25 +2590,27 @@ qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb)
2592{ 2590{
2593 struct qla_work_evt *e; 2591 struct qla_work_evt *e;
2594 2592
2595 e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK, 1); 2593 e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK);
2596 if (!e) 2594 if (!e)
2597 return QLA_FUNCTION_FAILED; 2595 return QLA_FUNCTION_FAILED;
2598 2596
2599 memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t)); 2597 memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
2600 return qla2x00_post_work(vha, e, 1); 2598 return qla2x00_post_work(vha, e);
2601} 2599}
2602 2600
2603static void 2601static void
2604qla2x00_do_work(struct scsi_qla_host *vha) 2602qla2x00_do_work(struct scsi_qla_host *vha)
2605{ 2603{
2606 struct qla_work_evt *e; 2604 struct qla_work_evt *e, *tmp;
2607 struct qla_hw_data *ha = vha->hw; 2605 unsigned long flags;
2606 LIST_HEAD(work);
2608 2607
2609 spin_lock_irq(&ha->hardware_lock); 2608 spin_lock_irqsave(&vha->work_lock, flags);
2610 while (!list_empty(&vha->work_list)) { 2609 list_splice_init(&vha->work_list, &work);
2611 e = list_entry(vha->work_list.next, struct qla_work_evt, list); 2610 spin_unlock_irqrestore(&vha->work_lock, flags);
2611
2612 list_for_each_entry_safe(e, tmp, &work, list) {
2612 list_del_init(&e->list); 2613 list_del_init(&e->list);
2613 spin_unlock_irq(&ha->hardware_lock);
2614 2614
2615 switch (e->type) { 2615 switch (e->type) {
2616 case QLA_EVT_AEN: 2616 case QLA_EVT_AEN:
@@ -2623,10 +2623,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
2623 } 2623 }
2624 if (e->flags & QLA_EVT_FLAG_FREE) 2624 if (e->flags & QLA_EVT_FLAG_FREE)
2625 kfree(e); 2625 kfree(e);
2626 spin_lock_irq(&ha->hardware_lock);
2627 } 2626 }
2628 spin_unlock_irq(&ha->hardware_lock);
2629} 2627}
2628
2630/* Relogins all the fcports of a vport 2629/* Relogins all the fcports of a vport
2631 * Context: dpc thread 2630 * Context: dpc thread
2632 */ 2631 */