diff options
author | Quinn Tran <quinn.tran@qlogic.com> | 2015-12-17 14:57:05 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2016-01-07 16:57:46 -0500 |
commit | cdb898c52d1dfad4b4800b83a58b3fe5d352edde (patch) | |
tree | a75040b860ca23bf650979950ca5c467e7c8670b | |
parent | 7560151b6b3c1f4432c1c5b5b6496070d1f38484 (diff) |
qla2xxx: Add irq affinity notification
Register to receive notification of when irq setting change
occured.
Signed-off-by: Quinn Tran <quinn.tran@qlogic.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r-- | drivers/scsi/qla2xxx/qla_def.h | 6 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 76 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 12 |
3 files changed, 93 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 216a944c1ca5..c4fc32e9aaf9 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -2714,11 +2714,16 @@ struct isp_operations { | |||
2714 | 2714 | ||
2715 | struct scsi_qla_host; | 2715 | struct scsi_qla_host; |
2716 | 2716 | ||
2717 | |||
2718 | #define QLA83XX_RSPQ_MSIX_ENTRY_NUMBER 1 /* refer to qla83xx_msix_entries */ | ||
2719 | |||
2717 | struct qla_msix_entry { | 2720 | struct qla_msix_entry { |
2718 | int have_irq; | 2721 | int have_irq; |
2719 | uint32_t vector; | 2722 | uint32_t vector; |
2720 | uint16_t entry; | 2723 | uint16_t entry; |
2721 | struct rsp_que *rsp; | 2724 | struct rsp_que *rsp; |
2725 | struct irq_affinity_notify irq_notify; | ||
2726 | int cpuid; | ||
2722 | }; | 2727 | }; |
2723 | 2728 | ||
2724 | #define WATCH_INTERVAL 1 /* number of seconds */ | 2729 | #define WATCH_INTERVAL 1 /* number of seconds */ |
@@ -2930,6 +2935,7 @@ struct qlt_hw_data { | |||
2930 | spinlock_t q_full_lock; | 2935 | spinlock_t q_full_lock; |
2931 | uint32_t leak_exchg_thresh_hold; | 2936 | uint32_t leak_exchg_thresh_hold; |
2932 | spinlock_t sess_lock; | 2937 | spinlock_t sess_lock; |
2938 | int rspq_vector_cpuid; | ||
2933 | }; | 2939 | }; |
2934 | 2940 | ||
2935 | #define MAX_QFULL_CMDS_ALLOC 8192 | 2941 | #define MAX_QFULL_CMDS_ALLOC 8192 |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ea7e8e8a065a..cf0fe8ec12c7 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -18,6 +18,10 @@ static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, void *); | |||
18 | static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *); | 18 | static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *); |
19 | static void qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *, | 19 | static void qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *, |
20 | sts_entry_t *); | 20 | sts_entry_t *); |
21 | static void qla_irq_affinity_notify(struct irq_affinity_notify *, | ||
22 | const cpumask_t *); | ||
23 | static void qla_irq_affinity_release(struct kref *); | ||
24 | |||
21 | 25 | ||
22 | /** | 26 | /** |
23 | * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. | 27 | * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. |
@@ -2548,6 +2552,14 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, | |||
2548 | if (!vha->flags.online) | 2552 | if (!vha->flags.online) |
2549 | return; | 2553 | return; |
2550 | 2554 | ||
2555 | if (rsp->msix->cpuid != smp_processor_id()) { | ||
2556 | /* if kernel does not notify qla of IRQ's CPU change, | ||
2557 | * then set it here. | ||
2558 | */ | ||
2559 | rsp->msix->cpuid = smp_processor_id(); | ||
2560 | ha->tgt.rspq_vector_cpuid = rsp->msix->cpuid; | ||
2561 | } | ||
2562 | |||
2551 | while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) { | 2563 | while (rsp->ring_ptr->signature != RESPONSE_PROCESSED) { |
2552 | pkt = (struct sts_entry_24xx *)rsp->ring_ptr; | 2564 | pkt = (struct sts_entry_24xx *)rsp->ring_ptr; |
2553 | 2565 | ||
@@ -2979,8 +2991,11 @@ qla24xx_disable_msix(struct qla_hw_data *ha) | |||
2979 | 2991 | ||
2980 | for (i = 0; i < ha->msix_count; i++) { | 2992 | for (i = 0; i < ha->msix_count; i++) { |
2981 | qentry = &ha->msix_entries[i]; | 2993 | qentry = &ha->msix_entries[i]; |
2982 | if (qentry->have_irq) | 2994 | if (qentry->have_irq) { |
2995 | /* un-register irq cpu affinity notification */ | ||
2996 | irq_set_affinity_notifier(qentry->vector, NULL); | ||
2983 | free_irq(qentry->vector, qentry->rsp); | 2997 | free_irq(qentry->vector, qentry->rsp); |
2998 | } | ||
2984 | } | 2999 | } |
2985 | pci_disable_msix(ha->pdev); | 3000 | pci_disable_msix(ha->pdev); |
2986 | kfree(ha->msix_entries); | 3001 | kfree(ha->msix_entries); |
@@ -3043,6 +3058,9 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) | |||
3043 | qentry->entry = entries[i].entry; | 3058 | qentry->entry = entries[i].entry; |
3044 | qentry->have_irq = 0; | 3059 | qentry->have_irq = 0; |
3045 | qentry->rsp = NULL; | 3060 | qentry->rsp = NULL; |
3061 | qentry->irq_notify.notify = qla_irq_affinity_notify; | ||
3062 | qentry->irq_notify.release = qla_irq_affinity_release; | ||
3063 | qentry->cpuid = -1; | ||
3046 | } | 3064 | } |
3047 | 3065 | ||
3048 | /* Enable MSI-X vectors for the base queue */ | 3066 | /* Enable MSI-X vectors for the base queue */ |
@@ -3061,6 +3079,18 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) | |||
3061 | qentry->have_irq = 1; | 3079 | qentry->have_irq = 1; |
3062 | qentry->rsp = rsp; | 3080 | qentry->rsp = rsp; |
3063 | rsp->msix = qentry; | 3081 | rsp->msix = qentry; |
3082 | |||
3083 | /* Register for CPU affinity notification. */ | ||
3084 | irq_set_affinity_notifier(qentry->vector, &qentry->irq_notify); | ||
3085 | |||
3086 | /* Schedule work (ie. trigger a notification) to read cpu | ||
3087 | * mask for this specific irq. | ||
3088 | * kref_get is required because | ||
3089 | * irq_affinity_notify() will do | ||
3090 | * kref_put(). | ||
3091 | */ | ||
3092 | kref_get(&qentry->irq_notify.kref); | ||
3093 | schedule_work(&qentry->irq_notify.work); | ||
3064 | } | 3094 | } |
3065 | 3095 | ||
3066 | /* | 3096 | /* |
@@ -3240,3 +3270,47 @@ int qla25xx_request_irq(struct rsp_que *rsp) | |||
3240 | msix->rsp = rsp; | 3270 | msix->rsp = rsp; |
3241 | return ret; | 3271 | return ret; |
3242 | } | 3272 | } |
3273 | |||
3274 | |||
3275 | /* irq_set_affinity/irqbalance will trigger notification of cpu mask update */ | ||
3276 | static void qla_irq_affinity_notify(struct irq_affinity_notify *notify, | ||
3277 | const cpumask_t *mask) | ||
3278 | { | ||
3279 | struct qla_msix_entry *e = | ||
3280 | container_of(notify, struct qla_msix_entry, irq_notify); | ||
3281 | struct qla_hw_data *ha; | ||
3282 | struct scsi_qla_host *base_vha; | ||
3283 | |||
3284 | /* user is recommended to set mask to just 1 cpu */ | ||
3285 | e->cpuid = cpumask_first(mask); | ||
3286 | |||
3287 | ha = e->rsp->hw; | ||
3288 | base_vha = pci_get_drvdata(ha->pdev); | ||
3289 | |||
3290 | ql_dbg(ql_dbg_init, base_vha, 0xffff, | ||
3291 | "%s: host %ld : vector %d cpu %d \n", __func__, | ||
3292 | base_vha->host_no, e->vector, e->cpuid); | ||
3293 | |||
3294 | if (e->have_irq) { | ||
3295 | if ((IS_QLA83XX(ha) || IS_QLA27XX(ha)) && | ||
3296 | (e->entry == QLA83XX_RSPQ_MSIX_ENTRY_NUMBER)) { | ||
3297 | ha->tgt.rspq_vector_cpuid = e->cpuid; | ||
3298 | ql_dbg(ql_dbg_init, base_vha, 0xffff, | ||
3299 | "%s: host%ld: rspq vector %d cpu %d runtime change\n", | ||
3300 | __func__, base_vha->host_no, e->vector, e->cpuid); | ||
3301 | } | ||
3302 | } | ||
3303 | } | ||
3304 | |||
3305 | void qla_irq_affinity_release(struct kref *ref) | ||
3306 | { | ||
3307 | struct irq_affinity_notify *notify = | ||
3308 | container_of(ref, struct irq_affinity_notify, kref); | ||
3309 | struct qla_msix_entry *e = | ||
3310 | container_of(notify, struct qla_msix_entry, irq_notify); | ||
3311 | struct scsi_qla_host *base_vha = pci_get_drvdata(e->rsp->hw->pdev); | ||
3312 | |||
3313 | ql_dbg(ql_dbg_init, base_vha, 0xffff, | ||
3314 | "%s: host%ld: vector %d cpu %d \n", __func__, | ||
3315 | base_vha->host_no, e->vector, e->cpuid); | ||
3316 | } | ||
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 6136987df164..9a4aed0e8241 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c | |||
@@ -6232,6 +6232,7 @@ qlt_enable_vha(struct scsi_qla_host *vha) | |||
6232 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; | 6232 | struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; |
6233 | unsigned long flags; | 6233 | unsigned long flags; |
6234 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | 6234 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); |
6235 | int rspq_ent = QLA83XX_RSPQ_MSIX_ENTRY_NUMBER; | ||
6235 | 6236 | ||
6236 | if (!tgt) { | 6237 | if (!tgt) { |
6237 | ql_dbg(ql_dbg_tgt, vha, 0xe069, | 6238 | ql_dbg(ql_dbg_tgt, vha, 0xe069, |
@@ -6250,6 +6251,17 @@ qlt_enable_vha(struct scsi_qla_host *vha) | |||
6250 | qla24xx_disable_vp(vha); | 6251 | qla24xx_disable_vp(vha); |
6251 | qla24xx_enable_vp(vha); | 6252 | qla24xx_enable_vp(vha); |
6252 | } else { | 6253 | } else { |
6254 | if (ha->msix_entries) { | ||
6255 | ql_dbg(ql_dbg_tgt, vha, 0xffff, | ||
6256 | "%s: host%ld : vector %d cpu %d\n", | ||
6257 | __func__, vha->host_no, | ||
6258 | ha->msix_entries[rspq_ent].vector, | ||
6259 | ha->msix_entries[rspq_ent].cpuid); | ||
6260 | |||
6261 | ha->tgt.rspq_vector_cpuid = | ||
6262 | ha->msix_entries[rspq_ent].cpuid; | ||
6263 | } | ||
6264 | |||
6253 | set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); | 6265 | set_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags); |
6254 | qla2xxx_wake_dpc(base_vha); | 6266 | qla2xxx_wake_dpc(base_vha); |
6255 | qla2x00_wait_for_hba_online(base_vha); | 6267 | qla2x00_wait_for_hba_online(base_vha); |