diff options
author | Vikas Chaudhary <vikas.chaudhary@qlogic.com> | 2011-08-29 14:13:02 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 10:34:04 -0500 |
commit | ff884430801c08bd909fd95f6cb1a0446afd30db (patch) | |
tree | 19f42d50bcbd0e03add3460221d0c7eb716c9b0b /drivers/scsi/qla4xxx | |
parent | a11e25459558421ec5c4adc3fc46fe320ab74bd3 (diff) |
[SCSI] qla4xxx: added support for host event
Added support to post kernel host event to application using
netlink interface.
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla4xxx')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 18 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 6 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 85 |
4 files changed, 111 insertions, 0 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index ec48dc30b9a2..f91808ce572e 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -301,7 +301,21 @@ struct ql4_tuple_ddb { | |||
301 | #define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */ | 301 | #define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */ |
302 | #define DF_FO_MASKED 3 | 302 | #define DF_FO_MASKED 3 |
303 | 303 | ||
304 | enum qla4_work_type { | ||
305 | QLA4_EVENT_AEN, | ||
306 | }; | ||
304 | 307 | ||
308 | struct qla4_work_evt { | ||
309 | struct list_head list; | ||
310 | enum qla4_work_type type; | ||
311 | union { | ||
312 | struct { | ||
313 | enum iscsi_host_event_code code; | ||
314 | uint32_t data_size; | ||
315 | uint8_t data[0]; | ||
316 | } aen; | ||
317 | } u; | ||
318 | }; | ||
305 | 319 | ||
306 | struct ql82xx_hw_data { | 320 | struct ql82xx_hw_data { |
307 | /* Offsets for flash/nvram access (set to ~0 if not used). */ | 321 | /* Offsets for flash/nvram access (set to ~0 if not used). */ |
@@ -672,6 +686,10 @@ struct scsi_qla_host { | |||
672 | uint16_t sec_ddb_idx; | 686 | uint16_t sec_ddb_idx; |
673 | int is_reset; | 687 | int is_reset; |
674 | uint16_t temperature; | 688 | uint16_t temperature; |
689 | |||
690 | /* event work list */ | ||
691 | struct list_head work_list; | ||
692 | spinlock_t work_lock; | ||
675 | }; | 693 | }; |
676 | 694 | ||
677 | struct ql4_task_data { | 695 | struct ql4_task_data { |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index d0dd4b330206..34cf851978e9 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -181,6 +181,8 @@ int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
181 | int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | 181 | int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, |
182 | struct ddb_entry *ddb_entry, uint32_t state); | 182 | struct ddb_entry *ddb_entry, uint32_t state); |
183 | void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset); | 183 | void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset); |
184 | int qla4xxx_post_aen_work(struct scsi_qla_host *ha, uint32_t aen_code, | ||
185 | uint32_t data_size, uint8_t *data); | ||
184 | 186 | ||
185 | /* BSG Functions */ | 187 | /* BSG Functions */ |
186 | int qla4xxx_bsg_request(struct bsg_job *bsg_job); | 188 | int qla4xxx_bsg_request(struct bsg_job *bsg_job); |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 95828862eea0..954fe84be575 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -576,6 +576,9 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
576 | set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); | 576 | set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); |
577 | 577 | ||
578 | ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__); | 578 | ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__); |
579 | qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKUP, | ||
580 | sizeof(mbox_sts), | ||
581 | (uint8_t *) mbox_sts); | ||
579 | break; | 582 | break; |
580 | 583 | ||
581 | case MBOX_ASTS_LINK_DOWN: | 584 | case MBOX_ASTS_LINK_DOWN: |
@@ -584,6 +587,9 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, | |||
584 | set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); | 587 | set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); |
585 | 588 | ||
586 | ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__); | 589 | ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__); |
590 | qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKDOWN, | ||
591 | sizeof(mbox_sts), | ||
592 | (uint8_t *) mbox_sts); | ||
587 | break; | 593 | break; |
588 | 594 | ||
589 | case MBOX_ASTS_HEARTBEAT: | 595 | case MBOX_ASTS_HEARTBEAT: |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 2cd20775836f..d423f7afbbd7 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -2282,6 +2282,10 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
2282 | } | 2282 | } |
2283 | } | 2283 | } |
2284 | 2284 | ||
2285 | /* Process any deferred work. */ | ||
2286 | if (!list_empty(&ha->work_list)) | ||
2287 | start_dpc++; | ||
2288 | |||
2285 | /* Wakeup the dpc routine for this adapter, if needed. */ | 2289 | /* Wakeup the dpc routine for this adapter, if needed. */ |
2286 | if (start_dpc || | 2290 | if (start_dpc || |
2287 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 2291 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
@@ -2847,6 +2851,81 @@ void qla4xxx_wake_dpc(struct scsi_qla_host *ha) | |||
2847 | queue_work(ha->dpc_thread, &ha->dpc_work); | 2851 | queue_work(ha->dpc_thread, &ha->dpc_work); |
2848 | } | 2852 | } |
2849 | 2853 | ||
2854 | static struct qla4_work_evt * | ||
2855 | qla4xxx_alloc_work(struct scsi_qla_host *ha, uint32_t data_size, | ||
2856 | enum qla4_work_type type) | ||
2857 | { | ||
2858 | struct qla4_work_evt *e; | ||
2859 | uint32_t size = sizeof(struct qla4_work_evt) + data_size; | ||
2860 | |||
2861 | e = kzalloc(size, GFP_ATOMIC); | ||
2862 | if (!e) | ||
2863 | return NULL; | ||
2864 | |||
2865 | INIT_LIST_HEAD(&e->list); | ||
2866 | e->type = type; | ||
2867 | return e; | ||
2868 | } | ||
2869 | |||
2870 | static void qla4xxx_post_work(struct scsi_qla_host *ha, | ||
2871 | struct qla4_work_evt *e) | ||
2872 | { | ||
2873 | unsigned long flags; | ||
2874 | |||
2875 | spin_lock_irqsave(&ha->work_lock, flags); | ||
2876 | list_add_tail(&e->list, &ha->work_list); | ||
2877 | spin_unlock_irqrestore(&ha->work_lock, flags); | ||
2878 | qla4xxx_wake_dpc(ha); | ||
2879 | } | ||
2880 | |||
2881 | int qla4xxx_post_aen_work(struct scsi_qla_host *ha, | ||
2882 | enum iscsi_host_event_code aen_code, | ||
2883 | uint32_t data_size, uint8_t *data) | ||
2884 | { | ||
2885 | struct qla4_work_evt *e; | ||
2886 | |||
2887 | e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_AEN); | ||
2888 | if (!e) | ||
2889 | return QLA_ERROR; | ||
2890 | |||
2891 | e->u.aen.code = aen_code; | ||
2892 | e->u.aen.data_size = data_size; | ||
2893 | memcpy(e->u.aen.data, data, data_size); | ||
2894 | |||
2895 | qla4xxx_post_work(ha, e); | ||
2896 | |||
2897 | return QLA_SUCCESS; | ||
2898 | } | ||
2899 | |||
2900 | void qla4xxx_do_work(struct scsi_qla_host *ha) | ||
2901 | { | ||
2902 | struct qla4_work_evt *e, *tmp; | ||
2903 | unsigned long flags; | ||
2904 | LIST_HEAD(work); | ||
2905 | |||
2906 | spin_lock_irqsave(&ha->work_lock, flags); | ||
2907 | list_splice_init(&ha->work_list, &work); | ||
2908 | spin_unlock_irqrestore(&ha->work_lock, flags); | ||
2909 | |||
2910 | list_for_each_entry_safe(e, tmp, &work, list) { | ||
2911 | list_del_init(&e->list); | ||
2912 | |||
2913 | switch (e->type) { | ||
2914 | case QLA4_EVENT_AEN: | ||
2915 | iscsi_post_host_event(ha->host_no, | ||
2916 | &qla4xxx_iscsi_transport, | ||
2917 | e->u.aen.code, | ||
2918 | e->u.aen.data_size, | ||
2919 | e->u.aen.data); | ||
2920 | break; | ||
2921 | default: | ||
2922 | ql4_printk(KERN_WARNING, ha, "event type: 0x%x not " | ||
2923 | "supported", e->type); | ||
2924 | } | ||
2925 | kfree(e); | ||
2926 | } | ||
2927 | } | ||
2928 | |||
2850 | /** | 2929 | /** |
2851 | * qla4xxx_do_dpc - dpc routine | 2930 | * qla4xxx_do_dpc - dpc routine |
2852 | * @data: in our case pointer to adapter structure | 2931 | * @data: in our case pointer to adapter structure |
@@ -2878,6 +2957,9 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
2878 | return; | 2957 | return; |
2879 | } | 2958 | } |
2880 | 2959 | ||
2960 | /* post events to application */ | ||
2961 | qla4xxx_do_work(ha); | ||
2962 | |||
2881 | if (is_qla8022(ha)) { | 2963 | if (is_qla8022(ha)) { |
2882 | if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { | 2964 | if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { |
2883 | qla4_8xxx_idc_lock(ha); | 2965 | qla4_8xxx_idc_lock(ha); |
@@ -4450,6 +4532,9 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
4450 | 4532 | ||
4451 | spin_lock_init(&ha->hardware_lock); | 4533 | spin_lock_init(&ha->hardware_lock); |
4452 | 4534 | ||
4535 | /* Initialize work list */ | ||
4536 | INIT_LIST_HEAD(&ha->work_list); | ||
4537 | |||
4453 | /* Allocate dma buffers */ | 4538 | /* Allocate dma buffers */ |
4454 | if (qla4xxx_mem_alloc(ha)) { | 4539 | if (qla4xxx_mem_alloc(ha)) { |
4455 | ql4_printk(KERN_WARNING, ha, | 4540 | ql4_printk(KERN_WARNING, ha, |