diff options
author | Christof Schmitt <christof.schmitt@de.ibm.com> | 2009-11-24 10:54:09 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:02:11 -0500 |
commit | 9d05ce2c0a6704ff84df02cbb3baef94fcac4f5d (patch) | |
tree | 2388ff365f068511ceb6e9bfbc13fe2425f0ae4c /drivers/s390/scsi/zfcp_fc.c | |
parent | 4318e08c84e4916ac463002ffb7f9901ddb3c385 (diff) |
[SCSI] zfcp: Use common code definitions for FC ELS structs
Use common code definitions for FC plogi, logo, rscn and adisc structs
instead of inventing private ones. Move the private struct for issuing
ELS ADISC inside zfcp to zfcp_fc header file.
Reviewed-by: Swen Schillig <swen@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/scsi/zfcp_fc.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_fc.c | 131 |
1 files changed, 66 insertions, 65 deletions
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 | } |