aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_os.c
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2008-04-03 16:13:18 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-04-07 13:19:13 -0400
commit0971de7f56f809f40edae6fd372745e429e970e9 (patch)
tree8ae6829060081a81e62193db81278f6aa5365e08 /drivers/scsi/qla2xxx/qla_os.c
parentc6952483b070ec8a4f2450d1116be908fe59edcc (diff)
[SCSI] qla2xxx: Add FC-transport Asynchronous Event Notification support.
Supported events include LIP, LIP reset, RSCN, link up, and link down. To support AEN (and additional forthcoming features), we also introduce a simple deferred-work construct to manage events which require a non-atomic sleeping-capable context. This work-list is processed as part of the driver's standard DPC routine. 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_os.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 661a1596679d..eb77067533ab 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1704,6 +1704,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
1704 INIT_LIST_HEAD(&ha->list); 1704 INIT_LIST_HEAD(&ha->list);
1705 INIT_LIST_HEAD(&ha->fcports); 1705 INIT_LIST_HEAD(&ha->fcports);
1706 INIT_LIST_HEAD(&ha->vp_list); 1706 INIT_LIST_HEAD(&ha->vp_list);
1707 INIT_LIST_HEAD(&ha->work_list);
1707 1708
1708 set_bit(0, (unsigned long *) ha->vp_idx_map); 1709 set_bit(0, (unsigned long *) ha->vp_idx_map);
1709 1710
@@ -2197,6 +2198,76 @@ qla2x00_mem_free(scsi_qla_host_t *ha)
2197 kfree(ha->nvram); 2198 kfree(ha->nvram);
2198} 2199}
2199 2200
2201struct qla_work_evt *
2202qla2x00_alloc_work(struct scsi_qla_host *ha, enum qla_work_type type,
2203 int locked)
2204{
2205 struct qla_work_evt *e;
2206
2207 e = kzalloc(sizeof(struct qla_work_evt), locked ? GFP_ATOMIC:
2208 GFP_KERNEL);
2209 if (!e)
2210 return NULL;
2211
2212 INIT_LIST_HEAD(&e->list);
2213 e->type = type;
2214 e->flags = QLA_EVT_FLAG_FREE;
2215 return e;
2216}
2217
2218int
2219qla2x00_post_work(struct scsi_qla_host *ha, struct qla_work_evt *e, int locked)
2220{
2221 unsigned long flags;
2222
2223 if (!locked)
2224 spin_lock_irqsave(&ha->hardware_lock, flags);
2225 list_add_tail(&e->list, &ha->work_list);
2226 qla2xxx_wake_dpc(ha);
2227 if (!locked)
2228 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2229 return QLA_SUCCESS;
2230}
2231
2232int
2233qla2x00_post_aen_work(struct scsi_qla_host *ha, enum fc_host_event_code code,
2234 u32 data)
2235{
2236 struct qla_work_evt *e;
2237
2238 e = qla2x00_alloc_work(ha, QLA_EVT_AEN, 1);
2239 if (!e)
2240 return QLA_FUNCTION_FAILED;
2241
2242 e->u.aen.code = code;
2243 e->u.aen.data = data;
2244 return qla2x00_post_work(ha, e, 1);
2245}
2246
2247static void
2248qla2x00_do_work(struct scsi_qla_host *ha)
2249{
2250 struct qla_work_evt *e;
2251
2252 spin_lock_irq(&ha->hardware_lock);
2253 while (!list_empty(&ha->work_list)) {
2254 e = list_entry(ha->work_list.next, struct qla_work_evt, list);
2255 list_del_init(&e->list);
2256 spin_unlock_irq(&ha->hardware_lock);
2257
2258 switch (e->type) {
2259 case QLA_EVT_AEN:
2260 fc_host_post_event(ha->host, fc_get_event_number(),
2261 e->u.aen.code, e->u.aen.data);
2262 break;
2263 }
2264 if (e->flags & QLA_EVT_FLAG_FREE)
2265 kfree(e);
2266 spin_lock_irq(&ha->hardware_lock);
2267 }
2268 spin_unlock_irq(&ha->hardware_lock);
2269}
2270
2200/************************************************************************** 2271/**************************************************************************
2201* qla2x00_do_dpc 2272* qla2x00_do_dpc
2202* This kernel thread is a task that is schedule by the interrupt handler 2273* This kernel thread is a task that is schedule by the interrupt handler
@@ -2248,6 +2319,8 @@ qla2x00_do_dpc(void *data)
2248 continue; 2319 continue;
2249 } 2320 }
2250 2321
2322 qla2x00_do_work(ha);
2323
2251 if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) { 2324 if (test_and_clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) {
2252 2325
2253 DEBUG(printk("scsi(%ld): dpc: sched " 2326 DEBUG(printk("scsi(%ld): dpc: sched "