diff options
author | Anirban Chakraborty <anirban.chakraborty@qlogic.com> | 2009-04-07 01:33:40 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-05-20 18:21:07 -0400 |
commit | 2afa19a9377ca61b9489e44bf50029574fbe63be (patch) | |
tree | cdfa3878eb04d833bbcd9ce92196bc4456b5ccf5 /drivers/scsi/qla2xxx/qla_mid.c | |
parent | 7640335ea5b1a2da0d64303e6003012c619ae01a (diff) |
[SCSI] qla2xxx: Add QoS support.
Set the number of request queues to the module paramater
ql2xmaxqueues. Each vport gets a request queue. The QoS value
set to the request queues determines priority control for queued
IOs. If QoS value is not specified, the vports use the default
queue 0.
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
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_mid.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mid.c | 107 |
1 files changed, 45 insertions, 62 deletions
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 51716c7e3008..9c08479c3e1b 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
@@ -398,9 +398,8 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) | |||
398 | 398 | ||
399 | qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL); | 399 | qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL); |
400 | 400 | ||
401 | memset(vha->req_ques, 0, sizeof(vha->req_ques)); | 401 | vha->req = base_vha->req; |
402 | vha->req_ques[0] = ha->req_q_map[0]->id; | 402 | host->can_queue = base_vha->req->length + 128; |
403 | host->can_queue = ha->req_q_map[0]->length + 128; | ||
404 | host->this_id = 255; | 403 | host->this_id = 255; |
405 | host->cmd_per_lun = 3; | 404 | host->cmd_per_lun = 3; |
406 | host->max_cmd_len = MAX_CMDSZ; | 405 | host->max_cmd_len = MAX_CMDSZ; |
@@ -515,76 +514,53 @@ int qla25xx_update_req_que(struct scsi_qla_host *vha, uint8_t que, uint8_t qos) | |||
515 | 514 | ||
516 | /* Delete all queues for a given vhost */ | 515 | /* Delete all queues for a given vhost */ |
517 | int | 516 | int |
518 | qla25xx_delete_queues(struct scsi_qla_host *vha, uint8_t que_no) | 517 | qla25xx_delete_queues(struct scsi_qla_host *vha) |
519 | { | 518 | { |
520 | int cnt, ret = 0; | 519 | int cnt, ret = 0; |
521 | struct req_que *req = NULL; | 520 | struct req_que *req = NULL; |
522 | struct rsp_que *rsp = NULL; | 521 | struct rsp_que *rsp = NULL; |
523 | struct qla_hw_data *ha = vha->hw; | 522 | struct qla_hw_data *ha = vha->hw; |
524 | 523 | ||
525 | if (que_no) { | 524 | /* Delete request queues */ |
526 | /* Delete request queue */ | 525 | for (cnt = 1; cnt < ha->max_req_queues; cnt++) { |
527 | req = ha->req_q_map[que_no]; | 526 | req = ha->req_q_map[cnt]; |
528 | if (req) { | 527 | if (req) { |
529 | rsp = req->rsp; | ||
530 | ret = qla25xx_delete_req_que(vha, req); | 528 | ret = qla25xx_delete_req_que(vha, req); |
531 | if (ret != QLA_SUCCESS) { | 529 | if (ret != QLA_SUCCESS) { |
532 | qla_printk(KERN_WARNING, ha, | 530 | qla_printk(KERN_WARNING, ha, |
533 | "Couldn't delete req que %d\n", req->id); | 531 | "Couldn't delete req que %d\n", |
532 | req->id); | ||
534 | return ret; | 533 | return ret; |
535 | } | 534 | } |
536 | /* Delete associated response queue */ | ||
537 | if (rsp) { | ||
538 | ret = qla25xx_delete_rsp_que(vha, rsp); | ||
539 | if (ret != QLA_SUCCESS) { | ||
540 | qla_printk(KERN_WARNING, ha, | ||
541 | "Couldn't delete rsp que %d\n", | ||
542 | rsp->id); | ||
543 | return ret; | ||
544 | } | ||
545 | } | ||
546 | } | 535 | } |
547 | } else { /* delete all queues of this host */ | 536 | } |
548 | for (cnt = 0; cnt < QLA_MAX_HOST_QUES; cnt++) { | 537 | |
549 | /* Delete request queues */ | 538 | /* Delete response queues */ |
550 | req = ha->req_q_map[vha->req_ques[cnt]]; | 539 | for (cnt = 1; cnt < ha->max_rsp_queues; cnt++) { |
551 | if (req && req->id) { | 540 | rsp = ha->rsp_q_map[cnt]; |
552 | rsp = req->rsp; | 541 | if (rsp) { |
553 | ret = qla25xx_delete_req_que(vha, req); | 542 | ret = qla25xx_delete_rsp_que(vha, rsp); |
554 | if (ret != QLA_SUCCESS) { | 543 | if (ret != QLA_SUCCESS) { |
555 | qla_printk(KERN_WARNING, ha, | 544 | qla_printk(KERN_WARNING, ha, |
556 | "Couldn't delete req que %d\n", | 545 | "Couldn't delete rsp que %d\n", |
557 | vha->req_ques[cnt]); | 546 | rsp->id); |
558 | return ret; | 547 | return ret; |
559 | } | ||
560 | vha->req_ques[cnt] = ha->req_q_map[0]->id; | ||
561 | /* Delete associated response queue */ | ||
562 | if (rsp && rsp->id) { | ||
563 | ret = qla25xx_delete_rsp_que(vha, rsp); | ||
564 | if (ret != QLA_SUCCESS) { | ||
565 | qla_printk(KERN_WARNING, ha, | ||
566 | "Couldn't delete rsp que %d\n", | ||
567 | rsp->id); | ||
568 | return ret; | ||
569 | } | ||
570 | } | ||
571 | } | 548 | } |
572 | } | 549 | } |
573 | } | 550 | } |
574 | qla_printk(KERN_INFO, ha, "Queues deleted for vport:%d\n", | ||
575 | vha->vp_idx); | ||
576 | return ret; | 551 | return ret; |
577 | } | 552 | } |
578 | 553 | ||
579 | int | 554 | int |
580 | qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options, | 555 | qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options, |
581 | uint8_t vp_idx, uint16_t rid, uint8_t rsp_que, uint8_t qos) | 556 | uint8_t vp_idx, uint16_t rid, int rsp_que, uint8_t qos) |
582 | { | 557 | { |
583 | int ret = 0; | 558 | int ret = 0; |
584 | struct req_que *req = NULL; | 559 | struct req_que *req = NULL; |
585 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); | 560 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); |
586 | uint16_t que_id = 0; | 561 | uint16_t que_id = 0; |
587 | device_reg_t __iomem *reg; | 562 | device_reg_t __iomem *reg; |
563 | uint32_t cnt; | ||
588 | 564 | ||
589 | req = kzalloc(sizeof(struct req_que), GFP_KERNEL); | 565 | req = kzalloc(sizeof(struct req_que), GFP_KERNEL); |
590 | if (req == NULL) { | 566 | if (req == NULL) { |
@@ -604,8 +580,8 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options, | |||
604 | } | 580 | } |
605 | 581 | ||
606 | mutex_lock(&ha->vport_lock); | 582 | mutex_lock(&ha->vport_lock); |
607 | que_id = find_first_zero_bit(ha->req_qid_map, ha->max_queues); | 583 | que_id = find_first_zero_bit(ha->req_qid_map, ha->max_req_queues); |
608 | if (que_id >= ha->max_queues) { | 584 | if (que_id >= ha->max_req_queues) { |
609 | mutex_unlock(&ha->vport_lock); | 585 | mutex_unlock(&ha->vport_lock); |
610 | qla_printk(KERN_INFO, ha, "No resources to create " | 586 | qla_printk(KERN_INFO, ha, "No resources to create " |
611 | "additional request queue\n"); | 587 | "additional request queue\n"); |
@@ -617,10 +593,10 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options, | |||
617 | req->vp_idx = vp_idx; | 593 | req->vp_idx = vp_idx; |
618 | req->qos = qos; | 594 | req->qos = qos; |
619 | 595 | ||
620 | if (ha->rsp_q_map[rsp_que]) { | 596 | if (rsp_que < 0) |
597 | req->rsp = NULL; | ||
598 | else | ||
621 | req->rsp = ha->rsp_q_map[rsp_que]; | 599 | req->rsp = ha->rsp_q_map[rsp_que]; |
622 | req->rsp->req = req; | ||
623 | } | ||
624 | /* Use alternate PCI bus number */ | 600 | /* Use alternate PCI bus number */ |
625 | if (MSB(req->rid)) | 601 | if (MSB(req->rid)) |
626 | options |= BIT_4; | 602 | options |= BIT_4; |
@@ -628,13 +604,16 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options, | |||
628 | if (LSB(req->rid)) | 604 | if (LSB(req->rid)) |
629 | options |= BIT_5; | 605 | options |= BIT_5; |
630 | req->options = options; | 606 | req->options = options; |
607 | |||
608 | for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) | ||
609 | req->outstanding_cmds[cnt] = NULL; | ||
610 | req->current_outstanding_cmd = 1; | ||
611 | |||
631 | req->ring_ptr = req->ring; | 612 | req->ring_ptr = req->ring; |
632 | req->ring_index = 0; | 613 | req->ring_index = 0; |
633 | req->cnt = req->length; | 614 | req->cnt = req->length; |
634 | req->id = que_id; | 615 | req->id = que_id; |
635 | reg = ISP_QUE_REG(ha, que_id); | 616 | reg = ISP_QUE_REG(ha, que_id); |
636 | req->req_q_in = ®->isp25mq.req_q_in; | ||
637 | req->req_q_out = ®->isp25mq.req_q_out; | ||
638 | req->max_q_depth = ha->req_q_map[0]->max_q_depth; | 617 | req->max_q_depth = ha->req_q_map[0]->max_q_depth; |
639 | mutex_unlock(&ha->vport_lock); | 618 | mutex_unlock(&ha->vport_lock); |
640 | 619 | ||
@@ -657,7 +636,7 @@ que_failed: | |||
657 | /* create response queue */ | 636 | /* create response queue */ |
658 | int | 637 | int |
659 | qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, | 638 | qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, |
660 | uint8_t vp_idx, uint16_t rid) | 639 | uint8_t vp_idx, uint16_t rid, int req) |
661 | { | 640 | { |
662 | int ret = 0; | 641 | int ret = 0; |
663 | struct rsp_que *rsp = NULL; | 642 | struct rsp_que *rsp = NULL; |
@@ -672,7 +651,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, | |||
672 | goto que_failed; | 651 | goto que_failed; |
673 | } | 652 | } |
674 | 653 | ||
675 | rsp->length = RESPONSE_ENTRY_CNT_2300; | 654 | rsp->length = RESPONSE_ENTRY_CNT_MQ; |
676 | rsp->ring = dma_alloc_coherent(&ha->pdev->dev, | 655 | rsp->ring = dma_alloc_coherent(&ha->pdev->dev, |
677 | (rsp->length + 1) * sizeof(response_t), | 656 | (rsp->length + 1) * sizeof(response_t), |
678 | &rsp->dma, GFP_KERNEL); | 657 | &rsp->dma, GFP_KERNEL); |
@@ -683,8 +662,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, | |||
683 | } | 662 | } |
684 | 663 | ||
685 | mutex_lock(&ha->vport_lock); | 664 | mutex_lock(&ha->vport_lock); |
686 | que_id = find_first_zero_bit(ha->rsp_qid_map, ha->max_queues); | 665 | que_id = find_first_zero_bit(ha->rsp_qid_map, ha->max_rsp_queues); |
687 | if (que_id >= ha->max_queues) { | 666 | if (que_id >= ha->max_rsp_queues) { |
688 | mutex_unlock(&ha->vport_lock); | 667 | mutex_unlock(&ha->vport_lock); |
689 | qla_printk(KERN_INFO, ha, "No resources to create " | 668 | qla_printk(KERN_INFO, ha, "No resources to create " |
690 | "additional response queue\n"); | 669 | "additional response queue\n"); |
@@ -708,8 +687,6 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, | |||
708 | if (LSB(rsp->rid)) | 687 | if (LSB(rsp->rid)) |
709 | options |= BIT_5; | 688 | options |= BIT_5; |
710 | rsp->options = options; | 689 | rsp->options = options; |
711 | rsp->ring_ptr = rsp->ring; | ||
712 | rsp->ring_index = 0; | ||
713 | rsp->id = que_id; | 690 | rsp->id = que_id; |
714 | reg = ISP_QUE_REG(ha, que_id); | 691 | reg = ISP_QUE_REG(ha, que_id); |
715 | rsp->rsp_q_in = ®->isp25mq.rsp_q_in; | 692 | rsp->rsp_q_in = ®->isp25mq.rsp_q_in; |
@@ -728,9 +705,12 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, | |||
728 | mutex_unlock(&ha->vport_lock); | 705 | mutex_unlock(&ha->vport_lock); |
729 | goto que_failed; | 706 | goto que_failed; |
730 | } | 707 | } |
708 | if (req >= 0) | ||
709 | rsp->req = ha->req_q_map[req]; | ||
710 | else | ||
711 | rsp->req = NULL; | ||
731 | 712 | ||
732 | qla2x00_init_response_q_entries(rsp); | 713 | qla2x00_init_response_q_entries(rsp); |
733 | |||
734 | return rsp->id; | 714 | return rsp->id; |
735 | 715 | ||
736 | que_failed: | 716 | que_failed: |
@@ -744,14 +724,16 @@ qla25xx_create_queues(struct scsi_qla_host *vha, uint8_t qos) | |||
744 | uint16_t options = 0; | 724 | uint16_t options = 0; |
745 | uint8_t ret = 0; | 725 | uint8_t ret = 0; |
746 | struct qla_hw_data *ha = vha->hw; | 726 | struct qla_hw_data *ha = vha->hw; |
727 | struct rsp_que *rsp; | ||
747 | 728 | ||
748 | options |= BIT_1; | 729 | options |= BIT_1; |
749 | ret = qla25xx_create_rsp_que(ha, options, vha->vp_idx, 0); | 730 | ret = qla25xx_create_rsp_que(ha, options, vha->vp_idx, 0, -1); |
750 | if (!ret) { | 731 | if (!ret) { |
751 | qla_printk(KERN_WARNING, ha, "Response Que create failed\n"); | 732 | qla_printk(KERN_WARNING, ha, "Response Que create failed\n"); |
752 | return ret; | 733 | return ret; |
753 | } else | 734 | } else |
754 | qla_printk(KERN_INFO, ha, "Response Que:%d created.\n", ret); | 735 | qla_printk(KERN_INFO, ha, "Response Que:%d created.\n", ret); |
736 | rsp = ha->rsp_q_map[ret]; | ||
755 | 737 | ||
756 | options = 0; | 738 | options = 0; |
757 | if (qos & BIT_7) | 739 | if (qos & BIT_7) |
@@ -759,10 +741,11 @@ qla25xx_create_queues(struct scsi_qla_host *vha, uint8_t qos) | |||
759 | ret = qla25xx_create_req_que(ha, options, vha->vp_idx, 0, ret, | 741 | ret = qla25xx_create_req_que(ha, options, vha->vp_idx, 0, ret, |
760 | qos & ~BIT_7); | 742 | qos & ~BIT_7); |
761 | if (ret) { | 743 | if (ret) { |
762 | vha->req_ques[0] = ret; | 744 | vha->req = ha->req_q_map[ret]; |
763 | qla_printk(KERN_INFO, ha, "Request Que:%d created.\n", ret); | 745 | qla_printk(KERN_INFO, ha, "Request Que:%d created.\n", ret); |
764 | } else | 746 | } else |
765 | qla_printk(KERN_WARNING, ha, "Request Que create failed\n"); | 747 | qla_printk(KERN_WARNING, ha, "Request Que create failed\n"); |
748 | rsp->req = ha->req_q_map[ret]; | ||
766 | 749 | ||
767 | return ret; | 750 | return ret; |
768 | } | 751 | } |