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: (56 commits)
  ieee1394: remove garbage from Kconfig
  ieee1394: more help in Kconfig
  ieee1394: ohci1394: Fix mistake in printk message.
  ieee1394: ohci1394: remove unnecessary rcvPhyPkt bit flipping in LinkControl register
  ieee1394: ohci1394: fix cosmetic problem in error logging
  ieee1394: eth1394: send async streams at S100 on 1394b buses
  ieee1394: eth1394: fix error path in module_init
  ieee1394: eth1394: correct return codes in hard_start_xmit
  ieee1394: eth1394: hard_start_xmit is called in atomic context
  ieee1394: eth1394: some conditions are unlikely
  ieee1394: eth1394: clean up fragment_overlap
  ieee1394: eth1394: don't use alloc_etherdev
  ieee1394: eth1394: omit useless set_mac_address callback
  ieee1394: eth1394: CONFIG_INET is always defined
  ieee1394: eth1394: allow MTU bigger than 1500
  ieee1394: unexport highlevel_host_reset
  ieee1394: eth1394: contain host reset
  ieee1394: eth1394: shorter error messages
  ieee1394: eth1394: correct a memset argument
  ieee1394: eth1394: refactor .probe and .update
  ...
This commit is contained in:
Linus Torvalds 2007-04-30 08:59:57 -07:00
commit 40caf5ea5a
26 changed files with 1446 additions and 2013 deletions

View File

@ -1,11 +1,8 @@
# -*- shell-script -*-
menu "IEEE 1394 (FireWire) support"
config IEEE1394
tristate "IEEE 1394 (FireWire) support"
depends on PCI || BROKEN
select NET
help
IEEE 1394 describes a high performance serial bus, which is also
known as FireWire(tm) or i.Link(tm) and is used for connecting all
@ -35,24 +32,7 @@ config IEEE1394_VERBOSEDEBUG
Say Y if you really want or need the debugging output, everyone
else says N.
config IEEE1394_EXTRA_CONFIG_ROMS
bool "Build in extra config rom entries for certain functionality"
depends on IEEE1394
help
Some IEEE1394 functionality depends on extra config rom entries
being available in the host adapters CSR. These options will
allow you to choose which ones.
config IEEE1394_CONFIG_ROM_IP1394
bool "IP-1394 Entry"
depends on IEEE1394_EXTRA_CONFIG_ROMS && IEEE1394
help
Adds an entry for using IP-over-1394. If you want to use your
IEEE1394 bus as a network for IP systems (including interacting
with MacOSX and WinXP IP-over-1394), enable this option and the
eth1394 option below.
comment "Device Drivers"
comment "Controllers"
depends on IEEE1394
comment "Texas Instruments PCILynx requires I2C"
@ -70,6 +50,10 @@ config IEEE1394_PCILYNX
To compile this driver as a module, say M here: the
module will be called pcilynx.
Only some old and now very rare PCI and CardBus cards and
PowerMacs G3 B&W contain the PCILynx controller. Therefore
almost everybody can say N here.
config IEEE1394_OHCI1394
tristate "OHCI-1394 support"
depends on PCI && IEEE1394
@ -83,7 +67,7 @@ config IEEE1394_OHCI1394
To compile this driver as a module, say M here: the
module will be called ohci1394.
comment "Protocol Drivers"
comment "Protocols"
depends on IEEE1394
config IEEE1394_VIDEO1394
@ -121,11 +105,15 @@ config IEEE1394_SBP2_PHYS_DMA
This option is buggy and currently broken on some architectures.
If unsure, say N.
config IEEE1394_ETH1394_ROM_ENTRY
depends on IEEE1394
bool
default n
config IEEE1394_ETH1394
tristate "Ethernet over 1394"
tristate "IP over 1394"
depends on IEEE1394 && EXPERIMENTAL && INET
select IEEE1394_CONFIG_ROM_IP1394
select IEEE1394_EXTRA_CONFIG_ROMS
select IEEE1394_ETH1394_ROM_ENTRY
help
This driver implements a functional majority of RFC 2734: IPv4 over
1394. It will provide IP connectivity with implementations of RFC
@ -134,6 +122,8 @@ config IEEE1394_ETH1394
This driver is still considered experimental. It does not yet support
MCAP, therefore multicast support is significantly limited.
The module is called eth1394 although it does not emulate Ethernet.
config IEEE1394_DV1394
tristate "OHCI-DV I/O support (deprecated)"
depends on IEEE1394 && IEEE1394_OHCI1394
@ -146,12 +136,12 @@ config IEEE1394_RAWIO
tristate "Raw IEEE1394 I/O support"
depends on IEEE1394
help
Say Y here if you want support for the raw device. This is generally
a good idea, so you should say Y here. The raw device enables
direct communication of user programs with the IEEE 1394 bus and
thus with the attached peripherals.
This option adds support for the raw1394 device file which enables
direct communication of user programs with the IEEE 1394 bus and thus
with the attached peripherals. Almost all application programs which
access FireWire require this option.
To compile this driver as a module, say M here: the
module will be called raw1394.
To compile this driver as a module, say M here: the module will be
called raw1394.
endmenu

View File

@ -26,12 +26,6 @@ struct hpsb_config_rom_entry {
/* Base initialization, called at module load */
int (*init)(void);
/* Add entry to specified host */
int (*add)(struct hpsb_host *host);
/* Remove entry from specified host */
void (*remove)(struct hpsb_host *host);
/* Cleanup called at module exit */
void (*cleanup)(void);
@ -39,7 +33,7 @@ struct hpsb_config_rom_entry {
unsigned int flag;
};
/* The default host entry. This must succeed. */
int hpsb_default_host_entry(struct hpsb_host *host)
{
struct csr1212_keyval *root;
@ -63,9 +57,9 @@ int hpsb_default_host_entry(struct hpsb_host *host)
return -ENOMEM;
}
ret = csr1212_associate_keyval(vend_id, text);
csr1212_associate_keyval(vend_id, text);
csr1212_release_keyval(text);
ret |= csr1212_attach_keyval_to_directory(root, vend_id);
ret = csr1212_attach_keyval_to_directory(root, vend_id);
csr1212_release_keyval(vend_id);
if (ret != CSR1212_SUCCESS) {
csr1212_destroy_csr(host->csr.rom);
@ -78,7 +72,7 @@ int hpsb_default_host_entry(struct hpsb_host *host)
}
#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394
#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
#include "eth1394.h"
static struct csr1212_keyval *ip1394_ud;
@ -103,10 +97,12 @@ static int config_rom_ip1394_init(void)
if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc)
goto ip1394_fail;
if (csr1212_associate_keyval(spec_id, spec_desc) == CSR1212_SUCCESS &&
csr1212_associate_keyval(ver, ver_desc) == CSR1212_SUCCESS &&
csr1212_attach_keyval_to_directory(ip1394_ud, spec_id) == CSR1212_SUCCESS &&
csr1212_attach_keyval_to_directory(ip1394_ud, ver) == CSR1212_SUCCESS)
csr1212_associate_keyval(spec_id, spec_desc);
csr1212_associate_keyval(ver, ver_desc);
if (csr1212_attach_keyval_to_directory(ip1394_ud, spec_id)
== CSR1212_SUCCESS &&
csr1212_attach_keyval_to_directory(ip1394_ud, ver)
== CSR1212_SUCCESS)
ret = 0;
ip1394_fail:
@ -135,7 +131,7 @@ static void config_rom_ip1394_cleanup(void)
}
}
static int config_rom_ip1394_add(struct hpsb_host *host)
int hpsb_config_rom_ip1394_add(struct hpsb_host *host)
{
if (!ip1394_ud)
return -ENODEV;
@ -144,92 +140,55 @@ static int config_rom_ip1394_add(struct hpsb_host *host)
ip1394_ud) != CSR1212_SUCCESS)
return -ENOMEM;
host->config_roms |= HPSB_CONFIG_ROM_ENTRY_IP1394;
host->update_config_rom = 1;
return 0;
}
EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_add);
static void config_rom_ip1394_remove(struct hpsb_host *host)
void hpsb_config_rom_ip1394_remove(struct hpsb_host *host)
{
csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, ip1394_ud);
host->config_roms &= ~HPSB_CONFIG_ROM_ENTRY_IP1394;
host->update_config_rom = 1;
}
EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_remove);
static struct hpsb_config_rom_entry ip1394_entry = {
.name = "ip1394",
.init = config_rom_ip1394_init,
.add = config_rom_ip1394_add,
.remove = config_rom_ip1394_remove,
.cleanup = config_rom_ip1394_cleanup,
.flag = HPSB_CONFIG_ROM_ENTRY_IP1394,
};
#endif /* CONFIG_IEEE1394_CONFIG_ROM_IP1394 */
#endif /* CONFIG_IEEE1394_ETH1394_ROM_ENTRY */
static struct hpsb_config_rom_entry *const config_rom_entries[] = {
#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394
#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
&ip1394_entry,
#endif
NULL,
};
/* Initialize all config roms */
int hpsb_init_config_roms(void)
{
int i, error = 0;
for (i = 0; config_rom_entries[i]; i++) {
if (!config_rom_entries[i]->init)
continue;
for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
if (config_rom_entries[i]->init()) {
HPSB_ERR("Failed to initialize config rom entry `%s'",
config_rom_entries[i]->name);
error = -1;
} else
HPSB_DEBUG("Initialized config rom entry `%s'",
config_rom_entries[i]->name);
}
return error;
}
/* Cleanup all config roms */
void hpsb_cleanup_config_roms(void)
{
int i;
for (i = 0; config_rom_entries[i]; i++) {
if (config_rom_entries[i]->cleanup)
for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
config_rom_entries[i]->cleanup();
}
}
int hpsb_add_extra_config_roms(struct hpsb_host *host)
{
int i, error = 0;
for (i = 0; config_rom_entries[i]; i++) {
if (config_rom_entries[i]->add(host)) {
HPSB_ERR("fw-host%d: Failed to attach config rom entry `%s'",
host->id, config_rom_entries[i]->name);
error = -1;
} else {
host->config_roms |= config_rom_entries[i]->flag;
host->update_config_rom = 1;
}
}
return error;
}
void hpsb_remove_extra_config_roms(struct hpsb_host *host)
{
int i;
for (i = 0; config_rom_entries[i]; i++) {
if (!(host->config_roms & config_rom_entries[i]->flag))
continue;
config_rom_entries[i]->remove(host);
host->config_roms &= ~config_rom_entries[i]->flag;
host->update_config_rom = 1;
}
}

View File

@ -1,27 +1,19 @@
#ifndef _IEEE1394_CONFIG_ROMS_H
#define _IEEE1394_CONFIG_ROMS_H
#include "ieee1394_types.h"
#include "hosts.h"
struct hpsb_host;
/* The default host entry. This must succeed. */
int hpsb_default_host_entry(struct hpsb_host *host);
/* Initialize all config roms */
int hpsb_init_config_roms(void);
/* Cleanup all config roms */
void hpsb_cleanup_config_roms(void);
/* Add extra config roms to specified host */
int hpsb_add_extra_config_roms(struct hpsb_host *host);
/* Remove extra config roms from specified host */
void hpsb_remove_extra_config_roms(struct hpsb_host *host);
/* List of flags to check if a host contains a certain extra config rom
* entry. Available in the host->config_roms member. */
#define HPSB_CONFIG_ROM_ENTRY_IP1394 0x00000001
#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
int hpsb_config_rom_ip1394_add(struct hpsb_host *host);
void hpsb_config_rom_ip1394_remove(struct hpsb_host *host);
#endif
#endif /* _IEEE1394_CONFIG_ROMS_H */

File diff suppressed because it is too large Load Diff

View File

