Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/ieee1394/linux1394-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
  firewire: fix NULL pointer deref. and resource leak
  Documentation: correction to debugging-via-ohci1394
  ieee1394: sbp2: fix rescan-scsi-bus
  firewire: fw-sbp2: fix NULL pointer deref. in scsi_remove_device
  firewire: fw-sbp2: fix NULL pointer deref. in slave_alloc
  firewire: fw-sbp2: (try to) avoid I/O errors during reconnect
  firewire: fw-sbp2: enforce a retry of __scsi_add_device if bus generation changed
  firewire: fw-sbp2: sort includes
  firewire: fw-sbp2: logout and login after failed reconnect
  firewire: fw-sbp2: don't add scsi_device twice
  firewire: fw-sbp2: log bus_id at management request failures
  firewire: fw-sbp2: wait for completion of fetch agent reset
  ieee1394: sbp2: add INQUIRY delay workaround
  firewire: fw-sbp2: add INQUIRY delay workaround
  firewire: log GUID of new devices
  firewire: fw-sbp2: don't retry login or reconnect after unplug
  firewire: fix "kobject_add failed for fw* with -EEXIST"
  firewire: fw-sbp2: fix logout before login retry
  firewire: fw-sbp2: unsigned int vs. unsigned
  • Loading branch information
Linus Torvalds committed Feb 26, 2008
2 parents 7c811e4 + fae6031 commit 98c1fc9
Show file tree
Hide file tree
Showing 7 changed files with 350 additions and 109 deletions.
17 changes: 9 additions & 8 deletions Documentation/debugging-via-ohci1394.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ available (notebooks) or too slow for extensive debug information (like ACPI).
Drivers
-------

The OHCI-1394 drivers in drivers/firewire and drivers/ieee1394 initialize
the OHCI-1394 controllers to a working state and can be used to enable
physical DMA. By default you only have to load the driver, and physical
DMA access will be granted to all remote nodes, but it can be turned off
when using the ohci1394 driver.

