2009-12-26 00:41:52

by Stefan Richter

[permalink] [raw]
Subject: [PATCH 0/3] firewire: small refactoring

This moves some functionality related to config ROM parsing into a core
function for use by drivers (repost of a patch from Clemens Ladisch to
linux1394-devel), plus small related bits.

firewire: add fw_csr_string() helper function
firewire: core: fw_csr_string addendum
firewire: qualify config ROM cache pointers as const pointers

drivers/firewire/core-device.c | 127 ++++++++++++++++--------
drivers/firewire/sbp2.c | 5
drivers/media/dvb/firewire/firedtv-fw.c | 39 -------
include/linux/firewire.h | 11 +-
4 files changed, 103 insertions(+), 79 deletions(-)
--
Stefan Richter
-=====-==--= ==-- ==-=-
http://arcgraph.de/sr/


2009-12-26 00:42:53

by Stefan Richter

[permalink] [raw]
Subject: [PATCH 1/3 resend] firewire: add fw_csr_string() helper function

Date: Thu, 24 Dec 2009 11:59:57 +0100
From: Clemens Ladisch <[email protected]>

The core (sysfs attributes), the firedtv driver, and possible future
drivers all read strings from some configuration ROM directory. Factor
out the generic code from show_text_leaf() into a new helper function,
modified slightly to handle arbitrary buffer sizes.

Signed-off-by: Clemens Ladisch <[email protected]>
Signed-off-by: Stefan Richter <[email protected]>
---
drivers/firewire/core-device.c | 110 +++++++++++++++++-------
drivers/media/dvb/firewire/firedtv-fw.c | 39 +--------
include/linux/firewire.h | 2 +
3 files changed, 84 insertions(+), 67 deletions(-)

Index: linux-2.6.33-rc2/include/linux/firewire.h
===================================================================
--- linux-2.6.33-rc2.orig/include/linux/firewire.h
+++ linux-2.6.33-rc2/include/linux/firewire.h
@@ -72,6 +72,8 @@ struct fw_csr_iterator {
void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p);
int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value);

+int fw_csr_string(u32 *directory, int key, char *buf, size_t size);
+
extern struct bus_type fw_bus_type;

struct fw_card_driver;
Index: linux-2.6.33-rc2/drivers/firewire/core-device.c
===================================================================
--- linux-2.6.33-rc2.orig/drivers/firewire/core-device.c
+++ linux-2.6.33-rc2/drivers/firewire/core-device.c
@@ -59,6 +59,67 @@ int fw_csr_iterator_next(struct fw_csr_i
}
EXPORT_SYMBOL(fw_csr_iterator_next);

