Commit 1e119fa9 authored by Jay Fenlason's avatar Jay Fenlason Committed by Stefan Richter

firewire: fw_send_request_sync()

Share code between fw_send_request + wait_for_completion callers.
Signed-off-by: default avatarJay Fenlason <fenlason@redhat.com>

Addendum:
Removes an unnecessary struct and an ununsed retry loop.
Calls it fw_run_transaction() instead of fw_send_request_sync().
Signed-off-by: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
Acked-by: default avatarKristian Høgsberg <krh@redhat.com>
parent fc392fe8
...@@ -189,39 +189,16 @@ static const char gap_count_table[] = { ...@@ -189,39 +189,16 @@ static const char gap_count_table[] = {
63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
}; };
struct bm_data {
struct fw_transaction t;
struct {
__be32 arg;
__be32 data;
} lock;
u32 old;
int rcode;
struct completion done;
};
static void
complete_bm_lock(struct fw_card *card, int rcode,
void *payload, size_t length, void *data)
{
struct bm_data *bmd = data;
if (rcode == RCODE_COMPLETE)
bmd->old = be32_to_cpu(*(__be32 *) payload);
bmd->rcode = rcode;
complete(&bmd->done);
}
static void static void
fw_card_bm_work(struct work_struct *work) fw_card_bm_work(struct work_struct *work)
{ {
struct fw_card *card = container_of(work, struct fw_card, work.work); struct fw_card *card = container_of(work, struct fw_card, work.work);
struct fw_device *root_device; struct fw_device *root_device;
struct fw_node *root_node, *local_node; struct fw_node *root_node, *local_node;
struct bm_data bmd;
unsigned long flags; unsigned long flags;
int root_id, new_root_id, irm_id, gap_count, generation, grace; int root_id, new_root_id, irm_id, gap_count, generation, grace, rcode;
bool do_reset = false; bool do_reset = false;
__be32 lock_data[2];
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
local_node = card->local_node; local_node = card->local_node;
...@@ -263,33 +240,28 @@ fw_card_bm_work(struct work_struct *work) ...@@ -263,33 +240,28 @@ fw_card_bm_work(struct work_struct *work)
goto pick_me; goto pick_me;
} }
bmd.lock.arg = cpu_to_be32(0x3f); lock_data[0] = cpu_to_be32(0x3f);
bmd.lock.data = cpu_to_be32(local_node->node_id); lock_data[1] = cpu_to_be32(local_node->node_id);
spin_unlock_irqrestore(&card->lock, flags); spin_unlock_irqrestore(&card->lock, flags);
init_completion(&bmd.done); rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100,
irm_id, generation, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, lock_data, sizeof(lock_data));
&bmd.lock, sizeof(bmd.lock),
complete_bm_lock, &bmd);
wait_for_completion(&bmd.done);
if (bmd.rcode == RCODE_GENERATION) { if (rcode == RCODE_GENERATION)
/* /* Another bus reset, BM work has been rescheduled. */
* Another bus reset happened. Just return,
* the BM work has been rescheduled.
*/
goto out; goto out;
}
if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f) if (rcode == RCODE_COMPLETE &&
lock_data[0] != cpu_to_be32(0x3f))
/* Somebody else is BM, let them do the work. */ /* Somebody else is BM, let them do the work. */
goto out; goto out;
spin_lock_irqsave(&card->lock, flags); spin_lock_irqsave(&card->lock, flags);
if (bmd.rcode != RCODE_COMPLETE) {
if (rcode != RCODE_COMPLETE) {
/* /*
* The lock request failed, maybe the IRM * The lock request failed, maybe the IRM
* isn't really IRM capable after all. Let's * isn't really IRM capable after all. Let's
......
...@@ -381,46 +381,21 @@ static struct device_attribute fw_device_attributes[] = { ...@@ -381,46 +381,21 @@ static struct device_attribute fw_device_attributes[] = {
__ATTR_NULL, __ATTR_NULL,
}; };
struct read_quadlet_callback_data {
struct completion done;
int rcode;
u32 data;
};
static void
complete_transaction(struct fw_card *card, int rcode,
void *payload, size_t length, void *data)
{
struct read_quadlet_callback_data *callback_data = data;
if (rcode == RCODE_COMPLETE)
callback_data->data = be32_to_cpu(*(__be32 *)payload);
callback_data->rcode = rcode;
complete(&callback_data->done);
}
static int static int
read_rom(struct fw_device *device, int generation, int index, u32 *data) read_rom(struct fw_device *device, int generation, int index, u32 *data)
{ {
struct read_quadlet_callback_data callback_data; int rcode;
struct fw_transaction t;
u64 offset;
/* device->node_id, accessed below, must not be older than generation */ /* device->node_id, accessed below, must not be older than generation */
smp_rmb(); smp_rmb();
init_completion(&callback_data.done); rcode = fw_run_transaction(device->card, TCODE_READ_QUADLET_REQUEST,
offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4;
fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
device->node_id, generation, device->max_speed, device->node_id, generation, device->max_speed,
offset, NULL, 4, complete_transaction, &callback_data); (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4,
data, 4);
wait_for_completion(&callback_data.done); be32_to_cpus(data);
*data = callback_data.data;
return callback_data.rcode; return rcode;
} }
#define READ_BIB_ROM_SIZE 256 #define READ_BIB_ROM_SIZE 256
......
...@@ -621,25 +621,15 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, ...@@ -621,25 +621,15 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
return retval; return retval;
} }
static void
complete_agent_reset_write(struct fw_card *card, int rcode,
void *payload, size_t length, void *done)
{
complete(done);
}
static void sbp2_agent_reset(struct sbp2_logical_unit *lu) static void sbp2_agent_reset(struct sbp2_logical_unit *lu)
{ {
struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
DECLARE_COMPLETION_ONSTACK(done); __be32 d = 0;
struct fw_transaction t;
static u32 z;
fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST, fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
lu->tgt->node_id, lu->generation, device->max_speed, lu->tgt->node_id, lu->generation, device->max_speed,
lu->command_block_agent_address + SBP2_AGENT_RESET, lu->command_block_agent_address + SBP2_AGENT_RESET,
&z, sizeof(z), complete_agent_reset_write, &done); &d, sizeof(d));
wait_for_completion(&done);
} }
static void static void
...@@ -653,7 +643,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) ...@@ -653,7 +643,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
{ {
struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
struct fw_transaction *t; struct fw_transaction *t;
static u32 z; static __be32 d;
t = kmalloc(sizeof(*t), GFP_ATOMIC); t = kmalloc(sizeof(*t), GFP_ATOMIC);
if (t == NULL) if (t == NULL)
...@@ -662,7 +652,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) ...@@ -662,7 +652,7 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
lu->tgt->node_id, lu->generation, device->max_speed, lu->tgt->node_id, lu->generation, device->max_speed,
lu->command_block_agent_address + SBP2_AGENT_RESET, lu->command_block_agent_address + SBP2_AGENT_RESET,
&z, sizeof(z), complete_agent_reset_write_no_wait, t); &d, sizeof(d), complete_agent_reset_write_no_wait, t);
} }
static void sbp2_set_generation(struct sbp2_logical_unit *lu, int generation) static void sbp2_set_generation(struct sbp2_logical_unit *lu, int generation)
...@@ -823,13 +813,6 @@ static void sbp2_target_put(struct sbp2_target *tgt) ...@@ -823,13 +813,6 @@ static void sbp2_target_put(struct sbp2_target *tgt)
kref_put(&tgt->kref, sbp2_release_target); kref_put(&tgt->kref, sbp2_release_target);
} }
static void
complete_set_busy_timeout(struct fw_card *card, int rcode,
void *payload, size_t length, void *done)
{
complete(done);
}
/* /*
* Write retransmit retry values into the BUSY_TIMEOUT register. * Write retransmit retry values into the BUSY_TIMEOUT register.
* - The single-phase retry protocol is supported by all SBP-2 devices, but the * - The single-phase retry protocol is supported by all SBP-2 devices, but the
...@@ -849,17 +832,12 @@ complete_set_busy_timeout(struct fw_card *card, int rcode, ...@@ -849,17 +832,12 @@ complete_set_busy_timeout(struct fw_card *card, int rcode,
static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu) static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
{ {
struct fw_device *device = fw_device(lu->tgt->unit->device.parent); struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
DECLARE_COMPLETION_ONSTACK(done); __be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
struct fw_transaction t;
static __be32 busy_timeout;
busy_timeout = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST, fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
lu->tgt->node_id, lu->generation, device->max_speed, lu->tgt->node_id, lu->generation, device->max_speed,
CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, &busy_timeout, CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT,
sizeof(busy_timeout), complete_set_busy_timeout, &done); &d, sizeof(d));
wait_for_completion(&done);
} }
static void sbp2_reconnect(struct work_struct *work); static void sbp2_reconnect(struct work_struct *work);
......
...@@ -247,7 +247,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, ...@@ -247,7 +247,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
*/ */
void void
fw_send_request(struct fw_card *card, struct fw_transaction *t, fw_send_request(struct fw_card *card, struct fw_transaction *t,
int tcode, int node_id, int generation, int speed, int tcode, int destination_id, int generation, int speed,
unsigned long long offset, unsigned long long offset,
void *payload, size_t length, void *payload, size_t length,
fw_transaction_callback_t callback, void *callback_data) fw_transaction_callback_t callback, void *callback_data)
...@@ -279,13 +279,14 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, ...@@ -279,13 +279,14 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
card->current_tlabel = (card->current_tlabel + 1) & 0x1f; card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
card->tlabel_mask |= (1 << tlabel); card->tlabel_mask |= (1 << tlabel);
t->node_id = node_id; t->node_id = destination_id;
t->tlabel = tlabel; t->tlabel = tlabel;
t->callback = callback; t->callback = callback;
t->callback_data = callback_data; t->callback_data = callback_data;
fw_fill_request(&t->packet, tcode, t->tlabel, node_id, card->node_id, fw_fill_request(&t->packet, tcode, t->tlabel,
generation, speed, offset, payload, length); destination_id, card->node_id, generation,
speed, offset, payload, length);
t->packet.callback = transmit_complete_callback; t->packet.callback = transmit_complete_callback;
list_add_tail(&t->link, &card->transaction_list); list_add_tail(&t->link, &card->transaction_list);
...@@ -296,6 +297,45 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, ...@@ -296,6 +297,45 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t,
} }
EXPORT_SYMBOL(fw_send_request); EXPORT_SYMBOL(fw_send_request);
struct transaction_callback_data {
struct completion done;
void *payload;
int rcode;
};
static void transaction_callback(struct fw_card *card, int rcode,
void *payload, size_t length, void *data)
{
struct transaction_callback_data *d = data;
if (rcode == RCODE_COMPLETE)
memcpy(d->payload, payload, length);
d->rcode = rcode;
complete(&d->done);
}
/**
* fw_run_transaction - send request and sleep until transaction is completed
*
* Returns the RCODE.
*/
int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
int generation, int speed, unsigned long long offset,
void *data, size_t length)
{
struct transaction_callback_data d;
struct fw_transaction t;
init_completion(&d.done);
d.payload = data;
fw_send_request(card, &t, tcode, destination_id, generation, speed,
offset, data, length, transaction_callback, &d);
wait_for_completion(&d.done);
return d.rcode;
}
EXPORT_SYMBOL(fw_run_transaction);
static DEFINE_MUTEX(phy_config_mutex); static DEFINE_MUTEX(phy_config_mutex);
static DECLARE_COMPLETION(phy_config_done); static DECLARE_COMPLETION(phy_config_done);
......
...@@ -426,11 +426,14 @@ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); ...@@ -426,11 +426,14 @@ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
void void
fw_send_request(struct fw_card *card, struct fw_transaction *t, fw_send_request(struct fw_card *card, struct fw_transaction *t,
int tcode, int node_id, int generation, int speed, int tcode, int destination_id, int generation, int speed,
unsigned long long offset, unsigned long long offset, void *data, size_t length,
void *data, size_t length,
fw_transaction_callback_t callback, void *callback_data); fw_transaction_callback_t callback, void *callback_data);
int fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
int generation, int speed, unsigned long long offset,
void *data, size_t length);
int fw_cancel_transaction(struct fw_card *card, int fw_cancel_transaction(struct fw_card *card,
struct fw_transaction *transaction); struct fw_transaction *transaction);
......
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