@ -30,94 +30,13 @@
#ifndef __CSR1212_H__
#define __CSR1212_H__
/* Compatibility layer */
#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/vmalloc.h>
#include <asm/pgalloc.h>
#define CSR1212_MALLOC(size) vmalloc((size))
#define CSR1212_FREE(ptr) vfree(ptr)
#define CSR1212_BE16_TO_CPU(quad) be16_to_cpu(quad)
#define CSR1212_CPU_TO_BE16(quad) cpu_to_be16(quad)
#define CSR1212_BE32_TO_CPU(quad) be32_to_cpu(quad)
#define CSR1212_CPU_TO_BE32(quad) cpu_to_be32(quad)
#define CSR1212_BE64_TO_CPU(quad) be64_to_cpu(quad)
#define CSR1212_CPU_TO_BE64(quad) cpu_to_be64(quad)
#define CSR1212_MALLOC(size) kmalloc((size), GFP_KERNEL)
#define CSR1212_FREE(ptr) kfree(ptr)
#define CSR1212_LE16_TO_CPU(quad) le16_to_cpu(quad)
#define CSR1212_CPU_TO_LE16(quad) cpu_to_le16(quad)
#define CSR1212_LE32_TO_CPU(quad) le32_to_cpu(quad)
#define CSR1212_CPU_TO_LE32(quad) cpu_to_le32(quad)
#define CSR1212_LE64_TO_CPU(quad) le64_to_cpu(quad)
#define CSR1212_CPU_TO_LE64(quad) cpu_to_le64(quad)
#include <linux/errno.h>
#define CSR1212_SUCCESS (0)
#define CSR1212_EINVAL (-EINVAL)
#define CSR1212_ENOMEM (-ENOMEM)
#define CSR1212_ENOENT (-ENOENT)
#define CSR1212_EIO (-EIO)
#define CSR1212_EBUSY (-EBUSY)
#else /* Userspace */
#include <sys/types.h>
#include <malloc.h>
#define CSR1212_MALLOC(size) malloc(size)
#define CSR1212_FREE(ptr) free(ptr)
#include <endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
#include <byteswap.h>
#define CSR1212_BE16_TO_CPU(quad) bswap_16(quad)
#define CSR1212_CPU_TO_BE16(quad) bswap_16(quad)
#define CSR1212_BE32_TO_CPU(quad) bswap_32(quad)
#define CSR1212_CPU_TO_BE32(quad) bswap_32(quad)
#define CSR1212_BE64_TO_CPU(quad) bswap_64(quad)
#define CSR1212_CPU_TO_BE64(quad) bswap_64(quad)
#define CSR1212_LE16_TO_CPU(quad) (quad)
#define CSR1212_CPU_TO_LE16(quad) (quad)
#define CSR1212_LE32_TO_CPU(quad) (quad)
#define CSR1212_CPU_TO_LE32(quad) (quad)
#define CSR1212_LE64_TO_CPU(quad) (quad)
#define CSR1212_CPU_TO_LE64(quad) (quad)
#else
#define CSR1212_BE16_TO_CPU(quad) (quad)
#define CSR1212_CPU_TO_BE16(quad) (quad)
#define CSR1212_BE32_TO_CPU(quad) (quad)
#define CSR1212_CPU_TO_BE32(quad) (quad)
#define CSR1212_BE64_TO_CPU(quad) (quad)
#define CSR1212_CPU_TO_BE64(quad) (quad)
#define CSR1212_LE16_TO_CPU(quad) bswap_16(quad)
#define CSR1212_CPU_TO_LE16(quad) bswap_16(quad)
#define CSR1212_LE32_TO_CPU(quad) bswap_32(quad)
#define CSR1212_CPU_TO_LE32(quad) bswap_32(quad)
#define CSR1212_LE64_TO_CPU(quad) bswap_64(quad)
#define CSR1212_CPU_TO_LE64(quad) bswap_64(quad)
#endif
#include <errno.h>
#define CSR1212_SUCCESS (0)
#define CSR1212_EINVAL (EINVAL)
#define CSR1212_ENOMEM (ENOMEM)
#define CSR1212_ENOENT (ENOENT)
#define CSR1212_EIO (EIO)
#define CSR1212_EBUSY (EBUSY)
#endif
#define CSR1212_KV_VAL_MASK 0xffffff
#define CSR1212_KV_KEY_SHIFT 24
#define CSR1212_KV_KEY_TYPE_SHIFT 6
#define CSR1212_KV_KEY_ID_MASK 0x3f
#define CSR1212_KV_KEY_TYPE_MASK 0x3 /* After shift */
/* CSR 1212 key types */
@ -190,48 +109,22 @@
#define CSR1212_UNITS_SPACE_END (CSR1212_UNITS_SPACE_BASE + CSR1212_UNITS_SPACE_SIZE)
#define CSR1212_UNITS_SPACE_OFFSET (CSR1212_UNITS_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
#define CSR1212_EXTENDED_ROM_SIZE (0x10000 * sizeof(u_int32_t))
#define CSR1212_INVALID_ADDR_SPACE -1
/* Config ROM image structures */
struct csr1212_bus_info_block_img {
u_int8_t length;
u_int8_t crc_length;
u_int16_t crc;
u8 length;
u8 crc_length;
u16 crc;
/* Must be last */
u_int32_t data[0]; /* older gcc can't handle [] which is standard */
};
#define CSR1212_KV_KEY(quad) (CSR1212_BE32_TO_CPU(quad) >> CSR1212_KV_KEY_SHIFT)
#define CSR1212_KV_KEY_TYPE(quad) (CSR1212_KV_KEY(quad) >> CSR1212_KV_KEY_TYPE_SHIFT)
#define CSR1212_KV_KEY_ID(quad) (CSR1212_KV_KEY(quad) & CSR1212_KV_KEY_ID_MASK)
#define CSR1212_KV_VAL(quad) (CSR1212_BE32_TO_CPU(quad) & CSR1212_KV_VAL_MASK)
#define CSR1212_SET_KV_KEY(quad, key) ((quad) = \
CSR1212_CPU_TO_BE32(CSR1212_KV_VAL(quad) | ((key) << CSR1212_KV_KEY_SHIFT)))
#define CSR1212_SET_KV_VAL(quad, val) ((quad) = \
CSR1212_CPU_TO_BE32((CSR1212_KV_KEY(quad) << CSR1212_KV_KEY_SHIFT) | (val)))
#define CSR1212_SET_KV_TYPEID(quad, type, id) ((quad) = \
CSR1212_CPU_TO_BE32(CSR1212_KV_VAL(quad) | \
(((((type) & CSR1212_KV_KEY_TYPE_MASK) << CSR1212_KV_KEY_TYPE_SHIFT) | \
((id) & CSR1212_KV_KEY_ID_MASK)) << CSR1212_KV_KEY_SHIFT)))
typedef u_int32_t csr1212_quad_t;
struct csr1212_keyval_img {
u_int16_t length;
u_int16_t crc;
/* Must be last */
csr1212_quad_t data[0]; /* older gcc can't handle [] which is standard */
u32 data[0]; /* older gcc can't handle [] which is standard */
};
struct csr1212_leaf {
int len;
u_int32_t *data;
u32 *data;
};
struct csr1212_dentry {
@ -246,12 +139,12 @@ struct csr1212_directory {
struct csr1212_keyval {
struct {
u_int8_t type;
u_int8_t id;
u8 type;
u8 id;
} key;
union {
u_int32_t immediate;
u_int32_t csr_offset;
u32 immediate;
u32 csr_offset;
struct csr1212_leaf leaf;
struct csr1212_directory directory;
} value;
@ -260,15 +153,15 @@ struct csr1212_keyval {
/* used in generating and/or parsing CSR image */
struct csr1212_keyval *next, *prev; /* flat list of CSR elements */
u_int32_t offset; /* position in CSR from 0xffff f000 0000 */
u_int8_t valid; /* flag indicating keyval has valid data*/
u32 offset; /* position in CSR from 0xffff f000 0000 */
u8 valid; /* flag indicating keyval has valid data*/
};
struct csr1212_cache_region {
struct csr1212_cache_region *next, *prev;
u_int32_t offset_start; /* inclusive */
u_int32_t offset_end; /* exclusive */
u32 offset_start; /* inclusive */
u32 offset_end; /* exclusive */
};
struct csr1212_csr_rom_cache {
@ -276,18 +169,18 @@ struct csr1212_csr_rom_cache {
struct csr1212_cache_region *filled_head, *filled_tail;
struct csr1212_keyval *layout_head, *layout_tail;
size_t size;
u_int32_t offset;
u32 offset;
struct csr1212_keyval *ext_rom;
size_t len;
/* Must be last */
u_int32_t data[0]; /* older gcc can't handle [] which is standard */
u32 data[0]; /* older gcc can't handle [] which is standard */
};
struct csr1212_csr {
size_t bus_info_len; /* bus info block length in bytes */
size_t crc_len; /* crc length in bytes */
u_int32_t *bus_info_data; /* bus info data incl bus name and EUI */
u32 *bus_info_data; /* bus info data incl bus name and EUI */
void *private; /* private, bus specific data */
struct csr1212_bus_ops *ops;
@ -305,52 +198,38 @@ struct csr1212_bus_ops {
* from remote nodes when parsing a Config ROM (i.e., read Config ROM
* entries located in the Units Space. Must return 0 on success
* anything else indicates an error. */
int (*bus_read) (struct csr1212_csr *csr, u_int64_t addr,
u_int16_t length, void *buffer, void *private);
int (*bus_read) (struct csr1212_csr *csr, u64 addr,
u16 length, void *buffer, void *private);
/* This function is used by csr1212 to allocate a region in units space
* in the event that Config ROM entries don't all fit in the predefined
* 1K region. The void *private parameter is private member of struct
* csr1212_csr. */
u_int64_t (*allocate_addr_range) (u_int64_t size, u_int32_t alignment,
void *private);
u64 (*allocate_addr_range) (u64 size, u32 alignment, void *private);
/* This function is used by csr1212 to release a region in units space
* that is no longer needed. */
void (*release_addr) (u_int64_t addr, void *private);
void (*release_addr) (u64 addr, void *private);
/* This function is used by csr1212 to determine the max read request
* supported by a remote node when reading the ConfigROM space. Must
* return 0, 1, or 2 per IEEE 1212. */
int (*get_max_rom) (u_int32_t *bus_info, void *private);
int (*get_max_rom) (u32 *bus_info, void *private);
};
/* Descriptor Leaf manipulation macros */
#define CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT 24
#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK 0xffffff
#define CSR1212_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u_int32_t))
#define CSR1212_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u32))
#define CSR1212_DESCRIPTOR_LEAF_TYPE(kv) \
(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[0]) >> CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)
(be32_to_cpu((kv)->value.leaf.data[0]) >> \
CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)
#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) \
(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[0]) & \
(be32_to_cpu((kv)->value.leaf.data[0]) & \
CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK)
#define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \
(&((kv)->value.leaf.data[1]))
#define CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, type) \
((kv)->value.leaf.data[0] = \
CSR1212_CPU_TO_BE32(CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) | \
((type) << CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)))
#define CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, spec_id) \
((kv)->value.leaf.data[0] = \
CSR1212_CPU_TO_BE32((CSR1212_DESCRIPTOR_LEAF_TYPE(kv) << \
CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) | \
((spec_id) & CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK)))
/* Text Descriptor Leaf manipulation macros */
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT 28
@ -358,182 +237,21 @@ struct csr1212_bus_ops {
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT 16
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK 0xfff /* after shift */
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u_int32_t))
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u32))
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) \
(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) >> \
(be32_to_cpu((kv)->value.leaf.data[1]) >> \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT)
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) \
((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) >> \
((be32_to_cpu((kv)->value.leaf.data[1]) >> \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT) & \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK)
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) \
(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]) & \
(be32_to_cpu((kv)->value.leaf.data[1]) & \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK)
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv) \
(&((kv)->value.leaf.data[2]))
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, width) \
((kv)->value.leaf.data[1] = \
((kv)->value.leaf.data[1] & \
CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK << \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT))) | \
CSR1212_CPU_TO_BE32(((width) & \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK) << \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT))
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, char_set) \
((kv)->value.leaf.data[1] = \
((kv)->value.leaf.data[1] & \
CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK << \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT))) | \
CSR1212_CPU_TO_BE32(((char_set) & \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK) << \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT))
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language) \
((kv)->value.leaf.data[1] = \
((kv)->value.leaf.data[1] & \
CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | \
CSR1212_CPU_TO_BE32(((language) & \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK)))
/* Icon Descriptor Leaf manipulation macros */
#define CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK 0xffffff
#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT 30
#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK 0x3 /* after shift */
#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT 16
#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK 0xf /* after shift */
#define CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff
#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT 16
#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK 0xffff /* after shift */
#define CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK 0xffff
#define CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD (3 * sizeof(u_int32_t))
#define CSR1212_ICON_DESCRIPTOR_LEAF_VERSION(kv) \
(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[2]) & \
CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK)
#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH(kv) \
(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) >> \
CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT)
#define CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE(kv) \
((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) >> \
CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT) & \
CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK)
#define CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE(kv) \
(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[3]) & \
CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK)
#define CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN(kv) \
((CSR1212_BE32_TO_CPU((kv)->value.leaf.data[4]) >> \
CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_HSCAN_SHIFT) & \
CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_HSCAN_MASK)
#define CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN(kv) \
(CSR1212_BE32_TO_CPU((kv)->value.leaf.data[4]) & \
CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK)
#define CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv) \
(&((kv)->value.leaf.data[5]))
static inline u_int32_t *CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(struct csr1212_keyval *kv)
{
static const int pd[4] = { 0, 4, 16, 256 };
static const int cs[16] = { 4, 2 };
int ps = pd[CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH(kv)];
return &kv->value.leaf.data[5 +
(ps * cs[CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE(kv)]) /
sizeof(u_int32_t)];
}
#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version) \
((kv)->value.leaf.data[2] = \
((kv)->value.leaf.data[2] & \
CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK))) | \
CSR1212_CPU_TO_BE32(((version) & \
CSR1212_ICON_DESCRIPTOR_LEAF_VERSION_MASK)))
#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth) \
((kv)->value.leaf.data[3] = \
((kv)->value.leaf.data[3] & \
CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK << \
CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT))) | \
CSR1212_CPU_TO_BE32(((palette_depth) & \
CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_MASK) << \
CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE_DEPTH_SHIFT))
#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space) \
((kv)->value.leaf.data[3] = \
((kv)->value.leaf.data[3] & \
CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK << \
CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT))) | \
CSR1212_CPU_TO_BE32(((color_space) & \
CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_MASK) << \
CSR1212_ICON_DESCRIPTOR_LEAF_COLOR_SPACE_SHIFT))
#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language) \
((kv)->value.leaf.data[3] = \
((kv)->value.leaf.data[3] & \
CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | \
CSR1212_CPU_TO_BE32(((language) & \
CSR1212_ICON_DESCRIPTOR_LEAF_LANGUAGE_MASK)))
#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan) \
((kv)->value.leaf.data[4] = \
((kv)->value.leaf.data[4] & \
CSR1212_CPU_TO_BE32(~(CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK << \
CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT))) | \
CSR1212_CPU_TO_BE32(((hscan) & \
CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_MASK) << \
CSR1212_ICON_DESCRIPTOR_LEAF_HSCAN_SHIFT))
#define CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan) \
((kv)->value.leaf.data[4] = \
(((kv)->value.leaf.data[4] & \
CSR1212_CPU_TO_BE32(~CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK))) | \
CSR1212_CPU_TO_BE32(((vscan) & \
CSR1212_ICON_DESCRIPTOR_LEAF_VSCAN_MASK)))
/* Modifiable Descriptor Leaf manipulation macros */
#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT 16
#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK 0xffff
#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_SHIFT 32
#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK 0xffff
#define CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_LO_MASK 0xffffffffULL
#define CSR1212_MODIFIABLE_DESCRIPTOR_MAX_SIZE(kv) \
CSR1212_BE16_TO_CPU((kv)->value.leaf.data[0] >> CSR1212_MODIFIABLE_DESCRIPTOR_MAX_SIZE_SHIFT)
#define CSR1212_MODIFIABLE_DESCRIPTOR_ADDRESS(kv) \
(CSR1212_BE16_TO_CPU(((u_int64_t)((kv)->value.leaf.data[0])) << \
CSR1212_MODIFIABLE_DESCRIPTOR_ADDR_HI_SHIFT) | \
CSR1212_BE32_TO_CPU((kv)->value.leaf.data[1]))
#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, size) \
((kv)->value.leaf.data[0] = \
((kv)->value.leaf.data[0] & \
CSR1212_CPU_TO_BE32(~(CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK << \
CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT))) | \
CSR1212_CPU_TO_BE32(((size) & \
CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_MASK) << \
CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_MAX_SIZE_SHIFT))
#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, addr) \
((kv)->value.leaf.data[0] = \
((kv)->value.leaf.data[0] & \
CSR1212_CPU_TO_BE32(~(CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK))) | \
CSR1212_CPU_TO_BE32(((addr) & \
CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_HI_MASK)))
#define CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, addr) \
((kv)->value.leaf.data[1] = \
CSR1212_CPU_TO_BE32(addr & CSR1212_MODIFIABLE_DESCRIPTOR_LEAF_ADDR_LO_MASK))
/* The following 2 function are for creating new Configuration ROM trees. The
* first function is used for both creating local trees and parsing remote
@ -543,11 +261,10 @@ extern struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
size_t bus_info_size,
void *private);
extern void csr1212_init_local_csr(struct csr1212_csr *csr,
const u_int32_t *bus_info_data, int max_rom);
const u32 *bus_info_data, int max_rom);
/* The following function destroys a Configuration ROM tree and release all
* memory taken by the tree. */
/* Destroy a Configuration ROM tree and release all memory taken by the tree. */
extern void csr1212_destroy_csr(struct csr1212_csr *csr);
@ -555,50 +272,20 @@ extern void csr1212_destroy_csr(struct csr1212_csr *csr);
* a Configuration ROM tree. Code that creates new keyvals with these functions
* must release those keyvals with csr1212_release_keyval() when they are no
* longer needed. */
extern struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value);
extern struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data,
size_t data_len);
extern struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key,
u_int32_t csr_offset);
extern struct csr1212_keyval *csr1212_new_directory(u_int8_t key);
extern struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec,
u_int32_t key,
u_int32_t value);
extern struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec,
u_int32_t key,
const void *data,
size_t data_len);
extern struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype,
u_int32_t specifier_id,
const void *data,
size_t data_len);
extern struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth,
u_int16_t cset,
u_int16_t language,
const void *data,
size_t data_len);
extern struct csr1212_keyval *csr1212_new_immediate(u8 key, u32 value);
extern struct csr1212_keyval *csr1212_new_directory(u8 key);
extern struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s);
extern struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version,
u_int8_t palette_depth,
u_int8_t color_space,
u_int16_t language,
u_int16_t hscan,
u_int16_t vscan,
u_int32_t *palette,
u_int32_t *pixels);
extern struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size,
u_int64_t address);
extern struct csr1212_keyval *csr1212_new_keyword_leaf(int strc,
const char *strv[]);
/* The following functions manage association between keyvals. Typically,
/* The following function manages association between keyvals. Typically,
* Descriptor Leaves and Directories will be associated with another keyval and
* it is desirable for the Descriptor keyval to be place immediately after the
* keyval that it is associated with.*/
extern int csr1212_associate_keyval(struct csr1212_keyval *kv,
* keyval that it is associated with.
* Take care with subsequent ROM modifications: There is no function to remove
* previously specified associations.
*/
extern void csr1212_associate_keyval(struct csr1212_keyval *kv,
struct csr1212_keyval *associate);
extern void csr1212_disassociate_keyval(struct csr1212_keyval *kv);
/* The following functions manage the association of a keyval and directories.
@ -609,23 +296,15 @@ extern void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
struct csr1212_keyval *kv);
/* The following functions create a Configuration ROM image from the tree of
* keyvals provided. csr1212_generate_csr_image() creates a complete image in
* the list of caches available via csr->cache_head. The other functions are
* provided should there be a need to create a flat image without restrictions
* placed by IEEE 1212. */
extern struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
struct csr1212_keyval *start_kv,
int start_pos);
extern size_t csr1212_generate_layout_order(struct csr1212_keyval *kv);
extern void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache);
/* Creates a complete Configuration ROM image in the list of caches available
* via csr->cache_head. */
extern int csr1212_generate_csr_image(struct csr1212_csr *csr);
/* This is a convience function for reading a block of data out of one of the
* caches in the csr->cache_head list. */
extern int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer,
u_int32_t len);
extern int csr1212_read(struct csr1212_csr *csr, u32 offset, void *buffer,
u32 len);
/* The following functions are in place for parsing Configuration ROM images.
@ -635,15 +314,11 @@ extern int csr1212_parse_keyval(struct csr1212_keyval *kv,
struct csr1212_csr_rom_cache *cache);
extern int csr1212_parse_csr(struct csr1212_csr *csr);
/* These are internal functions referenced by inline functions below. */
extern int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv);
extern void _csr1212_destroy_keyval(struct csr1212_keyval *kv);
/* This function allocates a new cache which may be used for either parsing or
* generating sub-sets of Configuration ROM images. */
static inline struct csr1212_csr_rom_cache *csr1212_rom_cache_malloc(u_int32_t offset,
size_t size)
static inline struct csr1212_csr_rom_cache *
csr1212_rom_cache_malloc(u32 offset, size_t size)
{
struct csr1212_csr_rom_cache *cache;
@ -667,16 +342,8 @@ static inline struct csr1212_csr_rom_cache *csr1212_rom_cache_malloc(u_int32_t o
/* This function ensures that a keyval contains data when referencing a keyval
* created by parsing a Configuration ROM. */
static inline struct csr1212_keyval *csr1212_get_keyval(struct csr1212_csr *csr,
struct csr1212_keyval *kv)
{
if (!kv)
return NULL;
if (!kv->valid)
if (_csr1212_read_keyval(csr, kv) != CSR1212_SUCCESS)
return NULL;
return kv;
}
extern struct csr1212_keyval *
csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv);
/* This function increments the reference count for a keyval should there be a
@ -691,37 +358,29 @@ static inline void csr1212_keep_keyval(struct csr1212_keyval *kv)
* keyval when there are no more users of the keyval. This should be called by
* any code that calls csr1212_keep_keyval() or any of the keyval creation
* routines csr1212_new_*(). */
static inline void csr1212_release_keyval(struct csr1212_keyval *kv)
{
if (kv->refcnt > 1)
kv->refcnt--;
else
_csr1212_destroy_keyval(kv);
}
extern void csr1212_release_keyval(struct csr1212_keyval *kv);
/*
* This macro allows for looping over the keyval entries in a directory and it
* ensures that keyvals from remote ConfigROMs are parsed properly.
*
* _csr is a struct csr1212_csr * that points to CSR associated with dir.
* _kv is a struct csr1212_keyval * that'll point to the current keyval (loop index).
* _dir is a struct csr1212_keyval * that points to the directory to be looped.
* _pos is a struct csr1212_dentry * that is used internally for indexing.
* struct csr1212_csr *_csr points to the CSR associated with dir.
* struct csr1212_keyval *_kv points to the current keyval (loop index).
* struct csr1212_keyval *_dir points to the directory to be looped.
* struct csr1212_dentry *_pos is used internally for indexing.
*
* kv will be NULL upon exit of the loop.
*/
#define csr1212_for_each_dir_entry(_csr, _kv, _dir, _pos) \
for (csr1212_get_keyval((_csr), (_dir)), \
_pos = (_dir)->value.directory.dentries_head, \
_kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : NULL; \
_kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : NULL;\
(_kv) && (_pos); \
(_kv->associate == NULL) ? \
((_pos = _pos->next), \
(_kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : \
((_pos = _pos->next), (_kv = (_pos) ? \
csr1212_get_keyval((_csr), _pos->kv) : \
NULL)) : \
(_kv = csr1212_get_keyval((_csr), _kv->associate)))
#endif /* __CSR1212_H__ */

View File

@ -62,6 +62,9 @@ void dma_prog_region_free(struct dma_prog_region *prog)
/* dma_region */
/**
* dma_region_init - clear out all fields but do not allocate anything
*/
void dma_region_init(struct dma_region *dma)
{
dma->kvirt = NULL;
@ -71,6 +74,9 @@ void dma_region_init(struct dma_region *dma)
dma->sglist = NULL;
}
/**
* dma_region_alloc - allocate the buffer and map it to the IOMMU
*/
int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
struct pci_dev *dev, int direction)
{
@ -128,6 +134,9 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
return -ENOMEM;
}
/**
* dma_region_free - unmap and free the buffer
*/
void dma_region_free(struct dma_region *dma)
{
if (dma->n_dma_pages) {
@ -167,6 +176,12 @@ static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
return i;
}
/**
* dma_region_offset_to_bus - get bus address of an offset within a DMA region
*
* Returns the DMA bus address of the byte with the given @offset relative to
* the beginning of the @dma.
*/
dma_addr_t dma_region_offset_to_bus(struct dma_region * dma,
unsigned long offset)
{
@ -177,6 +192,9 @@ dma_addr_t dma_region_offset_to_bus(struct dma_region * dma,
return sg_dma_address(sg) + rem;
}
/**
* dma_region_sync_for_cpu - sync the CPU's view of the buffer
*/
void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
unsigned long len)
{
@ -193,6 +211,9 @@ void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
dma->direction);
}
/**
* dma_region_sync_for_device - sync the IO bus' view of the buffer
*/
void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
unsigned long len)
{
@ -244,6 +265,9 @@ static struct vm_operations_struct dma_region_vm_ops = {
.nopage = dma_region_pagefault,
};
/**
* dma_region_mmap - map the buffer into a user space process
*/
int dma_region_mmap(struct dma_region *dma, struct file *file,
struct vm_area_struct *vma)
{

View File

@ -66,35 +66,23 @@ struct dma_region {
int direction;
};
/* clear out all fields but do not allocate anything */
void dma_region_init(struct dma_region *dma);
/* allocate the buffer and map it to the IOMMU */
int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
struct pci_dev *dev, int direction);
/* unmap and free the buffer */
void dma_region_free(struct dma_region *dma);
/* sync the CPU's view of the buffer */
void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
unsigned long len);
/* sync the IO bus' view of the buffer */
void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
unsigned long len);
/* map the buffer into a user space process */
int dma_region_mmap(struct dma_region *dma, struct file *file,
struct vm_area_struct *vma);
/* macro to index into a DMA region (or dma_prog_region) */
#define dma_region_i(_dma, _type, _index) \
( ((_type*) ((_dma)->kvirt)) + (_index) )
/* return the DMA bus address of the byte with the given offset
* relative to the beginning of the dma_region */
dma_addr_t dma_region_offset_to_bus(struct dma_region *dma,
unsigned long offset);
/**
* dma_region_i - macro to index into a DMA region (or dma_prog_region)
*/
#define dma_region_i(_dma, _type, _index) \
( ((_type*) ((_dma)->kvirt)) + (_index) )
#endif /* IEEE1394_DMA_H */

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,11 @@
#define __ETH1394_H
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <asm/byteorder.h>
#include "ieee1394.h"
#include "ieee1394_types.h"
/* Register for incoming packets. This is 4096 bytes, which supports up to
* S3200 (per Table 16-3 of IEEE 1394b-2002). */
@ -34,22 +37,15 @@
/* GASP identifier numbers for IPv4 over IEEE 1394 */
#define ETHER1394_GASP_SPECIFIER_ID 0x00005E
#define ETHER1394_GASP_SPECIFIER_ID_HI ((ETHER1394_GASP_SPECIFIER_ID >> 8) & 0xffff)
#define ETHER1394_GASP_SPECIFIER_ID_LO (ETHER1394_GASP_SPECIFIER_ID & 0xff)
#define ETHER1394_GASP_SPECIFIER_ID_HI ((0x00005E >> 8) & 0xffff)
#define ETHER1394_GASP_SPECIFIER_ID_LO (0x00005E & 0xff)
#define ETHER1394_GASP_VERSION 1
#define ETHER1394_GASP_OVERHEAD (2 * sizeof(quadlet_t)) /* GASP header overhead */
#define ETHER1394_GASP_OVERHEAD (2 * sizeof(quadlet_t)) /* for GASP header */
#define ETHER1394_GASP_BUFFERS 16
/* rawiso buffer size - due to a limitation in rawiso, we must limit each
* GASP buffer to be less than PAGE_SIZE. */
#define ETHER1394_ISO_BUF_SIZE ETHER1394_GASP_BUFFERS * \
min((unsigned int)PAGE_SIZE, \
2 * (1U << (priv->host->csr.max_rec + 1)))
/* Node set == 64 */
#define NODE_SET (ALL_NODES + 1)
#define NODE_SET (ALL_NODES + 1) /* Node set == 64 */
enum eth1394_bc_states { ETHER1394_BC_ERROR,
ETHER1394_BC_RUNNING,
@ -85,19 +81,14 @@ struct eth1394hdr {
unsigned short h_proto; /* packet type ID field */
} __attribute__((packed));
#ifdef __KERNEL__
#include <linux/skbuff.h>
static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb)
{
return (struct eth1394hdr *)skb_mac_header(skb);
}
#endif
typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
/* IP1394 headers */
#include <asm/byteorder.h>
/* Unfragmented */
#if defined __BIG_ENDIAN_BITFIELD