+static u32 *search_leaf(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(u32 *block, char *buf, size_t size)
+{
+ unsigned int quadlets, length;
+
+ 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 (length = 0; length < quadlets * 4 && length + 1 < size; length++) {
+ char c = block[length / 4] >> (24 - 8 * (length % 4));
+ if (c == '\0')
+ break;
+ buf[length] = c;
+ }
+ buf[length] = '\0';
+ return length;
+}
+
+/**
+ * fw_csr_string - reads a string from the configuration ROM
+ * @directory: device or unit directory;
+ * fw_device->config_rom+5 or fw_unit->directory
+ * @key: the key of the preceding directory entry
+ * @buf: where to put the string
+ * @size: size of @buf, in bytes
+ *
+ * Returns string length (>= 0) or error code (< 0).
+ */
+int fw_csr_string(u32 *directory, int key, char *buf, size_t size)
+{
+ 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,
@@ -226,10 +287,10 @@ static ssize_t show_text_leaf(struct 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;
+ u32 *dir;
+ size_t bufsize;
+ char dummy_buf[2];
+ int ret;

down_read(&fw_device_rwsem);

@@ -238,40 +299,23 @@ static ssize_t show_text_leaf(struct 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;
-
- if (block[1] != 0 || block[2] != 0)
- /* Unknown encoding. */
- goto out;
+ ret = fw_csr_string(dir, attr->key, buf, bufsize);

- 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;
Index: linux-2.6.33-rc2/drivers/media/dvb/firewire/firedtv-fw.c
===================================================================
--- linux-2.6.33-rc2.orig/drivers/media/dvb/firewire/firedtv-fw.c
+++ linux-2.6.33-rc2/drivers/media/dvb/firewire/firedtv-fw.c
@@ -239,47 +239,18 @@ static const struct fw_address_region fc
};

/* 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;


--
Stefan Richter
-=====-==--= ==-- ==-=-
http://arcgraph.de/sr/

2009-12-26 00:43:45

by Stefan Richter

[permalink] [raw]
Subject: [PATCH 2/3] firewire: core: fw_csr_string addendum

Witespace and comment changes, and a different way to say i + 1 < end.

Signed-off-by: Stefan Richter <[email protected]>
---
drivers/firewire/core-device.c | 26 ++++++++++++++++----------
include/linux/firewire.h | 1 -
2 files changed, 16 insertions(+), 11 deletions(-)

Index: linux-2.6.33-rc2/drivers/firewire/core-device.c
===================================================================
--- linux-2.6.33-rc2.orig/drivers/firewire/core-device.c
+++ linux-2.6.33-rc2/drivers/firewire/core-device.c
@@ -69,19 +69,22 @@ static u32 *search_leaf(u32 *directory,
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(u32 *block, char *buf, size_t size)
{
- unsigned int quadlets, length;
+ unsigned int quadlets, i;
+ char c;

if (!size || !buf)
return -EINVAL;

- quadlets = min(block[0] >> 16, 256u);
+ quadlets = min(block[0] >> 16, 256U);
if (quadlets < 2)
return -ENODATA;

@@ -91,31 +94,34 @@ static int textual_leaf_to_string(u32 *b

block += 3;
quadlets -= 2;
- for (length = 0; length < quadlets * 4 && length + 1 < size; length++) {
- char c = block[length / 4] >> (24 - 8 * (length % 4));
+ for (i = 0; i < quadlets * 4 && i < size - 1; i++) {
+ c = block[i / 4] >> (24 - 8 * (i % 4));
if (c == '\0')
break;
- buf[length] = c;
+ buf[i] = c;
}
- buf[length] = '\0';
- return length;
+ buf[i] = '\0';
+
+ return i;
}

/**
* fw_csr_string - reads a string from the configuration ROM
- * @directory: device or unit directory;
- * fw_device->config_rom+5 or fw_unit->directory
+ * @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
*
- * Returns string length (>= 0) or error code (< 0).
+ * 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(u32 *directory, int key, char *buf, size_t size)
{
u32 *leaf = search_leaf(directory, key);
if (!leaf)
return -ENOENT;
+
return textual_leaf_to_string(leaf, buf, size);
}
EXPORT_SYMBOL(fw_csr_string);
Index: linux-2.6.33-rc2/include/linux/firewire.h
===================================================================
--- linux-2.6.33-rc2.orig/include/linux/firewire.h
+++ linux-2.6.33-rc2/include/linux/firewire.h
@@ -71,7 +71,6 @@ struct fw_csr_iterator {

void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p);
int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value);
-
int fw_csr_string(u32 *directory, int key, char *buf, size_t size);

extern struct bus_type fw_bus_type;

--
Stefan Richter
-=====-==--= ==-- ==-=-
http://arcgraph.de/sr/

2009-12-26 00:44:32

by Stefan Richter

[permalink] [raw]
Subject: [PATCH 3/3] firewire: qualify config ROM cache pointers as const pointers

Several config ROM related functions only peek at the ROM cache; mark
their arguments as const pointers. Ditto fw_device.config_rom and
fw_unit.directory, as the memory behind them is meant to be write-once.

Signed-off-by: Stefan Richter <[email protected]>
---
drivers/firewire/core-device.c | 21 +++++++++++----------
drivers/firewire/sbp2.c | 5 +++--
include/linux/firewire.h | 12 ++++++------
3 files changed, 20 insertions(+), 18 deletions(-)

Index: linux-2.6.33-rc2/drivers/firewire/core-device.c
===================================================================
--- linux-2.6.33-rc2.orig/drivers/firewire/core-device.c
+++ linux-2.6.33-rc2/drivers/firewire/core-device.c
@@ -43,7 +43,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,7 +59,7 @@ int fw_csr_iterator_next(struct fw_csr_i
}
EXPORT_SYMBOL(fw_csr_iterator_next);

-static u32 *search_leaf(u32 *directory, int search_key)
+static const u32 *search_leaf(const u32 *directory, int search_key)
{
struct fw_csr_iterator ci;
int last_key = 0, key, value;
@@ -76,7 +76,7 @@ static u32 *search_leaf(u32 *directory,
return NULL;
}

-static int textual_leaf_to_string(u32 *block, char *buf, size_t size)
+static int textual_leaf_to_string(const u32 *block, char *buf, size_t size)
{
unsigned int quadlets, i;
char c;
@@ -116,9 +116,9 @@ static int textual_leaf_to_string(u32 *b
* the immediate entry with @key. The string is zero-terminated.
* Returns strlen(buf) or a negative error code.
*/
-int fw_csr_string(u32 *directory, int key, char *buf, size_t size)
+int fw_csr_string(const u32 *directory, int key, char *buf, size_t size)
{
- u32 *leaf = search_leaf(directory, key);
+ const u32 *leaf = search_leaf(directory, key);
if (!leaf)
return -ENOENT;

@@ -128,7 +128,7 @@ 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;
@@ -262,7 +262,7 @@ static ssize_t show_immediate(struct 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);
@@ -293,7 +293,7 @@ static ssize_t show_text_leaf(struct dev
{
struct config_rom_attribute *attr =
container_of(dattr, struct config_rom_attribute, attr);
- u32 *dir;
+ const u32 *dir;
size_t bufsize;
char dummy_buf[2];
int ret;
@@ -421,7 +421,7 @@ static ssize_t guid_show(struct device *
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;
@@ -503,7 +503,8 @@ static int read_rom(struct fw_device *de
*/
static int read_bus_info_block(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;

Index: linux-2.6.33-rc2/drivers/firewire/sbp2.c
===================================================================
--- linux-2.6.33-rc2.orig/drivers/firewire/sbp2.c
+++ linux-2.6.33-rc2/drivers/firewire/sbp2.c
@@ -1014,7 +1014,8 @@ static int sbp2_add_logical_unit(struct
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(st
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;
Index: linux-2.6.33-rc2/include/linux/firewire.h
===================================================================
--- linux-2.6.33-rc2.orig/include/linux/firewire.h
+++ linux-2.6.33-rc2/include/linux/firewire.h
@@ -65,13 +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(u32 *directory, int key, char *buf, size_t size);
+int fw_csr_string(const u32 *directory, int key, char *buf, size_t size);

extern struct bus_type fw_bus_type;

@@ -163,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;
@@ -205,7 +205,7 @@ int fw_device_enable_phys_dma(struct fw_
*/
struct fw_unit {
struct device device;
- u32 *directory;
+ const u32 *directory;
struct fw_attribute_group attribute_group;
};


--
Stefan Richter
-=====-==--= ==-- ==-=-
http://arcgraph.de/sr/