aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorSven Schuetz <sven@linux.vnet.ibm.com>2010-07-16 09:37:39 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-07-28 10:48:52 -0400
commit2d1e547f7523514d1da449bcf08645fe13579378 (patch)
tree44ebfa0721405d3bd6f20e9c8bfd44adb8908ffd /drivers/s390
parent706eca49a044a1ea89352dcc4b96ffc1631b2cb5 (diff)
[SCSI] zfcp: Post events through FC transport class
Post FC transport class netlink events for usage in the userspace, e.g. for HBAAPI. Supported events are those required for the polled events in HBAAPI. - link up - link down - incoming RSCN (events related to FC-AL are not supported, as zfcp has no support for FC-AL) Signed-off-by: Sven Schuetz <sven@linux.vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/s390')
-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)