提交 98c1fc93 编写于 作者: L Linus Torvalds

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: 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
......@@ -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:
......
......@@ -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);
......@@ -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;
......@@ -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;
......@@ -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);
......
......@@ -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[] = {
......@@ -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;
......@@ -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 = {
......@@ -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;
......@@ -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
......@@ -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)
......
......@@ -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 {
......
此差异已折叠。
......@@ -183,6 +183,9 @@ MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
* Avoids access beyond actual disk limits on devices with an off-by-one bug.
* Don't use this with devices which don't have this bug.
*
* - delay inquiry
* Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry.
*
* - override internal blacklist
* Instead of adding to the built-in blacklist, use only the workarounds
* specified in the module load parameter.
......@@ -195,6 +198,7 @@ MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36)
", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
", delay inquiry = " __stringify(SBP2_WORKAROUND_DELAY_INQUIRY)
", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
", or a combination)");
......@@ -357,6 +361,11 @@ static const struct {
.workarounds = SBP2_WORKAROUND_INQUIRY_36 |
SBP2_WORKAROUND_MODE_SENSE_8,
},
/* DViCO Momobay FX-3A with TSB42AA9A bridge */ {
.firmware_revision = 0x002800,
.model_id = 0x000000,
.workarounds = SBP2_WORKAROUND_DELAY_INQUIRY,
},
/* Initio bridges, actually only needed for some older ones */ {
.firmware_revision = 0x000200,
.model_id = SBP2_ROM_VALUE_WILDCARD,
......@@ -914,6 +923,9 @@ static int sbp2_start_device(struct sbp2_lu *lu)
sbp2_agent_reset(lu, 1);
sbp2_max_speed_and_size(lu);
if (lu->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
ssleep(SBP2_INQUIRY_DELAY);
error = scsi_add_device(lu->shost, 0, lu->ud->id, 0);
if (error) {
SBP2_ERR("scsi_add_device failed");
......@@ -1962,6 +1974,9 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
{
struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];
if (sdev->lun != 0 || sdev->id != lu->ud->id || sdev->channel != 0)
return -ENODEV;
lu->sdev = sdev;
sdev->allow_restart = 1;
......
......@@ -343,6 +343,8 @@ enum sbp2lu_state_types {
#define SBP2_WORKAROUND_INQUIRY_36 0x2
#define SBP2_WORKAROUND_MODE_SENSE_8 0x4
#define SBP2_WORKAROUND_FIX_CAPACITY 0x8
#define SBP2_WORKAROUND_DELAY_INQUIRY 0x10
#define SBP2_INQUIRY_DELAY 12
#define SBP2_WORKAROUND_OVERRIDE 0x100
#endif /* SBP2_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册