diff options
-rw-r--r-- | drivers/firewire/fw-card.c | 56 | ||||
-rw-r--r-- | drivers/firewire/fw-device.c | 37 | ||||
-rw-r--r-- | drivers/firewire/fw-sbp2.c | 46 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.c | 48 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.h | 9 |
5 files changed, 82 insertions, 114 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index bbd73a406e53..418c18f07e9d 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c @@ -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 }; -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 fw_card_bm_work(struct work_struct *work) { struct fw_card *card = container_of(work, struct fw_card, work.work); struct fw_device *root_device; struct fw_node *root_node, *local_node; - struct bm_data bmd; 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; + __be32 lock_data[2]; spin_lock_irqsave(&card->lock, flags); local_node = card->local_node; @@ -263,33 +240,28 @@ fw_card_bm_work(struct work_struct *work) goto pick_me; } - bmd.lock.arg = cpu_to_be32(0x3f); - bmd.lock.data = cpu_to_be32(local_node->node_id); + lock_data[0] = cpu_to_be32(0x3f); + lock_data[1] = cpu_to_be32(local_node->node_id); spin_unlock_irqrestore(&card->lock, flags); - init_completion(&bmd.done); - fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP, - irm_id, generation, - SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, - &bmd.lock, sizeof(bmd.lock), - complete_bm_lock, &bmd); - wait_for_completion(&bmd.done); + rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, + irm_id, generation, SCODE_100, + CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, + lock_data, sizeof(lock_data)); - if (bmd.rcode == RCODE_GENERATION) { - /* - * Another bus reset happened. Just return, - * the BM work has been rescheduled. - */ + if (rcode == RCODE_GENERATION) + /* Another bus reset, BM work has been rescheduled. */ 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. */ goto out; spin_lock_irqsave(&card->lock, flags); - if (bmd.rcode != RCODE_COMPLETE) { + + if (rcode != RCODE_COMPLETE) { /* * The lock request failed, maybe the IRM * isn't really IRM capable after all. Let's diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 0855fb5568e8..3fccdd484100 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -381,46 +381,21 @@ static struct device_attribute fw_device_attributes[] = { __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 read_rom(struct fw_device *device, int generation, int index, u32 *data) { - struct read_quadlet_callback_data callback_data; - struct fw_transaction t; - u64 offset; + int rcode; /* device->node_id, accessed below, must not be older than generation */ smp_rmb(); - init_completion(&callback_data.done); - - offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4; - fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST, + rcode = fw_run_transaction(device->card, TCODE_READ_QUADLET_REQUEST, device->node_id, generation, device->max_speed, - offset, NULL, 4, complete_transaction, &callback_data); - - wait_for_completion(&callback_data.done); - - *data = callback_data.data; + (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4, + data, 4); + be32_to_cpus(data); - return callback_data.rcode; + return rcode; } #define READ_BIB_ROM_SIZE 256 diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index aaff50ebba1d..05997cee4f37 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -621,25 +621,15 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, 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) { struct fw_device *device = fw_device(lu->tgt->unit->device.parent); - DECLARE_COMPLETION_ONSTACK(done); - struct fw_transaction t; - static u32 z; + __be32 d = 0; - fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST, - lu->tgt->node_id, lu->generation, device->max_speed, - lu->command_block_agent_address + SBP2_AGENT_RESET, - &z, sizeof(z), complete_agent_reset_write, &done); - wait_for_completion(&done); + fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST, + lu->tgt->node_id, lu->generation, device->max_speed, + lu->command_block_agent_address + SBP2_AGENT_RESET, + &d, sizeof(d)); } static void @@ -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_transaction *t; - static u32 z; + static __be32 d; t = kmalloc(sizeof(*t), GFP_ATOMIC); if (t == NULL) @@ -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, lu->tgt->node_id, lu->generation, device->max_speed, 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) @@ -823,13 +813,6 @@ static void sbp2_target_put(struct sbp2_target *tgt) 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. * - 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, static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu) { struct fw_device *device = fw_device(lu->tgt->unit->device.parent); - DECLARE_COMPLETION_ONSTACK(done); - struct fw_transaction t; - static __be32 busy_timeout; - - busy_timeout = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT); + __be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT); - fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST, - lu->tgt->node_id, lu->generation, device->max_speed, - CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, &busy_timeout, - sizeof(busy_timeout), complete_set_busy_timeout, &done); - wait_for_completion(&done); + fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST, + lu->tgt->node_id, lu->generation, device->max_speed, + CSR_REGISTER_BASE + CSR_BUSY_TIMEOUT, + &d, sizeof(d)); } static void sbp2_reconnect(struct work_struct *work); diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index e5d1a0b64fcf..022ac4fabb67 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c @@ -247,7 +247,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, */ void 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, void *payload, size_t length, fw_transaction_callback_t callback, void *callback_data) @@ -279,13 +279,14 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, card->current_tlabel = (card->current_tlabel + 1) & 0x1f; card->tlabel_mask |= (1 << tlabel); - t->node_id = node_id; + t->node_id = destination_id; t->tlabel = tlabel; t->callback = callback; t->callback_data = callback_data; - fw_fill_request(&t->packet, tcode, t->tlabel, node_id, card->node_id, - generation, speed, offset, payload, length); + fw_fill_request(&t->packet, tcode, t->tlabel, + destination_id, card->node_id, generation, + speed, offset, payload, length); t->packet.callback = transmit_complete_callback; list_add_tail(&t->link, &card->transaction_list); @@ -296,6 +297,45 @@ fw_send_request(struct fw_card *card, struct fw_transaction *t, } 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 DECLARE_COMPLETION(phy_config_done); diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 2ae1b0d6cb7b..027f58ce81ad 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h @@ -426,11 +426,14 @@ fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); void fw_send_request(struct fw_card *card, struct fw_transaction *t, - int tcode, int node_id, int generation, int speed, - unsigned long long offset, - void *data, size_t length, + int tcode, int destination_id, int generation, int speed, + unsigned long long offset, void *data, size_t length, 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, struct fw_transaction *transaction); |