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
This commit is contained in:
commit
dcb4a1f0e0
@ -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. */
|
/* Use an arbitrary short delay to combine multiple reset requests. */
|
||||||
fw_card_get(card);
|
fw_card_get(card);
|
||||||
if (!schedule_delayed_work(&card->br_work,
|
if (!queue_delayed_work(fw_workqueue, &card->br_work,
|
||||||
delayed ? DIV_ROUND_UP(HZ, 100) : 0))
|
delayed ? DIV_ROUND_UP(HZ, 100) : 0))
|
||||||
fw_card_put(card);
|
fw_card_put(card);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(fw_schedule_bus_reset);
|
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. */
|
/* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */
|
||||||
if (card->reset_jiffies != 0 &&
|
if (card->reset_jiffies != 0 &&
|
||||||
time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) {
|
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);
|
fw_card_put(card);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -258,8 +258,7 @@ static void allocate_broadcast_channel(struct fw_card *card, int generation)
|
|||||||
|
|
||||||
if (!card->broadcast_channel_allocated) {
|
if (!card->broadcast_channel_allocated) {
|
||||||
fw_iso_resource_manage(card, generation, 1ULL << 31,
|
fw_iso_resource_manage(card, generation, 1ULL << 31,
|
||||||
&channel, &bandwidth, true,
|
&channel, &bandwidth, true);
|
||||||
card->bm_transaction_data);
|
|
||||||
if (channel != 31) {
|
if (channel != 31) {
|
||||||
fw_notify("failed to allocate broadcast channel\n");
|
fw_notify("failed to allocate broadcast channel\n");
|
||||||
return;
|
return;
|
||||||
@ -294,6 +293,7 @@ static void bm_work(struct work_struct *work)
|
|||||||
bool root_device_is_cmc;
|
bool root_device_is_cmc;
|
||||||
bool irm_is_1394_1995_only;
|
bool irm_is_1394_1995_only;
|
||||||
bool keep_this_irm;
|
bool keep_this_irm;
|
||||||
|
__be32 transaction_data[2];
|
||||||
|
|
||||||
spin_lock_irq(&card->lock);
|
spin_lock_irq(&card->lock);
|
||||||
|
|
||||||
@ -355,21 +355,21 @@ static void bm_work(struct work_struct *work)
|
|||||||
goto pick_me;
|
goto pick_me;
|
||||||
}
|
}
|
||||||
|
|
||||||
card->bm_transaction_data[0] = cpu_to_be32(0x3f);
|
transaction_data[0] = cpu_to_be32(0x3f);
|
||||||
card->bm_transaction_data[1] = cpu_to_be32(local_id);
|
transaction_data[1] = cpu_to_be32(local_id);
|
||||||
|
|
||||||
spin_unlock_irq(&card->lock);
|
spin_unlock_irq(&card->lock);
|
||||||
|
|
||||||
rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
|
rcode = fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
|
||||||
irm_id, generation, SCODE_100,
|
irm_id, generation, SCODE_100,
|
||||||
CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
|
CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
|
||||||
card->bm_transaction_data, 8);
|
transaction_data, 8);
|
||||||
|
|
||||||
if (rcode == RCODE_GENERATION)
|
if (rcode == RCODE_GENERATION)
|
||||||
/* Another bus reset, BM work has been rescheduled. */
|
/* Another bus reset, BM work has been rescheduled. */
|
||||||
goto out;
|
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);
|
spin_lock_irq(&card->lock);
|
||||||
if (rcode == RCODE_COMPLETE && generation == card->generation)
|
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.
|
* 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,
|
rcode = fw_run_transaction(card, TCODE_WRITE_QUADLET_REQUEST,
|
||||||
root_id, generation, SCODE_100,
|
root_id, generation, SCODE_100,
|
||||||
CSR_REGISTER_BASE + CSR_STATE_SET,
|
CSR_REGISTER_BASE + CSR_STATE_SET,
|
||||||
card->bm_transaction_data, 4);
|
transaction_data, 4);
|
||||||
if (rcode == RCODE_GENERATION)
|
if (rcode == RCODE_GENERATION)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -630,6 +630,10 @@ static int dummy_queue_iso(struct fw_iso_context *ctx, struct fw_iso_packet *p,
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dummy_flush_queue_iso(struct fw_iso_context *ctx)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static const struct fw_card_driver dummy_driver_template = {
|
static const struct fw_card_driver dummy_driver_template = {
|
||||||
.read_phy_reg = dummy_read_phy_reg,
|
.read_phy_reg = dummy_read_phy_reg,
|
||||||
.update_phy_reg = dummy_update_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,
|
.start_iso = dummy_start_iso,
|
||||||
.set_iso_channels = dummy_set_iso_channels,
|
.set_iso_channels = dummy_set_iso_channels,
|
||||||
.queue_iso = dummy_queue_iso,
|
.queue_iso = dummy_queue_iso,
|
||||||
|
.flush_queue_iso = dummy_flush_queue_iso,
|
||||||
};
|
};
|
||||||
|
|
||||||
void fw_card_release(struct kref *kref)
|
void fw_card_release(struct kref *kref)
|
||||||
|
@ -141,7 +141,6 @@ struct iso_resource {
|
|||||||
int generation;
|
int generation;
|
||||||
u64 channels;
|
u64 channels;
|
||||||
s32 bandwidth;
|
s32 bandwidth;
|
||||||
__be32 transaction_data[2];
|
|
||||||
struct iso_resource_event *e_alloc, *e_dealloc;
|
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)
|
static void schedule_iso_resource(struct iso_resource *r, unsigned long delay)
|
||||||
{
|
{
|
||||||
client_get(r->client);
|
client_get(r->client);
|
||||||
if (!schedule_delayed_work(&r->work, delay))
|
if (!queue_delayed_work(fw_workqueue, &r->work, delay))
|
||||||
client_put(r->client);
|
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;
|
payload += u.packet.payload_length;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
fw_iso_context_queue_flush(ctx);
|
||||||
|
|
||||||
a->size -= uptr_to_u64(p) - a->packets;
|
a->size -= uptr_to_u64(p) - a->packets;
|
||||||
a->packets = uptr_to_u64(p);
|
a->packets = uptr_to_u64(p);
|
||||||
@ -1229,8 +1229,7 @@ static void iso_resource_work(struct work_struct *work)
|
|||||||
r->channels, &channel, &bandwidth,
|
r->channels, &channel, &bandwidth,
|
||||||
todo == ISO_RES_ALLOC ||
|
todo == ISO_RES_ALLOC ||
|
||||||
todo == ISO_RES_REALLOC ||
|
todo == ISO_RES_REALLOC ||
|
||||||
todo == ISO_RES_ALLOC_ONCE,
|
todo == ISO_RES_ALLOC_ONCE);
|
||||||
r->transaction_data);
|
|
||||||
/*
|
/*
|
||||||
* Is this generation outdated already? As long as this resource sticks
|
* 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
|
* in the idr, it will be scheduled again for a newer generation or at
|
||||||
|
@ -725,6 +725,15 @@ struct fw_device *fw_device_get_by_devt(dev_t devt)
|
|||||||
return device;
|
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
|
* These defines control the retry behavior for reading the config
|
||||||
* rom. It shouldn't be necessary to tweak these; if the device
|
* 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(),
|
if (time_before64(get_jiffies_64(),
|
||||||
device->card->reset_jiffies + SHUTDOWN_DELAY)
|
device->card->reset_jiffies + SHUTDOWN_DELAY)
|
||||||
&& !list_empty(&device->card->link)) {
|
&& !list_empty(&device->card->link)) {
|
||||||
schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
|
fw_schedule_device_work(device, SHUTDOWN_DELAY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -862,7 +871,7 @@ static int lookup_existing_device(struct device *dev, void *data)
|
|||||||
fw_notify("rediscovered device %s\n", dev_name(dev));
|
fw_notify("rediscovered device %s\n", dev_name(dev));
|
||||||
|
|
||||||
PREPARE_DELAYED_WORK(&old->work, fw_device_update);
|
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)
|
if (current_node == card->root_node)
|
||||||
fw_schedule_bm_work(card, 0);
|
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 &&
|
if (device->config_rom_retries < MAX_RETRIES &&
|
||||||
atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
|
atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
|
||||||
device->config_rom_retries++;
|
device->config_rom_retries++;
|
||||||
schedule_delayed_work(&device->work, RETRY_DELAY);
|
fw_schedule_device_work(device, RETRY_DELAY);
|
||||||
} else {
|
} else {
|
||||||
if (device->node->link_on)
|
if (device->node->link_on)
|
||||||
fw_notify("giving up on config rom for node id %x\n",
|
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_INITIALIZING,
|
||||||
FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
|
FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
|
||||||
PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
|
PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
|
||||||
schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
|
fw_schedule_device_work(device, SHUTDOWN_DELAY);
|
||||||
} else {
|
} else {
|
||||||
if (device->config_rom_retries)
|
if (device->config_rom_retries)
|
||||||
fw_notify("created device %s: GUID %08x%08x, S%d00, "
|
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 &&
|
if (device->config_rom_retries < MAX_RETRIES / 2 &&
|
||||||
atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
|
atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
|
||||||
device->config_rom_retries++;
|
device->config_rom_retries++;
|
||||||
schedule_delayed_work(&device->work, RETRY_DELAY / 2);
|
fw_schedule_device_work(device, RETRY_DELAY / 2);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1131,7 +1140,7 @@ static void fw_device_refresh(struct work_struct *work)
|
|||||||
if (device->config_rom_retries < MAX_RETRIES &&
|
if (device->config_rom_retries < MAX_RETRIES &&
|
||||||
atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
|
atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
|
||||||
device->config_rom_retries++;
|
device->config_rom_retries++;
|
||||||
schedule_delayed_work(&device->work, RETRY_DELAY);
|
fw_schedule_device_work(device, RETRY_DELAY);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1158,7 +1167,7 @@ static void fw_device_refresh(struct work_struct *work)
|
|||||||
gone:
|
gone:
|
||||||
atomic_set(&device->state, FW_DEVICE_GONE);
|
atomic_set(&device->state, FW_DEVICE_GONE);
|
||||||
PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
|
PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
|
||||||
schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
|
fw_schedule_device_work(device, SHUTDOWN_DELAY);
|
||||||
out:
|
out:
|
||||||
if (node_id == card->root_node->node_id)
|
if (node_id == card->root_node->node_id)
|
||||||
fw_schedule_bm_work(card, 0);
|
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.
|
* first config rom scan half a second after bus reset.
|
||||||
*/
|
*/
|
||||||
INIT_DELAYED_WORK(&device->work, fw_device_init);
|
INIT_DELAYED_WORK(&device->work, fw_device_init);
|
||||||
schedule_delayed_work(&device->work, INITIAL_DELAY);
|
fw_schedule_device_work(device, INITIAL_DELAY);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FW_NODE_INITIATED_RESET:
|
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_RUNNING,
|
||||||
FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
|
FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
|
||||||
PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
|
PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
|
||||||
schedule_delayed_work(&device->work,
|
fw_schedule_device_work(device,
|
||||||
device->is_local ? 0 : INITIAL_DELAY);
|
device->is_local ? 0 : INITIAL_DELAY);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1245,7 +1254,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
|
|||||||
device->generation = card->generation;
|
device->generation = card->generation;
|
||||||
if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
|
if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
|
||||||
PREPARE_DELAYED_WORK(&device->work, fw_device_update);
|
PREPARE_DELAYED_WORK(&device->work, fw_device_update);
|
||||||
schedule_delayed_work(&device->work, 0);
|
fw_schedule_device_work(device, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1270,7 +1279,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
|
|||||||
if (atomic_xchg(&device->state,
|
if (atomic_xchg(&device->state,
|
||||||
FW_DEVICE_GONE) == FW_DEVICE_RUNNING) {
|
FW_DEVICE_GONE) == FW_DEVICE_RUNNING) {
|
||||||
PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
|
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);
|
list_empty(&card->link) ? 0 : SHUTDOWN_DELAY);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -185,6 +185,12 @@ int fw_iso_context_queue(struct fw_iso_context *ctx,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(fw_iso_context_queue);
|
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)
|
int fw_iso_context_stop(struct fw_iso_context *ctx)
|
||||||
{
|
{
|
||||||
return ctx->card->driver->stop_iso(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,
|
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;
|
int try, new, old = allocate ? BANDWIDTH_AVAILABLE_INITIAL : 0;
|
||||||
|
__be32 data[2];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On a 1394a IRM with low contention, try < 1 is enough.
|
* 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,
|
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 bit, all, old;
|
||||||
|
__be32 data[2];
|
||||||
int channel, ret = -EIO, retry = 5;
|
int channel, ret = -EIO, retry = 5;
|
||||||
|
|
||||||
old = all = allocate ? cpu_to_be32(~0) : 0;
|
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,
|
static void deallocate_channel(struct fw_card *card, int irm_id,
|
||||||
int generation, int channel, __be32 buffer[2])
|
int generation, int channel)
|
||||||
{
|
{
|
||||||
u32 mask;
|
u32 mask;
|
||||||
u64 offset;
|
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 :
|
offset = channel < 32 ? CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI :
|
||||||
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO;
|
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,
|
void fw_iso_resource_manage(struct fw_card *card, int generation,
|
||||||
u64 channels_mask, int *channel, int *bandwidth,
|
u64 channels_mask, int *channel, int *bandwidth,
|
||||||
bool allocate, __be32 buffer[2])
|
bool allocate)
|
||||||
{
|
{
|
||||||
u32 channels_hi = channels_mask; /* channels 31...0 */
|
u32 channels_hi = channels_mask; /* channels 31...0 */
|
||||||
u32 channels_lo = channels_mask >> 32; /* channels 63...32 */
|
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)
|
if (channels_hi)
|
||||||
c = manage_channel(card, irm_id, generation, channels_hi,
|
c = manage_channel(card, irm_id, generation, channels_hi,
|
||||||
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI,
|
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_HI,
|
||||||
allocate, buffer);
|
allocate);
|
||||||
if (channels_lo && c < 0) {
|
if (channels_lo && c < 0) {
|
||||||
c = manage_channel(card, irm_id, generation, channels_lo,
|
c = manage_channel(card, irm_id, generation, channels_lo,
|
||||||
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO,
|
CSR_REGISTER_BASE + CSR_CHANNELS_AVAILABLE_LO,
|
||||||
allocate, buffer);
|
allocate);
|
||||||
if (c >= 0)
|
if (c >= 0)
|
||||||
c += 32;
|
c += 32;
|
||||||
}
|
}
|
||||||
@ -351,14 +359,13 @@ void fw_iso_resource_manage(struct fw_card *card, int generation,
|
|||||||
if (*bandwidth == 0)
|
if (*bandwidth == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = manage_bandwidth(card, irm_id, generation, *bandwidth,
|
ret = manage_bandwidth(card, irm_id, generation, *bandwidth, allocate);
|
||||||
allocate, buffer);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
*bandwidth = 0;
|
*bandwidth = 0;
|
||||||
|
|
||||||
if (allocate && ret < 0) {
|
if (allocate && ret < 0) {
|
||||||
if (c >= 0)
|
if (c >= 0)
|
||||||
deallocate_channel(card, irm_id, generation, c, buffer);
|
deallocate_channel(card, irm_id, generation, c);
|
||||||
*channel = ret;
|
*channel = ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
#include <asm/byteorder.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.
|
* 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
|
* 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
|
* @length <= 8 or of local (loopback) requests. Hence make sure that the
|
||||||
* the buffer complies with the restrictions for DMA-mapped memory. The
|
* buffer complies with the restrictions of the streaming DMA mapping API.
|
||||||
* @payload must not be freed before the @callback is called.
|
* @payload must not be freed before the @callback is called.
|
||||||
*
|
*
|
||||||
* In case of request types without payload, @data is NULL and @length is 0.
|
* 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.
|
* Returns the RCODE. See fw_send_request() for parameter documentation.
|
||||||
* Unlike fw_send_request(), @data points to the payload of the request or/and
|
* 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 fw_run_transaction(struct fw_card *card, int tcode, int destination_id,
|
||||||
int generation, int speed, unsigned long long offset,
|
int generation, int speed, unsigned long long offset,
|
||||||
@ -1212,13 +1214,21 @@ static int __init fw_core_init(void)
|
|||||||
{
|
{
|
||||||
int ret;
|
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);
|
ret = bus_register(&fw_bus_type);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
destroy_workqueue(fw_workqueue);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops);
|
fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops);
|
||||||
if (fw_cdev_major < 0) {
|
if (fw_cdev_major < 0) {
|
||||||
bus_unregister(&fw_bus_type);
|
bus_unregister(&fw_bus_type);
|
||||||
|
destroy_workqueue(fw_workqueue);
|
||||||
return fw_cdev_major;
|
return fw_cdev_major;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1234,6 +1244,7 @@ static void __exit fw_core_cleanup(void)
|
|||||||
{
|
{
|
||||||
unregister_chrdev(fw_cdev_major, "firewire");
|
unregister_chrdev(fw_cdev_major, "firewire");
|
||||||
bus_unregister(&fw_bus_type);
|
bus_unregister(&fw_bus_type);
|
||||||
|
destroy_workqueue(fw_workqueue);
|
||||||
idr_destroy(&fw_device_idr);
|
idr_destroy(&fw_device_idr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +97,8 @@ struct fw_card_driver {
|
|||||||
struct fw_iso_buffer *buffer,
|
struct fw_iso_buffer *buffer,
|
||||||
unsigned long payload);
|
unsigned long payload);
|
||||||
|
|
||||||
|
void (*flush_queue_iso)(struct fw_iso_context *ctx);
|
||||||
|
|
||||||
int (*stop_iso)(struct fw_iso_context *ctx);
|
int (*stop_iso)(struct fw_iso_context *ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -881,7 +881,9 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
|
|||||||
|
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
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");
|
fw_error("requeue failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1006,13 +1006,12 @@ static void ar_context_run(struct ar_context *ctx)
|
|||||||
|
|
||||||
static struct descriptor *find_branch_descriptor(struct descriptor *d, int z)
|
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;
|
branch = d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS);
|
||||||
key = (le16_to_cpu(d->control) & DESCRIPTOR_KEY_IMMEDIATE) >> 8;
|
|
||||||
|
|
||||||
/* figure out which descriptor the branch address goes in */
|
/* 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;
|
return d;
|
||||||
else
|
else
|
||||||
return d + z - 1;
|
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 */
|
wmb(); /* finish init of new descriptors before branch_address update */
|
||||||
ctx->prev->branch_address = cpu_to_le32(d_bus | z);
|
ctx->prev->branch_address = cpu_to_le32(d_bus | z);
|
||||||
ctx->prev = find_branch_descriptor(d, 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)
|
static void context_stop(struct context *ctx)
|
||||||
@ -1218,6 +1214,7 @@ static void context_stop(struct context *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct driver_data {
|
struct driver_data {
|
||||||
|
u8 inline_data[8];
|
||||||
struct fw_packet *packet;
|
struct fw_packet *packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1301,20 +1298,28 @@ static int at_context_queue_packet(struct context *ctx,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BUILD_BUG_ON(sizeof(struct driver_data) > sizeof(struct descriptor));
|
||||||
driver_data = (struct driver_data *) &d[3];
|
driver_data = (struct driver_data *) &d[3];
|
||||||
driver_data->packet = packet;
|
driver_data->packet = packet;
|
||||||
packet->driver_data = driver_data;
|
packet->driver_data = driver_data;
|
||||||
|
|
||||||
if (packet->payload_length > 0) {
|
if (packet->payload_length > 0) {
|
||||||
payload_bus =
|
if (packet->payload_length > sizeof(driver_data->inline_data)) {
|
||||||
dma_map_single(ohci->card.device, packet->payload,
|
payload_bus = dma_map_single(ohci->card.device,
|
||||||
packet->payload_length, DMA_TO_DEVICE);
|
packet->payload,
|
||||||
if (dma_mapping_error(ohci->card.device, payload_bus)) {
|
packet->payload_length,
|
||||||
packet->ack = RCODE_SEND_ERROR;
|
DMA_TO_DEVICE);
|
||||||
return -1;
|
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].req_count = cpu_to_le16(packet->payload_length);
|
||||||
d[2].data_address = cpu_to_le32(payload_bus);
|
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);
|
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);
|
context_run(ctx, 0);
|
||||||
|
}
|
||||||
|
|
||||||
return 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_SelfIDBuffer, ohci->self_id_bus);
|
||||||
reg_write(ohci, OHCI1394_LinkControlSet,
|
reg_write(ohci, OHCI1394_LinkControlSet,
|
||||||
OHCI1394_LinkControl_rcvSelfID |
|
|
||||||
OHCI1394_LinkControl_rcvPhyPkt |
|
|
||||||
OHCI1394_LinkControl_cycleTimerEnable |
|
OHCI1394_LinkControl_cycleTimerEnable |
|
||||||
OHCI1394_LinkControl_cycleMaster);
|
OHCI1394_LinkControl_cycleMaster);
|
||||||
|
|
||||||
@ -2094,9 +2101,6 @@ static int ohci_enable(struct fw_card *card,
|
|||||||
reg_write(ohci, OHCI1394_FairnessControl, 0);
|
reg_write(ohci, OHCI1394_FairnessControl, 0);
|
||||||
card->priority_budget_implemented = ohci->pri_req_max != 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_PhyUpperBound, 0x00010000);
|
||||||
reg_write(ohci, OHCI1394_IntEventClear, ~0);
|
reg_write(ohci, OHCI1394_IntEventClear, ~0);
|
||||||
reg_write(ohci, OHCI1394_IntMaskClear, ~0);
|
reg_write(ohci, OHCI1394_IntMaskClear, ~0);
|
||||||
@ -2186,7 +2190,13 @@ static int ohci_enable(struct fw_card *card,
|
|||||||
reg_write(ohci, OHCI1394_HCControlSet,
|
reg_write(ohci, OHCI1394_HCControlSet,
|
||||||
OHCI1394_HCControl_linkEnable |
|
OHCI1394_HCControl_linkEnable |
|
||||||
OHCI1394_HCControl_BIBimageValid);
|
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. */
|
/* We are ready to go, reset bus to finish initialization. */
|
||||||
fw_schedule_bus_reset(&ohci->card, false, true);
|
fw_schedule_bus_reset(&ohci->card, false, true);
|
||||||
@ -3112,6 +3122,15 @@ static int ohci_queue_iso(struct fw_iso_context *base,
|
|||||||
return ret;
|
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 = {
|
static const struct fw_card_driver ohci_driver = {
|
||||||
.enable = ohci_enable,
|
.enable = ohci_enable,
|
||||||
.read_phy_reg = ohci_read_phy_reg,
|
.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,
|
.free_iso_context = ohci_free_iso_context,
|
||||||
.set_iso_channels = ohci_set_iso_channels,
|
.set_iso_channels = ohci_set_iso_channels,
|
||||||
.queue_iso = ohci_queue_iso,
|
.queue_iso = ohci_queue_iso,
|
||||||
|
.flush_queue_iso = ohci_flush_queue_iso,
|
||||||
.start_iso = ohci_start_iso,
|
.start_iso = ohci_start_iso,
|
||||||
.stop_iso = ohci_stop_iso,
|
.stop_iso = ohci_stop_iso,
|
||||||
};
|
};
|
||||||
|
@ -125,9 +125,6 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
|
|||||||
", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
|
", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
|
||||||
", or a combination)");
|
", 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";
|
static const char sbp2_driver_name[] = "sbp2";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -261,7 +258,6 @@ struct sbp2_orb {
|
|||||||
struct kref kref;
|
struct kref kref;
|
||||||
dma_addr_t request_bus;
|
dma_addr_t request_bus;
|
||||||
int rcode;
|
int rcode;
|
||||||
struct sbp2_pointer pointer;
|
|
||||||
void (*callback)(struct sbp2_orb * orb, struct sbp2_status * status);
|
void (*callback)(struct sbp2_orb * orb, struct sbp2_status * status);
|
||||||
struct list_head link;
|
struct list_head link;
|
||||||
};
|
};
|
||||||
@ -314,7 +310,6 @@ struct sbp2_command_orb {
|
|||||||
u8 command_block[SBP2_MAX_CDB_SIZE];
|
u8 command_block[SBP2_MAX_CDB_SIZE];
|
||||||
} request;
|
} request;
|
||||||
struct scsi_cmnd *cmd;
|
struct scsi_cmnd *cmd;
|
||||||
scsi_done_fn_t done;
|
|
||||||
struct sbp2_logical_unit *lu;
|
struct sbp2_logical_unit *lu;
|
||||||
|
|
||||||
struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8)));
|
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)
|
int node_id, int generation, u64 offset)
|
||||||
{
|
{
|
||||||
struct fw_device *device = target_device(lu->tgt);
|
struct fw_device *device = target_device(lu->tgt);
|
||||||
|
struct sbp2_pointer orb_pointer;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
orb->pointer.high = 0;
|
orb_pointer.high = 0;
|
||||||
orb->pointer.low = cpu_to_be32(orb->request_bus);
|
orb_pointer.low = cpu_to_be32(orb->request_bus);
|
||||||
|
|
||||||
spin_lock_irqsave(&device->card->lock, flags);
|
spin_lock_irqsave(&device->card->lock, flags);
|
||||||
list_add_tail(&orb->link, &lu->orb_list);
|
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,
|
fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
|
||||||
node_id, generation, device->max_speed, offset,
|
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)
|
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);
|
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.
|
* 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.
|
* 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)
|
static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
|
||||||
{
|
{
|
||||||
sbp2_target_get(lu->tgt);
|
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);
|
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);
|
sbp2_unmap_scatterlist(device->card->device, orb);
|
||||||
|
|
||||||
orb->cmd->result = result;
|
orb->cmd->result = result;
|
||||||
orb->done(orb->cmd);
|
orb->cmd->scsi_done(orb->cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sbp2_map_scatterlist(struct sbp2_command_orb *orb,
|
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 */
|
/* 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 sbp2_logical_unit *lu = cmd->device->hostdata;
|
||||||
struct fw_device *device = target_device(lu->tgt);
|
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) {
|
if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
|
||||||
fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
|
fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
|
||||||
cmd->result = DID_ERROR << 16;
|
cmd->result = DID_ERROR << 16;
|
||||||
done(cmd);
|
cmd->scsi_done(cmd);
|
||||||
return 0;
|
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. */
|
/* Initialize rcode to something not RCODE_COMPLETE. */
|
||||||
orb->base.rcode = -1;
|
orb->base.rcode = -1;
|
||||||
kref_init(&orb->base.kref);
|
kref_init(&orb->base.kref);
|
||||||
|
orb->lu = lu;
|
||||||
orb->lu = lu;
|
orb->cmd = cmd;
|
||||||
orb->done = done;
|
|
||||||
orb->cmd = cmd;
|
|
||||||
|
|
||||||
orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL);
|
orb->request.next.high = cpu_to_be32(SBP2_ORB_NULL);
|
||||||
orb->request.misc = cpu_to_be32(
|
orb->request.misc = cpu_to_be32(
|
||||||
COMMAND_ORB_MAX_PAYLOAD(lu->tgt->max_payload) |
|
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;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEF_SCSI_QCMD(sbp2_scsi_queuecommand)
|
|
||||||
|
|
||||||
static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
|
static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
|
||||||
{
|
{
|
||||||
struct sbp2_logical_unit *lu = sdev->hostdata;
|
struct sbp2_logical_unit *lu = sdev->hostdata;
|
||||||
@ -1653,17 +1643,12 @@ MODULE_ALIAS("sbp2");
|
|||||||
|
|
||||||
static int __init sbp2_init(void)
|
static int __init sbp2_init(void)
|
||||||
{
|
{
|
||||||
sbp2_wq = create_singlethread_workqueue(KBUILD_MODNAME);
|
|
||||||
if (!sbp2_wq)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
return driver_register(&sbp2_driver.driver);
|
return driver_register(&sbp2_driver.driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit sbp2_cleanup(void)
|
static void __exit sbp2_cleanup(void)
|
||||||
{
|
{
|
||||||
driver_unregister(&sbp2_driver.driver);
|
driver_unregister(&sbp2_driver.driver);
|
||||||
destroy_workqueue(sbp2_wq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(sbp2_init);
|
module_init(sbp2_init);
|
||||||
|
@ -1320,14 +1320,10 @@ static int cmp_read(struct firedtv *fdtv, u64 addr, __be32 *data)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&fdtv->avc_mutex);
|
|
||||||
|
|
||||||
ret = fdtv_read(fdtv, addr, data);
|
ret = fdtv_read(fdtv, addr, data);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(fdtv->device, "CMP: read I/O error\n");
|
dev_err(fdtv->device, "CMP: read I/O error\n");
|
||||||
|
|
||||||
mutex_unlock(&fdtv->avc_mutex);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1335,18 +1331,9 @@ static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&fdtv->avc_mutex);
|
ret = fdtv_lock(fdtv, addr, data);
|
||||||
|
|
||||||
/* data[] is stack-allocated and should not be DMA-mapped. */
|
|
||||||
memcpy(fdtv->avc_data, data, 8);
|
|
||||||
|
|
||||||
ret = fdtv_lock(fdtv, addr, fdtv->avc_data);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(fdtv->device, "CMP: lock I/O error\n");
|
dev_err(fdtv->device, "CMP: lock I/O error\n");
|
||||||
else
|
|
||||||
memcpy(data, fdtv->avc_data, 8);
|
|
||||||
|
|
||||||
mutex_unlock(&fdtv->avc_mutex);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,7 @@ static void handle_iso(struct fw_iso_context *context, u32 cycle,
|
|||||||
|
|
||||||
i = (i + 1) & (N_PACKETS - 1);
|
i = (i + 1) & (N_PACKETS - 1);
|
||||||
}
|
}
|
||||||
|
fw_iso_context_queue_flush(ctx->context);
|
||||||
ctx->current_packet = i;
|
ctx->current_packet = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,6 @@ struct fw_card {
|
|||||||
struct delayed_work bm_work; /* bus manager job */
|
struct delayed_work bm_work; /* bus manager job */
|
||||||
int bm_retries;
|
int bm_retries;
|
||||||
int bm_generation;
|
int bm_generation;
|
||||||
__be32 bm_transaction_data[2];
|
|
||||||
int bm_node_id;
|
int bm_node_id;
|
||||||
bool bm_abdicate;
|
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_packet *packet,
|
||||||
struct fw_iso_buffer *buffer,
|
struct fw_iso_buffer *buffer,
|
||||||
unsigned long payload);
|
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 fw_iso_context_start(struct fw_iso_context *ctx,
|
||||||
int cycle, int sync, int tags);
|
int cycle, int sync, int tags);
|
||||||
int fw_iso_context_stop(struct fw_iso_context *ctx);
|
int fw_iso_context_stop(struct fw_iso_context *ctx);
|
||||||
void fw_iso_context_destroy(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,
|
void fw_iso_resource_manage(struct fw_card *card, int generation,
|
||||||
u64 channels_mask, int *channel, int *bandwidth,
|
u64 channels_mask, int *channel, int *bandwidth,
|
||||||
bool allocate, __be32 buffer[2]);
|
bool allocate);
|
||||||
|
|
||||||
|
extern struct workqueue_struct *fw_workqueue;
|
||||||
|
|
||||||
#endif /* _LINUX_FIREWIRE_H */
|
#endif /* _LINUX_FIREWIRE_H */
|
||||||
|
@ -396,6 +396,7 @@ static void out_packet_callback(struct fw_iso_context *context, u32 cycle,
|
|||||||
|
|
||||||
for (i = 0; i < packets; ++i)
|
for (i = 0; i < packets; ++i)
|
||||||
queue_out_packet(s, ++cycle);
|
queue_out_packet(s, ++cycle);
|
||||||
|
fw_iso_context_queue_flush(s->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int queue_initial_skip_packets(struct amdtp_out_stream *s)
|
static int queue_initial_skip_packets(struct amdtp_out_stream *s)
|
||||||
|
@ -49,10 +49,9 @@ static int pcr_modify(struct cmp_connection *c,
|
|||||||
enum bus_reset_handling bus_reset_handling)
|
enum bus_reset_handling bus_reset_handling)
|
||||||
{
|
{
|
||||||
struct fw_device *device = fw_parent_device(c->resources.unit);
|
struct fw_device *device = fw_parent_device(c->resources.unit);
|
||||||
__be32 *buffer = c->resources.buffer;
|
|
||||||
int generation = c->resources.generation;
|
int generation = c->resources.generation;
|
||||||
int rcode, errors = 0;
|
int rcode, errors = 0;
|
||||||
__be32 old_arg;
|
__be32 old_arg, buffer[2];
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
buffer[0] = c->last_pcr_value;
|
buffer[0] = c->last_pcr_value;
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include "iso-resources.h"
|
#include "iso-resources.h"
|
||||||
|
|
||||||
@ -25,10 +24,6 @@
|
|||||||
*/
|
*/
|
||||||
int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
|
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->channels_mask = ~0uLL;
|
||||||
r->unit = fw_unit_get(unit);
|
r->unit = fw_unit_get(unit);
|
||||||
mutex_init(&r->mutex);
|
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)
|
void fw_iso_resources_destroy(struct fw_iso_resources *r)
|
||||||
{
|
{
|
||||||
WARN_ON(r->allocated);
|
WARN_ON(r->allocated);
|
||||||
kfree(r->buffer);
|
|
||||||
mutex_destroy(&r->mutex);
|
mutex_destroy(&r->mutex);
|
||||||
fw_unit_put(r->unit);
|
fw_unit_put(r->unit);
|
||||||
}
|
}
|
||||||
@ -131,7 +125,7 @@ retry_after_bus_reset:
|
|||||||
|
|
||||||
bandwidth = r->bandwidth + r->bandwidth_overhead;
|
bandwidth = r->bandwidth + r->bandwidth_overhead;
|
||||||
fw_iso_resource_manage(card, r->generation, r->channels_mask,
|
fw_iso_resource_manage(card, r->generation, r->channels_mask,
|
||||||
&channel, &bandwidth, true, r->buffer);
|
&channel, &bandwidth, true);
|
||||||
if (channel == -EAGAIN) {
|
if (channel == -EAGAIN) {
|
||||||
mutex_unlock(&r->mutex);
|
mutex_unlock(&r->mutex);
|
||||||
goto retry_after_bus_reset;
|
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;
|
bandwidth = r->bandwidth + r->bandwidth_overhead;
|
||||||
|
|
||||||
fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
|
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
|
* When another bus reset happens, pretend that the allocation
|
||||||
* succeeded; we will try again for the new generation later.
|
* 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) {
|
if (r->allocated) {
|
||||||
bandwidth = r->bandwidth + r->bandwidth_overhead;
|
bandwidth = r->bandwidth + r->bandwidth_overhead;
|
||||||
fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
|
fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
|
||||||
&channel, &bandwidth, false, r->buffer);
|
&channel, &bandwidth, false);
|
||||||
if (channel < 0)
|
if (channel < 0)
|
||||||
dev_err(&r->unit->device,
|
dev_err(&r->unit->device,
|
||||||
"isochronous resource deallocation failed\n");
|
"isochronous resource deallocation failed\n");
|
||||||
|
@ -24,7 +24,6 @@ struct fw_iso_resources {
|
|||||||
unsigned int bandwidth_overhead;
|
unsigned int bandwidth_overhead;
|
||||||
int generation; /* in which allocation is valid */
|
int generation; /* in which allocation is valid */
|
||||||
bool allocated;
|
bool allocated;
|
||||||
__be32 *buffer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int fw_iso_resources_init(struct fw_iso_resources *r,
|
int fw_iso_resources_init(struct fw_iso_resources *r,
|
||||||
|
Loading…
Reference in New Issue
Block a user