diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/s390/scsi/zfcp_scsi.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/s390/scsi/zfcp_scsi.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 180 |
1 files changed, 86 insertions, 94 deletions
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 0e1a34627a2e..174b6d57d576 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -3,35 +3,41 @@ | |||
3 | * | 3 | * |
4 | * Interface to Linux SCSI midlayer. | 4 | * Interface to Linux SCSI midlayer. |
5 | * | 5 | * |
6 | * Copyright IBM Corporation 2002, 2009 | 6 | * Copyright IBM Corporation 2002, 2010 |
7 | */ | 7 | */ |
8 | 8 | ||
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 <linux/slab.h> | ||
14 | #include <scsi/fc/fc_fcp.h> | ||
12 | #include <asm/atomic.h> | 15 | #include <asm/atomic.h> |
13 | #include "zfcp_ext.h" | 16 | #include "zfcp_ext.h" |
14 | #include "zfcp_dbf.h" | 17 | #include "zfcp_dbf.h" |
18 | #include "zfcp_fc.h" | ||
19 | #include "zfcp_reqlist.h" | ||
15 | 20 | ||
16 | static unsigned int default_depth = 32; | 21 | static unsigned int default_depth = 32; |
17 | module_param_named(queue_depth, default_depth, uint, 0600); | 22 | module_param_named(queue_depth, default_depth, uint, 0600); |
18 | MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices"); | 23 | MODULE_PARM_DESC(queue_depth, "Default queue depth for new SCSI devices"); |
19 | 24 | ||
20 | /* Find start of Sense Information in FCP response unit*/ | 25 | static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth, |
21 | char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu) | 26 | int reason) |
22 | { | 27 | { |
23 | char *fcp_sns_info_ptr; | 28 | switch (reason) { |
24 | 29 | case SCSI_QDEPTH_DEFAULT: | |
25 | fcp_sns_info_ptr = (unsigned char *) &fcp_rsp_iu[1]; | 30 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); |
26 | if (fcp_rsp_iu->validity.bits.fcp_rsp_len_valid) | 31 | break; |
27 | fcp_sns_info_ptr += fcp_rsp_iu->fcp_rsp_len; | 32 | case SCSI_QDEPTH_QFULL: |
28 | 33 | scsi_track_queue_full(sdev, depth); | |
29 | return fcp_sns_info_ptr; | 34 | break; |
30 | } | 35 | case SCSI_QDEPTH_RAMP_UP: |
31 | 36 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); | |
32 | static int zfcp_scsi_change_queue_depth(struct scsi_device *sdev, int depth) | 37 | break; |
33 | { | 38 | default: |
34 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); | 39 | return -EOPNOTSUPP; |
40 | } | ||
35 | return sdev->queue_depth; | 41 | return sdev->queue_depth; |
36 | } | 42 | } |
37 | 43 | ||
@@ -39,7 +45,7 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) | |||
39 | { | 45 | { |
40 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; | 46 | struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; |
41 | unit->device = NULL; | 47 | unit->device = NULL; |
42 | zfcp_unit_put(unit); | 48 | put_device(&unit->dev); |
43 | } | 49 | } |
44 | 50 | ||
45 | static int zfcp_scsi_slave_configure(struct scsi_device *sdp) | 51 | static int zfcp_scsi_slave_configure(struct scsi_device *sdp) |
@@ -55,10 +61,9 @@ static void zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) | |||
55 | { | 61 | { |
56 | struct zfcp_adapter *adapter = | 62 | struct zfcp_adapter *adapter = |
57 | (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; | 63 | (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; |
64 | |||
58 | set_host_byte(scpnt, result); | 65 | set_host_byte(scpnt, result); |
59 | if ((scpnt->device != NULL) && (scpnt->device->host != NULL)) | 66 | zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt); |
60 | zfcp_dbf_scsi_result("fail", 4, adapter->dbf, scpnt, NULL); | ||
61 | /* return directly */ | ||
62 | scpnt->scsi_done(scpnt); | 67 | scpnt->scsi_done(scpnt); |
63 | } | 68 | } |
64 | 69 | ||
@@ -82,29 +87,35 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, | |||
82 | adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; | 87 | adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; |
83 | unit = scpnt->device->hostdata; | 88 | unit = scpnt->device->hostdata; |
84 | 89 | ||
85 | BUG_ON(!adapter || (adapter != unit->port->adapter)); | ||
86 | BUG_ON(!scpnt->scsi_done); | ||
87 | |||
88 | if (unlikely(!unit)) { | ||
89 | zfcp_scsi_command_fail(scpnt, DID_NO_CONNECT); | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | scsi_result = fc_remote_port_chkready(rport); | 90 | scsi_result = fc_remote_port_chkready(rport); |
94 | if (unlikely(scsi_result)) { | 91 | if (unlikely(scsi_result)) { |
95 | scpnt->result = scsi_result; | 92 | scpnt->result = scsi_result; |
96 | zfcp_dbf_scsi_result("fail", 4, adapter->dbf, scpnt, NULL); | 93 | zfcp_dbf_scsi_fail_send(adapter->dbf, scpnt); |
97 | scpnt->scsi_done(scpnt); | 94 | scpnt->scsi_done(scpnt); |
98 | return 0; | 95 | return 0; |
99 | } | 96 | } |
100 | 97 | ||
101 | status = atomic_read(&unit->status); | 98 | status = atomic_read(&unit->status); |
102 | if (unlikely((status & ZFCP_STATUS_COMMON_ERP_FAILED) || | 99 | if (unlikely(status & ZFCP_STATUS_COMMON_ERP_FAILED) && |
103 | !(status & ZFCP_STATUS_COMMON_RUNNING))) { | 100 | !(atomic_read(&unit->port->status) & |
101 | ZFCP_STATUS_COMMON_ERP_FAILED)) { | ||
102 | /* only unit access denied, but port is good | ||
103 | * not covered by FC transport, have to fail here */ | ||
104 | zfcp_scsi_command_fail(scpnt, DID_ERROR); | 104 | zfcp_scsi_command_fail(scpnt, DID_ERROR); |
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
107 | 107 | ||
108 | if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) { | ||
109 | /* This could be either | ||
110 | * open unit pending: this is temporary, will result in | ||
111 | * open unit or ERP_FAILED, so retry command | ||
112 | * call to rport_delete pending: mimic retry from | ||
113 | * fc_remote_port_chkready until rport is BLOCKED | ||
114 | */ | ||
115 | zfcp_scsi_command_fail(scpnt, DID_IMM_RETRY); | ||
116 | return 0; | ||
117 | } | ||
118 | |||
108 | ret = zfcp_fsf_send_fcp_command_task(unit, scpnt); | 119 | ret = zfcp_fsf_send_fcp_command_task(unit, scpnt); |
109 | if (unlikely(ret == -EBUSY)) | 120 | if (unlikely(ret == -EBUSY)) |
110 | return SCSI_MLQUEUE_DEVICE_BUSY; | 121 | return SCSI_MLQUEUE_DEVICE_BUSY; |
@@ -115,49 +126,44 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, | |||
115 | } | 126 | } |
116 | 127 | ||
117 | static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter, | 128 | static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *adapter, |
118 | int channel, unsigned int id, | 129 | unsigned int id, u64 lun) |
119 | unsigned int lun) | ||
120 | { | 130 | { |
131 | unsigned long flags; | ||
121 | struct zfcp_port *port; | 132 | struct zfcp_port *port; |
122 | struct zfcp_unit *unit; | 133 | struct zfcp_unit *unit = NULL; |
123 | int scsi_lun; | ||
124 | 134 | ||
125 | list_for_each_entry(port, &adapter->port_list_head, list) { | 135 | read_lock_irqsave(&adapter->port_list_lock, flags); |
136 | list_for_each_entry(port, &adapter->port_list, list) { | ||
126 | if (!port->rport || (id != port->rport->scsi_target_id)) | 137 | if (!port->rport || (id != port->rport->scsi_target_id)) |
127 | continue; | 138 | continue; |
128 | list_for_each_entry(unit, &port->unit_list_head, list) { | 139 | unit = zfcp_get_unit_by_lun(port, lun); |
129 | scsi_lun = scsilun_to_int( | 140 | if (unit) |
130 | (struct scsi_lun *)&unit->fcp_lun); | 141 | break; |
131 | if (lun == scsi_lun) | ||
132 | return unit; | ||
133 | } | ||
134 | } | 142 | } |
143 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
135 | 144 | ||
136 | return NULL; | 145 | return unit; |
137 | } | 146 | } |
138 | 147 | ||
139 | static int zfcp_scsi_slave_alloc(struct scsi_device *sdp) | 148 | static int zfcp_scsi_slave_alloc(struct scsi_device *sdp) |
140 | { | 149 | { |
141 | struct zfcp_adapter *adapter; | 150 | struct zfcp_adapter *adapter; |
142 | struct zfcp_unit *unit; | 151 | struct zfcp_unit *unit; |
143 | unsigned long flags; | 152 | u64 lun; |
144 | int retval = -ENXIO; | ||
145 | 153 | ||
146 | adapter = (struct zfcp_adapter *) sdp->host->hostdata[0]; | 154 | adapter = (struct zfcp_adapter *) sdp->host->hostdata[0]; |
147 | if (!adapter) | 155 | if (!adapter) |
148 | goto out; | 156 | goto out; |
149 | 157 | ||
150 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 158 | int_to_scsilun(sdp->lun, (struct scsi_lun *)&lun); |
151 | unit = zfcp_unit_lookup(adapter, sdp->channel, sdp->id, sdp->lun); | 159 | unit = zfcp_unit_lookup(adapter, sdp->id, lun); |
152 | if (unit) { | 160 | if (unit) { |
153 | sdp->hostdata = unit; | 161 | sdp->hostdata = unit; |
154 | unit->device = sdp; | 162 | unit->device = sdp; |
155 | zfcp_unit_get(unit); | 163 | return 0; |
156 | retval = 0; | ||
157 | } | 164 | } |
158 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | ||
159 | out: | 165 | out: |
160 | return retval; | 166 | return -ENXIO; |
161 | } | 167 | } |
162 | 168 | ||
163 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | 169 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) |
@@ -176,9 +182,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
176 | /* avoid race condition between late normal completion and abort */ | 182 | /* avoid race condition between late normal completion and abort */ |
177 | write_lock_irqsave(&adapter->abort_lock, flags); | 183 | write_lock_irqsave(&adapter->abort_lock, flags); |
178 | 184 | ||
179 | spin_lock(&adapter->req_list_lock); | 185 | old_req = zfcp_reqlist_find(adapter->req_list, old_reqid); |
180 | old_req = zfcp_reqlist_find(adapter, old_reqid); | ||
181 | spin_unlock(&adapter->req_list_lock); | ||
182 | if (!old_req) { | 186 | if (!old_req) { |
183 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 187 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
184 | zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL, | 188 | zfcp_dbf_scsi_abort("lte1", adapter->dbf, scpnt, NULL, |
@@ -196,6 +200,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
196 | break; | 200 | break; |
197 | 201 | ||
198 | zfcp_erp_wait(adapter); | 202 | zfcp_erp_wait(adapter); |
203 | fc_block_scsi_eh(scpnt); | ||
199 | if (!(atomic_read(&adapter->status) & | 204 | if (!(atomic_read(&adapter->status) & |
200 | ZFCP_STATUS_COMMON_RUNNING)) { | 205 | ZFCP_STATUS_COMMON_RUNNING)) { |
201 | zfcp_dbf_scsi_abort("nres", adapter->dbf, scpnt, NULL, | 206 | zfcp_dbf_scsi_abort("nres", adapter->dbf, scpnt, NULL, |
@@ -235,6 +240,7 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) | |||
235 | break; | 240 | break; |
236 | 241 | ||
237 | zfcp_erp_wait(adapter); | 242 | zfcp_erp_wait(adapter); |
243 | fc_block_scsi_eh(scpnt); | ||
238 | if (!(atomic_read(&adapter->status) & | 244 | if (!(atomic_read(&adapter->status) & |
239 | ZFCP_STATUS_COMMON_RUNNING)) { | 245 | ZFCP_STATUS_COMMON_RUNNING)) { |
240 | zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt); | 246 | zfcp_dbf_scsi_devreset("nres", tm_flags, unit, scpnt); |
@@ -249,9 +255,6 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) | |||
249 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { | 255 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { |
250 | zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt); | 256 | zfcp_dbf_scsi_devreset("fail", tm_flags, unit, scpnt); |
251 | retval = FAILED; | 257 | retval = FAILED; |
252 | } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) { | ||
253 | zfcp_dbf_scsi_devreset("nsup", tm_flags, unit, scpnt); | ||
254 | retval = FAILED; | ||
255 | } else | 258 | } else |
256 | zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt); | 259 | zfcp_dbf_scsi_devreset("okay", tm_flags, unit, scpnt); |
257 | 260 | ||
@@ -261,12 +264,12 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags) | |||
261 | 264 | ||
262 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) | 265 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) |
263 | { | 266 | { |
264 | return zfcp_task_mgmt_function(scpnt, FCP_LOGICAL_UNIT_RESET); | 267 | return zfcp_task_mgmt_function(scpnt, FCP_TMF_LUN_RESET); |
265 | } | 268 | } |
266 | 269 | ||
267 | static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) | 270 | static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt) |
268 | { | 271 | { |
269 | return zfcp_task_mgmt_function(scpnt, FCP_TARGET_RESET); | 272 | return zfcp_task_mgmt_function(scpnt, FCP_TMF_TGT_RESET); |
270 | } | 273 | } |
271 | 274 | ||
272 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | 275 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) |
@@ -276,6 +279,7 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | |||
276 | 279 | ||
277 | zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt); | 280 | zfcp_erp_adapter_reopen(adapter, 0, "schrh_1", scpnt); |
278 | zfcp_erp_wait(adapter); | 281 | zfcp_erp_wait(adapter); |
282 | fc_block_scsi_eh(scpnt); | ||
279 | 283 | ||
280 | return SUCCESS; | 284 | return SUCCESS; |
281 | } | 285 | } |
@@ -303,7 +307,7 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) | |||
303 | adapter->scsi_host->max_lun = 1; | 307 | adapter->scsi_host->max_lun = 1; |
304 | adapter->scsi_host->max_channel = 0; | 308 | adapter->scsi_host->max_channel = 0; |
305 | adapter->scsi_host->unique_id = dev_id.devno; | 309 | adapter->scsi_host->unique_id = dev_id.devno; |
306 | adapter->scsi_host->max_cmd_len = 255; | 310 | adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */ |
307 | adapter->scsi_host->transportt = zfcp_data.scsi_transport_template; | 311 | adapter->scsi_host->transportt = zfcp_data.scsi_transport_template; |
308 | 312 | ||
309 | adapter->scsi_host->hostdata[0] = (unsigned long) adapter; | 313 | adapter->scsi_host->hostdata[0] = (unsigned long) adapter; |
@@ -325,12 +329,11 @@ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) | |||
325 | if (!shost) | 329 | if (!shost) |
326 | return; | 330 | return; |
327 | 331 | ||
328 | read_lock_irq(&zfcp_data.config_lock); | 332 | read_lock_irq(&adapter->port_list_lock); |
329 | list_for_each_entry(port, &adapter->port_list_head, list) | 333 | list_for_each_entry(port, &adapter->port_list, list) |
330 | if (port->rport) | 334 | port->rport = NULL; |
331 | port->rport = NULL; | 335 | read_unlock_irq(&adapter->port_list_lock); |
332 | 336 | ||
333 | read_unlock_irq(&zfcp_data.config_lock); | ||
334 | fc_remove_host(shost); | 337 | fc_remove_host(shost); |
335 | scsi_remove_host(shost); | 338 | scsi_remove_host(shost); |
336 | scsi_host_put(shost); | 339 | scsi_host_put(shost); |
@@ -348,7 +351,7 @@ zfcp_init_fc_host_stats(struct zfcp_adapter *adapter) | |||
348 | fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL); | 351 | fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL); |
349 | if (!fc_stats) | 352 | if (!fc_stats) |
350 | return NULL; | 353 | return NULL; |
351 | adapter->fc_stats = fc_stats; /* freed in adater_dequeue */ | 354 | adapter->fc_stats = fc_stats; /* freed in adapter_release */ |
352 | } | 355 | } |
353 | memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats)); | 356 | memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats)); |
354 | return adapter->fc_stats; | 357 | return adapter->fc_stats; |
@@ -464,7 +467,7 @@ static void zfcp_reset_fc_host_stats(struct Scsi_Host *shost) | |||
464 | adapter->stats_reset = jiffies/HZ; | 467 | adapter->stats_reset = jiffies/HZ; |
465 | kfree(adapter->stats_reset_data); | 468 | kfree(adapter->stats_reset_data); |
466 | adapter->stats_reset_data = data; /* finally freed in | 469 | adapter->stats_reset_data = data; /* finally freed in |
467 | adapter_dequeue */ | 470 | adapter_release */ |
468 | } | 471 | } |
469 | } | 472 | } |
470 | 473 | ||
@@ -495,7 +498,7 @@ static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout) | |||
495 | * @rport: The FC rport where to teminate I/O | 498 | * @rport: The FC rport where to teminate I/O |
496 | * | 499 | * |
497 | * Abort all pending SCSI commands for a port by closing the | 500 | * Abort all pending SCSI commands for a port by closing the |
498 | * port. Using a reopen for avoids a conflict with a shutdown | 501 | * port. Using a reopen avoiding a conflict with a shutdown |
499 | * overwriting a reopen. | 502 | * overwriting a reopen. |
500 | */ | 503 | */ |
501 | static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) | 504 | static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) |
@@ -505,15 +508,11 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) | |||
505 | struct zfcp_adapter *adapter = | 508 | struct zfcp_adapter *adapter = |
506 | (struct zfcp_adapter *)shost->hostdata[0]; | 509 | (struct zfcp_adapter *)shost->hostdata[0]; |
507 | 510 | ||
508 | write_lock_irq(&zfcp_data.config_lock); | ||
509 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); | 511 | port = zfcp_get_port_by_wwpn(adapter, rport->port_name); |
510 | if (port) | ||
511 | zfcp_port_get(port); | ||
512 | write_unlock_irq(&zfcp_data.config_lock); | ||
513 | 512 | ||
514 | if (port) { | 513 | if (port) { |
515 | zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL); | 514 | zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL); |
516 | zfcp_port_put(port); | 515 | put_device(&port->dev); |
517 | } | 516 | } |
518 | } | 517 | } |
519 | 518 | ||
@@ -555,31 +554,34 @@ static void zfcp_scsi_rport_block(struct zfcp_port *port) | |||
555 | 554 | ||
556 | void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) | 555 | void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) |
557 | { | 556 | { |
558 | zfcp_port_get(port); | 557 | get_device(&port->dev); |
559 | port->rport_task = RPORT_ADD; | 558 | port->rport_task = RPORT_ADD; |
560 | 559 | ||
561 | if (!queue_work(port->adapter->work_queue, &port->rport_work)) | 560 | if (!queue_work(port->adapter->work_queue, &port->rport_work)) |
562 | zfcp_port_put(port); | 561 | put_device(&port->dev); |
563 | } | 562 | } |
564 | 563 | ||
565 | void zfcp_scsi_schedule_rport_block(struct zfcp_port *port) | 564 | void zfcp_scsi_schedule_rport_block(struct zfcp_port *port) |
566 | { | 565 | { |
567 | zfcp_port_get(port); | 566 | get_device(&port->dev); |
568 | port->rport_task = RPORT_DEL; | 567 | port->rport_task = RPORT_DEL; |
569 | 568 | ||
570 | if (port->rport && queue_work(port->adapter->work_queue, | 569 | if (port->rport && queue_work(port->adapter->work_queue, |
571 | &port->rport_work)) | 570 | &port->rport_work)) |
572 | return; | 571 | return; |
573 | 572 | ||
574 | zfcp_port_put(port); | 573 | put_device(&port->dev); |
575 | } | 574 | } |
576 | 575 | ||
577 | void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter) | 576 | void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter) |
578 | { | 577 | { |
578 | unsigned long flags; | ||
579 | struct zfcp_port *port; | 579 | struct zfcp_port *port; |
580 | 580 | ||
581 | list_for_each_entry(port, &adapter->port_list_head, list) | 581 | read_lock_irqsave(&adapter->port_list_lock, flags); |
582 | list_for_each_entry(port, &adapter->port_list, list) | ||
582 | zfcp_scsi_schedule_rport_block(port); | 583 | zfcp_scsi_schedule_rport_block(port); |
584 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
583 | } | 585 | } |
584 | 586 | ||
585 | void zfcp_scsi_rport_work(struct work_struct *work) | 587 | void zfcp_scsi_rport_work(struct work_struct *work) |
@@ -597,7 +599,7 @@ void zfcp_scsi_rport_work(struct work_struct *work) | |||
597 | } | 599 | } |
598 | } | 600 | } |
599 | 601 | ||
600 | zfcp_port_put(port); | 602 | put_device(&port->dev); |
601 | } | 603 | } |
602 | 604 | ||
603 | 605 | ||
@@ -615,21 +617,7 @@ void zfcp_scsi_scan(struct work_struct *work) | |||
615 | scsilun_to_int((struct scsi_lun *) | 617 | scsilun_to_int((struct scsi_lun *) |
616 | &unit->fcp_lun), 0); | 618 | &unit->fcp_lun), 0); |
617 | 619 | ||
618 | zfcp_unit_put(unit); | 620 | put_device(&unit->dev); |
619 | } | ||
620 | |||
621 | static int zfcp_execute_fc_job(struct fc_bsg_job *job) | ||
622 | { | ||
623 | switch (job->request->msgcode) { | ||
624 | case FC_BSG_RPT_ELS: | ||
625 | case FC_BSG_HST_ELS_NOLOGIN: | ||
626 | return zfcp_fc_execute_els_fc_job(job); | ||
627 | case FC_BSG_RPT_CT: | ||
628 | case FC_BSG_HST_CT: | ||
629 | return zfcp_fc_execute_ct_fc_job(job); | ||
630 | default: | ||
631 | return -EINVAL; | ||
632 | } | ||
633 | } | 621 | } |
634 | 622 | ||
635 | struct fc_function_template zfcp_transport_functions = { | 623 | struct fc_function_template zfcp_transport_functions = { |
@@ -643,6 +631,7 @@ struct fc_function_template zfcp_transport_functions = { | |||
643 | .show_host_port_name = 1, | 631 | .show_host_port_name = 1, |
644 | .show_host_permanent_port_name = 1, | 632 | .show_host_permanent_port_name = 1, |
645 | .show_host_supported_classes = 1, | 633 | .show_host_supported_classes = 1, |
634 | .show_host_supported_fc4s = 1, | ||
646 | .show_host_supported_speeds = 1, | 635 | .show_host_supported_speeds = 1, |
647 | .show_host_maxframe_size = 1, | 636 | .show_host_maxframe_size = 1, |
648 | .show_host_serial_number = 1, | 637 | .show_host_serial_number = 1, |
@@ -652,13 +641,16 @@ struct fc_function_template zfcp_transport_functions = { | |||
652 | .get_host_port_state = zfcp_get_host_port_state, | 641 | .get_host_port_state = zfcp_get_host_port_state, |
653 | .terminate_rport_io = zfcp_scsi_terminate_rport_io, | 642 | .terminate_rport_io = zfcp_scsi_terminate_rport_io, |
654 | .show_host_port_state = 1, | 643 | .show_host_port_state = 1, |
655 | .bsg_request = zfcp_execute_fc_job, | 644 | .show_host_active_fc4s = 1, |
645 | .bsg_request = zfcp_fc_exec_bsg_job, | ||
646 | .bsg_timeout = zfcp_fc_timeout_bsg_job, | ||
656 | /* no functions registered for following dynamic attributes but | 647 | /* no functions registered for following dynamic attributes but |
657 | directly set by LLDD */ | 648 | directly set by LLDD */ |
658 | .show_host_port_type = 1, | 649 | .show_host_port_type = 1, |
659 | .show_host_speed = 1, | 650 | .show_host_speed = 1, |
660 | .show_host_port_id = 1, | 651 | .show_host_port_id = 1, |
661 | .disable_target_scan = 1, | 652 | .disable_target_scan = 1, |
653 | .dd_bsg_size = sizeof(struct zfcp_fsf_ct_els), | ||
662 | }; | 654 | }; |
663 | 655 | ||
664 | struct zfcp_data zfcp_data = { | 656 | struct zfcp_data zfcp_data = { |