View File

@ -70,8 +70,12 @@ static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl,
return NULL;
}
/* Returns a per host/driver data structure that was previously stored by
* hpsb_create_hostinfo. */
/**
* hpsb_get_hostinfo - retrieve a hostinfo pointer bound to this driver/host
*
* Returns a per @host and @hl driver data structure that was previously stored
* by hpsb_create_hostinfo.
*/
void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
{
struct hl_host_info *hi = hl_get_hostinfo(hl, host);
@ -79,7 +83,13 @@ void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
return hi ? hi->data : NULL;
}
/* If size is zero, then the return here is only valid for error checking */
/**
* hpsb_create_hostinfo - allocate a hostinfo pointer bound to this driver/host
*
* Allocate a hostinfo pointer backed by memory with @data_size and bind it to
* to this @hl driver and @host. If @data_size is zero, then the return here is
* only valid for error checking.
*/
void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
size_t data_size)
{
@ -113,6 +123,11 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
return data;
}
/**
* hpsb_set_hostinfo - set the hostinfo pointer to something useful
*
* Usually follows a call to hpsb_create_hostinfo, where the size is 0.
*/
int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
void *data)
{
@ -132,6 +147,11 @@ int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
return -EINVAL;
}
/**
* hpsb_destroy_hostinfo - free and remove a hostinfo pointer
*
* Free and remove the hostinfo pointer bound to this @hl driver and @host.
*/
void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
{
struct hl_host_info *hi;
@ -147,6 +167,12 @@ void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
return;
}
/**
* hpsb_set_hostinfo_key - set an alternate lookup key for an hostinfo
*
* Sets an alternate lookup key for the hostinfo bound to this @hl driver and
* @host.
*/
void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned long key)
{
@ -158,6 +184,9 @@ void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
return;
}
/**
* hpsb_get_hostinfo_bykey - retrieve a hostinfo pointer by its alternate key
*/
void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
{
struct hl_host_info *hi;
@ -189,6 +218,12 @@ static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
return 0;
}
/**
* hpsb_register_highlevel - register highlevel driver
*
* The name pointer in @hl has to stay valid at all times because the string is
* not copied.
*/
void hpsb_register_highlevel(struct hpsb_highlevel *hl)
{
unsigned long flags;
@ -258,6 +293,9 @@ static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data)
return 0;
}
/**
* hpsb_unregister_highlevel - unregister highlevel driver
*/
void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
{
unsigned long flags;
@ -273,6 +311,19 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
nodemgr_for_each_host(hl, highlevel_for_each_host_unreg);
}
/**
* hpsb_allocate_and_register_addrspace - alloc' and reg' a host address space
*
* @start and @end are 48 bit pointers and have to be quadlet aligned.
* @end points to the first address behind the handled addresses. This
* function can be called multiple times for a single hpsb_highlevel @hl to
* implement sparse register sets. The requested region must not overlap any
* previously allocated region, otherwise registering will fail.
*
* It returns true for successful allocation. Address spaces can be
* unregistered with hpsb_unregister_addrspace. All remaining address spaces
* are automatically deallocated together with the hpsb_highlevel @hl.
*/
u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
struct hpsb_host *host,
struct hpsb_address_ops *ops,
@ -348,6 +399,19 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
return retval;
}
/**
* hpsb_register_addrspace - register a host address space
*
* @start and @end are 48 bit pointers and have to be quadlet aligned.
* @end points to the first address behind the handled addresses. This
* function can be called multiple times for a single hpsb_highlevel @hl to
* implement sparse register sets. The requested region must not overlap any
* previously allocated region, otherwise registering will fail.
*
* It returns true for successful allocation. Address spaces can be
* unregistered with hpsb_unregister_addrspace. All remaining address spaces
* are automatically deallocated together with the hpsb_highlevel @hl.
*/
int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
struct hpsb_address_ops *ops, u64 start, u64 end)
{
@ -419,6 +483,11 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return retval;
}
/**
* hpsb_listen_channel - enable receving a certain isochronous channel
*
* Reception is handled through the @hl's iso_receive op.
*/
int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel)
{
@ -431,6 +500,9 @@ int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
return 0;
}
/**
* hpsb_unlisten_channel - disable receving a certain isochronous channel
*/
void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel)
{
@ -528,6 +600,17 @@ void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
read_unlock_irqrestore(&hl_irqs_lock, flags);
}
/*
* highlevel_read, highlevel_write, highlevel_lock, highlevel_lock64:
*
* These functions are called to handle transactions. They are called when a
* packet arrives. The flags argument contains the second word of the first
* header quadlet of the incoming packet (containing transaction label, retry
* code, transaction code and priority). These functions either return a
* response code or a negative number. In the first case a response will be
* generated. In the latter case, no response will be sent and the driver which
* handled the request will send the response itself.
*/
int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
unsigned int length, u16 flags)
{

View File

@ -99,16 +99,6 @@ struct hpsb_address_ops {
void highlevel_add_host(struct hpsb_host *host);
void highlevel_remove_host(struct hpsb_host *host);
void highlevel_host_reset(struct hpsb_host *host);
/*
* These functions are called to handle transactions. They are called when a
* packet arrives. The flags argument contains the second word of the first
* header quadlet of the incoming packet (containing transaction label, retry
* code, transaction code and priority). These functions either return a
* response code or a negative number. In the first case a response will be
* generated. In the latter case, no response will be sent and the driver which
* handled the request will send the response itself.
*/
int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
unsigned int length, u16 flags);
int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data,
@ -119,30 +109,13 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags);
void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length);
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length);
/*
* Register highlevel driver. The name pointer has to stay valid at all times
* because the string is not copied.
*/
void hpsb_register_highlevel(struct hpsb_highlevel *hl);
void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
/*
* Register handlers for host address spaces. Start and end are 48 bit pointers
* and have to be quadlet aligned. Argument "end" points to the first address
* behind the handled addresses. This function can be called multiple times for
* a single hpsb_highlevel to implement sparse register sets. The requested
* region must not overlap any previously allocated region, otherwise
* registering will fail.
*
* It returns true for successful allocation. Address spaces can be
* unregistered with hpsb_unregister_addrspace. All remaining address spaces
* are automatically deallocated together with the hpsb_highlevel.
*/
u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
struct hpsb_host *host,
struct hpsb_address_ops *ops,
@ -152,45 +125,19 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
struct hpsb_address_ops *ops, u64 start, u64 end);
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
u64 start);
/*
* Enable or disable receving a certain isochronous channel through the
* iso_receive op.
*/
int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel);
void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel);
/* Retrieve a hostinfo pointer bound to this driver/host */
void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
/* Allocate a hostinfo pointer of data_size bound to this driver/host */
void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
size_t data_size);
/* Free and remove the hostinfo pointer bound to this driver/host */
void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
/* Set an alternate lookup key for the hostinfo bound to this driver/host */
void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned long key);
/* Retrieve the alternate lookup key for the hostinfo bound to this
* driver/host */
unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl,
struct hpsb_host *host);
/* Retrieve a hostinfo pointer bound to this driver using its alternate key */
void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key);
/* Set the hostinfo pointer to something useful. Usually follows a call to
* hpsb_create_hostinfo, where the size is 0. */
int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
void *data);
/* Retrieve hpsb_host using a highlevel handle and a key */
struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl,
unsigned long key);
#endif /* IEEE1394_HIGHLEVEL_H */

