Commit 2f78d8e2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'firewire-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394

Pull IEEE 1394 (FireWire) subsystem updates from Stefan Richter:

 - Fix mismatch between DMA mapping direction (was wrong) and DMA
   synchronization direction (was correct) of isochronous reception
   buffers of userspace drivers if vma-mapped for R/W access.  For
   example, libdc1394 was affected.

 - more consistent retry stategy in device discovery/ rediscovery, and
   improved failure diagnostics

 - various small cleanups, e.g. use SCSI layer's DMA mapping API in
   firewire-sbp2

* tag 'firewire-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394:
  firewire: sbp2: document the absence of alignment requirements
  firewire: sbp2: remove superfluous blk_queue_max_segment_size() call
  firewire: sbp2: use scsi_dma_(un)map
  firewire: sbp2: give correct DMA device to scsi framework
  firewire: core: fw_device_refresh(): clean up error handling
  firewire: core: log config rom reading errors
  firewire: core: log error in case of failed bus manager lock
  firewire: move rcode_string() to core
  firewire: core: improve reread_config_rom() interface
  firewire: core: wait for inaccessible devices after bus reset
  firewire: ohci: omit spinlock IRQ flags where possible
  firewire: ohci: correct signedness of a local variable
  firewire: core: fix DMA mapping direction
  firewire: use module_pci_driver
