From 651298cefa2273b956effc46b5f44b1e910ea8bf Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Fri, 15 Feb 2008 21:29:02 +0100 Subject: [PATCH] --- yaml --- r: 86367 b: refs/heads/master c: e80de3704ac30ddb7f9a12447a2ecee32ccd7880 h: refs/heads/master i: 86365: 7a510a2729783a9d24b54d34ef51e854c8441829 86363: c7126b5e1e40a623213b1b3b2b472aabec3a266c 86359: 126c558eee49e67528eec05e7187f6697f8f0bbf 86351: 8136814d3c79481c5da121f65e44a197f4fe61e5 86335: 0008f7d85dd3a930f9522d9b9d6c964a2ac41f9c v: v3 --- [refs] | 2 +- trunk/drivers/firewire/fw-sbp2.c | 49 +++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/[refs] b/[refs] index 0e29b05f94b9..6e51f9f7a15d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7bb6bf7c8ba0b4ccfecaa00d6faea51b0bd42c8c +refs/heads/master: e80de3704ac30ddb7f9a12447a2ecee32ccd7880 diff --git a/trunk/drivers/firewire/fw-sbp2.c b/trunk/drivers/firewire/fw-sbp2.c index 323b03bacd29..6d10934c58f1 100644 --- a/trunk/drivers/firewire/fw-sbp2.c +++ b/trunk/drivers/firewire/fw-sbp2.c @@ -762,22 +762,43 @@ static void sbp2_login(struct work_struct *work) sdev = __scsi_add_device(shost, 0, 0, scsilun_to_int(&eight_bytes_lun), lu); - if (IS_ERR(sdev)) { - smp_rmb(); /* generation may have changed */ - generation = device->generation; - smp_rmb(); /* node_id must not be older than generation */ + /* + * FIXME: We are unable to perform reconnects while in sbp2_login(). + * Therefore __scsi_add_device() will get into trouble if a bus reset + * happens in parallel. It will either fail or leave us with an + * unusable sdev. As a workaround we check for this and retry the + * whole login and SCSI probing. + */ - sbp2_send_management_orb(lu, device->node_id, generation, - SBP2_LOGOUT_REQUEST, lu->login_id, NULL); - /* - * Set this back to sbp2_login so we fall back and - * retry login on bus reset. - */ - PREPARE_DELAYED_WORK(&lu->work, sbp2_login); - } else { - lu->sdev = sdev; - scsi_device_put(sdev); + /* Reported error during __scsi_add_device() */ + if (IS_ERR(sdev)) + goto out_logout_login; + + scsi_device_put(sdev); + + /* Unreported error during __scsi_add_device() */ + smp_rmb(); /* get current card generation */ + if (generation != device->card->generation) { + scsi_remove_device(sdev); + goto out_logout_login; } + + /* No error during __scsi_add_device() */ + lu->sdev = sdev; + goto out; + + out_logout_login: + smp_rmb(); /* generation may have changed */ + generation = device->generation; + smp_rmb(); /* node_id must not be older than generation */ + + sbp2_send_management_orb(lu, device->node_id, generation, + SBP2_LOGOUT_REQUEST, lu->login_id, NULL); + /* + * If a bus reset happened, sbp2_update will have requeued + * lu->work already. Reset the work from reconnect to login. + */ + PREPARE_DELAYED_WORK(&lu->work, sbp2_login); out: sbp2_target_put(tgt); }