View File

@ -94,14 +94,6 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
return 0;
}
/*
* The pending_packet_queue is special in that it's processed
* from hardirq context too (such as hpsb_bus_reset()). Hence
* split the lock class from the usual networking skb-head
* lock class by using a separate key for it:
*/
static struct lock_class_key pending_packet_queue_key;
static DEFINE_MUTEX(host_num_alloc);
/**
@ -137,9 +129,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
h->hostdata = h + 1;
h->driver = drv;
skb_queue_head_init(&h->pending_packet_queue);
lockdep_set_class(&h->pending_packet_queue.lock,
&pending_packet_queue_key);
INIT_LIST_HEAD(&h->pending_packets);
INIT_LIST_HEAD(&h->addr_space);
for (i = 2; i < 16; i++)
@ -190,7 +180,7 @@ int hpsb_add_host(struct hpsb_host *host)
{
if (hpsb_default_host_entry(host))
return -ENOMEM;
hpsb_add_extra_config_roms(host);
highlevel_add_host(host);
return 0;
}
@ -212,12 +202,19 @@ void hpsb_remove_host(struct hpsb_host *host)
host->driver = &dummy_driver;
highlevel_remove_host(host);
hpsb_remove_extra_config_roms(host);
class_device_unregister(&host->class_dev);
device_unregister(&host->device);
}
/**
* hpsb_update_config_rom_image - updates configuration ROM image of a host
*
* Updates the configuration ROM image of a host. rom_version must be the
* current version, otherwise it will fail with return value -1. If this
* host does not support config-rom-update, it will return -%EINVAL.
* Return value 0 indicates success.
*/
int hpsb_update_config_rom_image(struct hpsb_host *host)
{
unsigned long reset_delay;

View File

@ -3,7 +3,6 @@
#include <linux/device.h>
#include <linux/list.h>
#include <linux/skbuff.h>
#include <linux/timer.h>
#include <linux/types.h>
#include <linux/workqueue.h>
@ -25,8 +24,7 @@ struct hpsb_host {
atomic_t generation;
struct sk_buff_head pending_packet_queue;
struct list_head pending_packets;
struct timer_list timeout;
unsigned long timeout_interval;
@ -202,12 +200,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
int hpsb_add_host(struct hpsb_host *host);
void hpsb_resume_host(struct hpsb_host *host);
void hpsb_remove_host(struct hpsb_host *host);
/* Updates the configuration rom image of a host. rom_version must be the
* current version, otherwise it will fail with return value -1. If this
* host does not support config-rom-update, it will return -EINVAL.
* Return value 0 indicates success.
*/
int hpsb_update_config_rom_image(struct hpsb_host *host);
#endif /* _IEEE1394_HOSTS_H */

View File

@ -30,7 +30,6 @@
#include <linux/moduleparam.h>
#include <linux/bitops.h>
#include <linux/kdev_t.h>
#include <linux/skbuff.h>
#include <linux/suspend.h>
#include <linux/kthread.h>
#include <linux/preempt.h>
@ -96,13 +95,15 @@ static void queue_packet_complete(struct hpsb_packet *packet);
/**
* hpsb_set_packet_complete_task - set the task that runs when a packet
* completes. You cannot call this more than once on a single packet
* before it is sent.
*
* hpsb_set_packet_complete_task - set task that runs when a packet completes
* @packet: the packet whose completion we want the task added to
* @routine: function to call
* @data: data (if any) to pass to the above function
*
* Set the task that runs when a packet completes. You cannot call this more
* than once on a single packet before it is sent.
*
* Typically, the complete @routine is responsible to call hpsb_free_packet().
*/
void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
void (*routine)(void *), void *data)
@ -115,12 +116,12 @@ void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
/**
* hpsb_alloc_packet - allocate new packet structure
* @data_size: size of the data block to be allocated
* @data_size: size of the data block to be allocated, in bytes
*
* This function allocates, initializes and returns a new &struct hpsb_packet.
* It can be used in interrupt context. A header block is always included, its
* size is big enough to contain all possible 1394 headers. The data block is
* only allocated when @data_size is not zero.
* It can be used in interrupt context. A header block is always included and
* initialized with zeros. Its size is big enough to contain all possible 1394
* headers. The data block is only allocated if @data_size is not zero.
*
* For packets for which responses will be received the @data_size has to be big
* enough to contain the response's data block since no further allocation
@ -135,50 +136,49 @@ void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
*/
struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
{
struct hpsb_packet *packet = NULL;
struct sk_buff *skb;
struct hpsb_packet *packet;
data_size = ((data_size + 3) & ~3);
skb = alloc_skb(data_size + sizeof(*packet), GFP_ATOMIC);
if (skb == NULL)
packet = kzalloc(sizeof(*packet) + data_size, GFP_ATOMIC);
if (!packet)
return NULL;
memset(skb->data, 0, data_size + sizeof(*packet));
packet = (struct hpsb_packet *)skb->data;
packet->skb = skb;
packet->header = packet->embedded_header;
packet->state = hpsb_unused;
packet->generation = -1;
INIT_LIST_HEAD(&packet->driver_list);
INIT_LIST_HEAD(&packet->queue);
atomic_set(&packet->refcnt, 1);
if (data_size) {
packet->data = (quadlet_t *)(skb->data + sizeof(*packet));
packet->data_size = data_size;
packet->data = packet->embedded_data;
packet->allocated_data_size = data_size;
}
return packet;
}
/**
* hpsb_free_packet - free packet and data associated with it
* @packet: packet to free (is NULL safe)
*
* This function will free packet->data and finally the packet itself.
* Frees @packet->data only if it was allocated through hpsb_alloc_packet().
*/
void hpsb_free_packet(struct hpsb_packet *packet)
{
if (packet && atomic_dec_and_test(&packet->refcnt)) {
BUG_ON(!list_empty(&packet->driver_list));
kfree_skb(packet->skb);
BUG_ON(!list_empty(&packet->driver_list) ||
!list_empty(&packet->queue));
kfree(packet);
}
}
/**
* hpsb_reset_bus - initiate bus reset on the given host
* @host: host controller whose bus to reset
* @type: one of enum reset_types
*
* Returns 1 if bus reset already in progress, 0 otherwise.
*/
int hpsb_reset_bus(struct hpsb_host *host, int type)
{
if (!host->in_bus_reset) {
@ -229,6 +229,14 @@ int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
return 0;
}
/**
* hpsb_bus_reset - notify a bus reset to the core
*
* For host driver module usage. Safe to use in interrupt context, although
* quite complex; so you may want to run it in the bottom rather than top half.
*
* Returns 1 if bus reset already in progress, 0 otherwise.
*/
int hpsb_bus_reset(struct hpsb_host *host)
{
if (host->in_bus_reset) {
@ -405,6 +413,14 @@ static void build_speed_map(struct hpsb_host *host, int nodecount)
}
/**
* hpsb_selfid_received - hand over received selfid packet to the core
*
* For host driver module usage. Safe to use in interrupt context.
*
* The host driver should have done a successful complement check (second
* quadlet is complement of first) beforehand.
*/
void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
{
if (host->in_bus_reset) {
@ -416,6 +432,15 @@ void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
}
}
/**
* hpsb_selfid_complete - notify completion of SelfID stage to the core
*
* For host driver module usage. Safe to use in interrupt context, although
* quite complex; so you may want to run it in the bottom rather than top half.
*
* Notify completion of SelfID stage to the core and report new physical ID
* and whether host is root now.
*/
void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
{
if (!host->in_bus_reset)
@ -462,30 +487,41 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
highlevel_host_reset(host);
}
static spinlock_t pending_packets_lock = SPIN_LOCK_UNLOCKED;
/**
* hpsb_packet_sent - notify core of sending a packet
*
* For host driver module usage. Safe to call from within a transmit packet
* routine.
*
* Notify core of sending a packet. Ackcode is the ack code returned for async
* transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE
* for other cases (internal errors that don't justify a panic).
*/
void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
int ackcode)
{
unsigned long flags;
spin_lock_irqsave(&host->pending_packet_queue.lock, flags);
spin_lock_irqsave(&pending_packets_lock, flags);
packet->ack_code = ackcode;
if (packet->no_waiter || packet->state == hpsb_complete) {
/* if packet->no_waiter, must not have a tlabel allocated */
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
spin_unlock_irqrestore(&pending_packets_lock, flags);
hpsb_free_packet(packet);
return;
}
atomic_dec(&packet->refcnt); /* drop HC's reference */
/* here the packet must be on the host->pending_packet_queue */
/* here the packet must be on the host->pending_packets queue */
if (ackcode != ACK_PENDING || !packet->expect_response) {
packet->state = hpsb_complete;
__skb_unlink(packet->skb, &host->pending_packet_queue);
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
list_del_init(&packet->queue);
spin_unlock_irqrestore(&pending_packets_lock, flags);
queue_packet_complete(packet);
return;
}
@ -493,7 +529,7 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
packet->state = hpsb_pending;
packet->sendtime = jiffies;
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
spin_unlock_irqrestore(&pending_packets_lock, flags);
mod_timer(&host->timeout, jiffies + host->timeout_interval);
}
@ -504,9 +540,10 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
* @rootid: root whose force_root bit should get set (-1 = don't set force_root)
* @gapcnt: gap count value to set (-1 = don't set gap count)
*
* This function sends a PHY config packet on the bus through the specified host.
* This function sends a PHY config packet on the bus through the specified
* host.
*
* Return value: 0 for success or error number otherwise.
* Return value: 0 for success or negative error number otherwise.
*/
int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
{
@ -567,12 +604,16 @@ int hpsb_send_packet(struct hpsb_packet *packet)
WARN_ON(packet->no_waiter && packet->expect_response);
if (!packet->no_waiter || packet->expect_response) {
unsigned long flags;
atomic_inc(&packet->refcnt);
/* Set the initial "sendtime" to 10 seconds from now, to
prevent premature expiry. If a packet takes more than
10 seconds to hit the wire, we have bigger problems :) */
packet->sendtime = jiffies + 10 * HZ;
skb_queue_tail(&host->pending_packet_queue, packet->skb);
spin_lock_irqsave(&pending_packets_lock, flags);
list_add_tail(&packet->queue, &host->pending_packets);
spin_unlock_irqrestore(&pending_packets_lock, flags);
}
if (packet->node_id == host->node_id) {
@ -621,6 +662,12 @@ static void complete_packet(void *data)
complete((struct completion *) data);
}
/**
* hpsb_send_packet_and_wait - enqueue packet, block until transaction completes
* @packet: packet to send
*
* Return value: 0 on success, negative errno on failure.
*/
int hpsb_send_packet_and_wait(struct hpsb_packet *packet)
{
struct completion done;
@ -642,86 +689,97 @@ static void send_packet_nocare(struct hpsb_packet *packet)
}
}
static size_t packet_size_to_data_size(size_t packet_size, size_t header_size,
size_t buffer_size, int tcode)
{
size_t ret = packet_size <= header_size ? 0 : packet_size - header_size;
if (unlikely(ret > buffer_size))
ret = buffer_size;
if (unlikely(ret + header_size != packet_size))
HPSB_ERR("unexpected packet size %zd (tcode %d), bug?",
packet_size, tcode);
return ret;
}
static void handle_packet_response(struct hpsb_host *host, int tcode,
quadlet_t *data, size_t size)
{
struct hpsb_packet *packet = NULL;
struct sk_buff *skb;
int tcode_match = 0;
int tlabel;
struct hpsb_packet *packet;
int tlabel = (data[0] >> 10) & 0x3f;
size_t header_size;
unsigned long flags;
tlabel = (data[0] >> 10) & 0x3f;
spin_lock_irqsave(&pending_packets_lock, flags);
spin_lock_irqsave(&host->pending_packet_queue.lock, flags);
list_for_each_entry(packet, &host->pending_packets, queue)
if (packet->tlabel == tlabel &&
packet->node_id == (data[1] >> 16))
goto found;
skb_queue_walk(&host->pending_packet_queue, skb) {
packet = (struct hpsb_packet *)skb->data;
if ((packet->tlabel == tlabel)
&& (packet->node_id == (data[1] >> 16))){
break;
}
packet = NULL;
}
if (packet == NULL) {
HPSB_DEBUG("unsolicited response packet received - no tlabel match");
spin_unlock_irqrestore(&pending_packets_lock, flags);
HPSB_DEBUG("unsolicited response packet received - %s",
"no tlabel match");
dump_packet("contents", data, 16, -1);
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
return;
}
found:
switch (packet->tcode) {
case TCODE_WRITEQ:
case TCODE_WRITEB:
if (tcode != TCODE_WRITE_RESPONSE)
break;
tcode_match = 1;
memcpy(packet->header, data, 12);
if (unlikely(tcode != TCODE_WRITE_RESPONSE))
break;
header_size = 12;
size = 0;
goto dequeue;
case TCODE_READQ:
if (tcode != TCODE_READQ_RESPONSE)
break;
tcode_match = 1;
memcpy(packet->header, data, 16);
if (unlikely(tcode != TCODE_READQ_RESPONSE))
break;
header_size = 16;
size = 0;
goto dequeue;
case TCODE_READB:
if (tcode != TCODE_READB_RESPONSE)
break;
tcode_match = 1;
BUG_ON(packet->skb->len - sizeof(*packet) < size - 16);
memcpy(packet->header, data, 16);
memcpy(packet->data, data + 4, size - 16);
if (unlikely(tcode != TCODE_READB_RESPONSE))
break;
header_size = 16;
size = packet_size_to_data_size(size, header_size,
packet->allocated_data_size,
tcode);
goto dequeue;
case TCODE_LOCK_REQUEST:
if (tcode != TCODE_LOCK_RESPONSE)
break;
tcode_match = 1;
size = min((size - 16), (size_t)8);
BUG_ON(packet->skb->len - sizeof(*packet) < size);
memcpy(packet->header, data, 16);
memcpy(packet->data, data + 4, size);
if (unlikely(tcode != TCODE_LOCK_RESPONSE))
break;
header_size = 16;
size = packet_size_to_data_size(min(size, (size_t)(16 + 8)),
header_size,
packet->allocated_data_size,
tcode);
goto dequeue;
}
if (!tcode_match) {
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
HPSB_INFO("unsolicited response packet received - tcode mismatch");
spin_unlock_irqrestore(&pending_packets_lock, flags);
HPSB_DEBUG("unsolicited response packet received - %s",
"tcode mismatch");
dump_packet("contents", data, 16, -1);
return;
}
__skb_unlink(skb, &host->pending_packet_queue);
dequeue:
list_del_init(&packet->queue);
spin_unlock_irqrestore(&pending_packets_lock, flags);
if (packet->state == hpsb_queued) {
packet->sendtime = jiffies;
packet->ack_code = ACK_PENDING;
}
packet->state = hpsb_complete;
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
memcpy(packet->header, data, header_size);
if (size)
memcpy(packet->data, data + 4, size);
queue_packet_complete(packet);
}
@ -735,6 +793,7 @@ static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
p = hpsb_alloc_packet(dsize);
if (unlikely(p == NULL)) {
/* FIXME - send data_error response */
HPSB_ERR("out of memory, cannot send response packet");
return NULL;
}
@ -784,7 +843,6 @@ static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode,
static void fill_async_write_resp(struct hpsb_packet *packet, int rcode)
{
PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE);
packet->header[2] = 0;
packet->header_size = 12;
packet->data_size = 0;
}
@ -801,12 +859,9 @@ static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extc
packet->data_size = length;
}
#define PREP_REPLY_PACKET(length) \
packet = create_reply_packet(host, data, length); \
if (packet == NULL) break
static void handle_incoming_packet(struct hpsb_host *host, int tcode,
quadlet_t *data, size_t size, int write_acked)
quadlet_t *data, size_t size,
int write_acked)
{
struct hpsb_packet *packet;
int length, rcode, extcode;
@ -816,74 +871,72 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
u16 flags = (u16) data[0];
u64 addr;
/* big FIXME - no error checking is done for an out of bounds length */
/* FIXME?
* Out-of-bounds lengths are left for highlevel_read|write to cap. */
switch (tcode) {
case TCODE_WRITEQ:
addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
rcode = highlevel_write(host, source, dest, data+3,
rcode = highlevel_write(host, source, dest, data + 3,
addr, 4, flags);
if (!write_acked
&& (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
&& (rcode >= 0)) {
/* not a broadcast write, reply */
PREP_REPLY_PACKET(0);
fill_async_write_resp(packet, rcode);
send_packet_nocare(packet);
}
break;
goto handle_write_request;
case TCODE_WRITEB:
addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
rcode = highlevel_write(host, source, dest, data+4,
addr, data[3]>>16, flags);
if (!write_acked
&& (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK)
&& (rcode >= 0)) {
rcode = highlevel_write(host, source, dest, data + 4,
addr, data[3] >> 16, flags);
handle_write_request:
if (rcode < 0 || write_acked ||
NODEID_TO_NODE(data[0] >> 16) == NODE_MASK)
return;
/* not a broadcast write, reply */
PREP_REPLY_PACKET(0);
packet = create_reply_packet(host, data, 0);
if (packet) {
fill_async_write_resp(packet, rcode);
send_packet_nocare(packet);
}
break;
return;
case TCODE_READQ:
addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
if (rcode < 0)
return;
if (rcode >= 0) {
PREP_REPLY_PACKET(0);
packet = create_reply_packet(host, data, 0);
if (packet) {
fill_async_readquad_resp(packet, rcode, buffer);
send_packet_nocare(packet);
}
break;
return;
case TCODE_READB:
length = data[3] >> 16;
PREP_REPLY_PACKET(length);
packet = create_reply_packet(host, data, length);
if (!packet)
return;
addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
rcode = highlevel_read(host, source, packet->data, addr,
length, flags);
if (rcode >= 0) {
if (rcode < 0) {
hpsb_free_packet(packet);
return;
}
fill_async_readblock_resp(packet, rcode, length);
send_packet_nocare(packet);
} else {
hpsb_free_packet(packet);
}
break;
return;
case TCODE_LOCK_REQUEST:
length = data[3] >> 16;
extcode = data[3] & 0xffff;
addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
PREP_REPLY_PACKET(8);
packet = create_reply_packet(host, data, 8);
if (!packet)
return;
if ((extcode == 0) || (extcode >= 7)) {
if (extcode == 0 || extcode >= 7) {
/* let switch default handle error */
length = 0;
}
@ -891,12 +944,12 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
switch (length) {
case 4:
rcode = highlevel_lock(host, source, packet->data, addr,
data[4], 0, extcode,flags);
data[4], 0, extcode, flags);
fill_async_lock_resp(packet, rcode, extcode, 4);
break;
case 8:
if ((extcode != EXTCODE_FETCH_ADD)
&& (extcode != EXTCODE_LITTLE_ADD)) {
if (extcode != EXTCODE_FETCH_ADD &&
extcode != EXTCODE_LITTLE_ADD) {
rcode = highlevel_lock(host, source,
packet->data, addr,
data[5], data[4],
@ -920,29 +973,38 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode,
break;
default:
rcode = RCODE_TYPE_ERROR;
fill_async_lock_resp(packet, rcode,
extcode, 0);
fill_async_lock_resp(packet, rcode, extcode, 0);
}
if (rcode >= 0) {
send_packet_nocare(packet);
} else {
if (rcode < 0)
hpsb_free_packet(packet);
else
send_packet_nocare(packet);
return;
}
break;
}
}
#undef PREP_REPLY_PACKET
/**
* hpsb_packet_received - hand over received packet to the core
*
* For host driver module usage.
*
* The contents of data are expected to be the full packet but with the CRCs
* left out (data block follows header immediately), with the header (i.e. the
* first four quadlets) in machine byte order and the data block in big endian.
* *@data can be safely overwritten after this call.
*
* If the packet is a write request, @write_acked is to be set to true if it was
* ack_complete'd already, false otherwise. This argument is ignored for any
* other packet type.
*/
void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
int write_acked)
{
int tcode;
if (host->in_bus_reset) {
HPSB_INFO("received packet during reset; ignoring");
if (unlikely(host->in_bus_reset)) {
HPSB_DEBUG("received packet during reset; ignoring");
return;
}
@ -976,23 +1038,27 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
break;
default:
HPSB_NOTICE("received packet with bogus transaction code %d",
HPSB_DEBUG("received packet with bogus transaction code %d",
tcode);
break;
}
}
static void abort_requests(struct hpsb_host *host)
{
struct hpsb_packet *packet;
struct sk_buff *skb;
struct hpsb_packet *packet, *p;
struct list_head tmp;
unsigned long flags;
host->driver->devctl(host, CANCEL_REQUESTS, 0);
while ((skb = skb_dequeue(&host->pending_packet_queue)) != NULL) {
packet = (struct hpsb_packet *)skb->data;
INIT_LIST_HEAD(&tmp);
spin_lock_irqsave(&pending_packets_lock, flags);
list_splice_init(&host->pending_packets, &tmp);
spin_unlock_irqrestore(&pending_packets_lock, flags);
list_for_each_entry_safe(packet, p, &tmp, queue) {
list_del_init(&packet->queue);
packet->state = hpsb_complete;
packet->ack_code = ACKX_ABORTED;
queue_packet_complete(packet);
@ -1002,87 +1068,90 @@ static void abort_requests(struct hpsb_host *host)
void abort_timedouts(unsigned long __opaque)
{
struct hpsb_host *host = (struct hpsb_host *)__opaque;
unsigned long flags;
struct hpsb_packet *packet;
struct sk_buff *skb;
unsigned long expire;
struct hpsb_packet *packet, *p;
struct list_head tmp;
unsigned long flags, expire, j;
spin_lock_irqsave(&host->csr.lock, flags);
expire = host->csr.expire;
spin_unlock_irqrestore(&host->csr.lock, flags);
/* Hold the lock around this, since we aren't dequeuing all
* packets, just ones we need. */
spin_lock_irqsave(&host->pending_packet_queue.lock, flags);
j = jiffies;
INIT_LIST_HEAD(&tmp);
spin_lock_irqsave(&pending_packets_lock, flags);
while (!skb_queue_empty(&host->pending_packet_queue)) {
skb = skb_peek(&host->pending_packet_queue);
packet = (struct hpsb_packet *)skb->data;
if (time_before(packet->sendtime + expire, jiffies)) {
__skb_unlink(skb, &host->pending_packet_queue);
packet->state = hpsb_complete;
packet->ack_code = ACKX_TIMEOUT;
queue_packet_complete(packet);
} else {
list_for_each_entry_safe(packet, p, &host->pending_packets, queue) {
if (time_before(packet->sendtime + expire, j))
list_move_tail(&packet->queue, &tmp);
else
/* Since packets are added to the tail, the oldest
* ones are first, always. When we get to one that
* isn't timed out, the rest aren't either. */
break;
}
if (!list_empty(&host->pending_packets))
mod_timer(&host->timeout, j + host->timeout_interval);
spin_unlock_irqrestore(&pending_packets_lock, flags);
list_for_each_entry_safe(packet, p, &tmp, queue) {
list_del_init(&packet->queue);
packet->state = hpsb_complete;
packet->ack_code = ACKX_TIMEOUT;
queue_packet_complete(packet);
}
if (!skb_queue_empty(&host->pending_packet_queue))
mod_timer(&host->timeout, jiffies + host->timeout_interval);
spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags);
}
/* Kernel thread and vars, which handles packets that are completed. Only
* packets that have a "complete" function are sent here. This way, the
* completion is run out of kernel context, and doesn't block the rest of
* the stack. */
static struct task_struct *khpsbpkt_thread;
static struct sk_buff_head hpsbpkt_queue;
static LIST_HEAD(hpsbpkt_queue);
static void queue_packet_complete(struct hpsb_packet *packet)
{
unsigned long flags;
if (packet->no_waiter) {
hpsb_free_packet(packet);
return;
}
if (packet->complete_routine != NULL) {
skb_queue_tail(&hpsbpkt_queue, packet->skb);
spin_lock_irqsave(&pending_packets_lock, flags);
list_add_tail(&packet->queue, &hpsbpkt_queue);
spin_unlock_irqrestore(&pending_packets_lock, flags);
wake_up_process(khpsbpkt_thread);
}
return;
}
/*
* Kernel thread which handles packets that are completed. This way the
* packet's "complete" function is asynchronously run in process context.
* Only packets which have a "complete" function may be sent here.
*/
static int hpsbpkt_thread(void *__hi)
{
struct sk_buff *skb;
struct hpsb_packet *packet;
void (*complete_routine)(void*);
void *complete_data;
struct hpsb_packet *packet, *p;
struct list_head tmp;
int may_schedule;
current->flags |= PF_NOFREEZE;
while (!kthread_should_stop()) {
while ((skb = skb_dequeue(&hpsbpkt_queue)) != NULL) {
packet = (struct hpsb_packet *)skb->data;
complete_routine = packet->complete_routine;
complete_data = packet->complete_data;
INIT_LIST_HEAD(&tmp);
spin_lock_irq(&pending_packets_lock);
list_splice_init(&hpsbpkt_queue, &tmp);
spin_unlock_irq(&pending_packets_lock);
packet->complete_routine = packet->complete_data = NULL;
complete_routine(complete_data);
list_for_each_entry_safe(packet, p, &tmp, queue) {
list_del_init(&packet->queue);
packet->complete_routine(packet->complete_data);
}
set_current_state(TASK_INTERRUPTIBLE);
if (!skb_peek(&hpsbpkt_queue))
spin_lock_irq(&pending_packets_lock);
may_schedule = list_empty(&hpsbpkt_queue);
spin_unlock_irq(&pending_packets_lock);
if (may_schedule)
schedule();
__set_current_state(TASK_RUNNING);
}
@ -1093,8 +1162,6 @@ static int __init ieee1394_init(void)
{
int i, ret;
skb_queue_head_init(&hpsbpkt_queue);
/* non-fatal error */
if (hpsb_init_config_roms()) {
HPSB_ERR("Failed to initialize some config rom entries.\n");
@ -1268,7 +1335,6 @@ EXPORT_SYMBOL(hpsb_destroy_hostinfo);
EXPORT_SYMBOL(hpsb_set_hostinfo_key);
EXPORT_SYMBOL(hpsb_get_hostinfo_bykey);
EXPORT_SYMBOL(hpsb_set_hostinfo);
EXPORT_SYMBOL(highlevel_host_reset);
/** nodemgr.c **/
EXPORT_SYMBOL(hpsb_node_fill_packet);
@ -1311,11 +1377,10 @@ EXPORT_SYMBOL(hpsb_iso_wake);
EXPORT_SYMBOL(hpsb_iso_recv_flush);
/** csr1212.c **/
EXPORT_SYMBOL(csr1212_new_directory);
EXPORT_SYMBOL(csr1212_attach_keyval_to_directory);
EXPORT_SYMBOL(csr1212_detach_keyval_from_directory);
EXPORT_SYMBOL(csr1212_release_keyval);
EXPORT_SYMBOL(csr1212_read);
EXPORT_SYMBOL(csr1212_get_keyval);
EXPORT_SYMBOL(csr1212_new_directory);
EXPORT_SYMBOL(csr1212_parse_keyval);
EXPORT_SYMBOL(_csr1212_read_keyval);
EXPORT_SYMBOL(_csr1212_destroy_keyval);
EXPORT_SYMBOL(csr1212_read);
EXPORT_SYMBOL(csr1212_release_keyval);

View File

@ -4,7 +4,6 @@
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/skbuff.h>
#include <linux/types.h>
#include <asm/atomic.h>
@ -13,7 +12,7 @@
struct hpsb_packet {
/* This struct is basically read-only for hosts with the exception of
* the data buffer contents and xnext - see below. */
* the data buffer contents and driver_list. */
/* This can be used for host driver internal linking.
*
@ -49,134 +48,65 @@ struct hpsb_packet {
/* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
unsigned speed_code:2;
/*
* *header and *data are guaranteed to be 32-bit DMAable and may be
* overwritten to allow in-place byte swapping. Neither of these is
* CRCed (the sizes also don't include CRC), but contain space for at
* least one additional quadlet to allow in-place CRCing. The memory is
* also guaranteed to be DMA mappable.
*/
quadlet_t *header;
quadlet_t *data;
size_t header_size;
size_t data_size;
struct hpsb_host *host;
unsigned int generation;
atomic_t refcnt;
struct list_head queue;
/* Function (and possible data to pass to it) to call when this
* packet is completed. */
void (*complete_routine)(void *);
void *complete_data;
/* XXX This is just a hack at the moment */
struct sk_buff *skb;
/* Store jiffies for implementing bus timeouts. */
unsigned long sendtime;
quadlet_t embedded_header[5];
/* Sizes are in bytes. *data can be DMA-mapped. */
size_t allocated_data_size; /* as allocated */
size_t data_size; /* as filled in */
size_t header_size; /* as filled in, not counting the CRC */
quadlet_t *data;
quadlet_t header[5];
quadlet_t embedded_data[0]; /* keep as last member */
};
/* Set a task for when a packet completes */
void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
void (*routine)(void *), void *data);
static inline struct hpsb_packet *driver_packet(struct list_head *l)
{
return list_entry(l, struct hpsb_packet, driver_list);
}
void abort_timedouts(unsigned long __opaque);
struct hpsb_packet *hpsb_alloc_packet(size_t data_size);
void hpsb_free_packet(struct hpsb_packet *packet);
/*
* Generation counter for the complete 1394 subsystem. Generation gets
* incremented on every change in the subsystem (e.g. bus reset).
/**
* get_hpsb_generation - generation counter for the complete 1394 subsystem
*
* Use the functions, not the variable.
* Generation gets incremented on every change in the subsystem (notably on bus
* resets). Use the functions, not the variable.
*/
static inline unsigned int get_hpsb_generation(struct hpsb_host *host)
{
return atomic_read(&host->generation);
}
/*
* Send a PHY configuration packet, return 0 on success, negative
* errno on failure.
*/
int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt);
/*
* Queue packet for transmitting, return 0 on success, negative errno
* on failure.
*/
int hpsb_send_packet(struct hpsb_packet *packet);
/*
* Queue packet for transmitting, and block until the transaction
* completes. Return 0 on success, negative errno on failure.
*/
int hpsb_send_packet_and_wait(struct hpsb_packet *packet);
/* Initiate bus reset on the given host. Returns 1 if bus reset already in
* progress, 0 otherwise. */
int hpsb_reset_bus(struct hpsb_host *host, int type);
int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
u64 *local_time);
/*
* The following functions are exported for host driver module usage. All of
* them are safe to use in interrupt contexts, although some are quite
* complicated so you may want to run them in bottom halves instead of calling
* them directly.
*/
/* Notify a bus reset to the core. Returns 1 if bus reset already in progress,
* 0 otherwise. */
int hpsb_bus_reset(struct hpsb_host *host);
/*
* Hand over received selfid packet to the core. Complement check (second
* quadlet is complement of first) is expected to be done and successful.
*/
void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid);
/*
* Notify completion of SelfID stage to the core and report new physical ID
* and whether host is root now.
*/
void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot);
/*
* Notify core of sending a packet. Ackcode is the ack code returned for async
* transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE
* for other cases (internal errors that don't justify a panic). Safe to call
* from within a transmit packet routine.
*/
void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
int ackcode);
/*
* Hand over received packet to the core. The contents of data are expected to
* be the full packet but with the CRCs left out (data block follows header
* immediately), with the header (i.e. the first four quadlets) in machine byte
* order and the data block in big endian. *data can be safely overwritten
* after this call.
*
* If the packet is a write request, write_acked is to be set to true if it was
* ack_complete'd already, false otherwise. This arg is ignored for any other
* packet type.
*/
void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
int write_acked);
/*
* CHARACTER DEVICE DISPATCHING
*
@ -217,7 +147,9 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, \
IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
/* return the index (within a minor number block) of a file */
/**
* ieee1394_file_to_instance - get the index within a minor number block
*/
static inline unsigned char ieee1394_file_to_instance(struct file *file)
{
return file->f_path.dentry->d_inode->i_cindex;

View File

@ -10,11 +10,16 @@
*/
#include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/hardirq.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/sched.h> /* because linux/wait.h is broken if CONFIG_SMP=n */
#include <linux/wait.h>
#include <asm/bug.h>
#include <asm/errno.h>
#include <asm/system.h>
#include "ieee1394.h"
#include "ieee1394_types.h"
@ -32,7 +37,7 @@
#ifndef HPSB_DEBUG_TLABELS
static
#endif
spinlock_t hpsb_tlabel_lock = SPIN_LOCK_UNLOCKED;
DEFINE_SPINLOCK(hpsb_tlabel_lock);
static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq);
@ -212,6 +217,15 @@ void hpsb_free_tlabel(struct hpsb_packet *packet)
wake_up_interruptible(&tlabel_wq);
}
/**
* hpsb_packet_success - Make sense of the ack and reply codes
*
* Make sense of the ack and reply codes and return more convenient error codes:
* 0 = success. -%EBUSY = node is busy, try again. -%EAGAIN = error which can
* probably resolved by retry. -%EREMOTEIO = node suffers from an internal
* error. -%EACCES = this transaction is not allowed on requested address.
* -%EINVAL = invalid address at node.
*/
int hpsb_packet_success(struct hpsb_packet *packet)
{
switch (packet->ack_code) {
@ -364,6 +378,13 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 * buffer,
}
packet->host = host;
/* Because it is too difficult to determine all PHY speeds and link
* speeds here, we use S100... */
packet->speed_code = IEEE1394_SPEED_100;
/* ...and prevent hpsb_send_packet() from overriding it. */
packet->node_id = LOCAL_BUS | ALL_NODES;
if (hpsb_get_tlabel(packet)) {
hpsb_free_packet(packet);
return NULL;
@ -493,6 +514,16 @@ struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
* avoid in kernel buffers for user space callers
*/
/**
* hpsb_read - generic read function
*
* Recognizes the local node ID and act accordingly. Automatically uses a
* quadlet read request if @length == 4 and and a block read request otherwise.
* It does not yet support lengths that are not a multiple of 4.
*
* You must explicitly specifiy the @generation for which the node ID is valid,
* to avoid sending packets to the wrong nodes when we race with a bus reset.
*/
int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t * buffer, size_t length)
{
@ -532,6 +563,16 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
return retval;
}
/**
* hpsb_write - generic write function
*
* Recognizes the local node ID and act accordingly. Automatically uses a
* quadlet write request if @length == 4 and and a block write request
* otherwise. It does not yet support lengths that are not a multiple of 4.
*
* You must explicitly specifiy the @generation for which the node ID is valid,
* to avoid sending packets to the wrong nodes when we race with a bus reset.
*/
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t * buffer, size_t length)
{

View File

@ -27,27 +27,7 @@ struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer,
int length, int channel, int tag,
int sync);
/*
* hpsb_packet_success - Make sense of the ack and reply codes and
* return more convenient error codes:
* 0 success
* -EBUSY node is busy, try again
* -EAGAIN error which can probably resolved by retry
* -EREMOTEIO node suffers from an internal error
* -EACCES this transaction is not allowed on requested address
* -EINVAL invalid address at node
*/
int hpsb_packet_success(struct hpsb_packet *packet);
/*
* The generic read and write functions. All recognize the local node ID
* and act accordingly. Read and write automatically use quadlet commands if
* length == 4 and and block commands otherwise (however, they do not yet
* support lengths that are not a multiple of 4). You must explicitly specifiy
* the generation for which the node ID is valid, to avoid sending packets to
* the wrong nodes when we race with a bus reset.
*/
int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t *buffer, size_t length);
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,

View File

@ -10,11 +10,15 @@
*/
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include "hosts.h"
#include "iso.h"
/**
* hpsb_iso_stop - stop DMA
*/
void hpsb_iso_stop(struct hpsb_iso *iso)
{
if (!(iso->flags & HPSB_ISO_DRIVER_STARTED))
@ -25,6 +29,9 @@ void hpsb_iso_stop(struct hpsb_iso *iso)
iso->flags &= ~HPSB_ISO_DRIVER_STARTED;
}
/**
* hpsb_iso_shutdown - deallocate buffer and DMA context
*/
void hpsb_iso_shutdown(struct hpsb_iso *iso)
{
if (iso->flags & HPSB_ISO_DRIVER_INIT) {
@ -130,6 +137,9 @@ static struct hpsb_iso *hpsb_iso_common_init(struct hpsb_host *host,
return NULL;
}
/**
* hpsb_iso_n_ready - returns number of packets ready to send or receive
*/
int hpsb_iso_n_ready(struct hpsb_iso *iso)
{
unsigned long flags;
@ -142,6 +152,9 @@ int hpsb_iso_n_ready(struct hpsb_iso *iso)
return val;
}
/**
* hpsb_iso_xmit_init - allocate the buffer and DMA context
*/
struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets,
@ -172,6 +185,11 @@ struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host,
return NULL;
}
/**
* hpsb_iso_recv_init - allocate the buffer and DMA context
*
* Note, if channel = -1, multi-channel receive is enabled.
*/
struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets,
@ -199,6 +217,11 @@ struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host,
return NULL;
}
/**
* hpsb_iso_recv_listen_channel
*
* multi-channel only
*/
int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel)
{
if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
@ -206,6 +229,11 @@ int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel)
return iso->host->driver->isoctl(iso, RECV_LISTEN_CHANNEL, channel);
}
/**
* hpsb_iso_recv_unlisten_channel
*
* multi-channel only
*/
int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel)
{
if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
@ -213,6 +241,11 @@ int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel)
return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel);
}
/**
* hpsb_iso_recv_set_channel_mask
*
* multi-channel only
*/
int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
{
if (iso->type != HPSB_ISO_RECV || iso->channel != -1)
@ -221,6 +254,12 @@ int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
(unsigned long)&mask);
}
/**
* hpsb_iso_recv_flush - check for arrival of new packets
*
* check for arrival of new packets immediately (even if irq_interval
* has not yet been reached)
*/
int hpsb_iso_recv_flush(struct hpsb_iso *iso)
{
if (iso->type != HPSB_ISO_RECV)
@ -238,6 +277,9 @@ static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle)
return retval;
}
/**
* hpsb_iso_xmit_start - start DMA
*/
int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer)
{
if (iso->type != HPSB_ISO_XMIT)
@ -270,6 +312,9 @@ int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer)
return 0;
}
/**
* hpsb_iso_recv_start - start DMA
*/
int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
{
int retval = 0;
@ -306,8 +351,7 @@ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
}
/* check to make sure the user has not supplied bogus values of offset/len
that would cause the kernel to access memory outside the buffer */
* that would cause the kernel to access memory outside the buffer */
static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
unsigned int offset, unsigned short len,
unsigned int *out_offset,
@ -331,6 +375,12 @@ static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
return 0;
}
/**
* hpsb_iso_xmit_queue_packet - queue a packet for transmission.
*
* @offset is relative to the beginning of the DMA buffer, where the packet's
* data payload should already have been placed.
*/
int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
u8 tag, u8 sy)
{
@ -380,6 +430,9 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
return rv;
}
/**
* hpsb_iso_xmit_sync - wait until all queued packets have been transmitted
*/
int hpsb_iso_xmit_sync(struct hpsb_iso *iso)
{
if (iso->type != HPSB_ISO_XMIT)
@ -390,6 +443,15 @@ int hpsb_iso_xmit_sync(struct hpsb_iso *iso)
iso->buf_packets);
}
/**
* hpsb_iso_packet_sent
*
* Available to low-level drivers.
*
* Call after a packet has been transmitted to the bus (interrupt context is
* OK). @cycle is the _exact_ cycle the packet was sent on. @error should be
* non-zero if some sort of error occurred when sending the packet.
*/
void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
{
unsigned long flags;
@ -413,6 +475,13 @@ void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
spin_unlock_irqrestore(&iso->lock, flags);
}
/**
* hpsb_iso_packet_received
*
* Available to low-level drivers.
*
* Call after a packet has been received (interrupt context is OK).
*/
void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
u16 total_len, u16 cycle, u8 channel, u8 tag,
u8 sy)
@ -442,6 +511,11 @@ void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
spin_unlock_irqrestore(&iso->lock, flags);
}
/**
* hpsb_iso_recv_release_packets - release packets, reuse buffer
*
* @n_packets have been read out of the buffer, re-use the buffer space
*/
int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
{
unsigned long flags;
@ -477,6 +551,13 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
return rv;
}
/**
* hpsb_iso_wake
*
* Available to low-level drivers.
*
* Call to wake waiting processes after buffer space has opened up.
*/
void hpsb_iso_wake(struct hpsb_iso *iso)
{
wake_up_interruptible(&iso->waitq);

View File

@ -150,8 +150,6 @@ struct hpsb_iso {
/* functions available to high-level drivers (e.g. raw1394) */
/* allocate the buffer and DMA context */
struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets,
@ -159,8 +157,6 @@ struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
int speed,
int irq_interval,
void (*callback)(struct hpsb_iso*));
/* note: if channel = -1, multi-channel receive is enabled */
struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets,
@ -168,56 +164,29 @@ struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
int dma_mode,
int irq_interval,
void (*callback)(struct hpsb_iso*));
/* multi-channel only */
int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel);
int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel);
int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask);
/* start/stop DMA */
int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle,
int prebuffer);
int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle,
int tag_mask, int sync);
void hpsb_iso_stop(struct hpsb_iso *iso);
/* deallocate buffer and DMA context */
void hpsb_iso_shutdown(struct hpsb_iso *iso);
/* queue a packet for transmission.
* 'offset' is relative to the beginning of the DMA buffer, where the packet's
* data payload should already have been placed. */
int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
u8 tag, u8 sy);
/* wait until all queued packets have been transmitted to the bus */
int hpsb_iso_xmit_sync(struct hpsb_iso *iso);
/* N packets have been read out of the buffer, re-use the buffer space */
int hpsb_iso_recv_release_packets(struct hpsb_iso *recv,
unsigned int n_packets);
/* check for arrival of new packets immediately (even if irq_interval
* has not yet been reached) */
int hpsb_iso_recv_flush(struct hpsb_iso *iso);
/* returns # of packets ready to send or receive */
int hpsb_iso_n_ready(struct hpsb_iso *iso);
/* the following are callbacks available to low-level drivers */
/* call after a packet has been transmitted to the bus (interrupt context is OK)
* 'cycle' is the _exact_ cycle the packet was sent on
* 'error' should be non-zero if some sort of error occurred when sending the
* packet */
void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error);
/* call after a packet has been received (interrupt context OK) */
void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
u16 total_len, u16 cycle, u8 channel, u8 tag,
u8 sy);
/* call to wake waiting processes after buffer space has opened up. */
void hpsb_iso_wake(struct hpsb_iso *iso);
#endif /* IEEE1394_ISO_H */

View File

@ -16,6 +16,7 @@
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/freezer.h>
#include <asm/atomic.h>
@ -115,7 +116,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci)
{
return (CSR1212_BE32_TO_CPU(bus_info_data[2]) >> 8) & 0x3;
return (be32_to_cpu(bus_info_data[2]) >> 8) & 0x3;
}
static struct csr1212_bus_ops nodemgr_csr_ops = {
@ -580,7 +581,7 @@ static void nodemgr_create_drv_files(struct hpsb_protocol_driver *driver)
goto fail;
return;
fail:
HPSB_ERR("Failed to add sysfs attribute for driver %s", driver->name);
HPSB_ERR("Failed to add sysfs attribute");
}
@ -604,8 +605,7 @@ static void nodemgr_create_ne_dev_files(struct node_entry *ne)
goto fail;
return;
fail:
HPSB_ERR("Failed to add sysfs attribute for node %016Lx",
(unsigned long long)ne->guid);
HPSB_ERR("Failed to add sysfs attribute");
}
@ -619,7 +619,7 @@ static void nodemgr_create_host_dev_files(struct hpsb_host *host)
goto fail;
return;
fail:
HPSB_ERR("Failed to add sysfs attribute for host %d", host->id);
HPSB_ERR("Failed to add sysfs attribute");
}
@ -679,8 +679,7 @@ static void nodemgr_create_ud_dev_files(struct unit_directory *ud)
}
return;
fail:
HPSB_ERR("Failed to add sysfs attributes for unit %s",
ud->device.bus_id);
HPSB_ERR("Failed to add sysfs attribute");
}
@ -1144,13 +1143,13 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
last_key_id = kv->key.id;
}
if (ne->vendor_name_kv &&
device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv))
goto fail;
return;
fail:
HPSB_ERR("Failed to add sysfs attribute for node %016Lx",
(unsigned long long)ne->guid);
if (ne->vendor_name_kv) {
int error = device_create_file(&ne->device,
&dev_attr_ne_vendor_name_kv);
if (error && error != -EEXIST)
HPSB_ERR("Failed to add sysfs attribute");
}
}
#ifdef CONFIG_HOTPLUG
@ -1738,7 +1737,19 @@ exit:
return 0;
}
int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
/**
* nodemgr_for_each_host - call a function for each IEEE 1394 host
* @data: an address to supply to the callback
* @cb: function to call for each host
*
* Iterate the hosts, calling a given function with supplied data for each host.
* If the callback fails on a host, i.e. if it returns a non-zero value, the
* iteration is stopped.
*
* Return value: 0 on success, non-zero on failure (same as returned by last run
* of the callback).
*/
int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
{
struct class_device *cdev;
struct hpsb_host *host;
@ -1748,7 +1759,7 @@ int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
list_for_each_entry(cdev, &hpsb_host_class.children, node) {
host = container_of(cdev, struct hpsb_host, class_dev);
if ((error = cb(host, __data)))
if ((error = cb(host, data)))
break;
}
up(&hpsb_host_class.sem);
@ -1756,7 +1767,7 @@ int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
return error;
}
/* The following four convenience functions use a struct node_entry
/* The following two convenience functions use a struct node_entry
* for addressing a node on the bus. They are intended for use by any
* process context, not just the nodemgr thread, so we need to be a
* little careful when reading out the node ID and generation. The
@ -1771,12 +1782,20 @@ int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
* ID's.
*/
void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt)
/**
* hpsb_node_fill_packet - fill some destination information into a packet
* @ne: destination node
* @packet: packet to fill in
*
* This will fill in the given, pre-initialised hpsb_packet with the current
* information from the node entry (host, node ID, bus generation number).
*/
void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet)
{
pkt->host = ne->host;
pkt->generation = ne->generation;
packet->host = ne->host;
packet->generation = ne->generation;
barrier();
pkt->node_id = ne->nodeid;
packet->node_id = ne->nodeid;
}
int hpsb_node_write(struct node_entry *ne, u64 addr,

View File

@ -153,30 +153,10 @@ static inline int hpsb_node_entry_valid(struct node_entry *ne)
{
return ne->generation == get_hpsb_generation(ne->host);
}
/*
* This will fill in the given, pre-initialised hpsb_packet with the current
* information from the node entry (host, node ID, generation number). It will
* return false if the node owning the GUID is not accessible (and not modify
* the hpsb_packet) and return true otherwise.
*
* Note that packet sending may still fail in hpsb_send_packet if a bus reset
* happens while you are trying to set up the packet (due to obsolete generation
* number). It will at least reliably fail so that you don't accidentally and
* unknowingly send your packet to the wrong node.
*/
void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt);
int hpsb_node_read(struct node_entry *ne, u64 addr,
quadlet_t *buffer, size_t length);
void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet);
int hpsb_node_write(struct node_entry *ne, u64 addr,
quadlet_t *buffer, size_t length);
int hpsb_node_lock(struct node_entry *ne, u64 addr,
int extcode, quadlet_t *data, quadlet_t arg);
/* Iterate the hosts, calling a given function with supplied data for each
* host. */
int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *));
int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *));
int init_ieee1394_nodemgr(void);
void cleanup_ieee1394_nodemgr(void);

