Commit 40caf5ea authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: (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
  ...
parents d6454706 bcfd09ee
# -*- shell-script -*-
menu "IEEE 1394 (FireWire) support" menu "IEEE 1394 (FireWire) support"
config IEEE1394 config IEEE1394
tristate "IEEE 1394 (FireWire) support" tristate "IEEE 1394 (FireWire) support"
depends on PCI || BROKEN depends on PCI || BROKEN
select NET
help help
IEEE 1394 describes a high performance serial bus, which is also 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 known as FireWire(tm) or i.Link(tm) and is used for connecting all
...@@ -35,24 +32,7 @@ config IEEE1394_VERBOSEDEBUG ...@@ -35,24 +32,7 @@ config IEEE1394_VERBOSEDEBUG
Say Y if you really want or need the debugging output, everyone Say Y if you really want or need the debugging output, everyone
else says N. else says N.
config IEEE1394_EXTRA_CONFIG_ROMS comment "Controllers"
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"
depends on IEEE1394 depends on IEEE1394
comment "Texas Instruments PCILynx requires I2C" comment "Texas Instruments PCILynx requires I2C"
...@@ -70,6 +50,10 @@ config IEEE1394_PCILYNX ...@@ -70,6 +50,10 @@ config IEEE1394_PCILYNX
To compile this driver as a module, say M here: the To compile this driver as a module, say M here: the
module will be called pcilynx. 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 config IEEE1394_OHCI1394
tristate "OHCI-1394 support" tristate "OHCI-1394 support"
depends on PCI && IEEE1394 depends on PCI && IEEE1394
...@@ -83,7 +67,7 @@ config IEEE1394_OHCI1394 ...@@ -83,7 +67,7 @@ config IEEE1394_OHCI1394
To compile this driver as a module, say M here: the To compile this driver as a module, say M here: the
module will be called ohci1394. module will be called ohci1394.
comment "Protocol Drivers" comment "Protocols"
depends on IEEE1394 depends on IEEE1394
config IEEE1394_VIDEO1394 config IEEE1394_VIDEO1394
...@@ -121,11 +105,15 @@ config IEEE1394_SBP2_PHYS_DMA ...@@ -121,11 +105,15 @@ config IEEE1394_SBP2_PHYS_DMA
This option is buggy and currently broken on some architectures. This option is buggy and currently broken on some architectures.
If unsure, say N. If unsure, say N.
config IEEE1394_ETH1394_ROM_ENTRY
depends on IEEE1394
bool
default n
config IEEE1394_ETH1394 config IEEE1394_ETH1394
tristate "Ethernet over 1394" tristate "IP over 1394"
depends on IEEE1394 && EXPERIMENTAL && INET depends on IEEE1394 && EXPERIMENTAL && INET
select IEEE1394_CONFIG_ROM_IP1394 select IEEE1394_ETH1394_ROM_ENTRY
select IEEE1394_EXTRA_CONFIG_ROMS
help help
This driver implements a functional majority of RFC 2734: IPv4 over This driver implements a functional majority of RFC 2734: IPv4 over
1394. It will provide IP connectivity with implementations of RFC 1394. It will provide IP connectivity with implementations of RFC
...@@ -134,6 +122,8 @@ config IEEE1394_ETH1394 ...@@ -134,6 +122,8 @@ config IEEE1394_ETH1394
This driver is still considered experimental. It does not yet support This driver is still considered experimental. It does not yet support
MCAP, therefore multicast support is significantly limited. MCAP, therefore multicast support is significantly limited.
The module is called eth1394 although it does not emulate Ethernet.
config IEEE1394_DV1394 config IEEE1394_DV1394
tristate "OHCI-DV I/O support (deprecated)" tristate "OHCI-DV I/O support (deprecated)"
depends on IEEE1394 && IEEE1394_OHCI1394 depends on IEEE1394 && IEEE1394_OHCI1394
...@@ -146,12 +136,12 @@ config IEEE1394_RAWIO ...@@ -146,12 +136,12 @@ config IEEE1394_RAWIO
tristate "Raw IEEE1394 I/O support" tristate "Raw IEEE1394 I/O support"
depends on IEEE1394 depends on IEEE1394
help help
Say Y here if you want support for the raw device. This is generally This option adds support for the raw1394 device file which enables
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
direct communication of user programs with the IEEE 1394 bus and with the attached peripherals. Almost all application programs which
thus with the attached peripherals. access FireWire require this option.
To compile this driver as a module, say M here: the To compile this driver as a module, say M here: the module will be
module will be called raw1394. called raw1394.
endmenu endmenu
...@@ -26,12 +26,6 @@ struct hpsb_config_rom_entry { ...@@ -26,12 +26,6 @@ struct hpsb_config_rom_entry {
/* Base initialization, called at module load */ /* Base initialization, called at module load */
int (*init)(void); 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 */ /* Cleanup called at module exit */
void (*cleanup)(void); void (*cleanup)(void);
...@@ -39,7 +33,7 @@ struct hpsb_config_rom_entry { ...@@ -39,7 +33,7 @@ struct hpsb_config_rom_entry {
unsigned int flag; unsigned int flag;
}; };
/* The default host entry. This must succeed. */
int hpsb_default_host_entry(struct hpsb_host *host) int hpsb_default_host_entry(struct hpsb_host *host)
{ {
struct csr1212_keyval *root; struct csr1212_keyval *root;
...@@ -63,9 +57,9 @@ int hpsb_default_host_entry(struct hpsb_host *host) ...@@ -63,9 +57,9 @@ int hpsb_default_host_entry(struct hpsb_host *host)
return -ENOMEM; return -ENOMEM;
} }
ret = csr1212_associate_keyval(vend_id, text); csr1212_associate_keyval(vend_id, text);
csr1212_release_keyval(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); csr1212_release_keyval(vend_id);
if (ret != CSR1212_SUCCESS) { if (ret != CSR1212_SUCCESS) {
csr1212_destroy_csr(host->csr.rom); csr1212_destroy_csr(host->csr.rom);
...@@ -78,7 +72,7 @@ int hpsb_default_host_entry(struct hpsb_host *host) ...@@ -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" #include "eth1394.h"
static struct csr1212_keyval *ip1394_ud; static struct csr1212_keyval *ip1394_ud;
...@@ -103,10 +97,12 @@ static int config_rom_ip1394_init(void) ...@@ -103,10 +97,12 @@ static int config_rom_ip1394_init(void)
if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc) if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc)
goto ip1394_fail; goto ip1394_fail;
if (csr1212_associate_keyval(spec_id, spec_desc) == CSR1212_SUCCESS && csr1212_associate_keyval(spec_id, spec_desc);
csr1212_associate_keyval(ver, ver_desc) == CSR1212_SUCCESS && csr1212_associate_keyval(ver, ver_desc);
csr1212_attach_keyval_to_directory(ip1394_ud, spec_id) == CSR1212_SUCCESS && if (csr1212_attach_keyval_to_directory(ip1394_ud, spec_id)
csr1212_attach_keyval_to_directory(ip1394_ud, ver) == CSR1212_SUCCESS) == CSR1212_SUCCESS &&
csr1212_attach_keyval_to_directory(ip1394_ud, ver)
== CSR1212_SUCCESS)
ret = 0; ret = 0;
ip1394_fail: ip1394_fail:
...@@ -135,7 +131,7 @@ static void config_rom_ip1394_cleanup(void) ...@@ -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) if (!ip1394_ud)
return -ENODEV; return -ENODEV;
...@@ -144,92 +140,55 @@ static int config_rom_ip1394_add(struct hpsb_host *host) ...@@ -144,92 +140,55 @@ static int config_rom_ip1394_add(struct hpsb_host *host)
ip1394_ud) != CSR1212_SUCCESS) ip1394_ud) != CSR1212_SUCCESS)
return -ENOMEM; return -ENOMEM;
host->config_roms |= HPSB_CONFIG_ROM_ENTRY_IP1394;
host->update_config_rom = 1;
return 0; 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); 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 = { static struct hpsb_config_rom_entry ip1394_entry = {
.name = "ip1394", .name = "ip1394",
.init = config_rom_ip1394_init, .init = config_rom_ip1394_init,
.add = config_rom_ip1394_add,
.remove = config_rom_ip1394_remove,
.cleanup = config_rom_ip1394_cleanup, .cleanup = config_rom_ip1394_cleanup,
.flag = HPSB_CONFIG_ROM_ENTRY_IP1394, .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[] = { static struct hpsb_config_rom_entry *const config_rom_entries[] = {
#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394 #ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
&ip1394_entry, &ip1394_entry,
#endif #endif
NULL,
}; };
/* Initialize all config roms */
int hpsb_init_config_roms(void) int hpsb_init_config_roms(void)
{ {
int i, error = 0; int i, error = 0;
for (i = 0; config_rom_entries[i]; i++) { for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
if (!config_rom_entries[i]->init)
continue;
if (config_rom_entries[i]->init()) { if (config_rom_entries[i]->init()) {
HPSB_ERR("Failed to initialize config rom entry `%s'", HPSB_ERR("Failed to initialize config rom entry `%s'",
config_rom_entries[i]->name); config_rom_entries[i]->name);
error = -1; error = -1;
} else
HPSB_DEBUG("Initialized config rom entry `%s'",
config_rom_entries[i]->name);
} }
return error; return error;
} }
/* Cleanup all config roms */
void hpsb_cleanup_config_roms(void) void hpsb_cleanup_config_roms(void)
{ {
int i; int i;
for (i = 0; config_rom_entries[i]; i++) { for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
if (config_rom_entries[i]->cleanup)
config_rom_entries[i]->cleanup(); 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;
}
} }
#ifndef _IEEE1394_CONFIG_ROMS_H #ifndef _IEEE1394_CONFIG_ROMS_H
#define _IEEE1394_CONFIG_ROMS_H #define _IEEE1394_CONFIG_ROMS_H
#include "ieee1394_types.h" struct hpsb_host;
#include "hosts.h"
/* The default host entry. This must succeed. */
int hpsb_default_host_entry(struct hpsb_host *host); int hpsb_default_host_entry(struct hpsb_host *host);
/* Initialize all config roms */
int hpsb_init_config_roms(void); int hpsb_init_config_roms(void);
/* Cleanup all config roms */
void hpsb_cleanup_config_roms(void); 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 /* List of flags to check if a host contains a certain extra config rom
* entry. Available in the host->config_roms member. */ * entry. Available in the host->config_roms member. */
#define HPSB_CONFIG_ROM_ENTRY_IP1394 0x00000001 #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 */ #endif /* _IEEE1394_CONFIG_ROMS_H */
This diff is collapsed.
This diff is collapsed.
...@@ -62,6 +62,9 @@ void dma_prog_region_free(struct dma_prog_region *prog) ...@@ -62,6 +62,9 @@ void dma_prog_region_free(struct dma_prog_region *prog)
/* dma_region */ /* dma_region */
/**
* dma_region_init - clear out all fields but do not allocate anything
*/
void dma_region_init(struct dma_region *dma) void dma_region_init(struct dma_region *dma)
{ {
dma->kvirt = NULL; dma->kvirt = NULL;
...@@ -71,6 +74,9 @@ void dma_region_init(struct dma_region *dma) ...@@ -71,6 +74,9 @@ void dma_region_init(struct dma_region *dma)
dma->sglist = NULL; 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, int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
struct pci_dev *dev, int direction) struct pci_dev *dev, int direction)
{ {
...@@ -128,6 +134,9 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, ...@@ -128,6 +134,9 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
return -ENOMEM; return -ENOMEM;
} }
/**
* dma_region_free - unmap and free the buffer
*/
void dma_region_free(struct dma_region *dma) void dma_region_free(struct dma_region *dma)
{ {
if (dma->n_dma_pages) { if (dma->n_dma_pages) {
...@@ -167,6 +176,12 @@ static inline int dma_region_find(struct dma_region *dma, unsigned long offset, ...@@ -167,6 +176,12 @@ static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
return i; 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, dma_addr_t dma_region_offset_to_bus(struct dma_region * dma,
unsigned long offset) unsigned long offset)
{ {
...@@ -177,6 +192,9 @@ dma_addr_t dma_region_offset_to_bus(struct dma_region * dma, ...@@ -177,6 +192,9 @@ dma_addr_t dma_region_offset_to_bus(struct dma_region * dma,
return sg_dma_address(sg) + rem; 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, void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
unsigned long len) unsigned long len)
{ {
...@@ -193,6 +211,9 @@ void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, ...@@ -193,6 +211,9 @@ void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
dma->direction); 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, void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
unsigned long len) unsigned long len)
{ {
...@@ -244,6 +265,9 @@ static struct vm_operations_struct dma_region_vm_ops = { ...@@ -244,6 +265,9 @@ static struct vm_operations_struct dma_region_vm_ops = {
.nopage = dma_region_pagefault, .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, int dma_region_mmap(struct dma_region *dma, struct file *file,
struct vm_area_struct *vma) struct vm_area_struct *vma)
{ {
......
...@@ -66,35 +66,23 @@ struct dma_region { ...@@ -66,35 +66,23 @@ struct dma_region {
int direction; int direction;
}; };
/* clear out all fields but do not allocate anything */
void dma_region_init(struct dma_region *dma); 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, int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
struct pci_dev *dev, int direction); struct pci_dev *dev, int direction);
/* unmap and free the buffer */
void dma_region_free(struct dma_region *dma); 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, void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
unsigned long len); unsigned long len);
/* sync the IO bus' view of the buffer */
void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
unsigned long len); unsigned long len);
/* map the buffer into a user space process */
int dma_region_mmap(struct dma_region *dma, struct file *file, int dma_region_mmap(struct dma_region *dma, struct file *file,
struct vm_area_struct *vma); struct vm_area_struct *vma);
dma_addr_t dma_region_offset_to_bus(struct dma_region *dma,
unsigned long offset);
/* macro to index into a DMA region (or dma_prog_region) */ /**
* dma_region_i - macro to index into a DMA region (or dma_prog_region)
*/
#define dma_region_i(_dma, _type, _index) \ #define dma_region_i(_dma, _type, _index) \
( ((_type*) ((_dma)->kvirt)) + (_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);
#endif /* IEEE1394_DMA_H */ #endif /* IEEE1394_DMA_H */
This diff is collapsed.
...@@ -25,8 +25,11 @@ ...@@ -25,8 +25,11 @@
#define __ETH1394_H #define __ETH1394_H
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <asm/byteorder.h>
#include "ieee1394.h" #include "ieee1394.h"
#include "ieee1394_types.h"
/* Register for incoming packets. This is 4096 bytes, which supports up to /* Register for incoming packets. This is 4096 bytes, which supports up to
* S3200 (per Table 16-3 of IEEE 1394b-2002). */ * S3200 (per Table 16-3 of IEEE 1394b-2002). */
...@@ -34,22 +37,15 @@ ...@@ -34,22 +37,15 @@
/* GASP identifier numbers for IPv4 over IEEE 1394 */ /* GASP identifier numbers for IPv4 over IEEE 1394 */
#define ETHER1394_GASP_SPECIFIER_ID 0x00005E #define ETHER1394_GASP_SPECIFIER_ID 0x00005E
#define ETHER1394_GASP_SPECIFIER_ID_HI ((ETHER1394_GASP_SPECIFIER_ID >> 8) & 0xffff) #define ETHER1394_GASP_SPECIFIER_ID_HI ((0x00005E >> 8) & 0xffff)
#define ETHER1394_GASP_SPECIFIER_ID_LO (ETHER1394_GASP_SPECIFIER_ID & 0xff) #define ETHER1394_GASP_SPECIFIER_ID_LO (0x00005E & 0xff)
#define ETHER1394_GASP_VERSION 1 #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 #define ETHER1394_GASP_BUFFERS 16
/* rawiso buffer size - due to a limitation in rawiso, we must limit each #define NODE_SET (ALL_NODES + 1) /* Node set == 64 */
* 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)
enum eth1394_bc_states { ETHER1394_BC_ERROR, enum eth1394_bc_states { ETHER1394_BC_ERROR,
ETHER1394_BC_RUNNING, ETHER1394_BC_RUNNING,
...@@ -85,19 +81,14 @@ struct eth1394hdr { ...@@ -85,19 +81,14 @@ struct eth1394hdr {
unsigned short h_proto; /* packet type ID field */ unsigned short h_proto; /* packet type ID field */
} __attribute__((packed)); } __attribute__((packed));
#ifdef __KERNEL__
#include <linux/skbuff.h>
static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb) static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb)
{ {
return (struct eth1394hdr *)skb_mac_header(skb); return (struct eth1394hdr *)skb_mac_header(skb);
} }
#endif
typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type; typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
/* IP1394 headers */ /* IP1394 headers */
#include <asm/byteorder.h>
/* Unfragmented */ /* Unfragmented */
#if defined __BIG_ENDIAN_BITFIELD #if defined __BIG_ENDIAN_BITFIELD
......
...@@ -70,8 +70,12 @@ static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl, ...@@ -70,8 +70,12 @@ static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl,
return NULL; 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) void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
{ {
struct hl_host_info *hi = hl_get_hostinfo(hl, 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) ...@@ -79,7 +83,13 @@ void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
return hi ? hi->data : NULL; 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, void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
size_t data_size) size_t data_size)
{ {
...@@ -113,6 +123,11 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, ...@@ -113,6 +123,11 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
return data; 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, int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
void *data) void *data)
{ {
...@@ -132,6 +147,11 @@ int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, ...@@ -132,6 +147,11 @@ int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
return -EINVAL; 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) void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
{ {
struct hl_host_info *hi; struct hl_host_info *hi;
...@@ -147,6 +167,12 @@ void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) ...@@ -147,6 +167,12 @@ void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
return; 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, void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned long key) unsigned long key)
{ {
...@@ -158,6 +184,9 @@ void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, ...@@ -158,6 +184,9 @@ void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
return; 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) void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
{ {
struct hl_host_info *hi; struct hl_host_info *hi;
...@@ -189,6 +218,12 @@ static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data) ...@@ -189,6 +218,12 @@ static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
return 0; 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) void hpsb_register_highlevel(struct hpsb_highlevel *hl)
{ {
unsigned long flags; unsigned long flags;
...@@ -258,6 +293,9 @@ static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data) ...@@ -258,6 +293,9 @@ static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data)
return 0; return 0;
} }
/**
* hpsb_unregister_highlevel - unregister highlevel driver
*/
void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
{ {
unsigned long flags; unsigned long flags;
...@@ -273,6 +311,19 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) ...@@ -273,6 +311,19 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
nodemgr_for_each_host(hl, highlevel_for_each_host_unreg); 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, u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
struct hpsb_host *host, struct hpsb_host *host,
struct hpsb_address_ops *ops, struct hpsb_address_ops *ops,
...@@ -348,6 +399,19 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, ...@@ -348,6 +399,19 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
return retval; 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, int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
struct hpsb_address_ops *ops, u64 start, u64 end) 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, ...@@ -419,6 +483,11 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
return retval; 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, int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel) unsigned int channel)
{ {
...@@ -431,6 +500,9 @@ int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, ...@@ -431,6 +500,9 @@ int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
return 0; return 0;
} }
/**
* hpsb_unlisten_channel - disable receving a certain isochronous channel
*/
void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel) unsigned int channel)
{ {
...@@ -528,6 +600,17 @@ void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, ...@@ -528,6 +600,17 @@ void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
read_unlock_irqrestore(&hl_irqs_lock, flags); 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, int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
unsigned int length, u16 flags) unsigned int length, u16 flags)
{ {
......
...@@ -99,16 +99,6 @@ struct hpsb_address_ops { ...@@ -99,16 +99,6 @@ struct hpsb_address_ops {
void highlevel_add_host(struct hpsb_host *host); void highlevel_add_host(struct hpsb_host *host);
void highlevel_remove_host(struct hpsb_host *host); void highlevel_remove_host(struct hpsb_host *host);
void highlevel_host_reset(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, int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
unsigned int length, u16 flags); unsigned int length, u16 flags);
int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data, 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, ...@@ -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, int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags); u16 flags);
void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length); 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 highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length); 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_register_highlevel(struct hpsb_highlevel *hl);
void hpsb_unregister_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, u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
struct hpsb_host *host, struct hpsb_host *host,
struct hpsb_address_ops *ops, struct hpsb_address_ops *ops,
...@@ -152,45 +125,19 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, ...@@ -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); struct hpsb_address_ops *ops, u64 start, u64 end);
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
u64 start); 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, int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel); unsigned int channel);
void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel); unsigned int channel);
/* Retrieve a hostinfo pointer bound to this driver/host */
void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *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, void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
size_t data_size); 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); 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, void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned long key); 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); 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, int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
void *data); 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 */ #endif /* IEEE1394_HIGHLEVEL_H */
...@@ -94,14 +94,6 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data) ...@@ -94,14 +94,6 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
return 0; 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); static DEFINE_MUTEX(host_num_alloc);
/** /**
...@@ -137,9 +129,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, ...@@ -137,9 +129,7 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
h->hostdata = h + 1; h->hostdata = h + 1;
h->driver = drv; h->driver = drv;
skb_queue_head_init(&h->pending_packet_queue); INIT_LIST_HEAD(&h->pending_packets);
lockdep_set_class(&h->pending_packet_queue.lock,
&pending_packet_queue_key);
INIT_LIST_HEAD(&h->addr_space); INIT_LIST_HEAD(&h->addr_space);
for (i = 2; i < 16; i++) for (i = 2; i < 16; i++)
...@@ -190,7 +180,7 @@ int hpsb_add_host(struct hpsb_host *host) ...@@ -190,7 +180,7 @@ int hpsb_add_host(struct hpsb_host *host)
{ {
if (hpsb_default_host_entry(host)) if (hpsb_default_host_entry(host))
return -ENOMEM; return -ENOMEM;
hpsb_add_extra_config_roms(host);
highlevel_add_host(host); highlevel_add_host(host);
return 0; return 0;
} }
...@@ -212,12 +202,19 @@ void hpsb_remove_host(struct hpsb_host *host) ...@@ -212,12 +202,19 @@ void hpsb_remove_host(struct hpsb_host *host)
host->driver = &dummy_driver; host->driver = &dummy_driver;
highlevel_remove_host(host); highlevel_remove_host(host);
hpsb_remove_extra_config_roms(host);
class_device_unregister(&host->class_dev); class_device_unregister(&host->class_dev);
device_unregister(&host->device); 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) int hpsb_update_config_rom_image(struct hpsb_host *host)
{ {
unsigned long reset_delay; unsigned long reset_delay;
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/skbuff.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
...@@ -25,8 +24,7 @@ struct hpsb_host { ...@@ -25,8 +24,7 @@ struct hpsb_host {
atomic_t generation; atomic_t generation;
struct sk_buff_head pending_packet_queue; struct list_head pending_packets;
struct timer_list timeout; struct timer_list timeout;
unsigned long timeout_interval; unsigned long timeout_interval;
...@@ -202,12 +200,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, ...@@ -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); int hpsb_add_host(struct hpsb_host *host);
void hpsb_resume_host(struct hpsb_host *host); void hpsb_resume_host(struct hpsb_host *host);
void hpsb_remove_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); int hpsb_update_config_rom_image(struct hpsb_host *host);
#endif /* _IEEE1394_HOSTS_H */ #endif /* _IEEE1394_HOSTS_H */
This diff is collapsed.
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/skbuff.h>
#include <linux/types.h> #include <linux/types.h>
#include <asm/atomic.h> #include <asm/atomic.h>
...@@ -13,7 +12,7 @@ ...@@ -13,7 +12,7 @@
struct hpsb_packet { struct hpsb_packet {
/* This struct is basically read-only for hosts with the exception of /* 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. /* This can be used for host driver internal linking.
* *
...@@ -49,134 +48,65 @@ struct hpsb_packet { ...@@ -49,134 +48,65 @@ struct hpsb_packet {
/* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */ /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
unsigned speed_code:2; 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; struct hpsb_host *host;
unsigned int generation; unsigned int generation;
atomic_t refcnt; atomic_t refcnt;
struct list_head queue;
/* Function (and possible data to pass to it) to call when this /* Function (and possible data to pass to it) to call when this
* packet is completed. */ * packet is completed. */
void (*complete_routine)(void *); void (*complete_routine)(void *);
void *complete_data; void *complete_data;
/* XXX This is just a hack at the moment */
struct sk_buff *skb;
/* Store jiffies for implementing bus timeouts. */ /* Store jiffies for implementing bus timeouts. */
unsigned long sendtime; 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 hpsb_set_packet_complete_task(struct hpsb_packet *packet,
void (*routine)(void *), void *data); void (*routine)(void *), void *data);
static inline struct hpsb_packet *driver_packet(struct list_head *l) static inline struct hpsb_packet *driver_packet(struct list_head *l)
{ {
return list_entry(l, struct hpsb_packet, driver_list); return list_entry(l, struct hpsb_packet, driver_list);
} }
void abort_timedouts(unsigned long __opaque); void abort_timedouts(unsigned long __opaque);
struct hpsb_packet *hpsb_alloc_packet(size_t data_size); struct hpsb_packet *hpsb_alloc_packet(size_t data_size);
void hpsb_free_packet(struct hpsb_packet *packet); void hpsb_free_packet(struct hpsb_packet *packet);
/* /**
* Generation counter for the complete 1394 subsystem. Generation gets * get_hpsb_generation - generation counter for the complete 1394 subsystem
* incremented on every change in the subsystem (e.g. bus reset).
* *
* 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) static inline unsigned int get_hpsb_generation(struct hpsb_host *host)
{ {
return atomic_read(&host->generation); 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); 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); 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); 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_reset_bus(struct hpsb_host *host, int type);
int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer, int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
u64 *local_time); 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); 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); 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); 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, void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
int ackcode); 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, void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
int write_acked); int write_acked);
/* /*
* CHARACTER DEVICE DISPATCHING * CHARACTER DEVICE DISPATCHING
* *
...@@ -217,7 +147,9 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, ...@@ -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, \ #define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, \
IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16) 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) static inline unsigned char ieee1394_file_to_instance(struct file *file)
{ {
return file->f_path.dentry->d_inode->i_cindex; return file->f_path.dentry->d_inode->i_cindex;
......
...@@ -10,11 +10,16 @@ ...@@ -10,11 +10,16 @@
*/ */
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/hardirq.h>
#include <linux/spinlock.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 <linux/wait.h>
#include <asm/bug.h> #include <asm/bug.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/system.h>
#include "ieee1394.h" #include "ieee1394.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
...@@ -32,7 +37,7 @@ ...@@ -32,7 +37,7 @@
#ifndef HPSB_DEBUG_TLABELS #ifndef HPSB_DEBUG_TLABELS
static static
#endif #endif
spinlock_t hpsb_tlabel_lock = SPIN_LOCK_UNLOCKED; DEFINE_SPINLOCK(hpsb_tlabel_lock);
static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq); static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq);
...@@ -212,6 +217,15 @@ void hpsb_free_tlabel(struct hpsb_packet *packet) ...@@ -212,6 +217,15 @@ void hpsb_free_tlabel(struct hpsb_packet *packet)
wake_up_interruptible(&tlabel_wq); 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) int hpsb_packet_success(struct hpsb_packet *packet)
{ {
switch (packet->ack_code) { switch (packet->ack_code) {
...@@ -364,6 +378,13 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 * buffer, ...@@ -364,6 +378,13 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 * buffer,
} }
packet->host = host; 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)) { if (hpsb_get_tlabel(packet)) {
hpsb_free_packet(packet); hpsb_free_packet(packet);
return NULL; return NULL;
...@@ -493,6 +514,16 @@ struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, ...@@ -493,6 +514,16 @@ struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host,
* avoid in kernel buffers for user space callers * 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, int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t * buffer, size_t length) 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, ...@@ -532,6 +563,16 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
return retval; 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, int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t * buffer, size_t length) u64 addr, quadlet_t * buffer, size_t length)
{ {
......
...@@ -27,27 +27,7 @@ struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host, ...@@ -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, struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer,
int length, int channel, int tag, int length, int channel, int tag,
int sync); 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); 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, int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t *buffer, size_t length); u64 addr, quadlet_t *buffer, size_t length);
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
......
...@@ -10,11 +10,15 @@ ...@@ -10,11 +10,15 @@
*/ */
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "hosts.h" #include "hosts.h"
#include "iso.h" #include "iso.h"
/**
* hpsb_iso_stop - stop DMA
*/
void hpsb_iso_stop(struct hpsb_iso *iso) void hpsb_iso_stop(struct hpsb_iso *iso)
{ {
if (!(iso->flags & HPSB_ISO_DRIVER_STARTED)) if (!(iso->flags & HPSB_ISO_DRIVER_STARTED))
...@@ -25,6 +29,9 @@ void hpsb_iso_stop(struct hpsb_iso *iso) ...@@ -25,6 +29,9 @@ void hpsb_iso_stop(struct hpsb_iso *iso)
iso->flags &= ~HPSB_ISO_DRIVER_STARTED; iso->flags &= ~HPSB_ISO_DRIVER_STARTED;
} }
/**
* hpsb_iso_shutdown - deallocate buffer and DMA context
*/
void hpsb_iso_shutdown(struct hpsb_iso *iso) void hpsb_iso_shutdown(struct hpsb_iso *iso)
{ {
if (iso->flags & HPSB_ISO_DRIVER_INIT) { if (iso->flags & HPSB_ISO_DRIVER_INIT) {
...@@ -130,6 +137,9 @@ static struct hpsb_iso *hpsb_iso_common_init(struct hpsb_host *host, ...@@ -130,6 +137,9 @@ static struct hpsb_iso *hpsb_iso_common_init(struct hpsb_host *host,
return NULL; return NULL;
} }
/**
* hpsb_iso_n_ready - returns number of packets ready to send or receive
*/
int hpsb_iso_n_ready(struct hpsb_iso *iso) int hpsb_iso_n_ready(struct hpsb_iso *iso)
{ {
unsigned long flags; unsigned long flags;
...@@ -142,6 +152,9 @@ int hpsb_iso_n_ready(struct hpsb_iso *iso) ...@@ -142,6 +152,9 @@ int hpsb_iso_n_ready(struct hpsb_iso *iso)
return val; return val;
} }
/**
* hpsb_iso_xmit_init - allocate the buffer and DMA context
*/
struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host, struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host,
unsigned int data_buf_size, unsigned int data_buf_size,
unsigned int buf_packets, unsigned int buf_packets,
...@@ -172,6 +185,11 @@ struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host, ...@@ -172,6 +185,11 @@ struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host,
return NULL; 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, struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host,
unsigned int data_buf_size, unsigned int data_buf_size,
unsigned int buf_packets, unsigned int buf_packets,
...@@ -199,6 +217,11 @@ struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host, ...@@ -199,6 +217,11 @@ struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host,
return NULL; return NULL;
} }
/**
* hpsb_iso_recv_listen_channel
*
* multi-channel only
*/
int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel) int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel)
{ {
if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) 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) ...@@ -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); 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) int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel)
{ {
if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) 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) ...@@ -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); 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) int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
{ {
if (iso->type != HPSB_ISO_RECV || iso->channel != -1) 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) ...@@ -221,6 +254,12 @@ int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
(unsigned long)&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) int hpsb_iso_recv_flush(struct hpsb_iso *iso)
{ {
if (iso->type != HPSB_ISO_RECV) if (iso->type != HPSB_ISO_RECV)
...@@ -238,6 +277,9 @@ static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle) ...@@ -238,6 +277,9 @@ static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle)
return retval; return retval;
} }
/**
* hpsb_iso_xmit_start - start DMA
*/
int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer) int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer)
{ {
if (iso->type != HPSB_ISO_XMIT) if (iso->type != HPSB_ISO_XMIT)
...@@ -270,6 +312,9 @@ int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer) ...@@ -270,6 +312,9 @@ int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer)
return 0; 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 hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
{ {
int retval = 0; int retval = 0;
...@@ -306,8 +351,7 @@ int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) ...@@ -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 /* 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, static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
unsigned int offset, unsigned short len, unsigned int offset, unsigned short len,
unsigned int *out_offset, unsigned int *out_offset,
...@@ -331,6 +375,12 @@ static int hpsb_iso_check_offset_len(struct hpsb_iso *iso, ...@@ -331,6 +375,12 @@ static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
return 0; 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, int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
u8 tag, u8 sy) u8 tag, u8 sy)
{ {
...@@ -380,6 +430,9 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, ...@@ -380,6 +430,9 @@ int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
return rv; return rv;
} }
/**
* hpsb_iso_xmit_sync - wait until all queued packets have been transmitted
*/
int hpsb_iso_xmit_sync(struct hpsb_iso *iso) int hpsb_iso_xmit_sync(struct hpsb_iso *iso)
{ {
if (iso->type != HPSB_ISO_XMIT) if (iso->type != HPSB_ISO_XMIT)
...@@ -390,6 +443,15 @@ int hpsb_iso_xmit_sync(struct hpsb_iso *iso) ...@@ -390,6 +443,15 @@ int hpsb_iso_xmit_sync(struct hpsb_iso *iso)
iso->buf_packets); 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) void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
{ {
unsigned long flags; unsigned long flags;
...@@ -413,6 +475,13 @@ void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error) ...@@ -413,6 +475,13 @@ void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
spin_unlock_irqrestore(&iso->lock, flags); 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, void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
u16 total_len, u16 cycle, u8 channel, u8 tag, u16 total_len, u16 cycle, u8 channel, u8 tag,
u8 sy) u8 sy)
...@@ -442,6 +511,11 @@ void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, ...@@ -442,6 +511,11 @@ void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
spin_unlock_irqrestore(&iso->lock, flags); 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) int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
{ {
unsigned long flags; unsigned long flags;
...@@ -477,6 +551,13 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets) ...@@ -477,6 +551,13 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
return rv; 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) void hpsb_iso_wake(struct hpsb_iso *iso)
{ {
wake_up_interruptible(&iso->waitq); wake_up_interruptible(&iso->waitq);
......
...@@ -150,8 +150,6 @@ struct hpsb_iso { ...@@ -150,8 +150,6 @@ struct hpsb_iso {
/* functions available to high-level drivers (e.g. raw1394) */ /* 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, struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
unsigned int data_buf_size, unsigned int data_buf_size,
unsigned int buf_packets, unsigned int buf_packets,
...@@ -159,8 +157,6 @@ struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, ...@@ -159,8 +157,6 @@ struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
int speed, int speed,
int irq_interval, int irq_interval,
void (*callback)(struct hpsb_iso*)); 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, struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
unsigned int data_buf_size, unsigned int data_buf_size,
unsigned int buf_packets, unsigned int buf_packets,
...@@ -168,56 +164,29 @@ struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, ...@@ -168,56 +164,29 @@ struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
int dma_mode, int dma_mode,
int irq_interval, int irq_interval,
void (*callback)(struct hpsb_iso*)); 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_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_unlisten_channel(struct hpsb_iso *iso, unsigned char channel);
int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask); 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 hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle,
int prebuffer); int prebuffer);
int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle, int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle,
int tag_mask, int sync); int tag_mask, int sync);
void hpsb_iso_stop(struct hpsb_iso *iso); void hpsb_iso_stop(struct hpsb_iso *iso);
/* deallocate buffer and DMA context */
void hpsb_iso_shutdown(struct hpsb_iso *iso); 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, int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
u8 tag, u8 sy); u8 tag, u8 sy);
/* wait until all queued packets have been transmitted to the bus */
int hpsb_iso_xmit_sync(struct hpsb_iso *iso); 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, int hpsb_iso_recv_release_packets(struct hpsb_iso *recv,
unsigned int n_packets); 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); 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); int hpsb_iso_n_ready(struct hpsb_iso *iso);
/* the following are callbacks available to low-level drivers */ /* 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); 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, void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
u16 total_len, u16 cycle, u8 channel, u8 tag, u16 total_len, u16 cycle, u8 channel, u8 tag,
u8 sy); u8 sy);
/* call to wake waiting processes after buffer space has opened up. */
void hpsb_iso_wake(struct hpsb_iso *iso); void hpsb_iso_wake(struct hpsb_iso *iso);
#endif /* IEEE1394_ISO_H */ #endif /* IEEE1394_ISO_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment