aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorSwen Schillig <swen@vnet.ibm.com>2009-04-17 09:08:04 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-04-27 11:07:26 -0400
commit92d5193b467c68e8432d6878980621c787e735af (patch)
treef38286d32216e23adfd4f8a8dc0e8ef152cd4de4 /drivers/s390
parentada81b748b768eb5b75567fd1db5e87ba5c98bf0 (diff)
[SCSI] zfcp: Dont block zfcp_wq with scan
When running the scsi_scan from the zfcp workqueue and the target device does not respond, the zfcp workqueue can block until the scsi_scan hits a timeout. Move the work to the scsi host workqueue, since this one is also used for the scan from the SCSI midlayer. Signed-off-by: Swen Schillig <swen@vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c5
-rw-r--r--drivers/s390/scsi/zfcp_def.h2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c50
-rw-r--r--drivers/s390/scsi/zfcp_ext.h1
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c17
5 files changed, 25 insertions, 50 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 616c60ffcf2c..5a01ef9aeb66 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -97,9 +97,7 @@ static void __init zfcp_init_device_configure(char *busid, u64 wwpn, u64 lun)
97 ccw_device_set_online(adapter->ccw_device); 97 ccw_device_set_online(adapter->ccw_device);
98 98
99 zfcp_erp_wait(adapter); 99 zfcp_erp_wait(adapter);
100 wait_event(adapter->erp_done_wqh, 100 flush_work(&unit->scsi_work);
101 !(atomic_read(&unit->status) &
102 ZFCP_STATUS_UNIT_SCSI_WORK_PENDING));
103 101
104 down(&zfcp_data.config_sema); 102 down(&zfcp_data.config_sema);
105 zfcp_unit_put(unit); 103 zfcp_unit_put(unit);
@@ -279,6 +277,7 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
279 277
280 atomic_set(&unit->refcount, 0); 278 atomic_set(&unit->refcount, 0);
281 init_waitqueue_head(&unit->remove_wq); 279 init_waitqueue_head(&unit->remove_wq);
280 INIT_WORK(&unit->scsi_work, zfcp_scsi_scan);
282 281
283 unit->port = port; 282 unit->port = port;
284 unit->fcp_lun = fcp_lun; 283 unit->fcp_lun = fcp_lun;
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index a0318630f047..4c362a9069f0 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -255,7 +255,6 @@ enum zfcp_wka_status {
255/* logical unit status */ 255/* logical unit status */
256#define ZFCP_STATUS_UNIT_SHARED 0x00000004 256#define ZFCP_STATUS_UNIT_SHARED 0x00000004
257#define ZFCP_STATUS_UNIT_READONLY 0x00000008 257#define ZFCP_STATUS_UNIT_READONLY 0x00000008
258#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020
259 258
260/* FSF request status (this does not have a common part) */ 259/* FSF request status (this does not have a common part) */
261#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002 260#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002
@@ -530,6 +529,7 @@ struct zfcp_unit {
530 struct zfcp_erp_action erp_action; /* pending error recovery */ 529 struct zfcp_erp_action erp_action; /* pending error recovery */
531 atomic_t erp_counter; 530 atomic_t erp_counter;
532 struct zfcp_latencies latencies; 531 struct zfcp_latencies latencies;
532 struct work_struct scsi_work;
533}; 533};
534 534
535/* FSF request */ 535/* FSF request */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 631bdb1dfd6c..4e160523c31b 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1176,48 +1176,6 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
1176 } 1176 }
1177} 1177}
1178 1178
1179struct zfcp_erp_add_work {
1180 struct zfcp_unit *unit;
1181 struct work_struct work;
1182};
1183
1184static void zfcp_erp_scsi_scan(struct work_struct *work)
1185{
1186 struct zfcp_erp_add_work *p =
1187 container_of(work, struct zfcp_erp_add_work, work);
1188 struct zfcp_unit *unit = p->unit;
1189 struct fc_rport *rport = unit->port->rport;
1190
1191 if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
1192 scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
1193 scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0);
1194 atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
1195 zfcp_unit_put(unit);
1196 wake_up(&unit->port->adapter->erp_done_wqh);
1197 kfree(p);
1198}
1199
1200static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
1201{
1202 struct zfcp_erp_add_work *p;
1203
1204 p = kzalloc(sizeof(*p), GFP_KERNEL);
1205 if (!p) {
1206 dev_err(&unit->port->adapter->ccw_device->dev,
1207 "Registering unit 0x%016Lx on port 0x%016Lx failed\n",
1208 (unsigned long long)unit->fcp_lun,
1209 (unsigned long long)unit->port->wwpn);
1210 return;
1211 }
1212
1213 zfcp_unit_get(unit);
1214 atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
1215 INIT_WORK(&p->work, zfcp_erp_scsi_scan);
1216 p->unit = unit;
1217 if (!queue_work(zfcp_data.work_queue, &p->work))
1218 zfcp_unit_put(unit);
1219}
1220
1221static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result) 1179static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
1222{ 1180{
1223 struct zfcp_adapter *adapter = act->adapter; 1181 struct zfcp_adapter *adapter = act->adapter;
@@ -1226,11 +1184,11 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
1226 1184
1227 switch (act->action) { 1185 switch (act->action) {
1228 case ZFCP_ERP_ACTION_REOPEN_UNIT: 1186 case ZFCP_ERP_ACTION_REOPEN_UNIT:
1229 flush_work(&port->rport_work);
1230 if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) { 1187 if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
1231 if (!(atomic_read(&unit->status) & 1188 zfcp_unit_get(unit);
1232 ZFCP_STATUS_UNIT_SCSI_WORK_PENDING)) 1189 if (scsi_queue_work(unit->port->adapter->scsi_host,
1233 zfcp_erp_schedule_work(unit); 1190 &unit->scsi_work) <= 0)
1191 zfcp_unit_put(unit);
1234 } 1192 }
1235 zfcp_unit_put(unit); 1193 zfcp_unit_put(unit);
1236 break; 1194 break;
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index f6399ca97bcb..df740f10d26a 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -158,6 +158,7 @@ extern void zfcp_scsi_rport_work(struct work_struct *);
158extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *); 158extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
159extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *); 159extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
160extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *); 160extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
161extern void zfcp_scsi_scan(struct work_struct *);
161 162
162/* zfcp_sysfs.c */ 163/* zfcp_sysfs.c */
163extern struct attribute_group zfcp_sysfs_unit_attrs; 164extern struct attribute_group zfcp_sysfs_unit_attrs;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 58201e1ae478..5b11386d70bb 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -583,6 +583,23 @@ void zfcp_scsi_rport_work(struct work_struct *work)
583} 583}
584 584
585 585
586void zfcp_scsi_scan(struct work_struct *work)
587{
588 struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
589 scsi_work);
590 struct fc_rport *rport;
591
592 flush_work(&unit->port->rport_work);
593 rport = unit->port->rport;
594
595 if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
596 scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
597 scsilun_to_int((struct scsi_lun *)
598 &unit->fcp_lun), 0);
599
600 zfcp_unit_put(unit);
601}
602
586struct fc_function_template zfcp_transport_functions = { 603struct fc_function_template zfcp_transport_functions = {
587 .show_starget_port_id = 1, 604 .show_starget_port_id = 1,
588 .show_starget_port_name = 1, 605 .show_starget_port_name = 1,