View File

@ -507,9 +507,8 @@ static void ohci_initialize(struct ti_ohci *ohci)
/* Set up self-id dma buffer */
reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus);
/* enable self-id and phys */
reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_RcvSelfID |
OHCI1394_LinkControl_RcvPhyPkt);
/* enable self-id */
reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_RcvSelfID);
/* Set the Config ROM mapping register */
reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus);
@ -518,9 +517,6 @@ static void ohci_initialize(struct ti_ohci *ohci)
ohci->max_packet_size =
1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
/* Don't accept phy packets into AR request context */
reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
/* Clear the interrupt mask */
reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
@ -617,7 +613,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
#endif
PRINT(KERN_DEBUG, "Serial EEPROM has suspicious values, "
"attempting to setting max_packet_size to 512 bytes");
"attempting to set max_packet_size to 512 bytes");
reg_write(ohci, OHCI1394_BusOptions,
(reg_read(ohci, OHCI1394_BusOptions) & 0xf007) | 0x8002);
ohci->max_packet_size = 512;
@ -2377,6 +2373,7 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id)
if (event & OHCI1394_postedWriteErr) {
PRINT(KERN_ERR, "physical posted write error");
/* no recovery strategy yet, had to involve protocol drivers */
event &= ~OHCI1394_postedWriteErr;
}
if (event & OHCI1394_cycleTooLong) {
if(printk_ratelimit())
@ -3658,6 +3655,7 @@ static struct pci_driver ohci1394_pci_driver = {
/* essentially the only purpose of this code is to allow another
module to hook into ohci's interrupt handler */
/* returns zero if successful, one if DMA context is locked up */
int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg)
{
int i=0;

View File

@ -461,9 +461,7 @@ int ohci1394_register_iso_tasklet(struct ti_ohci *ohci,
struct ohci1394_iso_tasklet *tasklet);
void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci,
struct ohci1394_iso_tasklet *tasklet);
/* returns zero if successful, one if DMA context is locked up */
int ohci1394_stop_context (struct ti_ohci *ohci, int reg, char *msg);
int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg);
struct ti_ohci *ohci1394_get_struct(int card_num);
#endif