Because these drivers depend on the PCI enumeration to be completed, an
initialization routine which can runs pretty early (long before console_init(),
The ohci1394 driver in drivers/ieee1394 initializes the OHCI-1394 controllers
to a working state and enables physical DMA by default for all remote nodes.
This can be turned off by ohci1394's module parameter phys_dma=0.

The alternative firewire-ohci driver in drivers/firewire uses filtered physical
DMA, hence is not yet suitable for remote debugging.

Because ohci1394 depends on the PCI enumeration to be completed, an
initialization routine which runs pretty early (long before console_init()
which makes the printk buffer appear on the console can be called) was written.

To activate it, enable CONFIG_PROVIDE_OHCI1394_DMA_INIT (Kernel hacking menu:
Expand Down
17 changes: 12 additions & 5 deletions drivers/firewire/fw-cdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,17 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
struct client *client;
unsigned long flags;

device = fw_device_from_devt(inode->i_rdev);
device = fw_device_get_by_devt(inode->i_rdev);
if (device == NULL)
return -ENODEV;

client = kzalloc(sizeof(*client), GFP_KERNEL);
if (client == NULL)
if (client == NULL) {
fw_device_put(device);
return -ENOMEM;
}

client->device = fw_device_get(device);
client->device = device;
INIT_LIST_HEAD(&client->event_list);
INIT_LIST_HEAD(&client->resource_list);
spin_lock_init(&client->lock);
Expand Down Expand Up @@ -644,6 +646,10 @@ static int ioctl_create_iso_context(struct client *client, void *buffer)
struct fw_cdev_create_iso_context *request = buffer;
struct fw_iso_context *context;

/* We only support one context at this time. */
if (client->iso_context != NULL)
return -EBUSY;

if (request->channel > 63)
return -EINVAL;

Expand Down Expand Up @@ -790,8 +796,9 @@ static int ioctl_start_iso(struct client *client, void *buffer)
{
struct fw_cdev_start_iso *request = buffer;

if (request->handle != 0)
if (client->iso_context == NULL || request->handle != 0)
return -EINVAL;

if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) {
if (request->tags == 0 || request->tags > 15)
return -EINVAL;
Expand All @@ -808,7 +815,7 @@ static int ioctl_stop_iso(struct client *client, void *buffer)
{
struct fw_cdev_stop_iso *request = buffer;

if (request->handle != 0)
if (client->iso_context == NULL || request->handle != 0)
return -EINVAL;

return fw_iso_context_stop(client->iso_context);
Expand Down
48 changes: 31 additions & 17 deletions drivers/firewire/fw-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,12 +358,9 @@ static ssize_t
guid_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fw_device *device = fw_device(dev);
u64 guid;

guid = ((u64)device->config_rom[3] << 32) | device->config_rom[4];

return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
(unsigned long long)guid);
return snprintf(buf, PAGE_SIZE, "0x%08x%08x\n",
device->config_rom[3], device->config_rom[4]);
}

static struct device_attribute fw_device_attributes[] = {
Expand Down Expand Up @@ -610,12 +607,14 @@ static DECLARE_RWSEM(idr_rwsem);
static DEFINE_IDR(fw_device_idr);
int fw_cdev_major;

struct fw_device *fw_device_from_devt(dev_t devt)
struct fw_device *fw_device_get_by_devt(dev_t devt)
{
struct fw_device *device;

down_read(&idr_rwsem);
device = idr_find(&fw_device_idr, MINOR(devt));
if (device)
fw_device_get(device);
up_read(&idr_rwsem);

return device;
Expand All @@ -627,13 +626,14 @@ static void fw_device_shutdown(struct work_struct *work)
container_of(work, struct fw_device, work.work);
int minor = MINOR(device->device.devt);

down_write(&idr_rwsem);
idr_remove(&fw_device_idr, minor);
up_write(&idr_rwsem);

fw_device_cdev_remove(device);
device_for_each_child(&device->device, NULL, shutdown_unit);
device_unregister(&device->device);

down_write(&idr_rwsem);
idr_remove(&fw_device_idr, minor);
up_write(&idr_rwsem);
fw_device_put(device);
}

static struct device_type fw_device_type = {
Expand Down Expand Up @@ -682,10 +682,13 @@ static void fw_device_init(struct work_struct *work)
}

err = -ENOMEM;

fw_device_get(device);
down_write(&idr_rwsem);
if (idr_pre_get(&fw_device_idr, GFP_KERNEL))
err = idr_get_new(&fw_device_idr, device, &minor);
up_write(&idr_rwsem);

if (err < 0)
goto error;

Expand Down Expand Up @@ -717,13 +720,22 @@ static void fw_device_init(struct work_struct *work)
*/
if (atomic_cmpxchg(&device->state,
FW_DEVICE_INITIALIZING,
FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN) {
fw_device_shutdown(&device->work.work);
else
fw_notify("created new fw device %s "
"(%d config rom retries, S%d00)\n",
device->device.bus_id, device->config_rom_retries,
1 << device->max_speed);
} else {
if (device->config_rom_retries)
fw_notify("created device %s: GUID %08x%08x, S%d00, "
"%d config ROM retries\n",
device->device.bus_id,
device->config_rom[3], device->config_rom[4],
1 << device->max_speed,
device->config_rom_retries);
else
fw_notify("created device %s: GUID %08x%08x, S%d00\n",
device->device.bus_id,
device->config_rom[3], device->config_rom[4],
1 << device->max_speed);
}

/*
* Reschedule the IRM work if we just finished reading the
Expand All @@ -741,7 +753,9 @@ static void fw_device_init(struct work_struct *work)
idr_remove(&fw_device_idr, minor);
up_write(&idr_rwsem);
error:
put_device(&device->device);
fw_device_put(device); /* fw_device_idr's reference */

put_device(&device->device); /* our reference */
}

static int update_unit(struct device *dev, void *data)
Expand Down
2 changes: 1 addition & 1 deletion drivers/firewire/fw-device.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ fw_device_is_shutdown(struct fw_device *device)
}

struct fw_device *fw_device_get(struct fw_device *device);
struct fw_device *fw_device_get_by_devt(dev_t devt);
void fw_device_put(struct fw_device *device);
int fw_device_enable_phys_dma(struct fw_device *device);

void fw_device_cdev_update(struct fw_device *device);
void fw_device_cdev_remove(struct fw_device *device);

struct fw_device *fw_device_from_devt(dev_t devt);
extern int fw_cdev_major;

struct fw_unit {
Expand Down
Loading

0 comments on commit 98c1fc9

Please sign in to comment.