diff options
Diffstat (limited to 'drivers/s390/scsi')
-rw-r--r-- | drivers/s390/scsi/zfcp_def.h | 45 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_ext.h | 4 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 131 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.h | 17 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.c | 45 | ||||
-rw-r--r-- | drivers/s390/scsi/zfcp_fsf.h | 20 |
6 files changed, 108 insertions, 154 deletions
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 0317e7f20850..fae8f2ebd43f 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -75,51 +75,6 @@ | |||
75 | 75 | ||
76 | #define ZFCP_DID_MASK 0x00FFFFFF | 76 | #define ZFCP_DID_MASK 0x00FFFFFF |
77 | 77 | ||
78 | /* see fc-fs */ | ||
79 | #define LS_RSCN 0x61 | ||
80 | #define LS_LOGO 0x05 | ||
81 | #define LS_PLOGI 0x03 | ||
82 | |||
83 | struct fcp_rscn_head { | ||
84 | u8 command; | ||
85 | u8 page_length; /* always 0x04 */ | ||
86 | u16 payload_len; | ||
87 | } __attribute__((packed)); | ||
88 | |||
89 | struct fcp_rscn_element { | ||
90 | u8 reserved:2; | ||
91 | u8 event_qual:4; | ||
92 | u8 addr_format:2; | ||
93 | u32 nport_did:24; | ||
94 | } __attribute__((packed)); | ||
95 | |||
96 | /* see fc-ph */ | ||
97 | struct fcp_logo { | ||
98 | u32 command; | ||
99 | u32 nport_did; | ||
100 | u64 nport_wwpn; | ||
101 | } __attribute__((packed)); | ||
102 | |||
103 | /* | ||
104 | * FC-FS stuff | ||
105 | */ | ||
106 | #define R_A_TOV 10 /* seconds */ | ||
107 | |||
108 | #define ZFCP_LS_RLS 0x0f | ||
109 | #define ZFCP_LS_ADISC 0x52 | ||
110 | #define ZFCP_LS_RPS 0x56 | ||
111 | #define ZFCP_LS_RSCN 0x61 | ||
112 | #define ZFCP_LS_RNID 0x78 | ||
113 | |||
114 | struct zfcp_ls_adisc { | ||
115 | u8 code; | ||
116 | u8 field[3]; | ||
117 | u32 hard_nport_id; | ||
118 | u64 wwpn; | ||
119 | u64 wwnn; | ||
120 | u32 nport_id; | ||
121 | } __attribute__ ((packed)); | ||
122 | |||
123 | /* | 78 | /* |
124 | * FC-GS-2 stuff | 79 | * FC-GS-2 stuff |
125 | */ | 80 | */ |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 3832fe0ae2e4..c2b23b5a3d0a 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -9,6 +9,8 @@ | |||
9 | #ifndef ZFCP_EXT_H | 9 | #ifndef ZFCP_EXT_H |
10 | #define ZFCP_EXT_H | 10 | #define ZFCP_EXT_H |
11 | 11 | ||
12 | #include <linux/types.h> | ||
13 | #include <scsi/fc/fc_els.h> | ||
12 | #include "zfcp_def.h" | 14 | #include "zfcp_def.h" |
13 | 15 | ||
14 | /* zfcp_aux.c */ | 16 | /* zfcp_aux.c */ |
@@ -98,7 +100,7 @@ extern void zfcp_fc_scan_ports(struct work_struct *); | |||
98 | extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *); | 100 | extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *); |
99 | extern void zfcp_fc_port_did_lookup(struct work_struct *); | 101 | extern void zfcp_fc_port_did_lookup(struct work_struct *); |
100 | extern void zfcp_fc_trigger_did_lookup(struct zfcp_port *); | 102 | extern void zfcp_fc_trigger_did_lookup(struct zfcp_port *); |
101 | extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); | 103 | extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fc_els_flogi *); |
102 | extern void zfcp_fc_test_link(struct zfcp_port *); | 104 | extern void zfcp_fc_test_link(struct zfcp_port *); |
103 | extern void zfcp_fc_link_test_work(struct work_struct *); | 105 | extern void zfcp_fc_link_test_work(struct work_struct *); |
104 | extern void zfcp_fc_wka_ports_force_offline(struct zfcp_wka_ports *); | 106 | extern void zfcp_fc_wka_ports_force_offline(struct zfcp_wka_ports *); |
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 7d6b3cadfb73..e03410043cd7 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c | |||
@@ -9,20 +9,17 @@ | |||
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 | }; | ||
20 | |||
21 | static u32 rscn_range_mask[] = { | ||
22 | [RSCN_PORT_ADDRESS] = 0xFFFFFF, | ||
23 | [RSCN_AREA_ADDRESS] = 0xFFFF00, | ||
24 | [RSCN_DOMAIN_ADDRESS] = 0xFF0000, | ||
25 | [RSCN_FABRIC_ADDRESS] = 0x000000, | ||
26 | }; | 23 | }; |
27 | 24 | ||
28 | struct gpn_ft_resp_acc { | 25 | struct gpn_ft_resp_acc { |
@@ -144,7 +141,7 @@ void zfcp_fc_wka_ports_force_offline(struct zfcp_wka_ports *gs) | |||
144 | } | 141 | } |
145 | 142 | ||
146 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, | 143 | static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, |
147 | struct fcp_rscn_element *elem) | 144 | struct fc_els_rscn_page *page) |
148 | { | 145 | { |
149 | unsigned long flags; | 146 | unsigned long flags; |
150 | struct zfcp_adapter *adapter = fsf_req->adapter; | 147 | struct zfcp_adapter *adapter = fsf_req->adapter; |
@@ -152,7 +149,7 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, | |||
152 | 149 | ||
153 | read_lock_irqsave(&adapter->port_list_lock, flags); | 150 | read_lock_irqsave(&adapter->port_list_lock, flags); |
154 | list_for_each_entry(port, &adapter->port_list, list) { | 151 | list_for_each_entry(port, &adapter->port_list, list) { |
155 | if ((port->d_id & range) == (elem->nport_did & range)) | 152 | if ((port->d_id & range) == (ntoh24(page->rscn_fid) & range)) |
156 | zfcp_fc_test_link(port); | 153 | zfcp_fc_test_link(port); |
157 | if (!port->d_id) | 154 | if (!port->d_id) |
158 | zfcp_erp_port_reopen(port, | 155 | zfcp_erp_port_reopen(port, |
@@ -165,24 +162,24 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, | |||
165 | static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) | 162 | static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req) |
166 | { | 163 | { |
167 | struct fsf_status_read_buffer *status_buffer = (void *)fsf_req->data; | 164 | struct fsf_status_read_buffer *status_buffer = (void *)fsf_req->data; |
168 | struct fcp_rscn_head *fcp_rscn_head; | 165 | struct fc_els_rscn *head; |
169 | struct fcp_rscn_element *fcp_rscn_element; | 166 | struct fc_els_rscn_page *page; |
170 | u16 i; | 167 | u16 i; |
171 | u16 no_entries; | 168 | u16 no_entries; |
172 | u32 range_mask; | 169 | unsigned int afmt; |
173 | 170 | ||
174 | fcp_rscn_head = (struct fcp_rscn_head *) status_buffer->payload.data; | 171 | head = (struct fc_els_rscn *) status_buffer->payload.data; |
175 | fcp_rscn_element = (struct fcp_rscn_element *) fcp_rscn_head; | 172 | page = (struct fc_els_rscn_page *) head; |
176 | 173 | ||
177 | /* see FC-FS */ | 174 | /* see FC-FS */ |
178 | no_entries = fcp_rscn_head->payload_len / | 175 | no_entries = head->rscn_plen / sizeof(struct fc_els_rscn_page); |
179 | sizeof(struct fcp_rscn_element); | ||
180 | 176 | ||
181 | for (i = 1; i < no_entries; i++) { | 177 | for (i = 1; i < no_entries; i++) { |
182 | /* skip head and start with 1st element */ | 178 | /* skip head and start with 1st element */ |
183 | fcp_rscn_element++; | 179 | page++; |
184 | range_mask = rscn_range_mask[fcp_rscn_element->addr_format]; | 180 | afmt = page->rscn_page_flags & ELS_RSCN_ADDR_FMT_MASK; |
185 | _zfcp_fc_incoming_rscn(fsf_req, range_mask, fcp_rscn_element); | 181 | _zfcp_fc_incoming_rscn(fsf_req, zfcp_fc_rscn_range_mask[afmt], |
182 | page); | ||
186 | } | 183 | } |
187 | queue_work(fsf_req->adapter->work_queue, &fsf_req->adapter->scan_work); | 184 | queue_work(fsf_req->adapter->work_queue, &fsf_req->adapter->scan_work); |
188 | } | 185 | } |
@@ -204,22 +201,22 @@ static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) | |||
204 | 201 | ||
205 | static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req) | 202 | static void zfcp_fc_incoming_plogi(struct zfcp_fsf_req *req) |
206 | { | 203 | { |
207 | struct fsf_status_read_buffer *status_buffer = | 204 | struct fsf_status_read_buffer *status_buffer; |
208 | (struct fsf_status_read_buffer *)req->data; | 205 | struct fc_els_flogi *plogi; |
209 | struct fsf_plogi *els_plogi = | ||
210 | (struct fsf_plogi *) status_buffer->payload.data; | ||
211 | 206 | ||
212 | zfcp_fc_incoming_wwpn(req, els_plogi->serv_param.wwpn); | 207 | status_buffer = (struct fsf_status_read_buffer *) req->data; |
208 | plogi = (struct fc_els_flogi *) status_buffer->payload.data; | ||
209 | zfcp_fc_incoming_wwpn(req, plogi->fl_wwpn); | ||
213 | } | 210 | } |
214 | 211 | ||
215 | static void zfcp_fc_incoming_logo(struct zfcp_fsf_req *req) | 212 | static void zfcp_fc_incoming_logo(struct zfcp_fsf_req *req) |
216 | { | 213 | { |
217 | struct fsf_status_read_buffer *status_buffer = | 214 | struct fsf_status_read_buffer *status_buffer = |
218 | (struct fsf_status_read_buffer *)req->data; | 215 | (struct fsf_status_read_buffer *)req->data; |
219 | struct fcp_logo *els_logo = | 216 | struct fc_els_logo *logo = |
220 | (struct fcp_logo *) status_buffer->payload.data; | 217 | (struct fc_els_logo *) status_buffer->payload.data; |
221 | 218 | ||
222 | zfcp_fc_incoming_wwpn(req, els_logo->nport_wwpn); | 219 | zfcp_fc_incoming_wwpn(req, logo->fl_n_port_wwn); |
223 | } | 220 | } |
224 | 221 | ||
225 | /** | 222 | /** |
@@ -233,11 +230,11 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req) | |||
233 | unsigned int els_type = status_buffer->payload.data[0]; | 230 | unsigned int els_type = status_buffer->payload.data[0]; |
234 | 231 | ||
235 | zfcp_dbf_san_incoming_els(fsf_req); | 232 | zfcp_dbf_san_incoming_els(fsf_req); |
236 | if (els_type == LS_PLOGI) | 233 | if (els_type == ELS_PLOGI) |
237 | zfcp_fc_incoming_plogi(fsf_req); | 234 | zfcp_fc_incoming_plogi(fsf_req); |
238 | else if (els_type == LS_LOGO) | 235 | else if (els_type == ELS_LOGO) |
239 | zfcp_fc_incoming_logo(fsf_req); | 236 | zfcp_fc_incoming_logo(fsf_req); |
240 | else if (els_type == LS_RSCN) | 237 | else if (els_type == ELS_RSCN) |
241 | zfcp_fc_incoming_rscn(fsf_req); | 238 | zfcp_fc_incoming_rscn(fsf_req); |
242 | } | 239 | } |
243 | 240 | ||
@@ -379,33 +376,36 @@ void zfcp_fc_trigger_did_lookup(struct zfcp_port *port) | |||
379 | * | 376 | * |
380 | * Evaluate PLOGI playload and copy important fields into zfcp_port structure | 377 | * Evaluate PLOGI playload and copy important fields into zfcp_port structure |
381 | */ | 378 | */ |
382 | void zfcp_fc_plogi_evaluate(struct zfcp_port *port, struct fsf_plogi *plogi) | 379 | void zfcp_fc_plogi_evaluate(struct zfcp_port *port, struct fc_els_flogi *plogi) |
383 | { | 380 | { |
384 | port->maxframe_size = plogi->serv_param.common_serv_param[7] | | 381 | if (plogi->fl_wwpn != port->wwpn) { |
385 | ((plogi->serv_param.common_serv_param[6] & 0x0F) << 8); | 382 | port->d_id = 0; |
386 | if (plogi->serv_param.class1_serv_param[0] & 0x80) | 383 | dev_warn(&port->adapter->ccw_device->dev, |
384 | "A port opened with WWPN 0x%016Lx returned data that " | ||
385 | "identifies it as WWPN 0x%016Lx\n", | ||
386 | (unsigned long long) port->wwpn, | ||
387 | (unsigned long long) plogi->fl_wwpn); | ||
388 | return; | ||
389 | } | ||
390 | |||
391 | port->wwnn = plogi->fl_wwnn; | ||
392 | port->maxframe_size = plogi->fl_csp.sp_bb_data; | ||
393 | |||
394 | if (plogi->fl_cssp[0].cp_class & FC_CPC_VALID) | ||
387 | port->supported_classes |= FC_COS_CLASS1; | 395 | port->supported_classes |= FC_COS_CLASS1; |
388 | if (plogi->serv_param.class2_serv_param[0] & 0x80) | 396 | if (plogi->fl_cssp[1].cp_class & FC_CPC_VALID) |
389 | port->supported_classes |= FC_COS_CLASS2; | 397 | port->supported_classes |= FC_COS_CLASS2; |
390 | if (plogi->serv_param.class3_serv_param[0] & 0x80) | 398 | if (plogi->fl_cssp[2].cp_class & FC_CPC_VALID) |
391 | port->supported_classes |= FC_COS_CLASS3; | 399 | port->supported_classes |= FC_COS_CLASS3; |
392 | if (plogi->serv_param.class4_serv_param[0] & 0x80) | 400 | if (plogi->fl_cssp[3].cp_class & FC_CPC_VALID) |
393 | port->supported_classes |= FC_COS_CLASS4; | 401 | port->supported_classes |= FC_COS_CLASS4; |
394 | } | 402 | } |
395 | 403 | ||
396 | struct zfcp_els_adisc { | ||
397 | struct zfcp_send_els els; | ||
398 | struct scatterlist req; | ||
399 | struct scatterlist resp; | ||
400 | struct zfcp_ls_adisc ls_adisc; | ||
401 | struct zfcp_ls_adisc ls_adisc_acc; | ||
402 | }; | ||
403 | |||
404 | static void zfcp_fc_adisc_handler(unsigned long data) | 404 | static void zfcp_fc_adisc_handler(unsigned long data) |
405 | { | 405 | { |
406 | struct zfcp_els_adisc *adisc = (struct zfcp_els_adisc *) data; | 406 | struct zfcp_fc_els_adisc *adisc = (struct zfcp_fc_els_adisc *) data; |
407 | struct zfcp_port *port = adisc->els.port; | 407 | struct zfcp_port *port = adisc->els.port; |
408 | struct zfcp_ls_adisc *ls_adisc = &adisc->ls_adisc_acc; | 408 | struct fc_els_adisc *adisc_resp = &adisc->adisc_resp; |
409 | 409 | ||
410 | if (adisc->els.status) { | 410 | if (adisc->els.status) { |
411 | /* request rejected or timed out */ | 411 | /* request rejected or timed out */ |
@@ -415,9 +415,9 @@ static void zfcp_fc_adisc_handler(unsigned long data) | |||
415 | } | 415 | } |
416 | 416 | ||
417 | if (!port->wwnn) | 417 | if (!port->wwnn) |
418 | port->wwnn = ls_adisc->wwnn; | 418 | port->wwnn = adisc_resp->adisc_wwnn; |
419 | 419 | ||
420 | if ((port->wwpn != ls_adisc->wwpn) || | 420 | if ((port->wwpn != adisc_resp->adisc_wwpn) || |
421 | !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) { | 421 | !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) { |
422 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, | 422 | zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, |
423 | "fcadh_2", NULL); | 423 | "fcadh_2", NULL); |
@@ -434,32 +434,33 @@ static void zfcp_fc_adisc_handler(unsigned long data) | |||
434 | 434 | ||
435 | static int zfcp_fc_adisc(struct zfcp_port *port) | 435 | static int zfcp_fc_adisc(struct zfcp_port *port) |
436 | { | 436 | { |
437 | struct zfcp_els_adisc *adisc; | 437 | struct zfcp_fc_els_adisc *adisc; |
438 | struct zfcp_adapter *adapter = port->adapter; | 438 | struct zfcp_adapter *adapter = port->adapter; |
439 | 439 | ||
440 | adisc = kzalloc(sizeof(struct zfcp_els_adisc), GFP_ATOMIC); | 440 | adisc = kzalloc(sizeof(struct zfcp_fc_els_adisc), GFP_ATOMIC); |
441 | if (!adisc) | 441 | if (!adisc) |
442 | return -ENOMEM; | 442 | return -ENOMEM; |
443 | 443 | ||
444 | adisc->els.req = &adisc->req; | 444 | adisc->els.req = &adisc->req; |
445 | adisc->els.resp = &adisc->resp; | 445 | adisc->els.resp = &adisc->resp; |
446 | sg_init_one(adisc->els.req, &adisc->ls_adisc, | 446 | sg_init_one(adisc->els.req, &adisc->adisc_req, |
447 | sizeof(struct zfcp_ls_adisc)); | 447 | sizeof(struct fc_els_adisc)); |
448 | sg_init_one(adisc->els.resp, &adisc->ls_adisc_acc, | 448 | sg_init_one(adisc->els.resp, &adisc->adisc_resp, |
449 | sizeof(struct zfcp_ls_adisc)); | 449 | sizeof(struct fc_els_adisc)); |
450 | 450 | ||
451 | adisc->els.adapter = adapter; | 451 | adisc->els.adapter = adapter; |
452 | adisc->els.port = port; | 452 | adisc->els.port = port; |
453 | adisc->els.d_id = port->d_id; | 453 | adisc->els.d_id = port->d_id; |
454 | adisc->els.handler = zfcp_fc_adisc_handler; | 454 | adisc->els.handler = zfcp_fc_adisc_handler; |
455 | adisc->els.handler_data = (unsigned long) adisc; | 455 | adisc->els.handler_data = (unsigned long) adisc; |
456 | adisc->els.ls_code = adisc->ls_adisc.code = ZFCP_LS_ADISC; | 456 | adisc->els.ls_code = adisc->adisc_req.adisc_cmd = ELS_ADISC; |
457 | 457 | ||
458 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports | 458 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports |
459 | without FC-AL-2 capability, so we don't set it */ | 459 | without FC-AL-2 capability, so we don't set it */ |
460 | adisc->ls_adisc.wwpn = fc_host_port_name(adapter->scsi_host); | 460 | adisc->adisc_req.adisc_wwpn = fc_host_port_name(adapter->scsi_host); |
461 | adisc->ls_adisc.wwnn = fc_host_node_name(adapter->scsi_host); | 461 | adisc->adisc_req.adisc_wwnn = fc_host_node_name(adapter->scsi_host); |
462 | adisc->ls_adisc.nport_id = fc_host_port_id(adapter->scsi_host); | 462 | hton24(adisc->adisc_req.adisc_port_id, |
463 | fc_host_port_id(adapter->scsi_host)); | ||
463 | 464 | ||
464 | return zfcp_fsf_send_els(&adisc->els); | 465 | return zfcp_fsf_send_els(&adisc->els); |
465 | } | 466 | } |
diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h index 814fc2d2525a..231e231b7fd7 100644 --- a/drivers/s390/scsi/zfcp_fc.h +++ b/drivers/s390/scsi/zfcp_fc.h | |||
@@ -10,11 +10,28 @@ | |||
10 | #ifndef ZFCP_FC_H | 10 | #ifndef ZFCP_FC_H |
11 | #define ZFCP_FC_H | 11 | #define ZFCP_FC_H |
12 | 12 | ||
13 | #include <scsi/fc/fc_els.h> | ||
13 | #include <scsi/fc/fc_fcp.h> | 14 | #include <scsi/fc/fc_fcp.h> |
14 | #include <scsi/scsi_cmnd.h> | 15 | #include <scsi/scsi_cmnd.h> |
15 | #include <scsi/scsi_tcq.h> | 16 | #include <scsi/scsi_tcq.h> |
16 | 17 | ||
17 | /** | 18 | /** |
19 | * struct zfcp_fc_els_adisc - everything required in zfcp for issuing ELS ADISC | ||
20 | * @els: data required for issuing els fsf command | ||
21 | * @req: scatterlist entry for ELS ADISC request | ||
22 | * @resp: scatterlist entry for ELS ADISC response | ||
23 | * @adisc_req: ELS ADISC request data | ||
24 | * @adisc_resp: ELS ADISC response data | ||
25 | */ | ||
26 | struct zfcp_fc_els_adisc { | ||
27 | struct zfcp_send_els els; | ||
28 | struct scatterlist req; | ||
29 | struct scatterlist resp; | ||
30 | struct fc_els_adisc adisc_req; | ||
31 | struct fc_els_adisc adisc_resp; | ||
32 | }; | ||
33 | |||
34 | /** | ||
18 | * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd | 35 | * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd |
19 | * @fcp: fcp_cmnd to setup | 36 | * @fcp: fcp_cmnd to setup |
20 | * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB | 37 | * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 5f4cd03797e9..9d7bf965d398 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 10 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
11 | 11 | ||
12 | #include <linux/blktrace_api.h> | 12 | #include <linux/blktrace_api.h> |
13 | #include <scsi/fc/fc_els.h> | ||
13 | #include "zfcp_ext.h" | 14 | #include "zfcp_ext.h" |
14 | #include "zfcp_fc.h" | 15 | #include "zfcp_fc.h" |
15 | #include "zfcp_dbf.h" | 16 | #include "zfcp_dbf.h" |
@@ -477,17 +478,22 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) | |||
477 | 478 | ||
478 | static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) | 479 | static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) |
479 | { | 480 | { |
480 | struct fsf_qtcb_bottom_config *bottom; | 481 | struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config; |
481 | struct zfcp_adapter *adapter = req->adapter; | 482 | struct zfcp_adapter *adapter = req->adapter; |
482 | struct Scsi_Host *shost = adapter->scsi_host; | 483 | struct Scsi_Host *shost = adapter->scsi_host; |
484 | struct fc_els_flogi *nsp, *plogi; | ||
483 | 485 | ||
484 | bottom = &req->qtcb->bottom.config; | 486 | /* adjust pointers for missing command code */ |
487 | nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param | ||
488 | - sizeof(u32)); | ||
489 | plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload | ||
490 | - sizeof(u32)); | ||
485 | 491 | ||
486 | if (req->data) | 492 | if (req->data) |
487 | memcpy(req->data, bottom, sizeof(*bottom)); | 493 | memcpy(req->data, bottom, sizeof(*bottom)); |
488 | 494 | ||
489 | fc_host_node_name(shost) = bottom->nport_serv_param.wwnn; | 495 | fc_host_port_name(shost) = nsp->fl_wwpn; |
490 | fc_host_port_name(shost) = bottom->nport_serv_param.wwpn; | 496 | fc_host_node_name(shost) = nsp->fl_wwnn; |
491 | fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; | 497 | fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; |
492 | fc_host_speed(shost) = bottom->fc_link_speed; | 498 | fc_host_speed(shost) = bottom->fc_link_speed; |
493 | fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; | 499 | fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; |
@@ -501,8 +507,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) | |||
501 | switch (bottom->fc_topology) { | 507 | switch (bottom->fc_topology) { |
502 | case FSF_TOPO_P2P: | 508 | case FSF_TOPO_P2P: |
503 | adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK; | 509 | adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK; |
504 | adapter->peer_wwpn = bottom->plogi_payload.wwpn; | 510 | adapter->peer_wwpn = plogi->fl_wwpn; |
505 | adapter->peer_wwnn = bottom->plogi_payload.wwnn; | 511 | adapter->peer_wwnn = plogi->fl_wwnn; |
506 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; | 512 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; |
507 | break; | 513 | break; |
508 | case FSF_TOPO_FABRIC: | 514 | case FSF_TOPO_FABRIC: |
@@ -1068,15 +1074,17 @@ static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req, | |||
1068 | int max_sbals) | 1074 | int max_sbals) |
1069 | { | 1075 | { |
1070 | int ret; | 1076 | int ret; |
1077 | unsigned int fcp_chan_timeout; | ||
1071 | 1078 | ||
1072 | ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp, max_sbals); | 1079 | ret = zfcp_fsf_setup_ct_els_sbals(req, sg_req, sg_resp, max_sbals); |
1073 | if (ret) | 1080 | if (ret) |
1074 | return ret; | 1081 | return ret; |
1075 | 1082 | ||
1076 | /* common settings for ct/gs and els requests */ | 1083 | /* common settings for ct/gs and els requests */ |
1084 | fcp_chan_timeout = 2 * FC_DEF_R_A_TOV / 1000; | ||
1077 | req->qtcb->bottom.support.service_class = FSF_CLASS_3; | 1085 | req->qtcb->bottom.support.service_class = FSF_CLASS_3; |
1078 | req->qtcb->bottom.support.timeout = 2 * R_A_TOV; | 1086 | req->qtcb->bottom.support.timeout = fcp_chan_timeout; |
1079 | zfcp_fsf_start_timer(req, (2 * R_A_TOV + 10) * HZ); | 1087 | zfcp_fsf_start_timer(req, (fcp_chan_timeout + 10) * HZ); |
1080 | 1088 | ||
1081 | return 0; | 1089 | return 0; |
1082 | } | 1090 | } |
@@ -1151,7 +1159,7 @@ static void zfcp_fsf_send_els_handler(struct zfcp_fsf_req *req) | |||
1151 | case FSF_ADAPTER_STATUS_AVAILABLE: | 1159 | case FSF_ADAPTER_STATUS_AVAILABLE: |
1152 | switch (header->fsf_status_qual.word[0]){ | 1160 | switch (header->fsf_status_qual.word[0]){ |
1153 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: | 1161 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
1154 | if (port && (send_els->ls_code != ZFCP_LS_ADISC)) | 1162 | if (port && (send_els->ls_code != ELS_ADISC)) |
1155 | zfcp_fc_test_link(port); | 1163 | zfcp_fc_test_link(port); |
1156 | /*fall through */ | 1164 | /*fall through */ |
1157 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: | 1165 | case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED: |
@@ -1419,7 +1427,7 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1419 | { | 1427 | { |
1420 | struct zfcp_port *port = req->data; | 1428 | struct zfcp_port *port = req->data; |
1421 | struct fsf_qtcb_header *header = &req->qtcb->header; | 1429 | struct fsf_qtcb_header *header = &req->qtcb->header; |
1422 | struct fsf_plogi *plogi; | 1430 | struct fc_els_flogi *plogi; |
1423 | 1431 | ||
1424 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) | 1432 | if (req->status & ZFCP_STATUS_FSFREQ_ERROR) |
1425 | goto out; | 1433 | goto out; |
@@ -1469,23 +1477,10 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) | |||
1469 | * another GID_PN straight after a port has been opened. | 1477 | * another GID_PN straight after a port has been opened. |
1470 | * Alternately, an ADISC/PDISC ELS should suffice, as well. | 1478 | * Alternately, an ADISC/PDISC ELS should suffice, as well. |
1471 | */ | 1479 | */ |
1472 | plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; | 1480 | plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els; |
1473 | if (req->qtcb->bottom.support.els1_length >= | 1481 | if (req->qtcb->bottom.support.els1_length >= |
1474 | FSF_PLOGI_MIN_LEN) { | 1482 | FSF_PLOGI_MIN_LEN) |
1475 | if (plogi->serv_param.wwpn != port->wwpn) { | ||
1476 | port->d_id = 0; | ||
1477 | dev_warn(&port->adapter->ccw_device->dev, | ||
1478 | "A port opened with WWPN 0x%016Lx " | ||
1479 | "returned data that identifies it as " | ||
1480 | "WWPN 0x%016Lx\n", | ||
1481 | (unsigned long long) port->wwpn, | ||
1482 | (unsigned long long) | ||
1483 | plogi->serv_param.wwpn); | ||
1484 | } else { | ||
1485 | port->wwnn = plogi->serv_param.wwnn; | ||
1486 | zfcp_fc_plogi_evaluate(port, plogi); | 1483 | zfcp_fc_plogi_evaluate(port, plogi); |
1487 | } | ||
1488 | } | ||
1489 | break; | 1484 | break; |
1490 | case FSF_UNKNOWN_OP_SUBTYPE: | 1485 | case FSF_UNKNOWN_OP_SUBTYPE: |
1491 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 1486 | req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index dcc7c1dbcf58..402e0235a357 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h | |||
@@ -309,22 +309,7 @@ struct fsf_qtcb_header { | |||
309 | u8 res4[16]; | 309 | u8 res4[16]; |
310 | } __attribute__ ((packed)); | 310 | } __attribute__ ((packed)); |
311 | 311 | ||
312 | struct fsf_nport_serv_param { | ||
313 | u8 common_serv_param[16]; | ||
314 | u64 wwpn; | ||
315 | u64 wwnn; | ||
316 | u8 class1_serv_param[16]; | ||
317 | u8 class2_serv_param[16]; | ||
318 | u8 class3_serv_param[16]; | ||
319 | u8 class4_serv_param[16]; | ||
320 | u8 vendor_version_level[16]; | ||
321 | } __attribute__ ((packed)); | ||
322 | |||
323 | #define FSF_PLOGI_MIN_LEN 112 | 312 | #define FSF_PLOGI_MIN_LEN 112 |
324 | struct fsf_plogi { | ||
325 | u32 code; | ||
326 | struct fsf_nport_serv_param serv_param; | ||
327 | } __attribute__ ((packed)); | ||
328 | 313 | ||
329 | #define FSF_FCP_CMND_SIZE 288 | 314 | #define FSF_FCP_CMND_SIZE 288 |
330 | #define FSF_FCP_RSP_SIZE 128 | 315 | #define FSF_FCP_RSP_SIZE 128 |
@@ -377,13 +362,12 @@ struct fsf_qtcb_bottom_config { | |||
377 | u16 timer_interval; | 362 | u16 timer_interval; |
378 | u8 res2[8]; | 363 | u8 res2[8]; |
379 | u32 s_id; | 364 | u32 s_id; |
380 | struct fsf_nport_serv_param nport_serv_param; | 365 | u8 nport_serv_param[128]; |
381 | u8 reserved_nport_serv_param[16]; | ||
382 | u8 res3[8]; | 366 | u8 res3[8]; |
383 | u32 adapter_ports; | 367 | u32 adapter_ports; |
384 | u32 hardware_version; | 368 | u32 hardware_version; |
385 | u8 serial_number[32]; | 369 | u8 serial_number[32]; |
386 | struct fsf_nport_serv_param plogi_payload; | 370 | u8 plogi_payload[112]; |
387 | struct fsf_statistics_info stat_info; | 371 | struct fsf_statistics_info stat_info; |
388 | u8 res4[112]; | 372 | u8 res4[112]; |
389 | } __attribute__ ((packed)); | 373 | } __attribute__ ((packed)); |