View File

@ -938,7 +938,8 @@ static int handle_async_send(struct file_info *fi, struct pending_request *req)
int header_length = req->req.misc & 0xffff;
int expect_response = req->req.misc >> 16;
if ((header_length > req->req.length) || (header_length < 12)) {
if (header_length > req->req.length || header_length < 12 ||
header_length > FIELD_SIZEOF(struct hpsb_packet, header)) {
req->req.error = RAW1394_ERROR_INVALID_ARG;
req->req.length = 0;
queue_complete_req(req);

View File

@ -59,8 +59,10 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/stat.h>
@ -469,19 +471,13 @@ static void sbp2util_write_doorbell(struct work_struct *work)
static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
{
struct sbp2_fwhost_info *hi = lu->hi;
int i;
unsigned long flags, orbs;
struct sbp2_command_info *cmd;
int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
spin_lock_irqsave(&lu->cmd_orb_lock, flags);
for (i = 0; i < orbs; i++) {
cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
if (!cmd) {
spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
}
cmd->command_orb_dma = dma_map_single(hi->host->device.parent,
&cmd->command_orb,
sizeof(struct sbp2_command_orb),
@ -489,11 +485,10 @@ static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
cmd->sge_dma = dma_map_single(hi->host->device.parent,
&cmd->scatter_gather_element,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
DMA_TO_DEVICE);
INIT_LIST_HEAD(&cmd->list);
list_add_tail(&cmd->list, &lu->cmd_orb_completed);
}
spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
return 0;
}
@ -514,7 +509,7 @@ static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu)
DMA_TO_DEVICE);
dma_unmap_single(host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
DMA_TO_DEVICE);
kfree(cmd);
}
spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
@ -757,6 +752,11 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
SBP2_ERR("failed to register lower 4GB address range");
goto failed_alloc;
}
#else
if (dma_set_mask(hi->host->device.parent, DMA_32BIT_MASK)) {
SBP2_ERR("failed to set 4GB DMA mask");
goto failed_alloc;
}
#endif
}
@ -865,11 +865,8 @@ static int sbp2_start_device(struct sbp2_lu *lu)
if (!lu->login_orb)
goto alloc_fail;
if (sbp2util_create_command_orb_pool(lu)) {
SBP2_ERR("sbp2util_create_command_orb_pool failed!");
sbp2_remove_device(lu);
return -ENOMEM;
}
if (sbp2util_create_command_orb_pool(lu))
goto alloc_fail;
/* Wait a second before trying to log in. Previously logged in
* initiators need a chance to reconnect. */
@ -1628,7 +1625,7 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
DMA_TO_DEVICE);
dma_sync_single_for_device(hi->host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
DMA_TO_DEVICE);
/* check to see if there are any previous orbs to use */
spin_lock_irqsave(&lu->cmd_orb_lock, flags);
@ -1794,7 +1791,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
DMA_TO_DEVICE);
dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
DMA_TO_DEVICE);
/* Grab SCSI command pointers and check status. */
/*
* FIXME: If the src field in the status is 1, the ORB DMA must
@ -1926,7 +1923,7 @@ static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
DMA_TO_DEVICE);
dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
DMA_TO_DEVICE);
sbp2util_mark_command_completed(lu, cmd);
if (cmd->Current_SCpnt) {
cmd->Current_SCpnt->result = status << 16;
@ -2057,7 +2054,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
dma_sync_single_for_cpu(hi->host->device.parent,
cmd->sge_dma,
sizeof(cmd->scatter_gather_element),
DMA_BIDIRECTIONAL);
DMA_TO_DEVICE);
sbp2util_mark_command_completed(lu, cmd);
if (cmd->Current_SCpnt) {
cmd->Current_SCpnt->result = DID_ABORT << 16;

View File

@ -250,15 +250,15 @@ enum sbp2_dma_types {
/* Per SCSI command */
struct sbp2_command_info {
struct list_head list;
struct sbp2_command_orb command_orb ____cacheline_aligned;
dma_addr_t command_orb_dma ____cacheline_aligned;
struct sbp2_command_orb command_orb;
dma_addr_t command_orb_dma;
struct scsi_cmnd *Current_SCpnt;
void (*Current_done)(struct scsi_cmnd *);
/* Also need s/g structure for each sbp2 command */
struct sbp2_unrestricted_page_table
scatter_gather_element[SG_ALL] ____cacheline_aligned;
dma_addr_t sge_dma ____cacheline_aligned;
scatter_gather_element[SG_ALL] __attribute__((aligned(8)));
dma_addr_t sge_dma;
void *sge_buffer;
dma_addr_t cmd_dma;
enum sbp2_dma_types dma_type;