aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/scsi/zfcp_aux.c4
-rw-r--r--drivers/s390/scsi/zfcp_def.h2
-rw-r--r--drivers/s390/scsi/zfcp_ext.h3
-rw-r--r--drivers/s390/scsi/zfcp_fc.c54
-rw-r--r--drivers/s390/scsi/zfcp_fc.h24
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c3
6 files changed, 90 insertions, 0 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 7c01c4c3f6b9..96fa1f536394 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -524,6 +524,10 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
524 rwlock_init(&adapter->port_list_lock); 524 rwlock_init(&adapter->port_list_lock);
525 INIT_LIST_HEAD(&adapter->port_list); 525 INIT_LIST_HEAD(&adapter->port_list);
526 526
527 INIT_LIST_HEAD(&adapter->events.list);
528 INIT_WORK(&adapter->events.work, zfcp_fc_post_event);
529 spin_lock_init(&adapter->events.list_lock);
530
527 init_waitqueue_head(&adapter->erp_ready_wq); 531 init_waitqueue_head(&adapter->erp_ready_wq);
528 init_waitqueue_head(&adapter->erp_done_wqh); 532 init_waitqueue_head(&adapter->erp_done_wqh);
529 533
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 86a8725430a4..cb3640c6477c 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -37,6 +37,7 @@
37#include <asm/ebcdic.h> 37#include <asm/ebcdic.h>
38#include <asm/sysinfo.h> 38#include <asm/sysinfo.h>
39#include "zfcp_fsf.h" 39#include "zfcp_fsf.h"
40#include "zfcp_fc.h"
40#include "zfcp_qdio.h" 41#include "zfcp_qdio.h"
41 42
42struct zfcp_reqlist; 43struct zfcp_reqlist;
@@ -190,6 +191,7 @@ struct zfcp_adapter {
190 struct service_level service_level; 191 struct service_level service_level;
191 struct workqueue_struct *work_queue; 192 struct workqueue_struct *work_queue;
192 struct device_dma_parameters dma_parms; 193 struct device_dma_parameters dma_parms;
194 struct zfcp_fc_events events;
193}; 195};
194 196
195struct zfcp_port { 197struct zfcp_port {
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 3aab0f5544d4..a8bb7488dc98 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -96,6 +96,9 @@ extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *,
96extern void zfcp_erp_timeout_handler(unsigned long); 96extern void zfcp_erp_timeout_handler(unsigned long);
97 97
98/* zfcp_fc.c */ 98/* zfcp_fc.c */
99extern void zfcp_fc_enqueue_event(struct zfcp_adapter *,
100 enum fc_host_event_code event_code, u32);
101extern void zfcp_fc_post_event(struct work_struct *);
99extern void zfcp_fc_scan_ports(struct work_struct *); 102extern void zfcp_fc_scan_ports(struct work_struct *);
100extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *); 103extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *);
101extern void zfcp_fc_port_did_lookup(struct work_struct *); 104extern void zfcp_fc_port_did_lookup(struct work_struct *);
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 6f8ab43a4856..6f3ed2b9a349 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -23,6 +23,58 @@ static u32 zfcp_fc_rscn_range_mask[] = {
23 [ELS_ADDR_FMT_FAB] = 0x000000, 23 [ELS_ADDR_FMT_FAB] = 0x000000,
24}; 24};
25 25
26/**
27 * zfcp_fc_post_event - post event to userspace via fc_transport
28 * @work: work struct with enqueued events
29 */
30void zfcp_fc_post_event(struct work_struct *work)
31{
32 struct zfcp_fc_event *event = NULL, *tmp = NULL;
33 LIST_HEAD(tmp_lh);
34 struct zfcp_fc_events *events = container_of(work,
35 struct zfcp_fc_events, work);
36 struct zfcp_adapter *adapter = container_of(events, struct zfcp_adapter,
37 events);
38
39 spin_lock_bh(&events->list_lock);
40 list_splice_init(&events->list, &tmp_lh);
41 spin_unlock_bh(&events->list_lock);
42
43 list_for_each_entry_safe(event, tmp, &tmp_lh, list) {
44 fc_host_post_event(adapter->scsi_host, fc_get_event_number(),
45 event->code, event->data);
46 list_del(&event->list);
47 kfree(event);
48 }
49
50}
51
52/**
53 * zfcp_fc_enqueue_event - safely enqueue FC HBA API event from irq context
54 * @adapter: The adapter where to enqueue the event
55 * @event_code: The event code (as defined in fc_host_event_code in
56 * scsi_transport_fc.h)
57 * @event_data: The event data (e.g. n_port page in case of els)
58 */
59void zfcp_fc_enqueue_event(struct zfcp_adapter *adapter,
60 enum fc_host_event_code event_code, u32 event_data)
61{
62 struct zfcp_fc_event *event;
63
64 event = kmalloc(sizeof(struct zfcp_fc_event), GFP_ATOMIC);
65 if (!event)
66 return;
67
68 event->code = event_code;
69 event->data = event_data;
70
71 spin_lock(&adapter->events.list_lock);
72 list_add_tail(&event->list, &adapter->events.list);
73 spin_unlock(&adapter->events.list_lock);
74
75 queue_work(adapter->work_queue, &adapter->events.work);
76}
77
26static int zfcp_fc_wka_port_get(struct zfcp_fc_wka_port *wka_port) 78static int zfcp_fc_wka_port_get(struct zfcp_fc_wka_port *wka_port)
27{ 79{
28 if (mutex_lock_interruptible(&wka_port->mutex)) 80 if (mutex_lock_interruptible(&wka_port->mutex))
@@ -148,6 +200,8 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
148 afmt = page->rscn_page_flags & ELS_RSCN_ADDR_FMT_MASK; 200 afmt = page->rscn_page_flags & ELS_RSCN_ADDR_FMT_MASK;
149 _zfcp_fc_incoming_rscn(fsf_req, zfcp_fc_rscn_range_mask[afmt], 201 _zfcp_fc_incoming_rscn(fsf_req, zfcp_fc_rscn_range_mask[afmt],
150 page); 202 page);
203 zfcp_fc_enqueue_event(fsf_req->adapter, FCH_EVT_RSCN,
204 *(u32 *)page);
151 } 205 }
152 queue_work(fsf_req->adapter->work_queue, &fsf_req->adapter->scan_work); 206 queue_work(fsf_req->adapter->work_queue, &fsf_req->adapter->scan_work);
153} 207}
diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h
index 0747b087390d..85c37d2b82c2 100644
--- a/drivers/s390/scsi/zfcp_fc.h
+++ b/drivers/s390/scsi/zfcp_fc.h
@@ -30,6 +30,30 @@
30#define ZFCP_FC_CTELS_TMO (2 * FC_DEF_R_A_TOV / 1000) 30#define ZFCP_FC_CTELS_TMO (2 * FC_DEF_R_A_TOV / 1000)
31 31
32/** 32/**
33 * struct zfcp_fc_event - FC HBAAPI event for internal queueing from irq context
34 * @code: Event code
35 * @data: Event data
36 * @list: list_head for zfcp_fc_events list
37 */
38struct zfcp_fc_event {
39 enum fc_host_event_code code;
40 u32 data;
41 struct list_head list;
42};
43
44/**
45 * struct zfcp_fc_events - Infrastructure for posting FC events from irq context
46 * @list: List for queueing of events from irq context to workqueue
47 * @list_lock: Lock for event list
48 * @work: work_struct for forwarding events in workqueue
49*/
50struct zfcp_fc_events {
51 struct list_head list;
52 spinlock_t list_lock;
53 struct work_struct work;
54};
55
56/**
33 * struct zfcp_fc_gid_pn_req - container for ct header plus gid_pn request 57 * struct zfcp_fc_gid_pn_req - container for ct header plus gid_pn request
34 * @ct_hdr: FC GS common transport header 58 * @ct_hdr: FC GS common transport header
35 * @gid_pn: GID_PN request 59 * @gid_pn: GID_PN request
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 0710c59b80ae..63402fd5f9ae 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -274,6 +274,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
274 break; 274 break;
275 case FSF_STATUS_READ_LINK_DOWN: 275 case FSF_STATUS_READ_LINK_DOWN:
276 zfcp_fsf_status_read_link_down(req); 276 zfcp_fsf_status_read_link_down(req);
277 zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKDOWN, 0);
277 break; 278 break;
278 case FSF_STATUS_READ_LINK_UP: 279 case FSF_STATUS_READ_LINK_UP:
279 dev_info(&adapter->ccw_device->dev, 280 dev_info(&adapter->ccw_device->dev,
@@ -286,6 +287,8 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
286 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | 287 ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
287 ZFCP_STATUS_COMMON_ERP_FAILED, 288 ZFCP_STATUS_COMMON_ERP_FAILED,
288 "fssrh_2", req); 289 "fssrh_2", req);
290 zfcp_fc_enqueue_event(adapter, FCH_EVT_LINKUP, 0);
291
289 break; 292 break;
290 case FSF_STATUS_READ_NOTIFICATION_LOST: 293 case FSF_STATUS_READ_NOTIFICATION_LOST:
291 if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED) 294 if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)