diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-21 23:25:07 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-21 23:25:07 +0400 |
commit | dcb4a1f0e0367efb813907e5083998bbb98b0456 (patch) | |
tree | 80b1edb72dd20ed20917e6c835bd49a0c0b52df2 | |
parent | c21fd1a8c68ce3f49b00caf10337169262cfb8ad (diff) | |
parent | 105e53f863c04e1d9e5bb34bf753c9fdbce6a60c (diff) | |
download | linux-dcb4a1f0e0367efb813907e5083998bbb98b0456.tar.xz |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
firewire: sbp2: parallelize login, reconnect, logout
firewire: sbp2: octlet AT payloads can be stack-allocated
firewire: sbp2: omit Scsi_Host lock from queuecommand
firewire: core: use non-reentrant workqueue with rescuer
firewire: optimize iso queueing by setting wake only after the last packet
firewire: octlet AT payloads can be stack-allocated
firewire: ohci: optimize find_branch_descriptor()
firewire: ohci: avoid separate DMA mapping for small AT payloads
firewire: ohci: do not start DMA contexts before link is enabled
-rw-r--r-- | drivers/firewire/core-card.c | 27 | ||||
-rw-r--r-- | drivers/firewire/core-cdev.c | 7 | ||||
-rw-r--r-- | drivers/firewire/core-device.c | 31 | ||||
-rw-r--r-- | drivers/firewire/core-iso.c | 27 | ||||
-rw-r--r-- | drivers/firewire/core-transaction.c | 19 | ||||
-rw-r--r-- | drivers/firewire/core.h | 2 | ||||
-rw-r--r-- | drivers/firewire/net.c | 4 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 64 | ||||
-rw-r--r-- | drivers/firewire/sbp2.c | 37 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-avc.c | 15 | ||||
-rw-r--r-- | drivers/media/dvb/firewire/firedtv-fw.c | 1 | ||||
-rw-r--r-- | include/linux/firewire.h | 6 | ||||
-rw-r--r-- | sound/firewire/amdtp.c | 1 | ||||
-rw-r--r-- | sound/firewire/cmp.c | 3 | ||||
-rw-r--r-- | sound/firewire/iso-resources.c | 12 | ||||
-rw-r--r-- | sound/firewire/iso-resources.h | 1 |
16 files changed, 140 insertions, 117 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 3c44fbc81acb..29d2423fae6d 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -228,8 +228,8 @@ void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset) /* Use an arbitrary short delay to combine multiple reset requests. */ fw_card_get(card); - if (!schedule_delayed_work(&card->br_work, - delayed ? DIV_ROUND_UP(HZ, 100) : 0)) + if (!queue_delayed_work(fw_workqueue, &card->br_work, + delayed ? DIV_ROUND_UP(HZ, 100) : 0)) fw_card_put(card); } EXPORT_SYMBOL(fw_schedule_bus_reset); @@ -241,7 +241,7 @@ static void br_work(struct work_struct *work) /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */ if (card->reset_jiffies != 0 && time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) { - if (!schedule_delayed_work(&card->br_work, 2 * HZ)) + if (!queue_delayed_work(fw_workqueue, &card->br_work, 2 * HZ)) fw_card_put(card); return; } @@ -258,8 +258,7 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation) if (!card->broadcast_channel_allocated) { fw_iso_resource_manage(card, generation, 1ULL << 31, - &channel, &bandwidth, true, - card->bm_transaction_data); + &channel, &bandwidth, true); if (channel != 31) { fw_notify("failed to allocate broadcast channel\n"); return; @@ -294,6 +293,7 @@ static void bm_work(struct work_struct *work) bool root_device_is_cmc; bool irm_is_1394_1995_only; bool keep_this_irm; + __be32 transaction_data[2]; spin_lock_irq(&card->lock); @@ -355,21 +355,21 @@ static void bm_work(struct work_struct *work) goto pick_me; } - card->bm_transaction_data[0] = cpu_to_be32(0x3f); - card->bm_transaction_data[1] = cpu_to_be32(local_id); + transaction_data[0] = cpu_to_be32(0x3f); + transaction_data[1] = cpu_to_be32(local_id); spin_unlock_irq(&card->lock); rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID, - card->bm_transaction_data, 8); + transaction_data, 8); if (rcode == RCODE_GENERATION) /* Another bus reset, BM work has been rescheduled. */ goto out; - bm_id = be32_to_cpu(card->bm_transaction_data[0]); + bm_id = be32_to_cpu(transaction_data[0]); spin_lock_irq(&card->lock); if (rcode == RCODE_COMPLETE && generation == card->generation) @@ -490,11 +490,11 @@ static void bm_work(struct work_struct *work) /* * Make sure that the cycle master sends cycle start packets. */ - card->bm_transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR); + transaction_data[0] = cpu_to_be32(CSR_STATE_BIT_CMSTR); rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST, root_id, generation, SCODE_100, CSR_REGISTER_BASE + CSR_STATE_SET, - card->bm_transaction_data, 4); + transaction_data, 4); if (rcode == RCODE_GENERATION) goto out; } @@ -630,6 +630,10 @@ static int dummy_queue_iso(struct fw_iso_context *ctx, struct fw_iso_packet *p, return -ENODEV; } +static void dummy_flush_queue_iso(struct fw_iso_context *ctx) +{ +} + static const struct fw_card_driver dummy_driver_template = { .read_phy_reg = dummy_read_phy_reg, .update_phy_reg = dummy_update_phy_reg, @@ -641,6 +645,7 @@ static const struct fw_card_driver dummy_driver_template = { .start_iso = dummy_start_iso, .set_iso_channels = dummy_set_iso_channels, .queue_iso = dummy_queue_iso, + .flush_queue_iso = dummy_flush_queue_iso, }; void fw_card_release(struct kref *kref) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 62ac111af243..b1c11775839c 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -141,7 +141,6 @@ struct iso_resource { int generation; u64 channels; s32 bandwidth; - __be32 transaction_data[2]; struct iso_resource_event *e_alloc, *e_dealloc; }; @@ -150,7 +149,7 @@ static void release_iso_resource(struct client *, struct client_resource *); static void schedule_iso_resource(struct iso_resource *r, unsigned long delay) { client_get(r->client); - if (!schedule_delayed_work(&r->work, delay)) + if (!queue_delayed_work(fw_workqueue, &r->work, delay)) client_put(r->client); } @@ -1108,6 +1107,7 @@ static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) payload += u.packet.payload_length; count++; } + fw_iso_context_queue_flush(ctx); a->size -= uptr_to_u64(p) - a->packets; a->packets = uptr_to_u64(p); @@ -1229,8 +1229,7 @@ static void iso_resource_work(struct work_struct *work) r->channels, &channel, &bandwidth, todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC || - todo == ISO_RES_ALLOC_ONCE, - r->transaction_data); + todo == ISO_RES_ALLOC_ONCE); /* * Is this generation outdated already? As long as this resource sticks * in the idr, it will be scheduled again for a newer generation or at diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 9a262439e3a7..95a471401892 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -725,6 +725,15 @@ struct fw_device *fw_device_get_by_devt(dev_t devt) return device; } +struct workqueue_struct *fw_workqueue; +EXPORT_SYMBOL(fw_workqueue); + +static void fw_schedule_device_work(struct fw_device *device, + unsigned long delay) +{ + queue_delayed_work(fw_workqueue, &device->work, delay); +} + /* * These defines control the retry behavior for reading the config * rom. It shouldn't be necessary to tweak these; if the device @@ -750,7 +759,7 @@ static void fw_device_shutdown(struct work_struct *work) if (time_before64(get_jiffies_64(), device->card->reset_jiffies + SHUTDOWN_DELAY) && !list_empty(&device->card->link)) { - schedule_delayed_work(&device->work, SHUTDOWN_DELAY); + fw_schedule_device_work(device, SHUTDOWN_DELAY); return; } @@ -862,7 +871,7 @@ static int lookup_existing_device(struct device *dev, void *data) fw_notify("rediscovered device %s\n", dev_name(dev)); PREPARE_DELAYED_WORK(&old->work, fw_device_update); - schedule_delayed_work(&old->work, 0); + fw_schedule_device_work(old, 0); if (current_node == card->root_node) fw_schedule_bm_work(card, 0); @@ -953,7 +962,7 @@ static void fw_device_init(struct work_struct *work) if (device->config_rom_retries < MAX_RETRIES && atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { device->config_rom_retries++; - schedule_delayed_work(&device->work, RETRY_DELAY); + fw_schedule_device_work(device, RETRY_DELAY); } else { if (device->node->link_on) fw_notify("giving up on config rom for node id %x\n", @@ -1019,7 +1028,7 @@ static void fw_device_init(struct work_struct *work) FW_DEVICE_INITIALIZING, FW_DEVICE_RUNNING) == FW_DEVICE_GONE) { PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); - schedule_delayed_work(&device->work, SHUTDOWN_DELAY); + fw_schedule_device_work(device, SHUTDOWN_DELAY); } else { if (device->config_rom_retries) fw_notify("created device %s: GUID %08x%08x, S%d00, " @@ -1098,7 +1107,7 @@ static void fw_device_refresh(struct work_struct *work) if (device->config_rom_retries < MAX_RETRIES / 2 && atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { device->config_rom_retries++; - schedule_delayed_work(&device->work, RETRY_DELAY / 2); + fw_schedule_device_work(device, RETRY_DELAY / 2); return; } @@ -1131,7 +1140,7 @@ static void fw_device_refresh(struct work_struct *work) if (device->config_rom_retries < MAX_RETRIES && atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { device->config_rom_retries++; - schedule_delayed_work(&device->work, RETRY_DELAY); + fw_schedule_device_work(device, RETRY_DELAY); return; } @@ -1158,7 +1167,7 @@ static void fw_device_refresh(struct work_struct *work) gone: atomic_set(&device->state, FW_DEVICE_GONE); PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); - schedule_delayed_work(&device->work, SHUTDOWN_DELAY); + fw_schedule_device_work(device, SHUTDOWN_DELAY); out: if (node_id == card->root_node->node_id) fw_schedule_bm_work(card, 0); @@ -1214,7 +1223,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) * first config rom scan half a second after bus reset. */ INIT_DELAYED_WORK(&device->work, fw_device_init); - schedule_delayed_work(&device->work, INITIAL_DELAY); + fw_schedule_device_work(device, INITIAL_DELAY); break; case FW_NODE_INITIATED_RESET: @@ -1230,7 +1239,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) FW_DEVICE_RUNNING, FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) { PREPARE_DELAYED_WORK(&device->work, fw_device_refresh); - schedule_delayed_work(&device->work, + fw_schedule_device_work(device, device->is_local ? 0 : INITIAL_DELAY); } break; @@ -1245,7 +1254,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) device->generation = card->generation; if (atomic_read(&device->state) == FW_DEVICE_RUNNING) { PREPARE_DELAYED_WORK(&device->work, fw_device_update); - schedule_delayed_work(&device->work, 0); + fw_schedule_device_work(device, 0); } break; @@ -1270,7 +1279,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) if (atomic_xchg(&device->state, FW_DEVICE_GONE) == FW_DEVICE_RUNNING) { PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); - schedule_delayed_work(&device->work, + fw_schedule_device_work(device, list_empty(&card->link) ? 0 : SHUTDOWN_DELAY); } break; diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 481056df9268..57c3973093ad 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -185,6 +185,12 @@ int fw_iso_context_queue(struct fw_iso_context *ctx, } EXPORT_SYMBOL(fw_iso_context_queue); +void fw_iso_context_queue_flush(struct fw_iso_context *ctx) +{ + ctx->card->driver->flush_queue_iso(ctx); +} +EXPORT_SYMBOL(fw_iso_context_queue_flush); + int fw_iso_context_stop(struct fw_iso_context *ctx) { return ctx->card->driver->stop_iso(ctx); @@ -196,9 +202,10 @@ EXPORT_SYMBOL(fw_iso_context_stop); */ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, - int bandwidth, bool allocate, __be32 data[2]) + int bandwidth, bool allocate) { int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0; + __be32 data[2]; /* * On a 1394a IRM with low contention, try < 1 is enough. @@ -233,9 +240,10 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, } static int manage_channel(struct fw_card *card, int irm_id, int generation, - u32 channels_mask, u64 offset, bool allocate, __be32 data[2]) + u32 channels_mask, u64 offset, bool allocate) { __be32 bit, all, old; + __be32 data[2]; int channel, ret = -EIO, retry = 5; old = all = allocate ? cpu_to_be32(~0) : 0; @@ -284,7 +292,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, } static void deallocate_channel(struct fw_card *card, int irm_id, - int generation, int channel, __be32 buffer[2]) + int generation, int channel) { u32 mask; u64 offset; @@ -293,7 +301,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI : CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO; - manage_channel(card, irm_id, generation, mask, offset, false, buffer); + manage_channel(card, irm_id, generation, mask, offset, false); } /** @@ -322,7 +330,7 @@ static void deallocate_channel(struct fw_card *card, int irm_id, */ void fw_iso_resource_manage(struct fw_card *card, int generation, u64 channels_mask, int *channel, int *bandwidth, - bool allocate, __be32 buffer[2]) + bool allocate) { u32 channels_hi = channels_mask; /* channels 31...0 */ u32 channels_lo = channels_mask >> 32; /* channels 63...32 */ @@ -335,11 +343,11 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, if (channels_hi) c = manage_channel(card, irm_id, generation, channels_hi, CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI, - allocate, buffer); + allocate); if (channels_lo && c < 0) { c = manage_channel(card, irm_id, generation, channels_lo, CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO, - allocate, buffer); + allocate); if (c >= 0) c += 32; } @@ -351,14 +359,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, if (*bandwidth == 0) return; - ret = manage_bandwidth(card, irm_id, generation, *bandwidth, - allocate, buffer); + ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate); if (ret < 0) *bandwidth = 0; if (allocate && ret < 0) { if (c >= 0) - deallocate_channel(card, irm_id, generation, c, buffer); + deallocate_channel(card, irm_id, generation, c); *channel = ret; } } diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index d00f8ce902cc..334b82a3542c 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -36,6 +36,7 @@ #include <linux/string.h> #include <linux/timer.h> #include <linux/types.h> +#include <linux/workqueue.h> #include <asm/byteorder.h> @@ -326,8 +327,8 @@ static int allocate_tlabel(struct fw_card *card) * It will contain tag, channel, and sy data instead of a node ID then. * * The payload buffer at @data is going to be DMA-mapped except in case of - * quadlet-sized payload or of local (loopback) requests. Hence make sure that - * the buffer complies with the restrictions for DMA-mapped memory. The + * @length <= 8 or of local (loopback) requests. Hence make sure that the + * buffer complies with the restrictions of the streaming DMA mapping API. * @payload must not be freed before the @callback is called. * * In case of request types without payload, @data is NULL and @length is 0. @@ -411,7 +412,8 @@ static void transaction_callback(struct fw_card *card, int rcode, * * Returns the RCODE. See fw_send_request() for parameter documentation. * Unlike fw_send_request(), @data points to the payload of the request or/and - * to the payload of the response. + * to the payload of the response. DMA mapping restrictions apply to outbound + * request payloads of >= 8 bytes but not to inbound response payloads. */ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, int generation, int speed, unsigned long long offset, @@ -1212,13 +1214,21 @@ static int __init fw_core_init(void) { int ret; + fw_workqueue = alloc_workqueue("firewire", + WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0); + if (!fw_workqueue) + return -ENOMEM; + ret = bus_register(&fw_bus_type); - if (ret < 0) + if (ret < 0) { + destroy_workqueue(fw_workqueue); return ret; + } fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops); if (fw_cdev_major < 0) { bus_unregister(&fw_bus_type); + destroy_workqueue(fw_workqueue); return fw_cdev_major; } @@ -1234,6 +1244,7 @@ static void __exit fw_core_cleanup(void) { unregister_chrdev(fw_cdev_major, "firewire"); bus_unregister(&fw_bus_type); + destroy_workqueue(fw_workqueue); idr_destroy(&fw_device_idr); } diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 25e729cde2f7..0fe4e4e6eda7 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -97,6 +97,8 @@ struct fw_card_driver { struct fw_iso_buffer *buffer, unsigned long payload); + void (*flush_queue_iso)(struct fw_iso_context *ctx); + int (*stop_iso)(struct fw_iso_context *ctx); }; diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 3f04dd3681cf..b9762d07198d 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -881,7 +881,9 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, spin_unlock_irqrestore(&dev->lock, flags); - if (retval < 0) + if (retval >= 0) + fw_iso_context_queue_flush(dev->broadcast_rcv_context); + else fw_error("requeue failed\n"); } diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 23d1468ad253..438e6c831170 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1006,13 +1006,12 @@ static void ar_context_run(struct ar_context *ctx) static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) { - int b, key; + __le16 branch; - b = (le16_to_cpu(d->control) & DESCRIPTOR_BRANCH_ALWAYS) >> 2; - key = (le16_to_cpu(d->control) & DESCRIPTOR_KEY_IMMEDIATE) >> 8; + branch = d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS); /* figure out which descriptor the branch address goes in */ - if (z == 2 && (b == 3 || key == 2)) + if (z == 2 && branch == cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)) return d; else return d + z - 1; @@ -1193,9 +1192,6 @@ static void context_append(struct context *ctx, wmb(); /* finish init of new descriptors before branch_address update */ ctx->prev->branch_address = cpu_to_le32(d_bus | z); ctx->prev = find_branch_descriptor(d, z); - - reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ctx->ohci); } static void context_stop(struct context *ctx) @@ -1218,6 +1214,7 @@ static void context_stop(struct context *ctx) } struct driver_data { + u8 inline_data[8]; struct fw_packet *packet; }; @@ -1301,20 +1298,28 @@ static int at_context_queue_packet(struct context *ctx, return -1; } + BUILD_BUG_ON(sizeof(struct driver_data) > sizeof(struct descriptor)); driver_data = (struct driver_data *) &d[3]; driver_data->packet = packet; packet->driver_data = driver_data; if (packet->payload_length > 0) { - payload_bus = - dma_map_single(ohci->card.device, packet->payload, - packet->payload_length, DMA_TO_DEVICE); - if (dma_mapping_error(ohci->card.device, payload_bus)) { - packet->ack = RCODE_SEND_ERROR; - return -1; + if (packet->payload_length > sizeof(driver_data->inline_data)) { + payload_bus = dma_map_single(ohci->card.device, + packet->payload, + packet->payload_length, + DMA_TO_DEVICE); + if (dma_mapping_error(ohci->card.device, payload_bus)) { + packet->ack = RCODE_SEND_ERROR; + return -1; + } + packet->payload_bus = payload_bus; + packet->payload_mapped = true; + } else { + memcpy(driver_data->inline_data, packet->payload, + packet->payload_length); + payload_bus = d_bus + 3 * sizeof(*d); } - packet->payload_bus = payload_bus; - packet->payload_mapped = true; d[2].req_count = cpu_to_le16(packet->payload_length); d[2].data_address = cpu_to_le32(payload_bus); @@ -1340,8 +1345,12 @@ static int at_context_queue_packet(struct context *ctx, context_append(ctx, d, z, 4 - z); - if (!ctx->running) + if (ctx->running) { + reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); + flush_writes(ohci); + } else { context_run(ctx, 0); + } return 0; } @@ -2066,8 +2075,6 @@ static int ohci_enable(struct fw_card *card, reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus); reg_write(ohci, OHCI1394_LinkControlSet, - OHCI1394_LinkControl_rcvSelfID | - OHCI1394_LinkControl_rcvPhyPkt | OHCI1394_LinkControl_cycleTimerEnable | OHCI1394_LinkControl_cycleMaster); @@ -2094,9 +2101,6 @@ static int ohci_enable(struct fw_card *card, reg_write(ohci, OHCI1394_FairnessControl, 0); card->priority_budget_implemented = ohci->pri_req_max != 0; - ar_context_run(&ohci->ar_request_ctx); - ar_context_run(&ohci->ar_response_ctx); - reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000); reg_write(ohci, OHCI1394_IntEventClear, ~0); reg_write(ohci, OHCI1394_IntMaskClear, ~0); @@ -2186,7 +2190,13 @@ static int ohci_enable(struct fw_card *card, reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable | OHCI1394_HCControl_BIBimageValid); - flush_writes(ohci); + + reg_write(ohci, OHCI1394_LinkControlSet, + OHCI1394_LinkControl_rcvSelfID | + OHCI1394_LinkControl_rcvPhyPkt); + + ar_context_run(&ohci->ar_request_ctx); + ar_context_run(&ohci->ar_response_ctx); /* also flushes writes */ /* We are ready to go, reset bus to finish initialization. */ fw_schedule_bus_reset(&ohci->card, false, true); @@ -3112,6 +3122,15 @@ static int ohci_queue_iso(struct fw_iso_context *base, return ret; } +static void ohci_flush_queue_iso(struct fw_iso_context *base) +{ + struct context *ctx = + &container_of(base, struct iso_context, base)->context; + + reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); + flush_writes(ctx->ohci); +} + static const struct fw_card_driver ohci_driver = { .enable = ohci_enable, .read_phy_reg = ohci_read_phy_reg, @@ -3128,6 +3147,7 @@ static const struct fw_card_driver ohci_driver = { .free_iso_context = ohci_free_iso_context, .set_iso_channels = ohci_set_iso_channels, .queue_iso = ohci_queue_iso, + .flush_queue_iso = ohci_flush_queue_iso, .start_iso = ohci_start_iso, .stop_iso = ohci_stop_iso, }; diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 77ed589b360d..41841a3e3f99 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -125,9 +125,6 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) ", or a combination)"); -/* I don't know why the SCSI stack doesn't define something like this... */ -typedef void (*scsi_done_fn_t)(struct scsi_cmnd *); - static const char sbp2_driver_name[] = "sbp2"; /* @@ -261,7 +258,6 @@ struct sbp2_orb { struct kref kref; dma_addr_t request_bus; int rcode; - struct sbp2_pointer pointer; void (*callback)(struct sbp2_orb * orb, struct sbp2_status * status); struct list_head link; }; @@ -314,7 +310,6 @@ struct sbp2_command_orb { u8 command_block[SBP2_MAX_CDB_SIZE]; } request; struct scsi_cmnd *cmd; - scsi_done_fn_t done; struct sbp2_logical_unit *lu; struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8))); @@ -494,10 +489,11 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, int node_id, int generation, u64 offset) { struct fw_device *device = target_device(lu->tgt); + struct sbp2_pointer orb_pointer; unsigned long flags; - orb->pointer.high = 0; - orb->pointer.low = cpu_to_be32(orb->request_bus); + orb_pointer.high = 0; + orb_pointer.low = cpu_to_be32(orb->request_bus); spin_lock_irqsave(&device->card->lock, flags); list_add_tail(&orb->link, &lu->orb_list); @@ -508,7 +504,7 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST, node_id, generation, device->max_speed, offset, - &orb->pointer, 8, complete_transaction, orb); + &orb_pointer, 8, complete_transaction, orb); } static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) @@ -830,8 +826,6 @@ static void sbp2_target_put(struct sbp2_target *tgt) kref_put(&tgt->kref, sbp2_release_target); } -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. @@ -839,7 +833,7 @@ static struct workqueue_struct *sbp2_wq; static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay) { sbp2_target_get(lu->tgt); - if (!queue_delayed_work(sbp2_wq, &lu->work, delay)) + if (!queue_delayed_work(fw_workqueue, &lu->work, delay)) sbp2_target_put(lu->tgt); } @@ -1398,7 +1392,7 @@ static void complete_command_orb(struct sbp2_orb *base_orb, sbp2_unmap_scatterlist(device->card->device, orb); orb->cmd->result = result; - orb->done(orb->cmd); + orb->cmd->scsi_done(orb->cmd); } static int sbp2_map_scatterlist(struct sbp2_command_orb *orb, @@ -1463,7 +1457,8 @@ static int sbp2_map_scatterlist(struct sbp2_command_orb *orb, /* SCSI stack integration */ -static int sbp2_scsi_queuecommand_lck(struct scsi_cmnd *cmd, scsi_done_fn_t done) +static int sbp2_scsi_queuecommand(struct Scsi_Host *shost, + struct scsi_cmnd *cmd) { struct sbp2_logical_unit *lu = cmd->device->hostdata; struct fw_device *device = target_device(lu->tgt); @@ -1477,7 +1472,7 @@ static int sbp2_scsi_queuecommand_lck(struct scsi_cmnd *cmd, scsi_done_fn_t done if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) { fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n"); cmd->result = DID_ERROR << 16; - done(cmd); + cmd->scsi_done(cmd); return 0; } @@ -1490,11 +1485,8 @@ static int sbp2_scsi_queuecommand_lck(struct scsi_cmnd *cmd, scsi_done_fn_t done /* Initialize rcode to something not RCODE_COMPLETE. */ orb->base.rcode = -1; kref_init(&orb->base.kref); - - orb->lu = lu; - orb->done = done; - orb->cmd = cmd; - + orb->lu = lu; + orb->cmd = cmd; orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL); orb->request.misc = cpu_to_be32( COMMAND_ORB_MAX_PAYLOAD(lu->tgt->max_payload) | @@ -1529,8 +1521,6 @@ static int sbp2_scsi_queuecommand_lck(struct scsi_cmnd *cmd, scsi_done_fn_t done return retval; } -static DEF_SCSI_QCMD(sbp2_scsi_queuecommand) - static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) { struct sbp2_logical_unit *lu = sdev->hostdata; @@ -1653,17 +1643,12 @@ MODULE_ALIAS("sbp2"); static int __init sbp2_init(void) { - sbp2_wq = create_singlethread_workqueue(KBUILD_MODNAME); - if (!sbp2_wq) - return -ENOMEM; - return driver_register(&sbp2_driver.driver); } static void __exit sbp2_cleanup(void) { driver_unregister(&sbp2_driver.driver); - destroy_workqueue(sbp2_wq); } module_init(sbp2_init); diff --git a/drivers/media/dvb/firewire/firedtv-avc.c b/drivers/media/dvb/firewire/firedtv-avc.c index fc5ccd8c923a..21c52e3b522e 100644 --- a/drivers/media/dvb/firewire/firedtv-avc.c +++ b/drivers/media/dvb/firewire/firedtv-avc.c @@ -1320,14 +1320,10 @@ static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data) { int ret; - mutex_lock(&fdtv->avc_mutex); - ret = fdtv_read(fdtv, addr, data); if (ret < 0) dev_err(fdtv->device, "CMP: read I/O error\n"); - mutex_unlock(&fdtv->avc_mutex); - return ret; } @@ -1335,18 +1331,9 @@ static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[]) { int ret; - mutex_lock(&fdtv->avc_mutex); - - /* data[] is stack-allocated and should not be DMA-mapped. */ - memcpy(fdtv->avc_data, data, 8); - - ret = fdtv_lock(fdtv, addr, fdtv->avc_data); + ret = fdtv_lock(fdtv, addr, data); if (ret < 0) dev_err(fdtv->device, "CMP: lock I/O error\n"); - else - memcpy(data, fdtv->avc_data, 8); - - mutex_unlock(&fdtv->avc_mutex); return ret; } diff --git a/drivers/media/dvb/firewire/firedtv-fw.c b/drivers/media/dvb/firewire/firedtv-fw.c index 8022b743af91..864b6274c729 100644 --- a/drivers/media/dvb/firewire/firedtv-fw.c +++ b/drivers/media/dvb/firewire/firedtv-fw.c @@ -125,6 +125,7 @@ static void handle_iso(struct fw_iso_context *context, u32 cycle, i = (i + 1) & (N_PACKETS - 1); } + fw_iso_context_queue_flush(ctx->context); ctx->current_packet = i; } diff --git a/include/linux/firewire.h b/include/linux/firewire.h index c64f3680d4f1..5e6f42789afe 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -125,7 +125,6 @@ struct fw_card { struct delayed_work bm_work; /* bus manager job */ int bm_retries; int bm_generation; - __be32 bm_transaction_data[2]; int bm_node_id; bool bm_abdicate; @@ -441,12 +440,15 @@ int fw_iso_context_queue(struct fw_iso_context *ctx, struct fw_iso_packet *packet, struct fw_iso_buffer *buffer, unsigned long payload); +void fw_iso_context_queue_flush(struct fw_iso_context *ctx); int fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags); int fw_iso_context_stop(struct fw_iso_context *ctx); void fw_iso_context_destroy(struct fw_iso_context *ctx); void fw_iso_resource_manage(struct fw_card *card, int generation, u64 channels_mask, int *channel, int *bandwidth, - bool allocate, __be32 buffer[2]); + bool allocate); + +extern struct workqueue_struct *fw_workqueue; #endif /* _LINUX_FIREWIRE_H */ diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c index b18140ff2b93..87657dd7714c 100644 --- a/sound/firewire/amdtp.c +++ b/sound/firewire/amdtp.c @@ -396,6 +396,7 @@ static void out_packet_callback(struct fw_iso_context *context, u32 cycle, for (i = 0; i < packets; ++i) queue_out_packet(s, ++cycle); + fw_iso_context_queue_flush(s->context); } static int queue_initial_skip_packets(struct amdtp_out_stream *s) diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c index 4a37f3a6fab9..14cacbc655dd 100644 --- a/sound/firewire/cmp.c +++ b/sound/firewire/cmp.c @@ -49,10 +49,9 @@ static int pcr_modify(struct cmp_connection *c, enum bus_reset_handling bus_reset_handling) { struct fw_device *device = fw_parent_device(c->resources.unit); - __be32 *buffer = c->resources.buffer; int generation = c->resources.generation; int rcode, errors = 0; - __be32 old_arg; + __be32 old_arg, buffer[2]; int err; buffer[0] = c->last_pcr_value; diff --git a/sound/firewire/iso-resources.c b/sound/firewire/iso-resources.c index 775dbd5f3445..bb9c0c1fb529 100644 --- a/sound/firewire/iso-resources.c +++ b/sound/firewire/iso-resources.c @@ -11,7 +11,6 @@ #include <linux/jiffies.h> #include <linux/mutex.h> #include <linux/sched.h> -#include <linux/slab.h> #include <linux/spinlock.h> #include "iso-resources.h" @@ -25,10 +24,6 @@ */ int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit) { - r->buffer = kmalloc(2 * 4, GFP_KERNEL); - if (!r->buffer) - return -ENOMEM; - r->channels_mask = ~0uLL; r->unit = fw_unit_get(unit); mutex_init(&r->mutex); @@ -44,7 +39,6 @@ int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit) void fw_iso_resources_destroy(struct fw_iso_resources *r) { WARN_ON(r->allocated); - kfree(r->buffer); mutex_destroy(&r->mutex); fw_unit_put(r->unit); } @@ -131,7 +125,7 @@ retry_after_bus_reset: bandwidth = r->bandwidth + r->bandwidth_overhead; fw_iso_resource_manage(card, r->generation, r->channels_mask, - &channel, &bandwidth, true, r->buffer); + &channel, &bandwidth, true); if (channel == -EAGAIN) { mutex_unlock(&r->mutex); goto retry_after_bus_reset; @@ -184,7 +178,7 @@ int fw_iso_resources_update(struct fw_iso_resources *r) bandwidth = r->bandwidth + r->bandwidth_overhead; fw_iso_resource_manage(card, r->generation, 1uLL << r->channel, - &channel, &bandwidth, true, r->buffer); + &channel, &bandwidth, true); /* * When another bus reset happens, pretend that the allocation * succeeded; we will try again for the new generation later. @@ -220,7 +214,7 @@ void fw_iso_resources_free(struct fw_iso_resources *r) if (r->allocated) { bandwidth = r->bandwidth + r->bandwidth_overhead; fw_iso_resource_manage(card, r->generation, 1uLL << r->channel, - &channel, &bandwidth, false, r->buffer); + &channel, &bandwidth, false); if (channel < 0) dev_err(&r->unit->device, "isochronous resource deallocation failed\n"); diff --git a/sound/firewire/iso-resources.h b/sound/firewire/iso-resources.h index 3f0730e4d841..5a9af7c61657 100644 --- a/sound/firewire/iso-resources.h +++ b/sound/firewire/iso-resources.h @@ -24,7 +24,6 @@ struct fw_iso_resources { unsigned int bandwidth_overhead; int generation; /* in which allocation is valid */ bool allocated; - __be32 *buffer; }; int fw_iso_resources_init(struct fw_iso_resources *r, |