Commit 285838eb authored by Stefan Richter's avatar Stefan Richter

firewire: fw-sbp2: refactor workq and kref handling

This somewhat reduces the size of firewire-sbp2.ko.
Signed-off-by: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent 85c5798b
...@@ -628,6 +628,21 @@ static void sbp2_release_target(struct kref *kref) ...@@ -628,6 +628,21 @@ static void sbp2_release_target(struct kref *kref)
static struct workqueue_struct *sbp2_wq; static struct workqueue_struct *sbp2_wq;
/*
* Always get the target's kref when scheduling work on one its units.
* Each workqueue job is responsible to call sbp2_target_put() upon return.
*/
static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
{
if (queue_delayed_work(sbp2_wq, &lu->work, delay))
kref_get(&lu->tgt->kref);
}
static void sbp2_target_put(struct sbp2_target *tgt)
{
kref_put(&tgt->kref, sbp2_release_target);
}
static void sbp2_reconnect(struct work_struct *work); static void sbp2_reconnect(struct work_struct *work);
static void sbp2_login(struct work_struct *work) static void sbp2_login(struct work_struct *work)
...@@ -649,16 +664,12 @@ static void sbp2_login(struct work_struct *work) ...@@ -649,16 +664,12 @@ static void sbp2_login(struct work_struct *work)
if (sbp2_send_management_orb(lu, node_id, generation, if (sbp2_send_management_orb(lu, node_id, generation,
SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) { SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
if (lu->retries++ < 5) { if (lu->retries++ < 5)
if (queue_delayed_work(sbp2_wq, &lu->work, sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
DIV_ROUND_UP(HZ, 5))) else
kref_get(&lu->tgt->kref);
} else {
fw_error("failed to login to %s LUN %04x\n", fw_error("failed to login to %s LUN %04x\n",
unit->device.bus_id, lu->lun); unit->device.bus_id, lu->lun);
} goto out;
kref_put(&lu->tgt->kref, sbp2_release_target);
return;
} }
lu->generation = generation; lu->generation = generation;
...@@ -700,7 +711,8 @@ static void sbp2_login(struct work_struct *work) ...@@ -700,7 +711,8 @@ static void sbp2_login(struct work_struct *work)
lu->sdev = sdev; lu->sdev = sdev;
scsi_device_put(sdev); scsi_device_put(sdev);
} }
kref_put(&lu->tgt->kref, sbp2_release_target); out:
sbp2_target_put(lu->tgt);
} }
static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
...@@ -865,18 +877,13 @@ static int sbp2_probe(struct device *dev) ...@@ -865,18 +877,13 @@ static int sbp2_probe(struct device *dev)
get_device(&unit->device); get_device(&unit->device);
/* /* Do the login in a workqueue so we can easily reschedule retries. */
* We schedule work to do the login so we can easily
* reschedule retries. Always get the ref before scheduling
* work.
*/
list_for_each_entry(lu, &tgt->lu_list, link) list_for_each_entry(lu, &tgt->lu_list, link)
if (queue_delayed_work(sbp2_wq, &lu->work, 0)) sbp2_queue_work(lu, 0);
kref_get(&tgt->kref);
return 0; return 0;
fail_tgt_put: fail_tgt_put:
kref_put(&tgt->kref, sbp2_release_target); sbp2_target_put(tgt);
return -ENOMEM; return -ENOMEM;
fail_shost_put: fail_shost_put:
...@@ -889,7 +896,7 @@ static int sbp2_remove(struct device *dev) ...@@ -889,7 +896,7 @@ static int sbp2_remove(struct device *dev)
struct fw_unit *unit = fw_unit(dev); struct fw_unit *unit = fw_unit(dev);
struct sbp2_target *tgt = unit->device.driver_data; struct sbp2_target *tgt = unit->device.driver_data;
kref_put(&tgt->kref, sbp2_release_target); sbp2_target_put(tgt);
return 0; return 0;
} }
...@@ -915,10 +922,8 @@ static void sbp2_reconnect(struct work_struct *work) ...@@ -915,10 +922,8 @@ static void sbp2_reconnect(struct work_struct *work)
lu->retries = 0; lu->retries = 0;
PREPARE_DELAYED_WORK(&lu->work, sbp2_login); PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
} }
if (queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5))) sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
kref_get(&lu->tgt->kref); goto out;
kref_put(&lu->tgt->kref, sbp2_release_target);
return;
} }
lu->generation = generation; lu->generation = generation;
...@@ -930,8 +935,8 @@ static void sbp2_reconnect(struct work_struct *work) ...@@ -930,8 +935,8 @@ static void sbp2_reconnect(struct work_struct *work)
sbp2_agent_reset(lu); sbp2_agent_reset(lu);
sbp2_cancel_orbs(lu); sbp2_cancel_orbs(lu);
out:
kref_put(&lu->tgt->kref, sbp2_release_target); sbp2_target_put(lu->tgt);
} }
static void sbp2_update(struct fw_unit *unit) static void sbp2_update(struct fw_unit *unit)
...@@ -947,8 +952,7 @@ static void sbp2_update(struct fw_unit *unit) ...@@ -947,8 +952,7 @@ static void sbp2_update(struct fw_unit *unit)
*/ */
list_for_each_entry(lu, &tgt->lu_list, link) { list_for_each_entry(lu, &tgt->lu_list, link) {
lu->retries = 0; lu->retries = 0;
if (queue_delayed_work(sbp2_wq, &lu->work, 0)) sbp2_queue_work(lu, 0);
kref_get(&tgt->kref);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment