diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_fc.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 677 |
1 files changed, 288 insertions, 389 deletions
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index df23bcead23d..ac5e3b7a3576 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c | |||
@@ -9,73 +9,38 @@ | |||
9 | #define KMSG_COMPONENT "zfcp" | 9 | #define KMSG_COMPONENT "zfcp" |
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
11 | 11 | ||
12 | #include <linux/types.h> | ||
13 | #include <scsi/fc/fc_els.h> | ||
14 | #include <scsi/libfc.h> | ||
12 | #include "zfcp_ext.h" | 15 | #include "zfcp_ext.h" |
16 | #include "zfcp_fc.h" | ||
13 | 17 | ||
14 | enum rscn_address_format { | 18 | static u32 zfcp_fc_rscn_range_mask[] = { |
15 | RSCN_PORT_ADDRESS = 0x0, | 19 | [ELS_ADDR_FMT_PORT] = 0xFFFFFF, |
16 | RSCN_AREA_ADDRESS = 0x1, | 20 | [ELS_ADDR_FMT_AREA] = 0xFFFF00, |
17 | RSCN_DOMAIN_ADDRESS = 0x2, | 21 | [ELS_ADDR_FMT_DOM] = 0xFF0000, |
18 | RSCN_FABRIC_ADDRESS = 0x3, | 22 | [ELS_ADDR_FMT_FAB] = 0x000000, |
19 | }; | 23 | }; |
20 | 24 | ||
21 | static u32 rscn_range_mask[] = { | 25 | static int zfcp_fc_wka_port_get(struct zfcp_fc_wka_port *wka_port) |
22 | [RSCN_PORT_ADDRESS] = 0xFFFFFF, | ||
23 | [RSCN_AREA_ADDRESS] = 0xFFFF00, | ||
24 | [RSCN_DOMAIN_ADDRESS] = 0xFF0000, | ||
25 | [RSCN_FABRIC_ADDRESS] = 0x000000, | ||
26 | }; | ||
27 | |||
28 | struct gpn_ft_resp_acc { | ||
29 | u8 control; | ||
30 | u8 port_id[3]; | ||
31 | u8 reserved[4]; | ||
32 | u64 wwpn; | ||
33 | } __attribute__ ((packed)); | ||
34 | |||
35 | #define ZFCP_CT_SIZE_ONE_PAGE (PAGE_SIZE - sizeof(struct ct_hdr)) | ||
36 | #define ZFCP_GPN_FT_ENTRIES (ZFCP_CT_SIZE_ONE_PAGE \ | ||
37 | / sizeof(struct gpn_ft_resp_acc)) | ||
38 | #define ZFCP_GPN_FT_BUFFERS 4 | ||
39 | #define ZFCP_GPN_FT_MAX_SIZE (ZFCP_GPN_FT_BUFFERS * PAGE_SIZE \ | ||
40 | - sizeof(struct ct_hdr)) | ||
41 | #define ZFCP_GPN_FT_MAX_ENTRIES ZFCP_GPN_FT_BUFFERS * (ZFCP_GPN_FT_ENTRIES + 1) | ||
42 | |||
43 | struct ct_iu_gpn_ft_resp { | ||
44 | struct ct_hdr header; | ||
45 | struct gpn_ft_resp_acc accept[ZFCP_GPN_FT_ENTRIES]; | ||
46 | } __attribute__ ((packed)); | ||
47 | |||
48 | struct zfcp_gpn_ft { | ||
49 | struct zfcp_send_ct ct; | ||
50 | struct scatterlist sg_req; | ||
51 | struct scatterlist sg_resp[ZFCP_GPN_FT_BUFFERS]; | ||
52 | }; | ||
53 | |||
54 | struct zfcp_fc_ns_handler_data { | ||
55 | struct completion done; | ||
56 | void (*handler)(unsigned long); | ||
57 | unsigned long handler_data; | ||
58 | }; | ||
59 | |||
60 | static int zfcp_fc_wka_port_get(struct zfcp_wka_port *wka_port) | ||
61 | { | 26 | { |
62 | if (mutex_lock_interruptible(&wka_port->mutex)) | 27 | if (mutex_lock_interruptible(&wka_port->mutex)) |
63 | return -ERESTARTSYS; | 28 | return -ERESTARTSYS; |
64 | 29 | ||
65 | if (wka_port->status == ZFCP_WKA_PORT_OFFLINE || | 30 | if (wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE || |
66 | wka_port->status == ZFCP_WKA_PORT_CLOSING) { | 31 | wka_port->status == ZFCP_FC_WKA_PORT_CLOSING) { |
67 | wka_port->status = ZFCP_WKA_PORT_OPENING; | 32 | wka_port->status = ZFCP_FC_WKA_PORT_OPENING; |
68 | if (zfcp_fsf_open_wka_port(wka_port)) | 33 | if (zfcp_fsf_open_wka_port(wka_port)) |
69 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | 34 | wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; |
70 | } | 35 | } |
71 | 36 | ||
72 | mutex_unlock(&wka_port->mutex); | 37 | mutex_unlock(&wka_port->mutex); |
73 | 38 | ||
74 | wait_event(wka_port->completion_wq, | 39 | wait_event(wka_port->completion_wq, |
75 | wka_port->status == ZFCP_WKA_PORT_ONLINE || | 40 | wka_port->status == ZFCP_FC_WKA_PORT_ONLINE || |
76 | wka_port->status == ZFCP_WKA_PORT_OFFLINE); | 41 | wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE); |
77 | 42 | ||
78 | if (wka_port->status == ZFCP_WKA_PORT_ONLINE) { | 43 | if (wka_port->status == ZFCP_FC_WKA_PORT_ONLINE) { |
79 | atomic_inc(&wka_port->refcount); | 44 | atomic_inc(&wka_port->refcount); |
80 | return 0; | 45 | return 0; |
81 | } | 46 | } |
@@ -85,24 +50,24 @@ static int zfcp_fc_wka_port_get(struct zfcp_wka_port *wka_port) | |||
85 | static void zfcp_fc_wka_port_offline(struct work_struct *work) | 50 | static void zfcp_fc_wka_port_offline(struct work_struct *work) |
86 | { | 51 | { |
87 | struct delayed_work *dw = to_delayed_work(work); | 52 | struct delayed_work *dw = to_delayed_work(work); |
88 | struct zfcp_wka_port *wka_port = | 53 | struct zfcp_fc_wka_port *wka_port = |
89 | container_of(dw, struct zfcp_wka_port, work); | 54 | container_of(dw, struct zfcp_fc_wka_port, work); |
90 | 55 | ||
91 | mutex_lock(&wka_port->mutex); | 56 | mutex_lock(&wka_port->mutex); |
92 | if ((atomic_read(&wka_port->refcount) != 0) || | 57 | if ((atomic_read(&wka_port->refcount) != 0) || |
93 | (wka_port->status != ZFCP_WKA_PORT_ONLINE)) | 58 | (wka_port->status != ZFCP_FC_WKA_PORT_ONLINE)) |
94 | goto out; | 59 | goto out; |
95 | 60 | ||
96 | wka_port->status = ZFCP_WKA_PORT_CLOSING; | 61 | wka_port->status = ZFCP_FC_WKA_PORT_CLOSING; |
97 | if (zfcp_fsf_close_wka_port(wka_port)) { | 62 | if (zfcp_fsf_close_wka_port(wka_port)) { |
98 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | 63 | wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; |
99 | wake_up(&wka_port->completion_wq); | 64 | wake_up(&wka_port->completion_wq); |
100 | } | 65 | } |
101 | out: | 66 | out: |
102 | mutex_unlock(&wka_port->mutex); | 67 | mutex_unlock(&wka_port->mutex); |
103 | } | 68 | } |
104 | 69 | ||
105 | static void zfcp_fc_wka_port_put(struct zfcp_wka_port *wka_port) | 70 | static void zfcp_fc_wka_port_put(struct zfcp_fc_wka_port *wka_port) |
106 | { | 71 | { |
107 | if (atomic_dec_return(&wka_port->refcount) != 0) | 72 | if (atomic_dec_return(&wka_port->refcount) != 0) |
108 | return; | 73 | return; |
@@ -110,7 +75,7 @@ static void zfcp_fc_wka_port_put(struct zfcp_wka_port *wka_port) | |||
110 | schedule_delayed_work(&wka_port->work, HZ / 100); | 75 | schedule_delayed_work(&wka_port->work, HZ / 100); |
111 | } | 76 | } |
112 | 77 | ||
113 | static void zfcp_fc_wka_port_init(struct zfcp_wka_port *wka_port, u32 d_id, | 78 | static void zfcp_fc_wka_port_init(struct zfcp_fc_wka_port *wka_port, u32 d_id, |
114 | struct zfcp_adapter *adapter) | 79 | struct zfcp_adapter *adapter) |
115 | { | 80 | { |
116 | init_waitqueue_head(&wka_port->completion_wq); | 81 | init_waitqueue_head(&wka_port->completion_wq); |
@@ -118,107 +83,107 @@ static void zfcp_fc_wka_port_init(struct zfcp_wka_port *wka_port, u32 d_id, | |||
118 | wka_port->adapter = adapter; | 83 | wka_port->adapter = adapter; |
119 | wka_port->d_id = d_id; | 84 | wka_port->d_id = d_id; |
120 | 85 | ||
121 | wka_port->status = ZFCP_WKA_PORT_OFFLINE; | 86 | wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE; |
122 | atomic_set(&wka_port->refcount, 0); | 87 | atomic_set(&wka_port->refcount, 0); |
123 | mutex_init(&wka_port->mutex); | 88 | mutex_init(&wka_port->mutex); |
124 | INIT_DELAYED_WORK(&wka_port->work, zfcp_fc_wka_port_offline); | 89 | INIT_DELAYED_WORK(&wka_port->work, zfcp_fc_wka_port_offline); |
125 | } | 90 | } |
126 | 91 | ||
127 | static void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka) | 92 | static void zfcp_fc_wka_port_force_offline(struct zfcp_fc_wka_port *wka) |
128 | { | 93 | { |
129 | cancel_delayed_work_sync(&wka->work); | 94 | cancel_delayed_work_sync(&wka->work); |
130 | mutex_lock(&wka->mutex); | 95 | mutex_lock(&wka->mutex); |
131 | wka->status = ZFCP_WKA_PORT_OFFLINE; | 96 | wka->status = ZFCP_FC_WKA_PORT_OFFLINE; |
132 | mutex_unlock(&wka->mutex); | 97 | mutex_unlock(&wka->mutex); |
133 | } | 98 | } |
134 | 99 | ||
135 | void zfcp_fc_wka_ports_force_offline(struct zfcp_wka_ports *gs) | 100 | void zfcp_fc_wka_ports_force_offline(struct zfcp_fc_wka_ports *gs) |
136 | { | 101 | { |
102 | if (!gs) | ||
103 | return; | ||
137 | zfcp_fc_wka_port_force_offline(&gs->ms); | 104 | zfcp_fc_wka_port_force_offline(&gs->ms); |
138 | zfcp_fc_wka_port_force_offline(&gs->ts); | 105 | zfcp_fc_wka_port_force_offline(&gs->ts); |
139 | zfcp_fc_wka_port_force_offline(&gs->ds); | 106 | zfcp_fc_wka_port_force_offline(&gs->ds); |
140 | zfcp_fc_wka_port_force_offline(&gs->as); | 107 | zfcp_fc_wka_port_force_offline(&gs->as); |
141 | zfcp_fc_wka_port_force_offline(&gs->ks); | ||
142 | } | 108 | } |
143 | 109 | ||
144 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, | 110 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, |
145 | struct fcp_rscn_element *elem) | 111 | struct fc_els_rscn_page *page) |
146 | { | 112 | { |
147 | unsigned long flags; | 113 | unsigned long flags; |
114 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
148 | struct zfcp_port *port; | 115 | struct zfcp_port *port; |
149 | 116 | ||
150 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 117 | read_lock_irqsave(&adapter->port_list_lock, flags); |
151 | list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) { | 118 | list_for_each_entry(port, &adapter->port_list, list) { |
152 | if ((port->d_id & range) == (elem->nport_did & range)) | 119 | if ((port->d_id & range) == (ntoh24(page->rscn_fid) & range)) |
153 | zfcp_fc_test_link(port); | 120 | zfcp_fc_test_link(port); |
154 | if (!port->d_id) | 121 | if (!port->d_id) |
155 | zfcp_erp_port_reopen(port, | 122 | zfcp_erp_port_reopen(port, |
156 | ZFCP_STATUS_COMMON_ERP_FAILED, | 123 | ZFCP_STATUS_COMMON_ERP_FAILED, |
157 | "fcrscn1", NULL); | 124 | "fcrscn1", NULL); |
158 | } | 125 | } |
159 | 126 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | |
160 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
161 | } | 127 | } |
162 | 128 | ||
163 | static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) | 129 | static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) |
164 | { | 130 | { |
165 | struct fsf_status_read_buffer *status_buffer = (void *)fsf_req->data; | 131 | struct fsf_status_read_buffer *status_buffer = (void *)fsf_req->data; |
166 | struct fcp_rscn_head *fcp_rscn_head; | 132 | struct fc_els_rscn *head; |
167 | struct fcp_rscn_element *fcp_rscn_element; | 133 | struct fc_els_rscn_page *page; |
168 | u16 i; | 134 | u16 i; |
169 | u16 no_entries; | 135 | u16 no_entries; |
170 | u32 range_mask; | 136 | unsigned int afmt; |
171 | 137 | ||
172 | fcp_rscn_head = (struct fcp_rscn_head *) status_buffer->payload.data; | 138 | head = (struct fc_els_rscn *) status_buffer->payload.data; |
173 | fcp_rscn_element = (struct fcp_rscn_element *) fcp_rscn_head; | 139 | page = (struct fc_els_rscn_page *) head; |
174 | 140 | ||
175 | /* see FC-FS */ | 141 | /* see FC-FS */ |
176 | no_entries = fcp_rscn_head->payload_len / | 142 | no_entries = head->rscn_plen / sizeof(struct fc_els_rscn_page); |
177 | sizeof(struct fcp_rscn_element); | ||
178 | 143 | ||
179 | for (i = 1; i < no_entries; i++) { | 144 | for (i = 1; i < no_entries; i++) { |
180 | /* skip head and start with 1st element */ | 145 | /* skip head and start with 1st element */ |
181 | fcp_rscn_element++; | 146 | page++; |
182 | range_mask = rscn_range_mask[fcp_rscn_element->addr_format]; | 147 | afmt = page->rscn_page_flags & ELS_RSCN_ADDR_FMT_MASK; |
183 | _zfcp_fc_incoming_rscn(fsf_req, range_mask, fcp_rscn_element); | 148 | _zfcp_fc_incoming_rscn(fsf_req, zfcp_fc_rscn_range_mask[afmt], |
149 | page); | ||
184 | } | 150 | } |
185 | schedule_work(&fsf_req->adapter->scan_work); | 151 | queue_work(fsf_req->adapter->work_queue, &fsf_req->adapter->scan_work); |
186 | } | 152 | } |
187 | 153 | ||
188 | static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) | 154 | static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) |
189 | { | 155 | { |
156 | unsigned long flags; | ||
190 | struct zfcp_adapter *adapter = req->adapter; | 157 | struct zfcp_adapter *adapter = req->adapter; |
191 | struct zfcp_port *port; | 158 | struct zfcp_port *port; |
192 | unsigned long flags; | ||
193 | 159 | ||
194 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 160 | read_lock_irqsave(&adapter->port_list_lock, flags); |
195 | list_for_each_entry(port, &adapter->port_list_head, list) | 161 | list_for_each_entry(port, &adapter->port_list, list) |
196 | if (port->wwpn == wwpn) | 162 | if (port->wwpn == wwpn) { |
163 | zfcp_erp_port_forced_reopen(port, 0, "fciwwp1", req); | ||
197 | break; | 164 | break; |
198 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 165 | } |
199 | 166 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | |
200 | if (port && (port->wwpn == wwpn)) | ||
201 | zfcp_erp_port_forced_reopen(port, 0, "fciwwp1", req); | ||
202 | } | 167 | } |
203 | 168 | ||
204 | static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req) | 169 | static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req) |
205 | { | 170 | { |
206 | struct fsf_status_read_buffer *status_buffer = | 171 | struct fsf_status_read_buffer *status_buffer; |
207 | (struct fsf_status_read_buffer *)req->data; | 172 | struct fc_els_flogi *plogi; |
208 | struct fsf_plogi *els_plogi = | ||
209 | (struct fsf_plogi *) status_buffer->payload.data; | ||
210 | 173 | ||
211 | zfcp_fc_incoming_wwpn(req, els_plogi->serv_param.wwpn); | 174 | status_buffer = (struct fsf_status_read_buffer *) req->data; |
175 | plogi = (struct fc_els_flogi *) status_buffer->payload.data; | ||
176 | zfcp_fc_incoming_wwpn(req, plogi->fl_wwpn); | ||
212 | } | 177 | } |
213 | 178 | ||
214 | static void zfcp_fc_incoming_logo(struct zfcp_fsf_req *req) | 179 | static void zfcp_fc_incoming_logo(struct zfcp_fsf_req *req) |
215 | { | 180 | { |
216 | struct fsf_status_read_buffer *status_buffer = | 181 | struct fsf_status_read_buffer *status_buffer = |
217 | (struct fsf_status_read_buffer *)req->data; | 182 | (struct fsf_status_read_buffer *)req->data; |
218 | struct fcp_logo *els_logo = | 183 | struct fc_els_logo *logo = |
219 | (struct fcp_logo *) status_buffer->payload.data; | 184 | (struct fc_els_logo *) status_buffer->payload.data; |
220 | 185 | ||
221 | zfcp_fc_incoming_wwpn(req, els_logo->nport_wwpn); | 186 | zfcp_fc_incoming_wwpn(req, logo->fl_n_port_wwn); |
222 | } | 187 | } |
223 | 188 | ||
224 | /** | 189 | /** |
@@ -232,79 +197,72 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req) | |||
232 | unsigned int els_type = status_buffer->payload.data[0]; | 197 | unsigned int els_type = status_buffer->payload.data[0]; |
233 | 198 | ||
234 | zfcp_dbf_san_incoming_els(fsf_req); | 199 | zfcp_dbf_san_incoming_els(fsf_req); |
235 | if (els_type == LS_PLOGI) | 200 | if (els_type == ELS_PLOGI) |
236 | zfcp_fc_incoming_plogi(fsf_req); | 201 | zfcp_fc_incoming_plogi(fsf_req); |
237 | else if (els_type == LS_LOGO) | 202 | else if (els_type == ELS_LOGO) |
238 | zfcp_fc_incoming_logo(fsf_req); | 203 | zfcp_fc_incoming_logo(fsf_req); |
239 | else if (els_type == LS_RSCN) | 204 | else if (els_type == ELS_RSCN) |
240 | zfcp_fc_incoming_rscn(fsf_req); | 205 | zfcp_fc_incoming_rscn(fsf_req); |
241 | } | 206 | } |
242 | 207 | ||
243 | static void zfcp_fc_ns_handler(unsigned long data) | 208 | static void zfcp_fc_ns_gid_pn_eval(void *data) |
244 | { | 209 | { |
245 | struct zfcp_fc_ns_handler_data *compl_rec = | 210 | struct zfcp_fc_gid_pn *gid_pn = data; |
246 | (struct zfcp_fc_ns_handler_data *) data; | 211 | struct zfcp_fsf_ct_els *ct = &gid_pn->ct; |
247 | 212 | struct zfcp_fc_gid_pn_req *gid_pn_req = sg_virt(ct->req); | |
248 | if (compl_rec->handler) | 213 | struct zfcp_fc_gid_pn_resp *gid_pn_resp = sg_virt(ct->resp); |
249 | compl_rec->handler(compl_rec->handler_data); | ||
250 | |||
251 | complete(&compl_rec->done); | ||
252 | } | ||
253 | |||
254 | static void zfcp_fc_ns_gid_pn_eval(unsigned long data) | ||
255 | { | ||
256 | struct zfcp_gid_pn_data *gid_pn = (struct zfcp_gid_pn_data *) data; | ||
257 | struct zfcp_send_ct *ct = &gid_pn->ct; | ||
258 | struct ct_iu_gid_pn_req *ct_iu_req = sg_virt(ct->req); | ||
259 | struct ct_iu_gid_pn_resp *ct_iu_resp = sg_virt(ct->resp); | ||
260 | struct zfcp_port *port = gid_pn->port; | 214 | struct zfcp_port *port = gid_pn->port; |
261 | 215 | ||
262 | if (ct->status) | 216 | if (ct->status) |
263 | return; | 217 | return; |
264 | if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) | 218 | if (gid_pn_resp->ct_hdr.ct_cmd != FC_FS_ACC) |
265 | return; | 219 | return; |
266 | 220 | ||
267 | /* paranoia */ | 221 | /* paranoia */ |
268 | if (ct_iu_req->wwpn != port->wwpn) | 222 | if (gid_pn_req->gid_pn.fn_wwpn != port->wwpn) |
269 | return; | 223 | return; |
270 | /* looks like a valid d_id */ | 224 | /* looks like a valid d_id */ |
271 | port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK; | 225 | port->d_id = ntoh24(gid_pn_resp->gid_pn.fp_fid); |
226 | } | ||
227 | |||
228 | static void zfcp_fc_complete(void *data) | ||
229 | { | ||
230 | complete(data); | ||
272 | } | 231 | } |
273 | 232 | ||
274 | static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port, | 233 | static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port, |
275 | struct zfcp_gid_pn_data *gid_pn) | 234 | struct zfcp_fc_gid_pn *gid_pn) |
276 | { | 235 | { |
277 | struct zfcp_adapter *adapter = port->adapter; | 236 | struct zfcp_adapter *adapter = port->adapter; |
278 | struct zfcp_fc_ns_handler_data compl_rec; | 237 | DECLARE_COMPLETION_ONSTACK(completion); |
279 | int ret; | 238 | int ret; |
280 | 239 | ||
281 | /* setup parameters for send generic command */ | 240 | /* setup parameters for send generic command */ |
282 | gid_pn->port = port; | 241 | gid_pn->port = port; |
283 | gid_pn->ct.wka_port = &adapter->gs->ds; | 242 | gid_pn->ct.handler = zfcp_fc_complete; |
284 | gid_pn->ct.handler = zfcp_fc_ns_handler; | 243 | gid_pn->ct.handler_data = &completion; |
285 | gid_pn->ct.handler_data = (unsigned long) &compl_rec; | 244 | gid_pn->ct.req = &gid_pn->sg_req; |
286 | gid_pn->ct.req = &gid_pn->req; | 245 | gid_pn->ct.resp = &gid_pn->sg_resp; |
287 | gid_pn->ct.resp = &gid_pn->resp; | 246 | sg_init_one(&gid_pn->sg_req, &gid_pn->gid_pn_req, |
288 | sg_init_one(&gid_pn->req, &gid_pn->ct_iu_req, | 247 | sizeof(struct zfcp_fc_gid_pn_req)); |
289 | sizeof(struct ct_iu_gid_pn_req)); | 248 | sg_init_one(&gid_pn->sg_resp, &gid_pn->gid_pn_resp, |
290 | sg_init_one(&gid_pn->resp, &gid_pn->ct_iu_resp, | 249 | sizeof(struct zfcp_fc_gid_pn_resp)); |
291 | sizeof(struct ct_iu_gid_pn_resp)); | ||
292 | 250 | ||
293 | /* setup nameserver request */ | 251 | /* setup nameserver request */ |
294 | gid_pn->ct_iu_req.header.revision = ZFCP_CT_REVISION; | 252 | gid_pn->gid_pn_req.ct_hdr.ct_rev = FC_CT_REV; |
295 | gid_pn->ct_iu_req.header.gs_type = ZFCP_CT_DIRECTORY_SERVICE; | 253 | gid_pn->gid_pn_req.ct_hdr.ct_fs_type = FC_FST_DIR; |
296 | gid_pn->ct_iu_req.header.gs_subtype = ZFCP_CT_NAME_SERVER; | 254 | gid_pn->gid_pn_req.ct_hdr.ct_fs_subtype = FC_NS_SUBTYPE; |
297 | gid_pn->ct_iu_req.header.options = ZFCP_CT_SYNCHRONOUS; | 255 | gid_pn->gid_pn_req.ct_hdr.ct_options = 0; |
298 | gid_pn->ct_iu_req.header.cmd_rsp_code = ZFCP_CT_GID_PN; | 256 | gid_pn->gid_pn_req.ct_hdr.ct_cmd = FC_NS_GID_PN; |
299 | gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_SIZE_ONE_PAGE / 4; | 257 | gid_pn->gid_pn_req.ct_hdr.ct_mr_size = ZFCP_FC_CT_SIZE_PAGE / 4; |
300 | gid_pn->ct_iu_req.wwpn = port->wwpn; | 258 | gid_pn->gid_pn_req.gid_pn.fn_wwpn = port->wwpn; |
301 | 259 | ||
302 | init_completion(&compl_rec.done); | 260 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, &gid_pn->ct, |
303 | compl_rec.handler = zfcp_fc_ns_gid_pn_eval; | 261 | adapter->pool.gid_pn_req); |
304 | compl_rec.handler_data = (unsigned long) gid_pn; | 262 | if (!ret) { |
305 | ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.gid_pn_req); | 263 | wait_for_completion(&completion); |
306 | if (!ret) | 264 | zfcp_fc_ns_gid_pn_eval(gid_pn); |
307 | wait_for_completion(&compl_rec.done); | 265 | } |
308 | return ret; | 266 | return ret; |
309 | } | 267 | } |
310 | 268 | ||
@@ -316,10 +274,10 @@ static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port, | |||
316 | static int zfcp_fc_ns_gid_pn(struct zfcp_port *port) | 274 | static int zfcp_fc_ns_gid_pn(struct zfcp_port *port) |
317 | { | 275 | { |
318 | int ret; | 276 | int ret; |
319 | struct zfcp_gid_pn_data *gid_pn; | 277 | struct zfcp_fc_gid_pn *gid_pn; |
320 | struct zfcp_adapter *adapter = port->adapter; | 278 | struct zfcp_adapter *adapter = port->adapter; |
321 | 279 | ||
322 | gid_pn = mempool_alloc(adapter->pool.gid_pn_data, GFP_ATOMIC); | 280 | gid_pn = mempool_alloc(adapter->pool.gid_pn, GFP_ATOMIC); |
323 | if (!gid_pn) | 281 | if (!gid_pn) |
324 | return -ENOMEM; | 282 | return -ENOMEM; |
325 | 283 | ||
@@ -333,7 +291,7 @@ static int zfcp_fc_ns_gid_pn(struct zfcp_port *port) | |||
333 | 291 | ||
334 | zfcp_fc_wka_port_put(&adapter->gs->ds); | 292 | zfcp_fc_wka_port_put(&adapter->gs->ds); |
335 | out: | 293 | out: |
336 | mempool_free(gid_pn, adapter->pool.gid_pn_data); | 294 | mempool_free(gid_pn, adapter->pool.gid_pn); |
337 | return ret; | 295 | return ret; |
338 | } | 296 | } |
339 | 297 | ||
@@ -357,7 +315,7 @@ void zfcp_fc_port_did_lookup(struct work_struct *work) | |||
357 | 315 | ||
358 | zfcp_erp_port_reopen(port, 0, "fcgpn_3", NULL); | 316 | zfcp_erp_port_reopen(port, 0, "fcgpn_3", NULL); |
359 | out: | 317 | out: |
360 | zfcp_port_put(port); | 318 | put_device(&port->sysfs_device); |
361 | } | 319 | } |
362 | 320 | ||
363 | /** | 321 | /** |
@@ -366,9 +324,9 @@ out: | |||
366 | */ | 324 | */ |
367 | void zfcp_fc_trigger_did_lookup(struct zfcp_port *port) | 325 | void zfcp_fc_trigger_did_lookup(struct zfcp_port *port) |
368 | { | 326 | { |
369 | zfcp_port_get(port); | 327 | get_device(&port->sysfs_device); |
370 | if (!queue_work(port->adapter->work_queue, &port->gid_pn_work)) | 328 | if (!queue_work(port->adapter->work_queue, &port->gid_pn_work)) |
371 | zfcp_port_put(port); | 329 | put_device(&port->sysfs_device); |
372 | } | 330 | } |
373 | 331 | ||
374 | /** | 332 | /** |
@@ -378,33 +336,36 @@ void zfcp_fc_trigger_did_lookup(struct zfcp_port *port) | |||
378 | * | 336 | * |
379 | * Evaluate PLOGI playload and copy important fields into zfcp_port structure | 337 | * Evaluate PLOGI playload and copy important fields into zfcp_port structure |
380 | */ | 338 | */ |
381 | void zfcp_fc_plogi_evaluate(struct zfcp_port *port, struct fsf_plogi *plogi) | 339 | void zfcp_fc_plogi_evaluate(struct zfcp_port *port, struct fc_els_flogi *plogi) |
382 | { | 340 | { |
383 | port->maxframe_size = plogi->serv_param.common_serv_param[7] | | 341 | if (plogi->fl_wwpn != port->wwpn) { |
384 | ((plogi->serv_param.common_serv_param[6] & 0x0F) << 8); | 342 | port->d_id = 0; |
385 | if (plogi->serv_param.class1_serv_param[0] & 0x80) | 343 | dev_warn(&port->adapter->ccw_device->dev, |
344 | "A port opened with WWPN 0x%016Lx returned data that " | ||
345 | "identifies it as WWPN 0x%016Lx\n", | ||
346 | (unsigned long long) port->wwpn, | ||
347 | (unsigned long long) plogi->fl_wwpn); | ||
348 | return; | ||
349 | } | ||
350 | |||
351 | port->wwnn = plogi->fl_wwnn; | ||
352 | port->maxframe_size = plogi->fl_csp.sp_bb_data; | ||
353 | |||
354 | if (plogi->fl_cssp[0].cp_class & FC_CPC_VALID) | ||
386 | port->supported_classes |= FC_COS_CLASS1; | 355 | port->supported_classes |= FC_COS_CLASS1; |
387 | if (plogi->serv_param.class2_serv_param[0] & 0x80) | 356 | if (plogi->fl_cssp[1].cp_class & FC_CPC_VALID) |
388 | port->supported_classes |= FC_COS_CLASS2; | 357 | port->supported_classes |= FC_COS_CLASS2; |
389 | if (plogi->serv_param.class3_serv_param[0] & 0x80) | 358 | if (plogi->fl_cssp[2].cp_class & FC_CPC_VALID) |
390 | port->supported_classes |= FC_COS_CLASS3; | 359 | port->supported_classes |= FC_COS_CLASS3; |
391 | if (plogi->serv_param.class4_serv_param[0] & 0x80) | 360 | if (plogi->fl_cssp[3].cp_class & FC_CPC_VALID) |
392 | port->supported_classes |= FC_COS_CLASS4; | 361 | port->supported_classes |= FC_COS_CLASS4; |
393 | } | 362 | } |
394 | 363 | ||
395 | struct zfcp_els_adisc { | 364 | static void zfcp_fc_adisc_handler(void *data) |
396 | struct zfcp_send_els els; | ||
397 | struct scatterlist req; | ||
398 | struct scatterlist resp; | ||
399 | struct zfcp_ls_adisc ls_adisc; | ||
400 | struct zfcp_ls_adisc ls_adisc_acc; | ||
401 | }; | ||
402 | |||
403 | static void zfcp_fc_adisc_handler(unsigned long data) | ||
404 | { | 365 | { |
405 | struct zfcp_els_adisc *adisc = (struct zfcp_els_adisc *) data; | 366 | struct zfcp_fc_els_adisc *adisc = data; |
406 | struct zfcp_port *port = adisc->els.port; | 367 | struct zfcp_port *port = adisc->els.port; |
407 | struct zfcp_ls_adisc *ls_adisc = &adisc->ls_adisc_acc; | 368 | struct fc_els_adisc *adisc_resp = &adisc->adisc_resp; |
408 | 369 | ||
409 | if (adisc->els.status) { | 370 | if (adisc->els.status) { |
410 | /* request rejected or timed out */ | 371 | /* request rejected or timed out */ |
@@ -414,9 +375,9 @@ static void zfcp_fc_adisc_handler(unsigned long data) | |||
414 | } | 375 | } |
415 | 376 | ||
416 | if (!port->wwnn) | 377 | if (!port->wwnn) |
417 | port->wwnn = ls_adisc->wwnn; | 378 | port->wwnn = adisc_resp->adisc_wwnn; |
418 | 379 | ||
419 | if ((port->wwpn != ls_adisc->wwpn) || | 380 | if ((port->wwpn != adisc_resp->adisc_wwpn) || |
420 | !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) { | 381 | !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) { |
421 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, | 382 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, |
422 | "fcadh_2", NULL); | 383 | "fcadh_2", NULL); |
@@ -427,40 +388,44 @@ static void zfcp_fc_adisc_handler(unsigned long data) | |||
427 | zfcp_scsi_schedule_rport_register(port); | 388 | zfcp_scsi_schedule_rport_register(port); |
428 | out: | 389 | out: |
429 | atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status); | 390 | atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status); |
430 | zfcp_port_put(port); | 391 | put_device(&port->sysfs_device); |
431 | kfree(adisc); | 392 | kmem_cache_free(zfcp_data.adisc_cache, adisc); |
432 | } | 393 | } |
433 | 394 | ||
434 | static int zfcp_fc_adisc(struct zfcp_port *port) | 395 | static int zfcp_fc_adisc(struct zfcp_port *port) |
435 | { | 396 | { |
436 | struct zfcp_els_adisc *adisc; | 397 | struct zfcp_fc_els_adisc *adisc; |
437 | struct zfcp_adapter *adapter = port->adapter; | 398 | struct zfcp_adapter *adapter = port->adapter; |
399 | int ret; | ||
438 | 400 | ||
439 | adisc = kzalloc(sizeof(struct zfcp_els_adisc), GFP_ATOMIC); | 401 | adisc = kmem_cache_alloc(zfcp_data.adisc_cache, GFP_ATOMIC); |
440 | if (!adisc) | 402 | if (!adisc) |
441 | return -ENOMEM; | 403 | return -ENOMEM; |
442 | 404 | ||
405 | adisc->els.port = port; | ||
443 | adisc->els.req = &adisc->req; | 406 | adisc->els.req = &adisc->req; |
444 | adisc->els.resp = &adisc->resp; | 407 | adisc->els.resp = &adisc->resp; |
445 | sg_init_one(adisc->els.req, &adisc->ls_adisc, | 408 | sg_init_one(adisc->els.req, &adisc->adisc_req, |
446 | sizeof(struct zfcp_ls_adisc)); | 409 | sizeof(struct fc_els_adisc)); |
447 | sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc, | 410 | sg_init_one(adisc->els.resp, &adisc->adisc_resp, |
448 | sizeof(struct zfcp_ls_adisc)); | 411 | sizeof(struct fc_els_adisc)); |
449 | 412 | ||
450 | adisc->els.adapter = adapter; | ||
451 | adisc->els.port = port; | ||
452 | adisc->els.d_id = port->d_id; | ||
453 | adisc->els.handler = zfcp_fc_adisc_handler; | 413 | adisc->els.handler = zfcp_fc_adisc_handler; |
454 | adisc->els.handler_data = (unsigned long) adisc; | 414 | adisc->els.handler_data = adisc; |
455 | adisc->els.ls_code = adisc->ls_adisc.code = ZFCP_LS_ADISC; | ||
456 | 415 | ||
457 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports | 416 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports |
458 | without FC-AL-2 capability, so we don't set it */ | 417 | without FC-AL-2 capability, so we don't set it */ |
459 | adisc->ls_adisc.wwpn = fc_host_port_name(adapter->scsi_host); | 418 | adisc->adisc_req.adisc_wwpn = fc_host_port_name(adapter->scsi_host); |
460 | adisc->ls_adisc.wwnn = fc_host_node_name(adapter->scsi_host); | 419 | adisc->adisc_req.adisc_wwnn = fc_host_node_name(adapter->scsi_host); |
461 | adisc->ls_adisc.nport_id = fc_host_port_id(adapter->scsi_host); | 420 | adisc->adisc_req.adisc_cmd = ELS_ADISC; |
421 | hton24(adisc->adisc_req.adisc_port_id, | ||
422 | fc_host_port_id(adapter->scsi_host)); | ||
423 | |||
424 | ret = zfcp_fsf_send_els(adapter, port->d_id, &adisc->els); | ||
425 | if (ret) | ||
426 | kmem_cache_free(zfcp_data.adisc_cache, adisc); | ||
462 | 427 | ||
463 | return zfcp_fsf_send_els(&adisc->els); | 428 | return ret; |
464 | } | 429 | } |
465 | 430 | ||
466 | void zfcp_fc_link_test_work(struct work_struct *work) | 431 | void zfcp_fc_link_test_work(struct work_struct *work) |
@@ -469,7 +434,7 @@ void zfcp_fc_link_test_work(struct work_struct *work) | |||
469 | container_of(work, struct zfcp_port, test_link_work); | 434 | container_of(work, struct zfcp_port, test_link_work); |
470 | int retval; | 435 | int retval; |
471 | 436 | ||
472 | zfcp_port_get(port); | 437 | get_device(&port->sysfs_device); |
473 | port->rport_task = RPORT_DEL; | 438 | port->rport_task = RPORT_DEL; |
474 | zfcp_scsi_rport_work(&port->rport_work); | 439 | zfcp_scsi_rport_work(&port->rport_work); |
475 | 440 | ||
@@ -488,7 +453,7 @@ void zfcp_fc_link_test_work(struct work_struct *work) | |||
488 | zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL); | 453 | zfcp_erp_port_forced_reopen(port, 0, "fcltwk1", NULL); |
489 | 454 | ||
490 | out: | 455 | out: |
491 | zfcp_port_put(port); | 456 | put_device(&port->sysfs_device); |
492 | } | 457 | } |
493 | 458 | ||
494 | /** | 459 | /** |
@@ -501,12 +466,12 @@ out: | |||
501 | */ | 466 | */ |
502 | void zfcp_fc_test_link(struct zfcp_port *port) | 467 | void zfcp_fc_test_link(struct zfcp_port *port) |
503 | { | 468 | { |
504 | zfcp_port_get(port); | 469 | get_device(&port->sysfs_device); |
505 | if (!queue_work(port->adapter->work_queue, &port->test_link_work)) | 470 | if (!queue_work(port->adapter->work_queue, &port->test_link_work)) |
506 | zfcp_port_put(port); | 471 | put_device(&port->sysfs_device); |
507 | } | 472 | } |
508 | 473 | ||
509 | static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft, int buf_num) | 474 | static void zfcp_free_sg_env(struct zfcp_fc_gpn_ft *gpn_ft, int buf_num) |
510 | { | 475 | { |
511 | struct scatterlist *sg = &gpn_ft->sg_req; | 476 | struct scatterlist *sg = &gpn_ft->sg_req; |
512 | 477 | ||
@@ -516,10 +481,10 @@ static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft, int buf_num) | |||
516 | kfree(gpn_ft); | 481 | kfree(gpn_ft); |
517 | } | 482 | } |
518 | 483 | ||
519 | static struct zfcp_gpn_ft *zfcp_alloc_sg_env(int buf_num) | 484 | static struct zfcp_fc_gpn_ft *zfcp_alloc_sg_env(int buf_num) |
520 | { | 485 | { |
521 | struct zfcp_gpn_ft *gpn_ft; | 486 | struct zfcp_fc_gpn_ft *gpn_ft; |
522 | struct ct_iu_gpn_ft_req *req; | 487 | struct zfcp_fc_gpn_ft_req *req; |
523 | 488 | ||
524 | gpn_ft = kzalloc(sizeof(*gpn_ft), GFP_KERNEL); | 489 | gpn_ft = kzalloc(sizeof(*gpn_ft), GFP_KERNEL); |
525 | if (!gpn_ft) | 490 | if (!gpn_ft) |
@@ -542,159 +507,152 @@ out: | |||
542 | } | 507 | } |
543 | 508 | ||
544 | 509 | ||
545 | static int zfcp_fc_send_gpn_ft(struct zfcp_gpn_ft *gpn_ft, | 510 | static int zfcp_fc_send_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, |
546 | struct zfcp_adapter *adapter, int max_bytes) | 511 | struct zfcp_adapter *adapter, int max_bytes) |
547 | { | 512 | { |
548 | struct zfcp_send_ct *ct = &gpn_ft->ct; | 513 | struct zfcp_fsf_ct_els *ct = &gpn_ft->ct; |
549 | struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req); | 514 | struct zfcp_fc_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req); |
550 | struct zfcp_fc_ns_handler_data compl_rec; | 515 | DECLARE_COMPLETION_ONSTACK(completion); |
551 | int ret; | 516 | int ret; |
552 | 517 | ||
553 | /* prepare CT IU for GPN_FT */ | 518 | /* prepare CT IU for GPN_FT */ |
554 | req->header.revision = ZFCP_CT_REVISION; | 519 | req->ct_hdr.ct_rev = FC_CT_REV; |
555 | req->header.gs_type = ZFCP_CT_DIRECTORY_SERVICE; | 520 | req->ct_hdr.ct_fs_type = FC_FST_DIR; |
556 | req->header.gs_subtype = ZFCP_CT_NAME_SERVER; | 521 | req->ct_hdr.ct_fs_subtype = FC_NS_SUBTYPE; |
557 | req->header.options = ZFCP_CT_SYNCHRONOUS; | 522 | req->ct_hdr.ct_options = 0; |
558 | req->header.cmd_rsp_code = ZFCP_CT_GPN_FT; | 523 | req->ct_hdr.ct_cmd = FC_NS_GPN_FT; |
559 | req->header.max_res_size = max_bytes / 4; | 524 | req->ct_hdr.ct_mr_size = max_bytes / 4; |
560 | req->flags = 0; | 525 | req->gpn_ft.fn_domain_id_scope = 0; |
561 | req->domain_id_scope = 0; | 526 | req->gpn_ft.fn_area_id_scope = 0; |
562 | req->area_id_scope = 0; | 527 | req->gpn_ft.fn_fc4_type = FC_TYPE_FCP; |
563 | req->fc4_type = ZFCP_CT_SCSI_FCP; | ||
564 | 528 | ||
565 | /* prepare zfcp_send_ct */ | 529 | /* prepare zfcp_send_ct */ |
566 | ct->wka_port = &adapter->gs->ds; | 530 | ct->handler = zfcp_fc_complete; |
567 | ct->handler = zfcp_fc_ns_handler; | 531 | ct->handler_data = &completion; |
568 | ct->handler_data = (unsigned long)&compl_rec; | ||
569 | ct->req = &gpn_ft->sg_req; | 532 | ct->req = &gpn_ft->sg_req; |
570 | ct->resp = gpn_ft->sg_resp; | 533 | ct->resp = gpn_ft->sg_resp; |
571 | 534 | ||
572 | init_completion(&compl_rec.done); | 535 | ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct, NULL); |
573 | compl_rec.handler = NULL; | ||
574 | ret = zfcp_fsf_send_ct(ct, NULL); | ||
575 | if (!ret) | 536 | if (!ret) |
576 | wait_for_completion(&compl_rec.done); | 537 | wait_for_completion(&completion); |
577 | return ret; | 538 | return ret; |
578 | } | 539 | } |
579 | 540 | ||
580 | static void zfcp_fc_validate_port(struct zfcp_port *port) | 541 | static void zfcp_fc_validate_port(struct zfcp_port *port, struct list_head *lh) |
581 | { | 542 | { |
582 | struct zfcp_adapter *adapter = port->adapter; | ||
583 | |||
584 | if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC)) | 543 | if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC)) |
585 | return; | 544 | return; |
586 | 545 | ||
587 | atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status); | 546 | atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status); |
588 | 547 | ||
589 | if ((port->supported_classes != 0) || | 548 | if ((port->supported_classes != 0) || |
590 | !list_empty(&port->unit_list_head)) { | 549 | !list_empty(&port->unit_list)) |
591 | zfcp_port_put(port); | ||
592 | return; | 550 | return; |
593 | } | 551 | |
594 | zfcp_erp_port_shutdown(port, 0, "fcpval1", NULL); | 552 | list_move_tail(&port->list, lh); |
595 | zfcp_erp_wait(adapter); | ||
596 | zfcp_port_put(port); | ||
597 | zfcp_port_dequeue(port); | ||
598 | } | 553 | } |
599 | 554 | ||
600 | static int zfcp_fc_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries) | 555 | static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft, |
556 | struct zfcp_adapter *adapter, int max_entries) | ||
601 | { | 557 | { |
602 | struct zfcp_send_ct *ct = &gpn_ft->ct; | 558 | struct zfcp_fsf_ct_els *ct = &gpn_ft->ct; |
603 | struct scatterlist *sg = gpn_ft->sg_resp; | 559 | struct scatterlist *sg = gpn_ft->sg_resp; |
604 | struct ct_hdr *hdr = sg_virt(sg); | 560 | struct fc_ct_hdr *hdr = sg_virt(sg); |
605 | struct gpn_ft_resp_acc *acc = sg_virt(sg); | 561 | struct fc_gpn_ft_resp *acc = sg_virt(sg); |
606 | struct zfcp_adapter *adapter = ct->wka_port->adapter; | ||
607 | struct zfcp_port *port, *tmp; | 562 | struct zfcp_port *port, *tmp; |
563 | unsigned long flags; | ||
564 | LIST_HEAD(remove_lh); | ||
608 | u32 d_id; | 565 | u32 d_id; |
609 | int ret = 0, x, last = 0; | 566 | int ret = 0, x, last = 0; |
610 | 567 | ||
611 | if (ct->status) | 568 | if (ct->status) |
612 | return -EIO; | 569 | return -EIO; |
613 | 570 | ||
614 | if (hdr->cmd_rsp_code != ZFCP_CT_ACCEPT) { | 571 | if (hdr->ct_cmd != FC_FS_ACC) { |
615 | if (hdr->reason_code == ZFCP_CT_UNABLE_TO_PERFORM_CMD) | 572 | if (hdr->ct_reason == FC_BA_RJT_UNABLE) |
616 | return -EAGAIN; /* might be a temporary condition */ | 573 | return -EAGAIN; /* might be a temporary condition */ |
617 | return -EIO; | 574 | return -EIO; |
618 | } | 575 | } |
619 | 576 | ||
620 | if (hdr->max_res_size) { | 577 | if (hdr->ct_mr_size) { |
621 | dev_warn(&adapter->ccw_device->dev, | 578 | dev_warn(&adapter->ccw_device->dev, |
622 | "The name server reported %d words residual data\n", | 579 | "The name server reported %d words residual data\n", |
623 | hdr->max_res_size); | 580 | hdr->ct_mr_size); |
624 | return -E2BIG; | 581 | return -E2BIG; |
625 | } | 582 | } |
626 | 583 | ||
627 | mutex_lock(&zfcp_data.config_mutex); | ||
628 | |||
629 | /* first entry is the header */ | 584 | /* first entry is the header */ |
630 | for (x = 1; x < max_entries && !last; x++) { | 585 | for (x = 1; x < max_entries && !last; x++) { |
631 | if (x % (ZFCP_GPN_FT_ENTRIES + 1)) | 586 | if (x % (ZFCP_FC_GPN_FT_ENT_PAGE + 1)) |
632 | acc++; | 587 | acc++; |
633 | else | 588 | else |
634 | acc = sg_virt(++sg); | 589 | acc = sg_virt(++sg); |
635 | 590 | ||
636 | last = acc->control & 0x80; | 591 | last = acc->fp_flags & FC_NS_FID_LAST; |
637 | d_id = acc->port_id[0] << 16 | acc->port_id[1] << 8 | | 592 | d_id = ntoh24(acc->fp_fid); |
638 | acc->port_id[2]; | ||
639 | 593 | ||
640 | /* don't attach ports with a well known address */ | 594 | /* don't attach ports with a well known address */ |
641 | if ((d_id & ZFCP_DID_WKA) == ZFCP_DID_WKA) | 595 | if (d_id >= FC_FID_WELL_KNOWN_BASE) |
642 | continue; | 596 | continue; |
643 | /* skip the adapter's port and known remote ports */ | 597 | /* skip the adapter's port and known remote ports */ |
644 | if (acc->wwpn == fc_host_port_name(adapter->scsi_host)) | 598 | if (acc->fp_wwpn == fc_host_port_name(adapter->scsi_host)) |
645 | continue; | ||
646 | port = zfcp_get_port_by_wwpn(adapter, acc->wwpn); | ||
647 | if (port) | ||
648 | continue; | 599 | continue; |
649 | 600 | ||
650 | port = zfcp_port_enqueue(adapter, acc->wwpn, | 601 | port = zfcp_port_enqueue(adapter, acc->fp_wwpn, |
651 | ZFCP_STATUS_COMMON_NOESC, d_id); | 602 | ZFCP_STATUS_COMMON_NOESC, d_id); |
652 | if (IS_ERR(port)) | 603 | if (!IS_ERR(port)) |
653 | ret = PTR_ERR(port); | ||
654 | else | ||
655 | zfcp_erp_port_reopen(port, 0, "fcegpf1", NULL); | 604 | zfcp_erp_port_reopen(port, 0, "fcegpf1", NULL); |
605 | else if (PTR_ERR(port) != -EEXIST) | ||
606 | ret = PTR_ERR(port); | ||
656 | } | 607 | } |
657 | 608 | ||
658 | zfcp_erp_wait(adapter); | 609 | zfcp_erp_wait(adapter); |
659 | list_for_each_entry_safe(port, tmp, &adapter->port_list_head, list) | 610 | write_lock_irqsave(&adapter->port_list_lock, flags); |
660 | zfcp_fc_validate_port(port); | 611 | list_for_each_entry_safe(port, tmp, &adapter->port_list, list) |
661 | mutex_unlock(&zfcp_data.config_mutex); | 612 | zfcp_fc_validate_port(port, &remove_lh); |
613 | write_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
614 | |||
615 | list_for_each_entry_safe(port, tmp, &remove_lh, list) { | ||
616 | zfcp_erp_port_shutdown(port, 0, "fcegpf2", NULL); | ||
617 | zfcp_device_unregister(&port->sysfs_device, | ||
618 | &zfcp_sysfs_port_attrs); | ||
619 | } | ||
620 | |||
662 | return ret; | 621 | return ret; |
663 | } | 622 | } |
664 | 623 | ||
665 | /** | 624 | /** |
666 | * zfcp_fc_scan_ports - scan remote ports and attach new ports | 625 | * zfcp_fc_scan_ports - scan remote ports and attach new ports |
667 | * @adapter: pointer to struct zfcp_adapter | 626 | * @work: reference to scheduled work |
668 | */ | 627 | */ |
669 | int zfcp_fc_scan_ports(struct zfcp_adapter *adapter) | 628 | void zfcp_fc_scan_ports(struct work_struct *work) |
670 | { | 629 | { |
630 | struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter, | ||
631 | scan_work); | ||
671 | int ret, i; | 632 | int ret, i; |
672 | struct zfcp_gpn_ft *gpn_ft; | 633 | struct zfcp_fc_gpn_ft *gpn_ft; |
673 | int chain, max_entries, buf_num, max_bytes; | 634 | int chain, max_entries, buf_num, max_bytes; |
674 | 635 | ||
675 | chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS; | 636 | chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS; |
676 | buf_num = chain ? ZFCP_GPN_FT_BUFFERS : 1; | 637 | buf_num = chain ? ZFCP_FC_GPN_FT_NUM_BUFS : 1; |
677 | max_entries = chain ? ZFCP_GPN_FT_MAX_ENTRIES : ZFCP_GPN_FT_ENTRIES; | 638 | max_entries = chain ? ZFCP_FC_GPN_FT_MAX_ENT : ZFCP_FC_GPN_FT_ENT_PAGE; |
678 | max_bytes = chain ? ZFCP_GPN_FT_MAX_SIZE : ZFCP_CT_SIZE_ONE_PAGE; | 639 | max_bytes = chain ? ZFCP_FC_GPN_FT_MAX_SIZE : ZFCP_FC_CT_SIZE_PAGE; |
679 | 640 | ||
680 | if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT && | 641 | if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT && |
681 | fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) | 642 | fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) |
682 | return 0; | 643 | return; |
683 | 644 | ||
684 | ret = zfcp_fc_wka_port_get(&adapter->gs->ds); | 645 | if (zfcp_fc_wka_port_get(&adapter->gs->ds)) |
685 | if (ret) | 646 | return; |
686 | return ret; | ||
687 | 647 | ||
688 | gpn_ft = zfcp_alloc_sg_env(buf_num); | 648 | gpn_ft = zfcp_alloc_sg_env(buf_num); |
689 | if (!gpn_ft) { | 649 | if (!gpn_ft) |
690 | ret = -ENOMEM; | ||
691 | goto out; | 650 | goto out; |
692 | } | ||
693 | 651 | ||
694 | for (i = 0; i < 3; i++) { | 652 | for (i = 0; i < 3; i++) { |
695 | ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes); | 653 | ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes); |
696 | if (!ret) { | 654 | if (!ret) { |
697 | ret = zfcp_fc_eval_gpn_ft(gpn_ft, max_entries); | 655 | ret = zfcp_fc_eval_gpn_ft(gpn_ft, adapter, max_entries); |
698 | if (ret == -EAGAIN) | 656 | if (ret == -EAGAIN) |
699 | ssleep(1); | 657 | ssleep(1); |
700 | else | 658 | else |
@@ -704,174 +662,116 @@ int zfcp_fc_scan_ports(struct zfcp_adapter *adapter) | |||
704 | zfcp_free_sg_env(gpn_ft, buf_num); | 662 | zfcp_free_sg_env(gpn_ft, buf_num); |
705 | out: | 663 | out: |
706 | zfcp_fc_wka_port_put(&adapter->gs->ds); | 664 | zfcp_fc_wka_port_put(&adapter->gs->ds); |
707 | return ret; | ||
708 | } | ||
709 | |||
710 | |||
711 | void _zfcp_fc_scan_ports_later(struct work_struct *work) | ||
712 | { | ||
713 | zfcp_fc_scan_ports(container_of(work, struct zfcp_adapter, scan_work)); | ||
714 | } | 665 | } |
715 | 666 | ||
716 | struct zfcp_els_fc_job { | 667 | static void zfcp_fc_ct_els_job_handler(void *data) |
717 | struct zfcp_send_els els; | ||
718 | struct fc_bsg_job *job; | ||
719 | }; | ||
720 | |||
721 | static void zfcp_fc_generic_els_handler(unsigned long data) | ||
722 | { | 668 | { |
723 | struct zfcp_els_fc_job *els_fc_job = (struct zfcp_els_fc_job *) data; | 669 | struct fc_bsg_job *job = data; |
724 | struct fc_bsg_job *job = els_fc_job->job; | 670 | struct zfcp_fsf_ct_els *zfcp_ct_els = job->dd_data; |
725 | struct fc_bsg_reply *reply = job->reply; | 671 | int status = zfcp_ct_els->status; |
726 | 672 | int reply_status; | |
727 | if (els_fc_job->els.status) { | ||
728 | /* request rejected or timed out */ | ||
729 | reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_REJECT; | ||
730 | goto out; | ||
731 | } | ||
732 | |||
733 | reply->reply_data.ctels_reply.status = FC_CTELS_STATUS_OK; | ||
734 | reply->reply_payload_rcv_len = job->reply_payload.payload_len; | ||
735 | 673 | ||
736 | out: | 674 | reply_status = status ? FC_CTELS_STATUS_REJECT : FC_CTELS_STATUS_OK; |
737 | job->state_flags = FC_RQST_STATE_DONE; | 675 | job->reply->reply_data.ctels_reply.status = reply_status; |
676 | job->reply->reply_payload_rcv_len = job->reply_payload.payload_len; | ||
738 | job->job_done(job); | 677 | job->job_done(job); |
739 | kfree(els_fc_job); | ||
740 | } | 678 | } |
741 | 679 | ||
742 | int zfcp_fc_execute_els_fc_job(struct fc_bsg_job *job) | 680 | static int zfcp_fc_exec_els_job(struct fc_bsg_job *job, |
681 | struct zfcp_adapter *adapter) | ||
743 | { | 682 | { |
744 | struct zfcp_els_fc_job *els_fc_job; | 683 | struct zfcp_fsf_ct_els *els = job->dd_data; |
745 | struct fc_rport *rport = job->rport; | 684 | struct fc_rport *rport = job->rport; |
746 | struct Scsi_Host *shost; | ||
747 | struct zfcp_adapter *adapter; | ||
748 | struct zfcp_port *port; | 685 | struct zfcp_port *port; |
749 | u8 *port_did; | 686 | u32 d_id; |
750 | |||
751 | shost = rport ? rport_to_shost(rport) : job->shost; | ||
752 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; | ||
753 | |||
754 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN)) | ||
755 | return -EINVAL; | ||
756 | |||
757 | els_fc_job = kzalloc(sizeof(struct zfcp_els_fc_job), GFP_KERNEL); | ||
758 | if (!els_fc_job) | ||
759 | return -ENOMEM; | ||
760 | 687 | ||
761 | els_fc_job->els.adapter = adapter; | ||
762 | if (rport) { | 688 | if (rport) { |
763 | read_lock_irq(&zfcp_data.config_lock); | ||
764 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); | 689 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); |
765 | if (port) | 690 | if (!port) |
766 | els_fc_job->els.d_id = port->d_id; | ||
767 | read_unlock_irq(&zfcp_data.config_lock); | ||
768 | if (!port) { | ||
769 | kfree(els_fc_job); | ||
770 | return -EINVAL; | 691 | return -EINVAL; |
771 | } | ||
772 | } else { | ||
773 | port_did = job->request->rqst_data.h_els.port_id; | ||
774 | els_fc_job->els.d_id = (port_did[0] << 16) + | ||
775 | (port_did[1] << 8) + port_did[2]; | ||
776 | } | ||
777 | |||
778 | els_fc_job->els.req = job->request_payload.sg_list; | ||
779 | els_fc_job->els.resp = job->reply_payload.sg_list; | ||
780 | els_fc_job->els.handler = zfcp_fc_generic_els_handler; | ||
781 | els_fc_job->els.handler_data = (unsigned long) els_fc_job; | ||
782 | els_fc_job->job = job; | ||
783 | |||
784 | return zfcp_fsf_send_els(&els_fc_job->els); | ||
785 | } | ||
786 | |||
787 | struct zfcp_ct_fc_job { | ||
788 | struct zfcp_send_ct ct; | ||
789 | struct fc_bsg_job *job; | ||
790 | }; | ||
791 | |||
792 | static void zfcp_fc_generic_ct_handler(unsigned long data) | ||
793 | { | ||
794 | struct zfcp_ct_fc_job *ct_fc_job = (struct zfcp_ct_fc_job *) data; | ||
795 | struct fc_bsg_job *job = ct_fc_job->job; | ||
796 | |||
797 | job->reply->reply_data.ctels_reply.status = ct_fc_job->ct.status ? | ||
798 | FC_CTELS_STATUS_REJECT : FC_CTELS_STATUS_OK; | ||
799 | job->reply->reply_payload_rcv_len = job->reply_payload.payload_len; | ||
800 | job->state_flags = FC_RQST_STATE_DONE; | ||
801 | job->job_done(job); | ||
802 | 692 | ||
803 | zfcp_fc_wka_port_put(ct_fc_job->ct.wka_port); | 693 | d_id = port->d_id; |
694 | put_device(&port->sysfs_device); | ||
695 | } else | ||
696 | d_id = ntoh24(job->request->rqst_data.h_els.port_id); | ||
804 | 697 | ||
805 | kfree(ct_fc_job); | 698 | return zfcp_fsf_send_els(adapter, d_id, els); |
806 | } | 699 | } |
807 | 700 | ||
808 | int zfcp_fc_execute_ct_fc_job(struct fc_bsg_job *job) | 701 | static int zfcp_fc_exec_ct_job(struct fc_bsg_job *job, |
702 | struct zfcp_adapter *adapter) | ||
809 | { | 703 | { |
810 | int ret; | 704 | int ret; |
811 | u8 gs_type; | 705 | u8 gs_type; |
812 | struct fc_rport *rport = job->rport; | 706 | struct zfcp_fsf_ct_els *ct = job->dd_data; |
813 | struct Scsi_Host *shost; | 707 | struct zfcp_fc_wka_port *wka_port; |
814 | struct zfcp_adapter *adapter; | ||
815 | struct zfcp_ct_fc_job *ct_fc_job; | ||
816 | u32 preamble_word1; | 708 | u32 preamble_word1; |
817 | 709 | ||
818 | shost = rport ? rport_to_shost(rport) : job->shost; | ||
819 | |||
820 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; | ||
821 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN)) | ||
822 | return -EINVAL; | ||
823 | |||
824 | ct_fc_job = kzalloc(sizeof(struct zfcp_ct_fc_job), GFP_KERNEL); | ||
825 | if (!ct_fc_job) | ||
826 | return -ENOMEM; | ||
827 | |||
828 | preamble_word1 = job->request->rqst_data.r_ct.preamble_word1; | 710 | preamble_word1 = job->request->rqst_data.r_ct.preamble_word1; |
829 | gs_type = (preamble_word1 & 0xff000000) >> 24; | 711 | gs_type = (preamble_word1 & 0xff000000) >> 24; |
830 | 712 | ||
831 | switch (gs_type) { | 713 | switch (gs_type) { |
832 | case FC_FST_ALIAS: | 714 | case FC_FST_ALIAS: |
833 | ct_fc_job->ct.wka_port = &adapter->gs->as; | 715 | wka_port = &adapter->gs->as; |
834 | break; | 716 | break; |
835 | case FC_FST_MGMT: | 717 | case FC_FST_MGMT: |
836 | ct_fc_job->ct.wka_port = &adapter->gs->ms; | 718 | wka_port = &adapter->gs->ms; |
837 | break; | 719 | break; |
838 | case FC_FST_TIME: | 720 | case FC_FST_TIME: |
839 | ct_fc_job->ct.wka_port = &adapter->gs->ts; | 721 | wka_port = &adapter->gs->ts; |
840 | break; | 722 | break; |
841 | case FC_FST_DIR: | 723 | case FC_FST_DIR: |
842 | ct_fc_job->ct.wka_port = &adapter->gs->ds; | 724 | wka_port = &adapter->gs->ds; |
843 | break; | 725 | break; |
844 | default: | 726 | default: |
845 | kfree(ct_fc_job); | ||
846 | return -EINVAL; /* no such service */ | 727 | return -EINVAL; /* no such service */ |
847 | } | 728 | } |
848 | 729 | ||
849 | ret = zfcp_fc_wka_port_get(ct_fc_job->ct.wka_port); | 730 | ret = zfcp_fc_wka_port_get(wka_port); |
850 | if (ret) { | 731 | if (ret) |
851 | kfree(ct_fc_job); | ||
852 | return ret; | 732 | return ret; |
853 | } | ||
854 | 733 | ||
855 | ct_fc_job->ct.req = job->request_payload.sg_list; | 734 | ret = zfcp_fsf_send_ct(wka_port, ct, NULL); |
856 | ct_fc_job->ct.resp = job->reply_payload.sg_list; | 735 | if (ret) |
857 | ct_fc_job->ct.handler = zfcp_fc_generic_ct_handler; | 736 | zfcp_fc_wka_port_put(wka_port); |
858 | ct_fc_job->ct.handler_data = (unsigned long) ct_fc_job; | ||
859 | ct_fc_job->ct.completion = NULL; | ||
860 | ct_fc_job->job = job; | ||
861 | 737 | ||
862 | ret = zfcp_fsf_send_ct(&ct_fc_job->ct, NULL); | ||
863 | if (ret) { | ||
864 | kfree(ct_fc_job); | ||
865 | zfcp_fc_wka_port_put(ct_fc_job->ct.wka_port); | ||
866 | } | ||
867 | return ret; | 738 | return ret; |
868 | } | 739 | } |
869 | 740 | ||
741 | int zfcp_fc_exec_bsg_job(struct fc_bsg_job *job) | ||
742 | { | ||
743 | struct Scsi_Host *shost; | ||
744 | struct zfcp_adapter *adapter; | ||
745 | struct zfcp_fsf_ct_els *ct_els = job->dd_data; | ||
746 | |||
747 | shost = job->rport ? rport_to_shost(job->rport) : job->shost; | ||
748 | adapter = (struct zfcp_adapter *)shost->hostdata[0]; | ||
749 | |||
750 | if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_OPEN)) | ||
751 | return -EINVAL; | ||
752 | |||
753 | ct_els->req = job->request_payload.sg_list; | ||
754 | ct_els->resp = job->reply_payload.sg_list; | ||
755 | ct_els->handler = zfcp_fc_ct_els_job_handler; | ||
756 | ct_els->handler_data = job; | ||
757 | |||
758 | switch (job->request->msgcode) { | ||
759 | case FC_BSG_RPT_ELS: | ||
760 | case FC_BSG_HST_ELS_NOLOGIN: | ||
761 | return zfcp_fc_exec_els_job(job, adapter); | ||
762 | case FC_BSG_RPT_CT: | ||
763 | case FC_BSG_HST_CT: | ||
764 | return zfcp_fc_exec_ct_job(job, adapter); | ||
765 | default: | ||
766 | return -EINVAL; | ||
767 | } | ||
768 | } | ||
769 | |||
870 | int zfcp_fc_gs_setup(struct zfcp_adapter *adapter) | 770 | int zfcp_fc_gs_setup(struct zfcp_adapter *adapter) |
871 | { | 771 | { |
872 | struct zfcp_wka_ports *wka_ports; | 772 | struct zfcp_fc_wka_ports *wka_ports; |
873 | 773 | ||
874 | wka_ports = kzalloc(sizeof(struct zfcp_wka_ports), GFP_KERNEL); | 774 | wka_ports = kzalloc(sizeof(struct zfcp_fc_wka_ports), GFP_KERNEL); |
875 | if (!wka_ports) | 775 | if (!wka_ports) |
876 | return -ENOMEM; | 776 | return -ENOMEM; |
877 | 777 | ||
@@ -880,7 +780,6 @@ int zfcp_fc_gs_setup(struct zfcp_adapter *adapter) | |||
880 | zfcp_fc_wka_port_init(&wka_ports->ts, FC_FID_TIME_SERV, adapter); | 780 | zfcp_fc_wka_port_init(&wka_ports->ts, FC_FID_TIME_SERV, adapter); |
881 | zfcp_fc_wka_port_init(&wka_ports->ds, FC_FID_DIR_SERV, adapter); | 781 | zfcp_fc_wka_port_init(&wka_ports->ds, FC_FID_DIR_SERV, adapter); |
882 | zfcp_fc_wka_port_init(&wka_ports->as, FC_FID_ALIASES, adapter); | 782 | zfcp_fc_wka_port_init(&wka_ports->as, FC_FID_ALIASES, adapter); |
883 | zfcp_fc_wka_port_init(&wka_ports->ks, FC_FID_SEC_KEY, adapter); | ||
884 | 783 | ||
885 | return 0; | 784 | return 0; |
886 | } | 785 | } |