Commit c1dcb4bb authored by Linus Torvalds's avatar 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: (23 commits)
  firewire: ohci: extend initialization log message
  firewire: ohci: fix IR/IT context mask mixup
  firewire: ohci: add module parameter to activate quirk fixes
  firewire: ohci: use an ID table for quirks detection
  firewire: ohci: reorder struct fw_ohci for better cache efficiency
  firewire: ohci: remove unused dualbuffer IR code
  firewire: core: combine a bit of repeated code
  firewire: core: change type of a data buffer
  firewire: cdev: increment ABI version number
  firewire: cdev: add more flexible cycle timer ioctl
  firewire: core: rename an internal function
  firewire: core: fix an information leak
  firewire: core: increase stack size of config ROM reader
  firewire: core: don't fail device creation in case of too large config ROM blocks
  firewire: core: fix "giving up on config rom" with Panasonic AG-DV2500
  firewire: remove incomplete Bus_Time CSR support
  firewire: get_cycle_timer optimization and cleanup
  firewire: ohci: enable cycle timer fix on ALi and NEC controllers
  firewire: ohci: work around cycle timer bugs on VIA controllers
  firewire: make PCI device id constant
  ...
parents 60f8a8d4 6fdb2ee2
This diff is collapsed.
......@@ -18,6 +18,7 @@
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/bug.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/device.h>
......@@ -43,7 +44,7 @@
#include "core.h"
void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p)
void fw_csr_iterator_init(struct fw_csr_iterator *ci, const u32 *p)
{
ci->p = p + 1;
ci->end = ci->p + (p[0] >> 16);
......@@ -59,9 +60,76 @@ int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value)
}
EXPORT_SYMBOL(fw_csr_iterator_next);
static const u32 *search_leaf(const u32 *directory, int search_key)
{
struct fw_csr_iterator ci;
int last_key = 0, key, value;
fw_csr_iterator_init(&ci, directory);
while (fw_csr_iterator_next(&ci, &key, &value)) {
if (last_key == search_key &&
key == (CSR_DESCRIPTOR | CSR_LEAF))
return ci.p - 1 + value;
last_key = key;
}
return NULL;
}
static int textual_leaf_to_string(const u32 *block, char *buf, size_t size)
{
unsigned int quadlets, i;
char c;
if (!size || !buf)
return -EINVAL;
quadlets = min(block[0] >> 16, 256U);
if (quadlets < 2)
return -ENODATA;
if (block[1] != 0 || block[2] != 0)
/* unknown language/character set */
return -ENODATA;
block += 3;
quadlets -= 2;
for (i = 0; i < quadlets * 4 && i < size - 1; i++) {
c = block[i / 4] >> (24 - 8 * (i % 4));
if (c == '\0')
break;
buf[i] = c;
}
buf[i] = '\0';
return i;
}
/**
* fw_csr_string - reads a string from the configuration ROM
* @directory: e.g. root directory or unit directory
* @key: the key of the preceding directory entry
* @buf: where to put the string
* @size: size of @buf, in bytes
*
* The string is taken from a minimal ASCII text descriptor leaf after
* the immediate entry with @key. The string is zero-terminated.
* Returns strlen(buf) or a negative error code.
*/
int fw_csr_string(const u32 *directory, int key, char *buf, size_t size)
{
const u32 *leaf = search_leaf(directory, key);
if (!leaf)
return -ENOENT;
return textual_leaf_to_string(leaf, buf, size);
}
EXPORT_SYMBOL(fw_csr_string);
static bool is_fw_unit(struct device *dev);
static int match_unit_directory(u32 *directory, u32 match_flags,
static int match_unit_directory(const u32 *directory, u32 match_flags,
const struct ieee1394_device_id *id)
{
struct fw_csr_iterator ci;
......@@ -195,7 +263,7 @@ static ssize_t show_immediate(struct device *dev,
struct config_rom_attribute *attr =
container_of(dattr, struct config_rom_attribute, attr);
struct fw_csr_iterator ci;
u32 *dir;
const u32 *dir;
int key, value, ret = -ENOENT;
down_read(&fw_device_rwsem);
......@@ -226,10 +294,10 @@ static ssize_t show_text_leaf(struct device *dev,
{
struct config_rom_attribute *attr =
container_of(dattr, struct config_rom_attribute, attr);
struct fw_csr_iterator ci;
u32 *dir, *block = NULL, *p, *end;
int length, key, value, last_key = 0, ret = -ENOENT;
char *b;
const u32 *dir;
size_t bufsize;
char dummy_buf[2];
int ret;
down_read(&fw_device_rwsem);
......@@ -238,40 +306,23 @@ static ssize_t show_text_leaf(struct device *dev,
else
dir = fw_device(dev)->config_rom + 5;
fw_csr_iterator_init(&ci, dir);
while (fw_csr_iterator_next(&ci, &key, &value)) {
if (attr->key == last_key &&
key == (CSR_DESCRIPTOR | CSR_LEAF))
block = ci.p - 1 + value;
last_key = key;
if (buf) {
bufsize = PAGE_SIZE - 1;
} else {
buf = dummy_buf;
bufsize = 1;
}
if (block == NULL)
goto out;
length = min(block[0] >> 16, 256U);
if (length < 3)
goto out;
ret = fw_csr_string(dir, attr->key, buf, bufsize);
if (block[1] != 0 || block[2] != 0)
/* Unknown encoding. */
goto out;
if (buf == NULL) {
ret = length * 4;
goto out;
if (ret >= 0) {
/* Strip trailing whitespace and add newline. */
while (ret > 0 && isspace(buf[ret - 1]))
ret--;
strcpy(buf + ret, "\n");
ret++;
}
b = buf;
end = &block[length + 1];
for (p = &block[3]; p < end; p++, b += 4)
* (u32 *) b = (__force u32) __cpu_to_be32(*p);
/* Strip trailing whitespace and add newline. */
while (b--, (isspace(*b) || *b == '\0') && b > buf);
strcpy(b + 1, "\n");
ret = b + 2 - buf;
out:
up_read(&fw_device_rwsem);
return ret;
......@@ -371,7 +422,7 @@ static ssize_t guid_show(struct device *dev,
return ret;
}
static int units_sprintf(char *buf, u32 *directory)
static int units_sprintf(char *buf, const u32 *directory)
{
struct fw_csr_iterator ci;
int key, value;
......@@ -441,28 +492,29 @@ static int read_rom(struct fw_device *device,
return rcode;
}
#define READ_BIB_ROM_SIZE 256
#define READ_BIB_STACK_SIZE 16
#define MAX_CONFIG_ROM_SIZE 256
/*
* Read the bus info block, perform a speed probe, and read all of the rest of
* the config ROM. We do all this with a cached bus generation. If the bus
* generation changes under us, read_bus_info_block 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
* are reading the ROM may have changed the ROM during the reset.
*/
static int read_bus_info_block(struct fw_device *device, int generation)
static int read_config_rom(struct fw_device *device, int generation)
{
u32 *rom, *stack, *old_rom, *new_rom;
const u32 *old_rom, *new_rom;
u32 *rom, *stack;
u32 sp, key;
int i, end, length, ret = -1;
rom = kmalloc(sizeof(*rom) * READ_BIB_ROM_SIZE +
sizeof(*stack) * READ_BIB_STACK_SIZE, GFP_KERNEL);
rom = kmalloc(sizeof(*rom) * MAX_CONFIG_ROM_SIZE +
sizeof(*stack) * MAX_CONFIG_ROM_SIZE, GFP_KERNEL);
if (rom == NULL)
return -ENOMEM;
stack = &rom[READ_BIB_ROM_SIZE];
stack = &rom[MAX_CONFIG_ROM_SIZE];
memset(rom, 0, sizeof(*rom) * MAX_CONFIG_ROM_SIZE);
device->max_speed = SCODE_100;
......@@ -529,40 +581,54 @@ static int read_bus_info_block(struct fw_device *device, int generation)
*/
key = stack[--sp];
i = key & 0xffffff;
if (i >= READ_BIB_ROM_SIZE)
/*
* The reference points outside the standard
* config rom area, something's fishy.
*/
if (WARN_ON(i >= MAX_CONFIG_ROM_SIZE))
goto out;
/* Read header quadlet for the block to get the length. */
if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
goto out;
end = i + (rom[i] >> 16) + 1;
i++;
if (end > READ_BIB_ROM_SIZE)
if (end > MAX_CONFIG_ROM_SIZE) {
/*
* This block extends outside standard config
* area (and the array we're reading it
* into). That's broken, so ignore this
* device.
* This block extends outside the config ROM which is
* a firmware bug. Ignore this whole block, i.e.
* simply set a fake block length of 0.
*/
goto out;
fw_error("skipped invalid ROM block %x at %llx\n",
rom[i],
i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
rom[i] = 0;
end = i;
}
i++;
/*
* Now read in the block. If this is a directory
* block, check the entries as we read them to see if
* it references another block, and push it in that case.
*/
while (i < end) {
for (; i < end; i++) {
if (read_rom(device, generation, i, &rom[i]) !=
RCODE_COMPLETE)
goto out;
if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
sp < READ_BIB_STACK_SIZE)
if ((key >> 30) != 3 || (rom[i] >> 30) < 2)
continue;
/*
* Offset points outside the ROM. May be a firmware
* bug or an Extended ROM entry (IEEE 1212-2001 clause
* 7.7.18). Simply overwrite this pointer here by a
* fake immediate entry so that later iterators over
* the ROM don't have to check offsets all the time.
*/
if (i + (rom[i] & 0xffffff) >= MAX_CONFIG_ROM_SIZE) {
fw_error("skipped unsupported ROM entry %x at %llx\n",
rom[i],
i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
rom[i] = 0;
continue;
}
stack[sp++] = i + rom[i];
i++;
}
if (length < i)
length = i;
......@@ -905,7 +971,7 @@ static void fw_device_init(struct work_struct *work)
* device.
*/
if (read_bus_info_block(device, device->generation) < 0) {
if (read_config_rom(device, device->generation) < 0) {
if (device->config_rom_retries < MAX_RETRIES &&
atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
device->config_rom_retries++;
......@@ -1022,7 +1088,7 @@ enum {
};
/* Reread and compare bus info block and header of root directory */
static int reread_bus_info_block(struct fw_device *device, int generation)
static int reread_config_rom(struct fw_device *device, int generation)
{
u32 q;
int i;
......@@ -1048,7 +1114,7 @@ static void fw_device_refresh(struct work_struct *work)
struct fw_card *card = device->card;
int node_id = device->node_id;
switch (reread_bus_info_block(device, device->generation)) {
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) {
......@@ -1082,7 +1148,7 @@ static void fw_device_refresh(struct work_struct *work)
*/
device_for_each_child(&device->device, NULL, shutdown_unit);
if (read_bus_info_block(device, device->generation) < 0) {
if (read_config_rom(device, device->generation) < 0) {
if (device->config_rom_retries < MAX_RETRIES &&
atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
device->config_rom_retries++;
......
......@@ -921,23 +921,15 @@ static void handle_registers(struct fw_card *card, struct fw_request *request,
void *payload, size_t length, void *callback_data)
{
int reg = offset & ~CSR_REGISTER_BASE;
unsigned long long bus_time;
__be32 *data = payload;
int rcode = RCODE_COMPLETE;
switch (reg) {
case CSR_CYCLE_TIME:
case CSR_BUS_TIME:
if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) {
rcode = RCODE_TYPE_ERROR;
break;
}
bus_time = card->driver->get_bus_time(card);
if (reg == CSR_CYCLE_TIME)
*data = cpu_to_be32(bus_time);
if (TCODE_IS_READ_REQUEST(tcode) && length == 4)
*data = cpu_to_be32(card->driver->get_cycle_time(card));
else
*data = cpu_to_be32(bus_time >> 25);
rcode = RCODE_TYPE_ERROR;
break;
case CSR_BROADCAST_CHANNEL:
......@@ -968,6 +960,9 @@ static void handle_registers(struct fw_card *card, struct fw_request *request,
case CSR_BUSY_TIMEOUT:
/* FIXME: Implement this. */
case CSR_BUS_TIME:
/* Useless without initialization by the bus manager. */
default:
rcode = RCODE_ADDRESS_ERROR;
break;
......
......@@ -70,7 +70,7 @@ struct fw_card_driver {
int (*enable_phys_dma)(struct fw_card *card,
int node_id, int generation);
u64 (*get_bus_time)(struct fw_card *card);
u32 (*get_cycle_time)(struct fw_card *card);
struct fw_iso_context *
(*allocate_iso_context)(struct fw_card *card,
......
This diff is collapsed.
......@@ -1014,7 +1014,8 @@ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
return 0;
}
static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, u32 *directory)
static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt,
const u32 *directory)
{
struct fw_csr_iterator ci;
int key, value;
......@@ -1027,7 +1028,7 @@ static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, u32 *directory)
return 0;
}
static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
static int sbp2_scan_unit_dir(struct sbp2_target *tgt, const u32 *directory,
u32 *model, u32 *firmware_revision)
{
struct fw_csr_iterator ci;
......
......@@ -239,47 +239,18 @@ static const struct fw_address_region fcp_region = {
};
/* Adjust the template string if models with longer names appear. */
#define MAX_MODEL_NAME_LEN ((int)DIV_ROUND_UP(sizeof("FireDTV ????"), 4))
static size_t model_name(u32 *directory, __be32 *buffer)
{
struct fw_csr_iterator ci;
int i, length, key, value, last_key = 0;
u32 *block = NULL;
fw_csr_iterator_init(&ci, directory);
while (fw_csr_iterator_next(&ci, &key, &value)) {
if (last_key == CSR_MODEL &&
key == (CSR_DESCRIPTOR | CSR_LEAF))
block = ci.p - 1 + value;
last_key = key;
}
if (block == NULL)
return 0;
length = min((int)(block[0] >> 16) - 2, MAX_MODEL_NAME_LEN);
if (length <= 0)
return 0;
/* fast-forward to text string */
block += 3;
for (i = 0; i < length; i++)
buffer[i] = cpu_to_be32(block[i]);
return length * 4;
}
#define MAX_MODEL_NAME_LEN sizeof("FireDTV ????")
static int node_probe(struct device *dev)
{
struct firedtv *fdtv;
__be32 name[MAX_MODEL_NAME_LEN];
char name[MAX_MODEL_NAME_LEN];
int name_len, err;
name_len = model_name(fw_unit(dev)->directory, name);
name_len = fw_csr_string(fw_unit(dev)->directory, CSR_MODEL,
name, sizeof(name));
fdtv = fdtv_alloc(dev, &backend, (char *)name, name_len);
fdtv = fdtv_alloc(dev, &backend, name, name_len >= 0 ? name_len : 0);
if (!fdtv)
return -ENOMEM;
......
......@@ -248,13 +248,20 @@ union fw_cdev_event {
#define FW_CDEV_IOC_SEND_BROADCAST_REQUEST _IOW('#', 0x12, struct fw_cdev_send_request)
#define FW_CDEV_IOC_SEND_STREAM_PACKET _IOW('#', 0x13, struct fw_cdev_send_stream_packet)
/* available since kernel version 2.6.34 */
#define FW_CDEV_IOC_GET_CYCLE_TIMER2 _IOWR('#', 0x14, struct fw_cdev_get_cycle_timer2)
/*
* FW_CDEV_VERSION History
* 1 (2.6.22) - initial version
* 2 (2.6.30) - changed &fw_cdev_event_iso_interrupt.header if
* &fw_cdev_create_iso_context.header_size is 8 or more
* (2.6.32) - added time stamp to xmit &fw_cdev_event_iso_interrupt
* (2.6.33) - IR has always packet-per-buffer semantics now, not one of
* dual-buffer or packet-per-buffer depending on hardware
* 3 (2.6.34) - made &fw_cdev_get_cycle_timer reliable
*/
#define FW_CDEV_VERSION 2
#define FW_CDEV_VERSION 3
/**
* struct fw_cdev_get_info - General purpose information ioctl
......@@ -544,20 +551,43 @@ struct fw_cdev_stop_iso {
/**
* struct fw_cdev_get_cycle_timer - read cycle timer register
* @local_time: system time, in microseconds since the Epoch
* @cycle_timer: isochronous cycle timer, as per OHCI 1.1 clause 5.13
* @cycle_timer: Cycle Time register contents
*
* The %FW_CDEV_IOC_GET_CYCLE_TIMER ioctl reads the isochronous cycle timer
* and also the system clock. This allows to express the receive time of an
* isochronous packet as a system time with microsecond accuracy.
* and also the system clock (%CLOCK_REALTIME). This allows to express the
* receive time of an isochronous packet as a system time.
*
* @cycle_timer consists of 7 bits cycleSeconds, 13 bits cycleCount, and
* 12 bits cycleOffset, in host byte order.
* 12 bits cycleOffset, in host byte order. Cf. the Cycle Time register
* per IEEE 1394 or Isochronous Cycle Timer register per OHCI-1394.
*
* In version 1 and 2 of the ABI, this ioctl returned unreliable (non-
* monotonic) @cycle_timer values on certain controllers.
*/
struct fw_cdev_get_cycle_timer {
__u64 local_time;
__u32 cycle_timer;
};
/**
* struct fw_cdev_get_cycle_timer2 - read cycle timer register
* @tv_sec: system time, seconds
* @tv_nsec: system time, sub-seconds part in nanoseconds
* @clk_id: input parameter, clock from which to get the system time
* @cycle_timer: Cycle Time register contents
*
* The %FW_CDEV_IOC_GET_CYCLE_TIMER2 works like
* %FW_CDEV_IOC_GET_CYCLE_TIMER but lets you choose a clock like with POSIX'
* clock_gettime function. Supported @clk_id values are POSIX' %CLOCK_REALTIME
* and %CLOCK_MONOTONIC and Linux' %CLOCK_MONOTONIC_RAW.
*/
struct fw_cdev_get_cycle_timer2 {
__s64 tv_sec;
__s32 tv_nsec;
__s32 clk_id;
__u32 cycle_timer;
};
/**
* struct fw_cdev_allocate_iso_resource - (De)allocate a channel or bandwidth
* @closure: Passed back to userspace in correponding iso resource events
......
......@@ -65,12 +65,13 @@
#define CSR_DIRECTORY_ID 0x20
struct fw_csr_iterator {
u32 *p;
u32 *end;
const u32 *p;
const u32 *end;
};
void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p);
void fw_csr_iterator_init(struct fw_csr_iterator *ci, const u32 *p);
int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value);
int fw_csr_string(const u32 *directory, int key, char *buf, size_t size);
extern struct bus_type fw_bus_type;
......@@ -162,7 +163,7 @@ struct fw_device {
struct mutex client_list_mutex;
struct list_head client_list;
u32 *config_rom;
const u32 *config_rom;
size_t config_rom_length;
int config_rom_retries;
unsigned is_local:1;
......@@ -204,7 +205,7 @@ int fw_device_enable_phys_dma(struct fw_device *device);
*/
struct fw_unit {
struct device device;
u32 *directory;
const u32 *directory;
struct fw_attribute_group attribute_group;
};
......
......@@ -770,7 +770,6 @@
#define PCI_VENDOR_ID_TI 0x104c
#define PCI_DEVICE_ID_TI_TVP4020 0x3d07
#define PCI_DEVICE_ID_TI_4450 0x8011
#define PCI_DEVICE_ID_TI_TSB43AB22 0x8023
#define PCI_DEVICE_ID_TI_XX21_XX11 0x8031
#define PCI_DEVICE_ID_TI_XX21_XX11_FM 0x8033
#define PCI_DEVICE_ID_TI_XX21_XX11_SD 0x8034
......
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