diff options
author | Vikas Chaudhary <vikas.chaudhary@qlogic.com> | 2011-08-29 23:43:02 +0530 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 09:34:04 -0600 |
commit | ff884430801c08bd909fd95f6cb1a0446afd30db (patch) | |
tree | 19f42d50bcbd0e03add3460221d0c7eb716c9b0b /drivers/scsi/qla4xxx/ql4_os.c | |
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/ql4_os.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 2cd20775836..d423f7afbbd 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) } } + /* Process any deferred work. */ + if (!list_empty(&ha->work_list)) + start_dpc++; + /* Wakeup the dpc routine for this adapter, if needed. */ if (start_dpc || test_bit(DPC_RESET_HA, &ha->dpc_flags) || @@ -2847,6 +2851,81 @@ void qla4xxx_wake_dpc(struct scsi_qla_host *ha) queue_work(ha->dpc_thread, &ha->dpc_work); } +static struct qla4_work_evt * +qla4xxx_alloc_work(struct scsi_qla_host *ha, uint32_t data_size, + enum qla4_work_type type) +{ + struct qla4_work_evt *e; + uint32_t size = sizeof(struct qla4_work_evt) + data_size; + + e = kzalloc(size, GFP_ATOMIC); + if (!e) + return NULL; + + INIT_LIST_HEAD(&e->list); + e->type = type; + return e; +} + +static void qla4xxx_post_work(struct scsi_qla_host *ha, + struct qla4_work_evt *e) +{ + unsigned long flags; + + spin_lock_irqsave(&ha->work_lock, flags); + list_add_tail(&e->list, &ha->work_list); + spin_unlock_irqrestore(&ha->work_lock, flags); + qla4xxx_wake_dpc(ha); +} + +int qla4xxx_post_aen_work(struct scsi_qla_host *ha, + enum iscsi_host_event_code aen_code, + uint32_t data_size, uint8_t *data) +{ + struct qla4_work_evt *e; + + e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_AEN); + if (!e) + return QLA_ERROR; + + e->u.aen.code = aen_code; + e->u.aen.data_size = data_size; + memcpy(e->u.aen.data, data, data_size); + + qla4xxx_post_work(ha, e); + + return QLA_SUCCESS; +} + +void qla4xxx_do_work(struct scsi_qla_host *ha) +{ + struct qla4_work_evt *e, *tmp; + unsigned long flags; + LIST_HEAD(work); + + spin_lock_irqsave(&ha->work_lock, flags); + list_splice_init(&ha->work_list, &work); + spin_unlock_irqrestore(&ha->work_lock, flags); + + list_for_each_entry_safe(e, tmp, &work, list) { + list_del_init(&e->list); + + switch (e->type) { + case QLA4_EVENT_AEN: + iscsi_post_host_event(ha->host_no, + &qla4xxx_iscsi_transport, + e->u.aen.code, + e->u.aen.data_size, + e->u.aen.data); + break; + default: + ql4_printk(KERN_WARNING, ha, "event type: 0x%x not " + "supported", e->type); + } + kfree(e); + } +} + /** * qla4xxx_do_dpc - dpc routine * @data: in our case pointer to adapter structure @@ -2878,6 +2957,9 @@ static void qla4xxx_do_dpc(struct work_struct *work) return; } + /* post events to application */ + qla4xxx_do_work(ha); + if (is_qla8022(ha)) { if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { qla4_8xxx_idc_lock(ha); @@ -4450,6 +4532,9 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, spin_lock_init(&ha->hardware_lock); + /* Initialize work list */ + INIT_LIST_HEAD(&ha->work_list); + /* Allocate dma buffers */ if (qla4xxx_mem_alloc(ha)) { ql4_printk(KERN_WARNING, ha, |