[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>
This commit is contained in:
Vikas Chaudhary 2011-08-29 23:43:02 +05:30 committed by James Bottomley
parent a11e254595
commit ff88443080
4 changed files with 111 additions and 0 deletions

View File

@ -301,7 +301,21 @@ struct ql4_tuple_ddb {
#define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */ #define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */
#define DF_FO_MASKED 3 #define DF_FO_MASKED 3
enum qla4_work_type {
QLA4_EVENT_AEN,
};
struct qla4_work_evt {
struct list_head list;
enum qla4_work_type type;
union {
struct {
enum iscsi_host_event_code code;
uint32_t data_size;
uint8_t data[0];
} aen;
} u;
};
struct ql82xx_hw_data { struct ql82xx_hw_data {
/* Offsets for flash/nvram access (set to ~0 if not used). */ /* Offsets for flash/nvram access (set to ~0 if not used). */
@ -672,6 +686,10 @@ struct scsi_qla_host {
uint16_t sec_ddb_idx; uint16_t sec_ddb_idx;
int is_reset; int is_reset;
uint16_t temperature; uint16_t temperature;
/* event work list */
struct list_head work_list;
spinlock_t work_lock;
}; };
struct ql4_task_data { struct ql4_task_data {

View File

@ -181,6 +181,8 @@ int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
struct ddb_entry *ddb_entry, uint32_t state); struct ddb_entry *ddb_entry, uint32_t state);
void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset); void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset);
int qla4xxx_post_aen_work(struct scsi_qla_host *ha, uint32_t aen_code,
uint32_t data_size, uint8_t *data);
/* BSG Functions */ /* BSG Functions */
int qla4xxx_bsg_request(struct bsg_job *bsg_job); int qla4xxx_bsg_request(struct bsg_job *bsg_job);

View File

@ -576,6 +576,9 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__); ql4_printk(KERN_INFO, ha, "%s: LINK UP\n", __func__);
qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKUP,
sizeof(mbox_sts),
(uint8_t *) mbox_sts);
break; break;
case MBOX_ASTS_LINK_DOWN: case MBOX_ASTS_LINK_DOWN:
@ -584,6 +587,9 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
set_bit(DPC_LINK_CHANGED, &ha->dpc_flags); set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__); ql4_printk(KERN_INFO, ha, "%s: LINK DOWN\n", __func__);
qla4xxx_post_aen_work(ha, ISCSI_EVENT_LINKDOWN,
sizeof(mbox_sts),
(uint8_t *) mbox_sts);
break; break;
case MBOX_ASTS_HEARTBEAT: case MBOX_ASTS_HEARTBEAT:

View File

@ -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. */ /* Wakeup the dpc routine for this adapter, if needed. */
if (start_dpc || if (start_dpc ||
test_bit(DPC_RESET_HA, &ha->dpc_flags) || 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); 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 * qla4xxx_do_dpc - dpc routine
* @data: in our case pointer to adapter structure * @data: in our case pointer to adapter structure
@ -2878,6 +2957,9 @@ static void qla4xxx_do_dpc(struct work_struct *work)
return; return;
} }
/* post events to application */
qla4xxx_do_work(ha);
if (is_qla8022(ha)) { if (is_qla8022(ha)) {
if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) { if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {
qla4_8xxx_idc_lock(ha); 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); spin_lock_init(&ha->hardware_lock);
/* Initialize work list */
INIT_LIST_HEAD(&ha->work_list);
/* Allocate dma buffers */ /* Allocate dma buffers */
if (qla4xxx_mem_alloc(ha)) { if (qla4xxx_mem_alloc(ha)) {
ql4_printk(KERN_WARNING, ha, ql4_printk(KERN_WARNING, ha,