parents f2fde3a6 26c72e22
...@@ -421,8 +421,8 @@ static void bm_work(struct work_struct *work) ...@@ -421,8 +421,8 @@ static void bm_work(struct work_struct *work)
* root, and thus, IRM. * root, and thus, IRM.
*/ */
new_root_id = local_id; new_root_id = local_id;
fw_notice(card, "%s, making local node (%02x) root\n", fw_notice(card, "BM lock failed (%s), making local node (%02x) root\n",
"BM lock failed", new_root_id); fw_rcode_string(rcode), new_root_id);
goto pick_me; goto pick_me;
} }
} else if (card->bm_generation != generation) { } else if (card->bm_generation != generation) {
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/firewire.h> #include <linux/firewire.h>
#include <linux/firewire-cdev.h> #include <linux/firewire-cdev.h>
...@@ -70,6 +71,7 @@ struct client { ...@@ -70,6 +71,7 @@ struct client {
u64 iso_closure; u64 iso_closure;
struct fw_iso_buffer buffer; struct fw_iso_buffer buffer;
unsigned long vm_start; unsigned long vm_start;
bool buffer_is_mapped;
struct list_head phy_receiver_link; struct list_head phy_receiver_link;
u64 phy_receiver_closure; u64 phy_receiver_closure;
...@@ -959,11 +961,20 @@ static void iso_mc_callback(struct fw_iso_context *context, ...@@ -959,11 +961,20 @@ static void iso_mc_callback(struct fw_iso_context *context,
sizeof(e->interrupt), NULL, 0); sizeof(e->interrupt), NULL, 0);
} }
static enum dma_data_direction iso_dma_direction(struct fw_iso_context *context)
{
if (context->type == FW_ISO_CONTEXT_TRANSMIT)
return DMA_TO_DEVICE;
else
return DMA_FROM_DEVICE;
}
static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
{ {
struct fw_cdev_create_iso_context *a = &arg->create_iso_context; struct fw_cdev_create_iso_context *a = &arg->create_iso_context;
struct fw_iso_context *context; struct fw_iso_context *context;
fw_iso_callback_t cb; fw_iso_callback_t cb;
int ret;
BUILD_BUG_ON(FW_CDEV_ISO_CONTEXT_TRANSMIT != FW_ISO_CONTEXT_TRANSMIT || BUILD_BUG_ON(FW_CDEV_ISO_CONTEXT_TRANSMIT != FW_ISO_CONTEXT_TRANSMIT ||
FW_CDEV_ISO_CONTEXT_RECEIVE != FW_ISO_CONTEXT_RECEIVE || FW_CDEV_ISO_CONTEXT_RECEIVE != FW_ISO_CONTEXT_RECEIVE ||
...@@ -1004,8 +1015,21 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) ...@@ -1004,8 +1015,21 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
if (client->iso_context != NULL) { if (client->iso_context != NULL) {
spin_unlock_irq(&client->lock); spin_unlock_irq(&client->lock);
fw_iso_context_destroy(context); fw_iso_context_destroy(context);
return -EBUSY; return -EBUSY;
} }
if (!client->buffer_is_mapped) {
ret = fw_iso_buffer_map_dma(&client->buffer,
client->device->card,
iso_dma_direction(context));
if (ret < 0) {
spin_unlock_irq(&client->lock);
fw_iso_context_destroy(context);
return ret;
}
client->buffer_is_mapped = true;
}
client->iso_closure = a->closure; client->iso_closure = a->closure;
client->iso_context = context; client->iso_context = context;
spin_unlock_irq(&client->lock); spin_unlock_irq(&client->lock);
...@@ -1651,7 +1675,6 @@ static long fw_device_op_compat_ioctl(struct file *file, ...@@ -1651,7 +1675,6 @@ static long fw_device_op_compat_ioctl(struct file *file,
static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
{ {
struct client *client = file->private_data; struct client *client = file->private_data;
enum dma_data_direction direction;
unsigned long size; unsigned long size;
int page_count, ret; int page_count, ret;
...@@ -1674,20 +1697,28 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) ...@@ -1674,20 +1697,28 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
if (size & ~PAGE_MASK) if (size & ~PAGE_MASK)
return -EINVAL; return -EINVAL;
if (vma->vm_flags & VM_WRITE) ret = fw_iso_buffer_alloc(&client->buffer, page_count);
direction = DMA_TO_DEVICE;
else
direction = DMA_FROM_DEVICE;
ret = fw_iso_buffer_init(&client->buffer, client->device->card,
page_count, direction);
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = fw_iso_buffer_map(&client->buffer, vma); spin_lock_irq(&client->lock);
if (client->iso_context) {
ret = fw_iso_buffer_map_dma(&client->buffer,
client->device->card,
iso_dma_direction(client->iso_context));
client->buffer_is_mapped = (ret == 0);
}
spin_unlock_irq(&client->lock);
if (ret < 0) if (ret < 0)
fw_iso_buffer_destroy(&client->buffer, client->device->card); goto fail;
ret = fw_iso_buffer_map_vma(&client->buffer, vma);
if (ret < 0)
goto fail;
return 0;
fail:
fw_iso_buffer_destroy(&client->buffer, client->device->card);
return ret; return ret;
} }
......
...@@ -481,6 +481,7 @@ static int read_rom(struct fw_device *device, ...@@ -481,6 +481,7 @@ static int read_rom(struct fw_device *device,
* generation changes under us, read_config_rom will fail and get retried. * generation changes under us, read_config_rom will fail and get retried.
* It's better to start all over in this case because the node from which we * It's better to start all over in this case because the node from which we
* are reading the ROM may have changed the ROM during the reset. * are reading the ROM may have changed the ROM during the reset.
* Returns either a result code or a negative error code.
*/ */
static int read_config_rom(struct fw_device *device, int generation) static int read_config_rom(struct fw_device *device, int generation)
{ {
...@@ -488,7 +489,7 @@ static int read_config_rom(struct fw_device *device, int generation) ...@@ -488,7 +489,7 @@ static int read_config_rom(struct fw_device *device, int generation)
const u32 *old_rom, *new_rom; const u32 *old_rom, *new_rom;
u32 *rom, *stack; u32 *rom, *stack;
u32 sp, key; u32 sp, key;
int i, end, length, ret = -1; int i, end, length, ret;
rom = kmalloc(sizeof(*rom) * MAX_CONFIG_ROM_SIZE + rom = kmalloc(sizeof(*rom) * MAX_CONFIG_ROM_SIZE +
sizeof(*stack) * MAX_CONFIG_ROM_SIZE, GFP_KERNEL); sizeof(*stack) * MAX_CONFIG_ROM_SIZE, GFP_KERNEL);
...@@ -502,18 +503,21 @@ static int read_config_rom(struct fw_device *device, int generation) ...@@ -502,18 +503,21 @@ static int read_config_rom(struct fw_device *device, int generation)
/* First read the bus info block. */ /* First read the bus info block. */
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE) ret = read_rom(device, generation, i, &rom[i]);
if (ret != RCODE_COMPLETE)
goto out; goto out;
/* /*
* As per IEEE1212 7.2, during power-up, devices can * As per IEEE1212 7.2, during initialization, devices can
* reply with a 0 for the first quadlet of the config * reply with a 0 for the first quadlet of the config
* rom to indicate that they are booting (for example, * rom to indicate that they are booting (for example,
* if the firmware is on the disk of a external * if the firmware is on the disk of a external
* harddisk). In that case we just fail, and the * harddisk). In that case we just fail, and the
* retry mechanism will try again later. * retry mechanism will try again later.
*/ */
if (i == 0 && rom[i] == 0) if (i == 0 && rom[i] == 0) {
ret = RCODE_BUSY;
goto out; goto out;
}
} }
device->max_speed = device->node->max_speed; device->max_speed = device->node->max_speed;
...@@ -563,11 +567,14 @@ static int read_config_rom(struct fw_device *device, int generation) ...@@ -563,11 +567,14 @@ static int read_config_rom(struct fw_device *device, int generation)
*/ */
key = stack[--sp]; key = stack[--sp];
i = key & 0xffffff; i = key & 0xffffff;
if (WARN_ON(i >= MAX_CONFIG_ROM_SIZE)) if (WARN_ON(i >= MAX_CONFIG_ROM_SIZE)) {
ret = -ENXIO;
goto out; goto out;
}
/* Read header quadlet for the block to get the length. */ /* Read header quadlet for the block to get the length. */
if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE) ret = read_rom(device, generation, i, &rom[i]);
if (ret != RCODE_COMPLETE)
goto out; goto out;
end = i + (rom[i] >> 16) + 1; end = i + (rom[i] >> 16) + 1;
if (end > MAX_CONFIG_ROM_SIZE) { if (end > MAX_CONFIG_ROM_SIZE) {
...@@ -590,8 +597,8 @@ static int read_config_rom(struct fw_device *device, int generation) ...@@ -590,8 +597,8 @@ static int read_config_rom(struct fw_device *device, int generation)
* it references another block, and push it in that case. * it references another block, and push it in that case.
*/ */
for (; i < end; i++) { for (; i < end; i++) {
if (read_rom(device, generation, i, &rom[i]) != ret = read_rom(device, generation, i, &rom[i]);
RCODE_COMPLETE) if (ret != RCODE_COMPLETE)
goto out; goto out;
if ((key >> 30) != 3 || (rom[i] >> 30) < 2) if ((key >> 30) != 3 || (rom[i] >> 30) < 2)
...@@ -619,8 +626,10 @@ static int read_config_rom(struct fw_device *device, int generation) ...@@ -619,8 +626,10 @@ static int read_config_rom(struct fw_device *device, int generation)
old_rom = device->config_rom; old_rom = device->config_rom;
new_rom = kmemdup(rom, length * 4, GFP_KERNEL); new_rom = kmemdup(rom, length * 4, GFP_KERNEL);
if (new_rom == NULL) if (new_rom == NULL) {
ret = -ENOMEM;
goto out; goto out;
}
down_write(&fw_device_rwsem); down_write(&fw_device_rwsem);
device->config_rom = new_rom; device->config_rom = new_rom;
...@@ -628,7 +637,7 @@ static int read_config_rom(struct fw_device *device, int generation) ...@@ -628,7 +637,7 @@ static int read_config_rom(struct fw_device *device, int generation)
up_write(&fw_device_rwsem); up_write(&fw_device_rwsem);
kfree(old_rom); kfree(old_rom);
ret = 0; ret = RCODE_COMPLETE;
device->max_rec = rom[2] >> 12 & 0xf; device->max_rec = rom[2] >> 12 & 0xf;
device->cmc = rom[2] >> 30 & 1; device->cmc = rom[2] >> 30 & 1;
device->irmc = rom[2] >> 31 & 1; device->irmc = rom[2] >> 31 & 1;
...@@ -967,15 +976,17 @@ static void fw_device_init(struct work_struct *work) ...@@ -967,15 +976,17 @@ static void fw_device_init(struct work_struct *work)
* device. * device.
*/ */
if (read_config_rom(device, device->generation) < 0) { ret = read_config_rom(device, device->generation);
if (ret != RCODE_COMPLETE) {
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++;
fw_schedule_device_work(device, RETRY_DELAY); fw_schedule_device_work(device, RETRY_DELAY);
} else { } else {
if (device->node->link_on) if (device->node->link_on)
fw_notice(card, "giving up on Config ROM for node id %x\n", fw_notice(card, "giving up on node %x: reading config rom failed: %s\n",
device->node_id); device->node_id,
fw_rcode_string(ret));
if (device->node == card->root_node) if (device->node == card->root_node)
fw_schedule_bm_work(card, 0); fw_schedule_bm_work(card, 0);
fw_device_release(&device->device); fw_device_release(&device->device);
...@@ -1069,31 +1080,30 @@ static void fw_device_init(struct work_struct *work) ...@@ -1069,31 +1080,30 @@ static void fw_device_init(struct work_struct *work)
put_device(&device->device); /* our reference */ put_device(&device->device); /* our reference */
} }
enum {
REREAD_BIB_ERROR,
REREAD_BIB_GONE,
REREAD_BIB_UNCHANGED,
REREAD_BIB_CHANGED,
};
/* Reread and compare bus info block and header of root directory */ /* Reread and compare bus info block and header of root directory */
static int reread_config_rom(struct fw_device *device, int generation) static int reread_config_rom(struct fw_device *device, int generation,
bool *changed)
{ {
u32 q; u32 q;
int i; int i, rcode;
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
if (read_rom(device, generation, i, &q) != RCODE_COMPLETE) rcode = read_rom(device, generation, i, &q);
return REREAD_BIB_ERROR; if (rcode != RCODE_COMPLETE)
return rcode;
if (i == 0 && q == 0) if (i == 0 && q == 0)
return REREAD_BIB_GONE; /* inaccessible (see read_config_rom); retry later */
return RCODE_BUSY;
if (q != device->config_rom[i]) if (q != device->config_rom[i]) {
return REREAD_BIB_CHANGED; *changed = true;
return RCODE_COMPLETE;
}
} }
return REREAD_BIB_UNCHANGED; *changed = false;
return RCODE_COMPLETE;
} }
static void fw_device_refresh(struct work_struct *work) static void fw_device_refresh(struct work_struct *work)
...@@ -1101,23 +1111,14 @@ static void fw_device_refresh(struct work_struct *work) ...@@ -1101,23 +1111,14 @@ static void fw_device_refresh(struct work_struct *work)
struct fw_device *device = struct fw_device *device =
container_of(work, struct fw_device, work.work); container_of(work, struct fw_device, work.work);
struct fw_card *card = device->card; struct fw_card *card = device->card;
int node_id = device->node_id; int ret, node_id = device->node_id;
bool changed;
switch (reread_config_rom(device, device->generation)) {
case REREAD_BIB_ERROR:
if (device->config_rom_retries < MAX_RETRIES / 2 &&
atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
device->config_rom_retries++;
fw_schedule_device_work(device, RETRY_DELAY / 2);
return;
}
goto give_up;
case REREAD_BIB_GONE: ret = reread_config_rom(device, device->generation, &changed);
goto gone; if (ret != RCODE_COMPLETE)
goto failed_config_rom;
case REREAD_BIB_UNCHANGED: if (!changed) {
if (atomic_cmpxchg(&device->state, if (atomic_cmpxchg(&device->state,
FW_DEVICE_INITIALIZING, FW_DEVICE_INITIALIZING,
FW_DEVICE_RUNNING) == FW_DEVICE_GONE) FW_DEVICE_RUNNING) == FW_DEVICE_GONE)
...@@ -1126,9 +1127,6 @@ static void fw_device_refresh(struct work_struct *work) ...@@ -1126,9 +1127,6 @@ static void fw_device_refresh(struct work_struct *work)
fw_device_update(work); fw_device_update(work);
device->config_rom_retries = 0; device->config_rom_retries = 0;
goto out; goto out;
case REREAD_BIB_CHANGED:
break;
} }
/* /*
...@@ -1137,16 +1135,9 @@ static void fw_device_refresh(struct work_struct *work) ...@@ -1137,16 +1135,9 @@ static void fw_device_refresh(struct work_struct *work)
*/ */
device_for_each_child(&device->device, NULL, shutdown_unit); device_for_each_child(&device->device, NULL, shutdown_unit);
if (read_config_rom(device, device->generation) < 0) { ret = read_config_rom(device, device->generation);
if (device->config_rom_retries < MAX_RETRIES && if (ret != RCODE_COMPLETE)
atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { goto failed_config_rom;
device->config_rom_retries++;
fw_schedule_device_work(device, RETRY_DELAY);
return;
}
goto give_up;
}
fw_device_cdev_update(device); fw_device_cdev_update(device);
create_units(device); create_units(device);
...@@ -1163,9 +1154,16 @@ static void fw_device_refresh(struct work_struct *work) ...@@ -1163,9 +1154,16 @@ static void fw_device_refresh(struct work_struct *work)
device->config_rom_retries = 0; device->config_rom_retries = 0;
goto out; goto out;
give_up: failed_config_rom:
fw_notice(card, "giving up on refresh of device %s\n", if (device->config_rom_retries < MAX_RETRIES &&
dev_name(&device->device)); atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
device->config_rom_retries++;
fw_schedule_device_work(device, RETRY_DELAY);
return;
}
fw_notice(card, "giving up on refresh of device %s: %s\n",
dev_name(&device->device), fw_rcode_string(ret));
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);
......
...@@ -39,52 +39,73 @@ ...@@ -39,52 +39,73 @@
* Isochronous DMA context management * Isochronous DMA context management
*/ */
int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, int fw_iso_buffer_alloc(struct fw_iso_buffer *buffer, int page_count)
int page_count, enum dma_data_direction direction)
{ {
int i, j; int i;
dma_addr_t address;
buffer->page_count = page_count;
buffer->direction = direction;
buffer->page_count = 0;
buffer->page_count_mapped = 0;
buffer->pages = kmalloc(page_count * sizeof(buffer->pages[0]), buffer->pages = kmalloc(page_count * sizeof(buffer->pages[0]),
GFP_KERNEL); GFP_KERNEL);
if (buffer->pages == NULL) if (buffer->pages == NULL)
goto out; return -ENOMEM;
for (i = 0; i < buffer->page_count; i++) { for (i = 0; i < page_count; i++) {
buffer->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); buffer->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
if (buffer->pages[i] == NULL) if (buffer->pages[i] == NULL)
goto out_pages; break;
}
buffer->page_count = i;
if (i < page_count) {
fw_iso_buffer_destroy(buffer, NULL);
return -ENOMEM;
}
return 0;
}
int fw_iso_buffer_map_dma(struct fw_iso_buffer *buffer, struct fw_card *card,
enum dma_data_direction direction)
{
dma_addr_t address;
int i;
buffer->direction = direction;
for (i = 0; i < buffer->page_count; i++) {
address = dma_map_page(card->device, buffer->pages[i], address = dma_map_page(card->device, buffer->pages[i],
0, PAGE_SIZE, direction); 0, PAGE_SIZE, direction);
if (dma_mapping_error(card->device, address)) { if (dma_mapping_error(card->device, address))
__free_page(buffer->pages[i]); break;
goto out_pages;
}
set_page_private(buffer->pages[i], address); set_page_private(buffer->pages[i], address);
} }
buffer->page_count_mapped = i;
if (i < buffer->page_count)
return -ENOMEM;
return 0; return 0;
}
out_pages: int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
for (j = 0; j < i; j++) { int page_count, enum dma_data_direction direction)
address = page_private(buffer->pages[j]); {
dma_unmap_page(card->device, address, int ret;
PAGE_SIZE, direction);
__free_page(buffer->pages[j]); ret = fw_iso_buffer_alloc(buffer, page_count);
} if (ret < 0)
kfree(buffer->pages); return ret;
out:
buffer->pages = NULL; ret = fw_iso_buffer_map_dma(buffer, card, direction);
if (ret < 0)
fw_iso_buffer_destroy(buffer, card);
return -ENOMEM; return ret;
} }
EXPORT_SYMBOL(fw_iso_buffer_init); EXPORT_SYMBOL(fw_iso_buffer_init);
int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma) int fw_iso_buffer_map_vma(struct fw_iso_buffer *buffer,
struct vm_area_struct *vma)
{ {
unsigned long uaddr; unsigned long uaddr;
int i, err; int i, err;
...@@ -107,15 +128,18 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, ...@@ -107,15 +128,18 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer,
int i; int i;
dma_addr_t address; dma_addr_t address;
for (i = 0; i < buffer->page_count; i++) { for (i = 0; i < buffer->page_count_mapped; i++) {
address = page_private(buffer->pages[i]); address = page_private(buffer->pages[i]);
dma_unmap_page(card->device, address, dma_unmap_page(card->device, address,
PAGE_SIZE, buffer->direction); PAGE_SIZE, buffer->direction);
__free_page(buffer->pages[i]);
} }
for (i = 0; i < buffer->page_count; i++)
__free_page(buffer->pages[i]);
kfree(buffer->pages); kfree(buffer->pages);
buffer->pages = NULL; buffer->pages = NULL;
buffer->page_count = 0;
buffer->page_count_mapped = 0;
} }
EXPORT_SYMBOL(fw_iso_buffer_destroy); EXPORT_SYMBOL(fw_iso_buffer_destroy);
......
...@@ -1003,6 +1003,32 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) ...@@ -1003,6 +1003,32 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
} }
EXPORT_SYMBOL(fw_core_handle_response); EXPORT_SYMBOL(fw_core_handle_response);
/**
* fw_rcode_string - convert a firewire result code to an error description
* @rcode: the result code
*/
const char *fw_rcode_string(int rcode)
{
static const char *const names[] = {
[RCODE_COMPLETE] = "no error",
[RCODE_CONFLICT_ERROR] = "conflict error",
[RCODE_DATA_ERROR] = "data error",
[RCODE_TYPE_ERROR] = "type error",
[RCODE_ADDRESS_ERROR] = "address error",
[RCODE_SEND_ERROR] = "send error",
[RCODE_CANCELLED] = "timeout",
[RCODE_BUSY] = "busy",
[RCODE_GENERATION] = "bus reset",
[RCODE_NO_ACK] = "no ack",
};
if ((unsigned int)rcode < ARRAY_SIZE(names) && names[rcode])
return names[rcode];
else
return "unknown";
}
EXPORT_SYMBOL(fw_rcode_string);
static const struct fw_address_region topology_map_region = static const struct fw_address_region topology_map_region =
{ .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP, { .start = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP,
.end = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, }; .end = CSR_REGISTER_BASE | CSR_TOPOLOGY_MAP_END, };
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/idr.h> #include <linux/idr.h>
...@@ -154,7 +155,11 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event); ...@@ -154,7 +155,11 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event);
/* -iso */ /* -iso */
int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); int fw_iso_buffer_alloc(struct fw_iso_buffer *buffer, int page_count);
int fw_iso_buffer_map_dma(struct fw_iso_buffer *buffer, struct fw_card *card,
enum dma_data_direction direction);
int fw_iso_buffer_map_vma(struct fw_iso_buffer *buffer,
struct vm_area_struct *vma);
/* -topology */ /* -topology */
......
...@@ -693,6 +693,8 @@ static struct pci_device_id pci_table[] __devinitdata = { ...@@ -693,6 +693,8 @@ static struct pci_device_id pci_table[] __devinitdata = {
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE(pci, pci_table);
static struct pci_driver lynx_pci_driver = { static struct pci_driver lynx_pci_driver = {
.name = driver_name, .name = driver_name,
.id_table = pci_table, .id_table = pci_table,
...@@ -700,22 +702,8 @@ static struct pci_driver lynx_pci_driver = { ...@@ -700,22 +702,8 @@ static struct pci_driver lynx_pci_driver = {
.remove = remove_card, .remove = remove_card,
}; };
module_pci_driver(lynx_pci_driver);
MODULE_AUTHOR("Kristian Hoegsberg"); MODULE_AUTHOR("Kristian Hoegsberg");
MODULE_DESCRIPTION("Snoop mode driver for TI pcilynx 1394 controllers"); MODULE_DESCRIPTION("Snoop mode driver for TI pcilynx 1394 controllers");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, pci_table);
static int __init nosy_init(void)
{
return pci_register_driver(&lynx_pci_driver);
}
static void __exit nosy_cleanup(void)
{
pci_unregister_driver(&lynx_pci_driver);
pr_info("Unloaded %s\n", driver_name);
}
module_init(nosy_init);
module_exit(nosy_cleanup);
...@@ -1821,9 +1821,8 @@ static void bus_reset_work(struct work_struct *work) ...@@ -1821,9 +1821,8 @@ static void bus_reset_work(struct work_struct *work)
{ {
struct fw_ohci *ohci = struct fw_ohci *ohci =
container_of(work, struct fw_ohci, bus_reset_work); container_of(work, struct fw_ohci, bus_reset_work);
int self_id_count, i, j, reg; int self_id_count, generation, new_generation, i, j;
int generation, new_generation; u32 reg;
unsigned long flags;
void *free_rom = NULL; void *free_rom = NULL;
dma_addr_t free_rom_bus = 0; dma_addr_t free_rom_bus = 0;
bool is_new_root; bool is_new_root;
...@@ -1930,13 +1929,13 @@ static void bus_reset_work(struct work_struct *work) ...@@ -1930,13 +1929,13 @@ static void bus_reset_work(struct work_struct *work)
} }
/* FIXME: Document how the locking works. */ /* FIXME: Document how the locking works. */
spin_lock_irqsave(&ohci->lock, flags); spin_lock_irq(&ohci->lock);
ohci->generation = -1; /* prevent AT packet queueing */ ohci->generation = -1; /* prevent AT packet queueing */
context_stop(&ohci->at_request_ctx); context_stop(&ohci->at_request_ctx);
context_stop(&ohci->at_response_ctx); context_stop(&ohci->at_response_ctx);
spin_unlock_irqrestore(&ohci->lock, flags); spin_unlock_irq(&ohci->lock);
/* /*
* Per OHCI 1.2 draft, clause 7.2.3.3, hardware may leave unsent * Per OHCI 1.2 draft, clause 7.2.3.3, hardware may leave unsent
...@@ -1946,7 +1945,7 @@ static void bus_reset_work(struct work_struct *work) ...@@ -1946,7 +1945,7 @@ static void bus_reset_work(struct work_struct *work)
at_context_flush(&ohci->at_request_ctx); at_context_flush(&ohci->at_request_ctx);
at_context_flush(&ohci->at_response_ctx); at_context_flush(&ohci->at_response_ctx);
spin_lock_irqsave(&ohci->lock, flags); spin_lock_irq(&ohci->lock);
ohci->generation = generation; ohci->generation = generation;
reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
...@@ -1990,7 +1989,7 @@ static void bus_reset_work(struct work_struct *work) ...@@ -1990,7 +1989,7 @@ static void bus_reset_work(struct work_struct *work)
reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0); reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0);
#endif #endif
spin_unlock_irqrestore(&ohci->lock, flags); spin_unlock_irq(&ohci->lock);
if (free_rom) if (free_rom)
dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
...@@ -2402,7 +2401,6 @@ static int ohci_set_config_rom(struct fw_card *card, ...@@ -2402,7 +2401,6 @@ static int ohci_set_config_rom(struct fw_card *card,
const __be32 *config_rom, size_t length) const __be32 *config_rom, size_t length)
{ {
struct fw_ohci *ohci; struct fw_ohci *ohci;
unsigned long flags;
__be32 *next_config_rom; __be32 *next_config_rom;
dma_addr_t uninitialized_var(next_config_rom_bus); dma_addr_t uninitialized_var(next_config_rom_bus);
...@@ -2441,7 +2439,7 @@ static int ohci_set_config_rom(struct fw_card *card, ...@@ -2441,7 +2439,7 @@ static int ohci_set_config_rom(struct fw_card *card,
if (next_config_rom == NULL) if (next_config_rom == NULL)
return -ENOMEM; return -ENOMEM;
spin_lock_irqsave(&ohci->lock, flags); spin_lock_irq(&ohci->lock);
/* /*
* If there is not an already pending config_rom update, * If there is not an already pending config_rom update,
...@@ -2467,7 +2465,7 @@ static int ohci_set_config_rom(struct fw_card *card, ...@@ -2467,7 +2465,7 @@ static int ohci_set_config_rom(struct fw_card *card,
reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus); reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus);
spin_unlock_irqrestore(&ohci->lock, flags); spin_unlock_irq(&ohci->lock);
/* If we didn't use the DMA allocation, delete it. */ /* If we didn't use the DMA allocation, delete it. */
if (next_config_rom != NULL) if (next_config_rom != NULL)
...@@ -2891,10 +2889,9 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, ...@@ -2891,10 +2889,9 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
descriptor_callback_t uninitialized_var(callback); descriptor_callback_t uninitialized_var(callback);
u64 *uninitialized_var(channels); u64 *uninitialized_var(channels);
u32 *uninitialized_var(mask), uninitialized_var(regs); u32 *uninitialized_var(mask), uninitialized_var(regs);
unsigned long flags;
int index, ret = -EBUSY; int index, ret = -EBUSY;
spin_lock_irqsave(&ohci->lock, flags); spin_lock_irq(&ohci->lock);
switch (type) { switch (type) {
case FW_ISO_CONTEXT_TRANSMIT: case FW_ISO_CONTEXT_TRANSMIT:
...@@ -2938,7 +2935,7 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, ...@@ -2938,7 +2935,7 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
ret = -ENOSYS; ret = -ENOSYS;
} }
spin_unlock_irqrestore(&ohci->lock, flags); spin_unlock_irq(&ohci->lock);
if (index < 0) if (index < 0)
return ERR_PTR(ret); return ERR_PTR(ret);
...@@ -2964,7 +2961,7 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, ...@@ -2964,7 +2961,7 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
out_with_header: out_with_header:
free_page((unsigned long)ctx->header); free_page((unsigned long)ctx->header);
out: out:
spin_lock_irqsave(&ohci->lock, flags); spin_lock_irq(&ohci->lock);
switch (type) { switch (type) {
case FW_ISO_CONTEXT_RECEIVE: case FW_ISO_CONTEXT_RECEIVE:
...@@ -2977,7 +2974,7 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, ...@@ -2977,7 +2974,7 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
} }
*mask |= 1 << index; *mask |= 1 << index;
spin_unlock_irqrestore(&ohci->lock, flags); spin_unlock_irq(&ohci->lock);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
...@@ -3789,6 +3786,8 @@ static struct pci_driver fw_ohci_pci_driver = { ...@@ -3789,6 +3786,8 @@ static struct pci_driver fw_ohci_pci_driver = {
#endif #endif
}; };
module_pci_driver(fw_ohci_pci_driver);
MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
MODULE_DESCRIPTION("Driver for PCI OHCI IEEE1394 controllers"); MODULE_DESCRIPTION("Driver for PCI OHCI IEEE1394 controllers");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -3797,16 +3796,3 @@ MODULE_LICENSE("GPL"); ...@@ -3797,16 +3796,3 @@ MODULE_LICENSE("GPL");
#ifndef CONFIG_IEEE1394_OHCI1394_MODULE #ifndef CONFIG_IEEE1394_OHCI1394_MODULE
MODULE_ALIAS("ohci1394"); MODULE_ALIAS("ohci1394");
#endif #endif
static int __init fw_ohci_init(void)
{
return pci_register_driver(&fw_ohci_pci_driver);
}
static void __exit fw_ohci_cleanup(void)
{
pci_unregister_driver(&fw_ohci_pci_driver);
}
module_init(fw_ohci_init);
module_exit(fw_ohci_cleanup);
...@@ -207,9 +207,8 @@ static const struct device *lu_dev(const struct sbp2_logical_unit *lu) ...@@ -207,9 +207,8 @@ static const struct device *lu_dev(const struct sbp2_logical_unit *lu)
#define SBP2_MAX_CDB_SIZE 16 #define SBP2_MAX_CDB_SIZE 16
/* /*
* The default maximum s/g segment size of a FireWire controller is * The maximum SBP-2 data buffer size is 0xffff. We quadlet-align this
* usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to * for compatibility with earlier versions of this driver.
* be quadlet-aligned, we set the length limit to 0xffff & ~3.
*/ */
#define SBP2_MAX_SEG_SIZE 0xfffc #define SBP2_MAX_SEG_SIZE 0xfffc
...@@ -1163,7 +1162,8 @@ static int sbp2_probe(struct device *dev) ...@@ -1163,7 +1162,8 @@ static int sbp2_probe(struct device *dev)
shost->max_cmd_len = SBP2_MAX_CDB_SIZE; shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
if (scsi_add_host(shost, &unit->device) < 0) if (scsi_add_host_with_dma(shost, &unit->device,
device->card->device) < 0)
goto fail_shost_put; goto fail_shost_put;
/* implicit directory ID */ /* implicit directory ID */
...@@ -1295,10 +1295,7 @@ static struct fw_driver sbp2_driver = { ...@@ -1295,10 +1295,7 @@ static struct fw_driver sbp2_driver = {
static void sbp2_unmap_scatterlist(struct device *card_device, static void sbp2_unmap_scatterlist(struct device *card_device,
struct sbp2_command_orb *orb) struct sbp2_command_orb *orb)
{ {
if (scsi_sg_count(orb->cmd)) scsi_dma_unmap(orb->cmd);
dma_unmap_sg(card_device, scsi_sglist(orb->cmd),
scsi_sg_count(orb->cmd),
orb->cmd->sc_data_direction);
if (orb->request.misc & cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT)) if (orb->request.misc & cpu_to_be32(COMMAND_ORB_PAGE_TABLE_PRESENT))
dma_unmap_single(card_device, orb->page_table_bus, dma_unmap_single(card_device, orb->page_table_bus,
...@@ -1404,9 +1401,8 @@ static int sbp2_map_scatterlist(struct sbp2_command_orb *orb, ...@@ -1404,9 +1401,8 @@ static int sbp2_map_scatterlist(struct sbp2_command_orb *orb,
struct scatterlist *sg = scsi_sglist(orb->cmd); struct scatterlist *sg = scsi_sglist(orb->cmd);
int i, n; int i, n;
n = dma_map_sg(device->card->device, sg, scsi_sg_count(orb->cmd), n = scsi_dma_map(orb->cmd);
orb->cmd->sc_data_direction); if (n <= 0)
if (n == 0)
goto fail; goto fail;
/* /*
...@@ -1452,8 +1448,7 @@ static int sbp2_map_scatterlist(struct sbp2_command_orb *orb, ...@@ -1452,8 +1448,7 @@ static int sbp2_map_scatterlist(struct sbp2_command_orb *orb,
return 0; return 0;
fail_page_table: fail_page_table:
dma_unmap_sg(device->card->device, scsi_sglist(orb->cmd), scsi_dma_unmap(orb->cmd);
scsi_sg_count(orb->cmd), orb->cmd->sc_data_direction);
fail: fail:
return -ENOMEM; return -ENOMEM;
} }
...@@ -1534,7 +1529,10 @@ static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) ...@@ -1534,7 +1529,10 @@ static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
sdev->allow_restart = 1; sdev->allow_restart = 1;
/* SBP-2 requires quadlet alignment of the data buffers. */ /*
* SBP-2 does not require any alignment, but we set it anyway
* for compatibility with earlier versions of this driver.
*/
blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1); blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36) if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36)
...@@ -1568,8 +1566,6 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) ...@@ -1568,8 +1566,6 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
blk_queue_max_hw_sectors(sdev->request_queue, 128 * 1024 / 512); blk_queue_max_hw_sectors(sdev->request_queue, 128 * 1024 / 512);
blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
return 0; return 0;
} }
......
...@@ -349,6 +349,7 @@ int fw_cancel_transaction(struct fw_card *card, ...@@ -349,6 +349,7 @@ int fw_cancel_transaction(struct fw_card *card,
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,
void *payload, size_t length); void *payload, size_t length);
const char *fw_rcode_string(int rcode);
static inline int fw_stream_packet_destination_id(int tag, int channel, int sy) static inline int fw_stream_packet_destination_id(int tag, int channel, int sy)
{ {
...@@ -406,6 +407,7 @@ struct fw_iso_buffer { ...@@ -406,6 +407,7 @@ struct fw_iso_buffer {
enum dma_data_direction direction; enum dma_data_direction direction;
struct page **pages; struct page **pages;
int page_count; int page_count;
int page_count_mapped;
}; };
int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card, int fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
......
...@@ -84,7 +84,7 @@ static int pcr_modify(struct cmp_connection *c, ...@@ -84,7 +84,7 @@ static int pcr_modify(struct cmp_connection *c,
return 0; return 0;
io_error: io_error:
cmp_error(c, "transaction failed: %s\n", rcode_string(rcode)); cmp_error(c, "transaction failed: %s\n", fw_rcode_string(rcode));
return -EIO; return -EIO;
bus_reset: bus_reset:
......
...@@ -13,32 +13,6 @@ ...@@ -13,32 +13,6 @@
#define ERROR_RETRY_DELAY_MS 5 #define ERROR_RETRY_DELAY_MS 5
/**
* rcode_string - convert a firewire result code to a string
* @rcode: the result
*/
const char *rcode_string(unsigned int rcode)
{
static const char *const names[] = {
[RCODE_COMPLETE] = "complete",
[RCODE_CONFLICT_ERROR] = "conflict error",
[RCODE_DATA_ERROR] = "data error",
[RCODE_TYPE_ERROR] = "type error",
[RCODE_ADDRESS_ERROR] = "address error",
[RCODE_SEND_ERROR] = "send error",
[RCODE_CANCELLED] = "cancelled",
[RCODE_BUSY] = "busy",
[RCODE_GENERATION] = "generation",
[RCODE_NO_ACK] = "no ack",
};
if (rcode < ARRAY_SIZE(names) && names[rcode])
return names[rcode];
else
return "unknown";
}
EXPORT_SYMBOL(rcode_string);
/** /**
* snd_fw_transaction - send a request and wait for its completion * snd_fw_transaction - send a request and wait for its completion
* @unit: the driver's unit on the target device * @unit: the driver's unit on the target device
...@@ -71,7 +45,7 @@ int snd_fw_transaction(struct fw_unit *unit, int tcode, ...@@ -71,7 +45,7 @@ int snd_fw_transaction(struct fw_unit *unit, int tcode,
if (rcode_is_permanent_error(rcode) || ++tries >= 3) { if (rcode_is_permanent_error(rcode) || ++tries >= 3) {
dev_err(&unit->device, "transaction failed: %s\n", dev_err(&unit->device, "transaction failed: %s\n",
rcode_string(rcode)); fw_rcode_string(rcode));
return -EIO; return -EIO;
} }
......
...@@ -8,7 +8,6 @@ struct fw_unit; ...@@ -8,7 +8,6 @@ struct fw_unit;
int snd_fw_transaction(struct fw_unit *unit, int tcode, int snd_fw_transaction(struct fw_unit *unit, int tcode,
u64 offset, void *buffer, size_t length); u64 offset, void *buffer, size_t length);
const char *rcode_string(unsigned int rcode);
/* returns true if retrying the transaction would not make sense */ /* returns true if retrying the transaction would not make sense */
static inline bool rcode_is_permanent_error(int rcode) static inline bool rcode_is_permanent_error(int rcode)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment