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

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: (48 commits)
  ieee1394: raw1394: arm functions slept in atomic context
  ieee1394: sbp2: enable auto spin-up for all SBP-2 devices
  MAINTAINERS: updates to IEEE 1394 subsystem maintainership
  ieee1394: ohci1394: check for errors in suspend or resume
  set power state of firewire host during suspend
  ieee1394: ohci1394: more obvious endianess handling
  ieee1394: ohci1394: fix endianess bug in debug message
  ieee1394: sbp2: don't prefer MODE SENSE 10
  ieee1394: nodemgr: grab class.subsys.rwsem in nodemgr_resume_ne
  ieee1394: nodemgr: fix rwsem recursion
  ieee1394: sbp2: more help in Kconfig
  ieee1394: sbp2: prevent rare deadlock in shutdown
  ieee1394: sbp2: update includes
  ieee1394: sbp2: better handling of transport errors
  ieee1394: sbp2: recheck node generation in sbp2_update
  ieee1394: sbp2: safer agent reset in error handlers
  ieee1394: sbp2: handle "sbp2util_node_write_no_wait failed"
  CONFIG_PM=n slim: drivers/ieee1394/ohci1394.c
  ieee1394: safer definition of empty macros
  video1394: add poll file operation support
  ...
This commit is contained in:
Linus Torvalds
2006-09-30 09:38:19 -07:00
31 changed files with 1214 additions and 1173 deletions
@@ -46,15 +46,6 @@ Who: Jody McIntyre <scjody@modernduck.com>
--------------------------- ---------------------------
What: sbp2: module parameter "force_inquiry_hack"
When: July 2006
Why: Superceded by parameter "workarounds". Both parameters are meant to be
used ad-hoc and for single devices only, i.e. not in modprobe.conf,
therefore the impact of this feature replacement should be low.
Who: Stefan Richter <stefanr@s5r6.in-berlin.de>
---------------------------
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices. What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
When: July 2006 When: July 2006
Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6 Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
+10 -27
View File
@@ -1398,36 +1398,29 @@ M: Gadi Oxman <gadio@netvision.net.il>
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
S: Maintained S: Maintained
IEEE 1394 ETHERNET (eth1394)
L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
S: Orphan
IEEE 1394 SUBSYSTEM IEEE 1394 SUBSYSTEM
P: Ben Collins P: Ben Collins
M: bcollins@debian.org M: bcollins@debian.org
P: Jody McIntyre P: Stefan Richter
M: scjody@modernduck.com M: stefanr@s5r6.in-berlin.de
L: linux1394-devel@lists.sourceforge.net L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/ W: http://www.linux1394.org/
T: git kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git T: git kernel.org:/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
S: Maintained S: Maintained
IEEE 1394 OHCI DRIVER IEEE 1394 IPV4 DRIVER (eth1394)
P: Ben Collins P: Stefan Richter
M: bcollins@debian.org M: stefanr@s5r6.in-berlin.de
P: Jody McIntyre
M: scjody@modernduck.com
L: linux1394-devel@lists.sourceforge.net L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/ S: Odd Fixes
S: Maintained
IEEE 1394 PCILYNX DRIVER IEEE 1394 PCILYNX DRIVER
P: Jody McIntyre P: Jody McIntyre
M: scjody@modernduck.com M: scjody@modernduck.com
P: Stefan Richter
M: stefanr@s5r6.in-berlin.de
L: linux1394-devel@lists.sourceforge.net L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/ S: Odd Fixes
S: Maintained
IEEE 1394 RAW I/O DRIVER IEEE 1394 RAW I/O DRIVER
P: Ben Collins P: Ben Collins
@@ -1435,16 +1428,6 @@ M: bcollins@debian.org
P: Dan Dennedy P: Dan Dennedy
M: dan@dennedy.org M: dan@dennedy.org
L: linux1394-devel@lists.sourceforge.net L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
S: Maintained
IEEE 1394 SBP2
P: Ben Collins
M: bcollins@debian.org
P: Stefan Richter
M: stefanr@s5r6.in-berlin.de
L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
S: Maintained S: Maintained
IMS TWINTURBO FRAMEBUFFER DRIVER IMS TWINTURBO FRAMEBUFFER DRIVER
+9 -2
View File
@@ -120,12 +120,19 @@ config IEEE1394_VIDEO1394
this option only if you have an IEEE 1394 video device connected to this option only if you have an IEEE 1394 video device connected to
an OHCI-1394 card. an OHCI-1394 card.
comment "SBP-2 support (for storage devices) requires SCSI"
depends on IEEE1394 && SCSI=n
config IEEE1394_SBP2 config IEEE1394_SBP2
tristate "SBP-2 support (Harddisks etc.)" tristate "SBP-2 support (Harddisks etc.)"
depends on IEEE1394 && SCSI && (PCI || BROKEN) depends on IEEE1394 && SCSI && (PCI || BROKEN)
help help
This option enables you to use SBP-2 devices connected to your IEEE This option enables you to use SBP-2 devices connected to an IEEE
1394 bus. SBP-2 devices include harddrives and DVD devices. 1394 bus. SBP-2 devices include storage devices like harddisks and
DVD drives, also some other FireWire devices like scanners.
You should also enable support for disks, CD-ROMs, etc. in the SCSI
configuration section.
config IEEE1394_SBP2_PHYS_DMA config IEEE1394_SBP2_PHYS_DMA
bool "Enable replacement for physical DMA in SBP2" bool "Enable replacement for physical DMA in SBP2"
+10 -21
View File
@@ -17,11 +17,13 @@
* *
*/ */
#include <linux/string.h> #include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/param.h> #include <linux/param.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/string.h>
#include "csr1212.h" #include "csr1212.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
@@ -149,31 +151,18 @@ static void host_reset(struct hpsb_host *host)
/* /*
* HI == seconds (bits 0:2) * HI == seconds (bits 0:2)
* LO == fraction units of 1/8000 of a second, as per 1394 (bits 19:31) * LO == fractions of a second in units of 125usec (bits 19:31)
* *
* Convert to units and then to HZ, for comparison to jiffies. * Convert SPLIT_TIMEOUT to jiffies.
* * The default and minimum as per 1394a-2000 clause 8.3.2.2.6 is 100ms.
* By default this will end up being 800 units, or 100ms (125usec per
* unit).
*
* NOTE: The spec says 1/8000, but also says we can compute based on 1/8192
* like CSR specifies. Should make our math less complex.
*/ */
static inline void calculate_expire(struct csr_control *csr) static inline void calculate_expire(struct csr_control *csr)
{ {
unsigned long units; unsigned long usecs =
(csr->split_timeout_hi & 0x07) * USEC_PER_SEC +
(csr->split_timeout_lo >> 19) * 125L;
/* Take the seconds, and convert to units */ csr->expire = usecs_to_jiffies(usecs > 100000L ? usecs : 100000L);
units = (unsigned long)(csr->split_timeout_hi & 0x07) << 13;
/* Add in the fractional units */
units += (unsigned long)(csr->split_timeout_lo >> 19);
/* Convert to jiffies */
csr->expire = (unsigned long)(units * HZ) >> 13UL;
/* Just to keep from rounding low */
csr->expire++;
HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ); HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ);
} }
+55 -52
View File
@@ -1,75 +1,73 @@
#ifndef _IEEE1394_CSR_H #ifndef _IEEE1394_CSR_H
#define _IEEE1394_CSR_H #define _IEEE1394_CSR_H
#ifdef CONFIG_PREEMPT #include <linux/spinlock_types.h>
#include <linux/sched.h>
#endif
#include "csr1212.h" #include "csr1212.h"
#include "ieee1394_types.h"
#define CSR_REGISTER_BASE 0xfffff0000000ULL #define CSR_REGISTER_BASE 0xfffff0000000ULL
/* register offsets relative to CSR_REGISTER_BASE */ /* register offsets relative to CSR_REGISTER_BASE */
#define CSR_STATE_CLEAR 0x0 #define CSR_STATE_CLEAR 0x0
#define CSR_STATE_SET 0x4 #define CSR_STATE_SET 0x4
#define CSR_NODE_IDS 0x8 #define CSR_NODE_IDS 0x8
#define CSR_RESET_START 0xc #define CSR_RESET_START 0xc
#define CSR_SPLIT_TIMEOUT_HI 0x18 #define CSR_SPLIT_TIMEOUT_HI 0x18
#define CSR_SPLIT_TIMEOUT_LO 0x1c #define CSR_SPLIT_TIMEOUT_LO 0x1c
#define CSR_CYCLE_TIME 0x200 #define CSR_CYCLE_TIME 0x200
#define CSR_BUS_TIME 0x204 #define CSR_BUS_TIME 0x204
#define CSR_BUSY_TIMEOUT 0x210 #define CSR_BUSY_TIMEOUT 0x210
#define CSR_BUS_MANAGER_ID 0x21c #define CSR_BUS_MANAGER_ID 0x21c
#define CSR_BANDWIDTH_AVAILABLE 0x220 #define CSR_BANDWIDTH_AVAILABLE 0x220
#define CSR_CHANNELS_AVAILABLE 0x224 #define CSR_CHANNELS_AVAILABLE 0x224
#define CSR_CHANNELS_AVAILABLE_HI 0x224 #define CSR_CHANNELS_AVAILABLE_HI 0x224
#define CSR_CHANNELS_AVAILABLE_LO 0x228 #define CSR_CHANNELS_AVAILABLE_LO 0x228
#define CSR_BROADCAST_CHANNEL 0x234 #define CSR_BROADCAST_CHANNEL 0x234
#define CSR_CONFIG_ROM 0x400 #define CSR_CONFIG_ROM 0x400
#define CSR_CONFIG_ROM_END 0x800 #define CSR_CONFIG_ROM_END 0x800
#define CSR_FCP_COMMAND 0xB00 #define CSR_FCP_COMMAND 0xB00
#define CSR_FCP_RESPONSE 0xD00 #define CSR_FCP_RESPONSE 0xD00
#define CSR_FCP_END 0xF00 #define CSR_FCP_END 0xF00
#define CSR_TOPOLOGY_MAP 0x1000 #define CSR_TOPOLOGY_MAP 0x1000
#define CSR_TOPOLOGY_MAP_END 0x1400 #define CSR_TOPOLOGY_MAP_END 0x1400
#define CSR_SPEED_MAP 0x2000 #define CSR_SPEED_MAP 0x2000
#define CSR_SPEED_MAP_END 0x3000 #define CSR_SPEED_MAP_END 0x3000
/* IEEE 1394 bus specific Configuration ROM Key IDs */ /* IEEE 1394 bus specific Configuration ROM Key IDs */
#define IEEE1394_KV_ID_POWER_REQUIREMENTS (0x30) #define IEEE1394_KV_ID_POWER_REQUIREMENTS (0x30)
/* IEEE 1394 Bus Inforamation Block specifics */ /* IEEE 1394 Bus Information Block specifics */
#define CSR_BUS_INFO_SIZE (5 * sizeof(quadlet_t)) #define CSR_BUS_INFO_SIZE (5 * sizeof(quadlet_t))
#define CSR_IRMC_SHIFT 31 #define CSR_IRMC_SHIFT 31
#define CSR_CMC_SHIFT 30 #define CSR_CMC_SHIFT 30
#define CSR_ISC_SHIFT 29 #define CSR_ISC_SHIFT 29
#define CSR_BMC_SHIFT 28 #define CSR_BMC_SHIFT 28
#define CSR_PMC_SHIFT 27 #define CSR_PMC_SHIFT 27
#define CSR_CYC_CLK_ACC_SHIFT 16 #define CSR_CYC_CLK_ACC_SHIFT 16
#define CSR_MAX_REC_SHIFT 12 #define CSR_MAX_REC_SHIFT 12
#define CSR_MAX_ROM_SHIFT 8 #define CSR_MAX_ROM_SHIFT 8
#define CSR_GENERATION_SHIFT 4 #define CSR_GENERATION_SHIFT 4
#define CSR_SET_BUS_INFO_GENERATION(csr, gen) \ #define CSR_SET_BUS_INFO_GENERATION(csr, gen) \
((csr)->bus_info_data[2] = \ ((csr)->bus_info_data[2] = \
cpu_to_be32((be32_to_cpu((csr)->bus_info_data[2]) & \ cpu_to_be32((be32_to_cpu((csr)->bus_info_data[2]) & \
~(0xf << CSR_GENERATION_SHIFT)) | \ ~(0xf << CSR_GENERATION_SHIFT)) | \
(gen) << CSR_GENERATION_SHIFT)) (gen) << CSR_GENERATION_SHIFT))
struct csr_control { struct csr_control {
spinlock_t lock; spinlock_t lock;
quadlet_t state; quadlet_t state;
quadlet_t node_ids; quadlet_t node_ids;
quadlet_t split_timeout_hi, split_timeout_lo; quadlet_t split_timeout_hi, split_timeout_lo;
unsigned long expire; // Calculated from split_timeout unsigned long expire; /* Calculated from split_timeout */
quadlet_t cycle_time; quadlet_t cycle_time;
quadlet_t bus_time; quadlet_t bus_time;
quadlet_t bus_manager_id; quadlet_t bus_manager_id;
quadlet_t bandwidth_available; quadlet_t bandwidth_available;
quadlet_t channels_available_hi, channels_available_lo; quadlet_t channels_available_hi, channels_available_lo;
quadlet_t broadcast_channel; quadlet_t broadcast_channel;
/* Bus Info */ /* Bus Info */
@@ -84,8 +82,8 @@ struct csr_control {
struct csr1212_csr *rom; struct csr1212_csr *rom;
quadlet_t topology_map[256]; quadlet_t topology_map[256];
quadlet_t speed_map[1024]; quadlet_t speed_map[1024];
}; };
extern struct csr1212_bus_ops csr_bus_ops; extern struct csr1212_bus_ops csr_bus_ops;
@@ -93,4 +91,9 @@ extern struct csr1212_bus_ops csr_bus_ops;
int init_csr(void); int init_csr(void);
void cleanup_csr(void); void cleanup_csr(void);
/* hpsb_update_config_rom() is deprecated */
struct hpsb_host;
int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom,
size_t size, unsigned char rom_version);
#endif /* _IEEE1394_CSR_H */ #endif /* _IEEE1394_CSR_H */
+6 -3
View File
@@ -7,10 +7,13 @@
* directory of the kernel sources for details. * directory of the kernel sources for details.
*/ */
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <asm/scatterlist.h>
#include "dma.h" #include "dma.h"
/* dma_prog_region */ /* dma_prog_region */
+54 -32
View File
@@ -10,69 +10,91 @@
#ifndef IEEE1394_DMA_H #ifndef IEEE1394_DMA_H
#define IEEE1394_DMA_H #define IEEE1394_DMA_H
#include <linux/pci.h> #include <asm/types.h>
#include <asm/scatterlist.h>
/* struct dma_prog_region struct pci_dev;
struct scatterlist;
a small, physically-contiguous DMA buffer with random-access, struct vm_area_struct;
synchronous usage characteristics
*/
/**
* struct dma_prog_region - small contiguous DMA buffer
* @kvirt: kernel virtual address
* @dev: PCI device
* @n_pages: number of kernel pages
* @bus_addr: base bus address
*
* a small, physically contiguous DMA buffer with random-access, synchronous
* usage characteristics
*/
struct dma_prog_region { struct dma_prog_region {
unsigned char *kvirt; /* kernel virtual address */ unsigned char *kvirt;
struct pci_dev *dev; /* PCI device */ struct pci_dev *dev;
unsigned int n_pages; /* # of kernel pages */ unsigned int n_pages;
dma_addr_t bus_addr; /* base bus address */ dma_addr_t bus_addr;
}; };
/* clear out all fields but do not allocate any memory */ /* clear out all fields but do not allocate any memory */
void dma_prog_region_init(struct dma_prog_region *prog); void dma_prog_region_init(struct dma_prog_region *prog);
int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev); int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
struct pci_dev *dev);
void dma_prog_region_free(struct dma_prog_region *prog); void dma_prog_region_free(struct dma_prog_region *prog);
static inline dma_addr_t dma_prog_region_offset_to_bus(struct dma_prog_region *prog, unsigned long offset) static inline dma_addr_t dma_prog_region_offset_to_bus(
struct dma_prog_region *prog, unsigned long offset)
{ {
return prog->bus_addr + offset; return prog->bus_addr + offset;
} }
/* struct dma_region /**
* struct dma_region - large non-contiguous DMA buffer
a large, non-physically-contiguous DMA buffer with streaming, * @virt: kernel virtual address
asynchronous usage characteristics * @dev: PCI device
*/ * @n_pages: number of kernel pages
* @n_dma_pages: number of IOMMU pages
* @sglist: IOMMU mapping
* @direction: PCI_DMA_TODEVICE, etc.
*
* a large, non-physically-contiguous DMA buffer with streaming, asynchronous
* usage characteristics
*/
struct dma_region { struct dma_region {
unsigned char *kvirt; /* kernel virtual address */ unsigned char *kvirt;
struct pci_dev *dev; /* PCI device */ struct pci_dev *dev;
unsigned int n_pages; /* # of kernel pages */ unsigned int n_pages;
unsigned int n_dma_pages; /* # of IOMMU pages */ unsigned int n_dma_pages;
struct scatterlist *sglist; /* IOMMU mapping */ struct scatterlist *sglist;
int direction; /* PCI_DMA_TODEVICE, etc */ int direction;
}; };
/* clear out all fields but do not allocate anything */ /* 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 */ /* 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); int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
struct pci_dev *dev, int direction);
/* unmap and free the buffer */ /* 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 */ /* sync the CPU's view of the buffer */
void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset, unsigned long len); void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
unsigned long len);
/* sync the IO bus' view of the buffer */ /* sync the IO bus' view of the buffer */
void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset, unsigned long len); void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
unsigned long len);
/* map the buffer into a user space process */ /* map the buffer into a user space process */
int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma); 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) */ /* macro to index into a DMA region (or dma_prog_region) */
#define dma_region_i(_dma, _type, _index) ( ((_type*) ((_dma)->kvirt)) + (_index) ) #define dma_region_i(_dma, _type, _index) \
( ((_type*) ((_dma)->kvirt)) + (_index) )
/* return the DMA bus address of the byte with the given offset /* return the DMA bus address of the byte with the given offset
relative to the beginning of the dma_region */ * relative to the beginning of the dma_region */
dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset); dma_addr_t dma_region_offset_to_bus(struct dma_region *dma,
unsigned long offset);
#endif /* IEEE1394_DMA_H */ #endif /* IEEE1394_DMA_H */
+3 -3
View File
@@ -460,7 +460,7 @@ struct video_card {
int dma_running; int dma_running;
/* /*
3) the sleeping semaphore 'sem' - this is used from process context only, 3) the sleeping mutex 'mtx' - this is used from process context only,
to serialize various operations on the video_card. Even though only one to serialize various operations on the video_card. Even though only one
open() is allowed, we still need to prevent multiple threads of execution open() is allowed, we still need to prevent multiple threads of execution
from entering calls like read, write, ioctl, etc. from entering calls like read, write, ioctl, etc.
@@ -468,9 +468,9 @@ struct video_card {
I honestly can't think of a good reason to use dv1394 from several threads I honestly can't think of a good reason to use dv1394 from several threads
at once, but we need to serialize anyway to prevent oopses =). at once, but we need to serialize anyway to prevent oopses =).
NOTE: if you need both spinlock and sem, take sem first to avoid deadlock! NOTE: if you need both spinlock and mtx, take mtx first to avoid deadlock!
*/ */
struct semaphore sem; struct mutex mtx;
/* people waiting for buffer space, please form a line here... */ /* people waiting for buffer space, please form a line here... */
wait_queue_head_t waitq; wait_queue_head_t waitq;
+25 -24
View File
@@ -95,6 +95,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/mutex.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/atomic.h> #include <asm/atomic.h>
@@ -110,15 +111,15 @@
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/cdev.h> #include <linux/cdev.h>
#include "ieee1394.h"
#include "ieee1394_types.h"
#include "nodemgr.h"
#include "hosts.h"
#include "ieee1394_core.h"
#include "highlevel.h"
#include "dv1394.h" #include "dv1394.h"
#include "dv1394-private.h" #include "dv1394-private.h"
#include "highlevel.h"
#include "hosts.h"
#include "ieee1394.h"
#include "ieee1394_core.h"
#include "ieee1394_hotplug.h"
#include "ieee1394_types.h"
#include "nodemgr.h"
#include "ohci1394.h" #include "ohci1394.h"
/* DEBUG LEVELS: /* DEBUG LEVELS:
@@ -136,13 +137,13 @@
#if DV1394_DEBUG_LEVEL >= 2 #if DV1394_DEBUG_LEVEL >= 2
#define irq_printk( args... ) printk( args ) #define irq_printk( args... ) printk( args )
#else #else
#define irq_printk( args... ) #define irq_printk( args... ) do {} while (0)
#endif #endif
#if DV1394_DEBUG_LEVEL >= 1 #if DV1394_DEBUG_LEVEL >= 1
#define debug_printk( args... ) printk( args) #define debug_printk( args... ) printk( args)
#else #else
#define debug_printk( args... ) #define debug_printk( args... ) do {} while (0)
#endif #endif
/* issue a dummy PCI read to force the preceding write /* issue a dummy PCI read to force the preceding write
@@ -247,7 +248,7 @@ static void frame_delete(struct frame *f)
Frame_prepare() must be called OUTSIDE the video->spinlock. Frame_prepare() must be called OUTSIDE the video->spinlock.
However, frame_prepare() must still be serialized, so However, frame_prepare() must still be serialized, so
it should be called WITH the video->sem taken. it should be called WITH the video->mtx taken.
*/ */
static void frame_prepare(struct video_card *video, unsigned int this_frame) static void frame_prepare(struct video_card *video, unsigned int this_frame)
@@ -1271,7 +1272,7 @@ static int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
int retval = -EINVAL; int retval = -EINVAL;
/* serialize mmap */ /* serialize mmap */
down(&video->sem); mutex_lock(&video->mtx);
if ( ! video_card_initialized(video) ) { if ( ! video_card_initialized(video) ) {
retval = do_dv1394_init_default(video); retval = do_dv1394_init_default(video);
@@ -1281,7 +1282,7 @@ static int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
retval = dma_region_mmap(&video->dv_buf, file, vma); retval = dma_region_mmap(&video->dv_buf, file, vma);
out: out:
up(&video->sem); mutex_unlock(&video->mtx);
return retval; return retval;
} }
@@ -1337,17 +1338,17 @@ static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t
/* serialize this to prevent multi-threaded mayhem */ /* serialize this to prevent multi-threaded mayhem */
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK) {
if (down_trylock(&video->sem)) if (!mutex_trylock(&video->mtx))
return -EAGAIN; return -EAGAIN;
} else { } else {
if (down_interruptible(&video->sem)) if (mutex_lock_interruptible(&video->mtx))
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if ( !video_card_initialized(video) ) { if ( !video_card_initialized(video) ) {
ret = do_dv1394_init_default(video); ret = do_dv1394_init_default(video);
if (ret) { if (ret) {
up(&video->sem); mutex_unlock(&video->mtx);
return ret; return ret;
} }
} }
@@ -1418,7 +1419,7 @@ static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t
remove_wait_queue(&video->waitq, &wait); remove_wait_queue(&video->waitq, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
up(&video->sem); mutex_unlock(&video->mtx);
return ret; return ret;
} }
@@ -1434,17 +1435,17 @@ static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count
/* serialize this to prevent multi-threaded mayhem */ /* serialize this to prevent multi-threaded mayhem */
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK) {
if (down_trylock(&video->sem)) if (!mutex_trylock(&video->mtx))
return -EAGAIN; return -EAGAIN;
} else { } else {
if (down_interruptible(&video->sem)) if (mutex_lock_interruptible(&video->mtx))
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if ( !video_card_initialized(video) ) { if ( !video_card_initialized(video) ) {
ret = do_dv1394_init_default(video); ret = do_dv1394_init_default(video);
if (ret) { if (ret) {
up(&video->sem); mutex_unlock(&video->mtx);
return ret; return ret;
} }
video->continuity_counter = -1; video->continuity_counter = -1;
@@ -1526,7 +1527,7 @@ static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count
remove_wait_queue(&video->waitq, &wait); remove_wait_queue(&video->waitq, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
up(&video->sem); mutex_unlock(&video->mtx);
return ret; return ret;
} }
@@ -1547,12 +1548,12 @@ static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
/* serialize this to prevent multi-threaded mayhem */ /* serialize this to prevent multi-threaded mayhem */
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK) {
if (down_trylock(&video->sem)) { if (!mutex_trylock(&video->mtx)) {
unlock_kernel(); unlock_kernel();
return -EAGAIN; return -EAGAIN;
} }
} else { } else {
if (down_interruptible(&video->sem)) { if (mutex_lock_interruptible(&video->mtx)) {
unlock_kernel(); unlock_kernel();
return -ERESTARTSYS; return -ERESTARTSYS;
} }
@@ -1778,7 +1779,7 @@ static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} }
out: out:
up(&video->sem); mutex_unlock(&video->mtx);
unlock_kernel(); unlock_kernel();
return ret; return ret;
} }
@@ -2253,7 +2254,7 @@ static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes
clear_bit(0, &video->open); clear_bit(0, &video->open);
spin_lock_init(&video->spinlock); spin_lock_init(&video->spinlock);
video->dma_running = 0; video->dma_running = 0;
init_MUTEX(&video->sem); mutex_init(&video->mtx);
init_waitqueue_head(&video->waitq); init_waitqueue_head(&video->waitq);
video->fasync = NULL; video->fasync = NULL;
+7 -7
View File
@@ -64,19 +64,19 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/semaphore.h>
#include <net/arp.h> #include <net/arp.h>
#include "config_roms.h"
#include "csr1212.h" #include "csr1212.h"
#include "ieee1394_types.h" #include "eth1394.h"
#include "ieee1394_core.h"
#include "ieee1394_transactions.h"
#include "ieee1394.h"
#include "highlevel.h" #include "highlevel.h"
#include "ieee1394.h"
#include "ieee1394_core.h"
#include "ieee1394_hotplug.h"
#include "ieee1394_transactions.h"
#include "ieee1394_types.h"
#include "iso.h" #include "iso.h"
#include "nodemgr.h" #include "nodemgr.h"
#include "eth1394.h"
#include "config_roms.h"
#define ETH1394_PRINT_G(level, fmt, args...) \ #define ETH1394_PRINT_G(level, fmt, args...) \
printk(level "%s: " fmt, driver_name, ## args) printk(level "%s: " fmt, driver_name, ## args)
+104 -97
View File
@@ -1,60 +1,61 @@
#ifndef IEEE1394_HIGHLEVEL_H #ifndef IEEE1394_HIGHLEVEL_H
#define IEEE1394_HIGHLEVEL_H #define IEEE1394_HIGHLEVEL_H
#include <linux/list.h>
#include <linux/spinlock_types.h>
#include <linux/types.h>
struct module;
#include "ieee1394_types.h"
struct hpsb_host;
/* internal to ieee1394 core */
struct hpsb_address_serve { struct hpsb_address_serve {
struct list_head host_list; /* per host list */ struct list_head host_list; /* per host list */
struct list_head hl_list; /* hpsb_highlevel list */
struct list_head hl_list; /* hpsb_highlevel list */ struct hpsb_address_ops *op;
struct hpsb_address_ops *op;
struct hpsb_host *host; struct hpsb_host *host;
u64 start; /* first address handled, quadlet aligned */
/* first address handled and first address behind, quadlet aligned */ u64 end; /* first address behind, quadlet aligned */
u64 start, end;
}; };
/* Only the following structures are of interest to actual highlevel drivers. */
/*
* The above structs are internal to highlevel driver handling. Only the
* following structures are of interest to actual highlevel drivers.
*/
struct hpsb_highlevel { struct hpsb_highlevel {
struct module *owner; struct module *owner;
const char *name; const char *name;
/* Any of the following pointers can legally be NULL, except for /* Any of the following pointers can legally be NULL, except for
* iso_receive which can only be NULL when you don't request * iso_receive which can only be NULL when you don't request
* channels. */ * channels. */
/* New host initialized. Will also be called during /* New host initialized. Will also be called during
* hpsb_register_highlevel for all hosts already installed. */ * hpsb_register_highlevel for all hosts already installed. */
void (*add_host) (struct hpsb_host *host); void (*add_host)(struct hpsb_host *host);
/* Host about to be removed. Will also be called during /* Host about to be removed. Will also be called during
* hpsb_unregister_highlevel once for each host. */ * hpsb_unregister_highlevel once for each host. */
void (*remove_host) (struct hpsb_host *host); void (*remove_host)(struct hpsb_host *host);
/* Host experienced bus reset with possible configuration changes. /* Host experienced bus reset with possible configuration changes.
* Note that this one may occur during interrupt/bottom half handling. * Note that this one may occur during interrupt/bottom half handling.
* You can not expect to be able to do stock hpsb_reads. */ * You can not expect to be able to do stock hpsb_reads. */
void (*host_reset) (struct hpsb_host *host); void (*host_reset)(struct hpsb_host *host);
/* An isochronous packet was received. Channel contains the channel /* An isochronous packet was received. Channel contains the channel
* number for your convenience, it is also contained in the included * number for your convenience, it is also contained in the included
* packet header (first quadlet, CRCs are missing). You may get called * packet header (first quadlet, CRCs are missing). You may get called
* for channel/host combinations you did not request. */ * for channel/host combinations you did not request. */
void (*iso_receive) (struct hpsb_host *host, int channel, void (*iso_receive)(struct hpsb_host *host, int channel,
quadlet_t *data, size_t length); quadlet_t *data, size_t length);
/* A write request was received on either the FCP_COMMAND (direction = /* A write request was received on either the FCP_COMMAND (direction =
* 0) or the FCP_RESPONSE (direction = 1) register. The cts arg * 0) or the FCP_RESPONSE (direction = 1) register. The cts arg
* contains the cts field (first byte of data). */ * contains the cts field (first byte of data). */
void (*fcp_request) (struct hpsb_host *host, int nodeid, int direction, void (*fcp_request)(struct hpsb_host *host, int nodeid, int direction,
int cts, u8 *data, size_t length); int cts, u8 *data, size_t length);
/* These are initialized by the subsystem when the /* These are initialized by the subsystem when the
* hpsb_higlevel is registered. */ * hpsb_higlevel is registered. */
@@ -67,61 +68,62 @@ struct hpsb_highlevel {
}; };
struct hpsb_address_ops { struct hpsb_address_ops {
/* /*
* Null function pointers will make the respective operation complete * Null function pointers will make the respective operation complete
* with RCODE_TYPE_ERROR. Makes for easy to implement read-only * with RCODE_TYPE_ERROR. Makes for easy to implement read-only
* registers (just leave everything but read NULL). * registers (just leave everything but read NULL).
* *
* All functions shall return appropriate IEEE 1394 rcodes. * All functions shall return appropriate IEEE 1394 rcodes.
*/ */
/* These functions have to implement block reads for themselves. */ /* These functions have to implement block reads for themselves.
/* These functions either return a response code *
or a negative number. In the first case a response will be generated; in the * These functions either return a response code or a negative number.
later case, no response will be sent and the driver, that handled the request * In the first case a response will be generated. In the latter case,
will send the response itself * no response will be sent and the driver which handled the request
*/ * will send the response itself. */
int (*read) (struct hpsb_host *host, int nodeid, quadlet_t *buffer, int (*read)(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
u64 addr, size_t length, u16 flags); u64 addr, size_t length, u16 flags);
int (*write) (struct hpsb_host *host, int nodeid, int destid, int (*write)(struct hpsb_host *host, int nodeid, int destid,
quadlet_t *data, u64 addr, size_t length, u16 flags); quadlet_t *data, u64 addr, size_t length, u16 flags);
/* Lock transactions: write results of ext_tcode operation into /* Lock transactions: write results of ext_tcode operation into
* *store. */ * *store. */
int (*lock) (struct hpsb_host *host, int nodeid, quadlet_t *store, int (*lock)(struct hpsb_host *host, int nodeid, quadlet_t *store,
u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags); u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
int (*lock64) (struct hpsb_host *host, int nodeid, octlet_t *store, u16 flags);
u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags); int (*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_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 * These functions are called to handle transactions. They are called when a
a packet arrives. The flags argument contains the second word of the first header * packet arrives. The flags argument contains the second word of the first
quadlet of the incoming packet (containing transaction label, retry code, * header quadlet of the incoming packet (containing transaction label, retry
transaction code and priority). These functions either return a response code * code, transaction code and priority). These functions either return a
or a negative number. In the first case a response will be generated; in the * response code or a negative number. In the first case a response will be
later case, no response will be sent and the driver, that handled the request * generated. In the latter case, no response will be sent and the driver which
will send the response itself. * handled the request will send the response itself.
*/ */
int highlevel_read(struct hpsb_host *host, int nodeid, void *data, int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
u64 addr, unsigned int length, u16 flags); unsigned int length, u16 flags);
int highlevel_write(struct hpsb_host *host, int nodeid, int destid, int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data,
void *data, u64 addr, unsigned int length, u16 flags); u64 addr, unsigned int length, u16 flags);
int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store, int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags); u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
u16 flags);
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, u16 flags); u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags);
void highlevel_iso_receive(struct hpsb_host *host, void *data, void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length);
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 * Register highlevel driver. The name pointer has to stay valid at all times
@@ -132,13 +134,15 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
/* /*
* Register handlers for host address spaces. Start and end are 48 bit pointers * Register handlers for host address spaces. Start and end are 48 bit pointers
* and have to be quadlet aligned (end points to the first address behind the * and have to be quadlet aligned. Argument "end" points to the first address
* handled addresses. This function can be called multiple times for a single * behind the handled addresses. This function can be called multiple times for
* hpsb_highlevel to implement sparse register sets. The requested region must * a single hpsb_highlevel to implement sparse register sets. The requested
* not overlap any previously allocated region, otherwise registering will fail. * region must not overlap any previously allocated region, otherwise
* registering will fail.
* *
* It returns true for successful allocation. There is no unregister function, * It returns true for successful allocation. Address spaces can be
* all address spaces are deallocated together with the hpsb_highlevel. * 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,
@@ -146,20 +150,18 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
u64 size, u64 alignment, u64 size, u64 alignment,
u64 start, u64 end); u64 start, u64 end);
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);
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 * Enable or disable receving a certain isochronous channel through the
* iso_receive op. * 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 */ /* 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);
@@ -172,19 +174,24 @@ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *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 */ /* 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); 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 */ /* Retrieve the alternate lookup key for the hostinfo bound to this
unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host); * 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 */ /* 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 /* Set the hostinfo pointer to something useful. Usually follows a call to
* hpsb_create_hostinfo, where the size is 0. */ * hpsb_create_hostinfo, where the size is 0. */
int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *data); int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
void *data);
/* Retrieve hpsb_host using a highlevel handle and a key */ /* Retrieve hpsb_host using a highlevel handle and a key */
struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key); struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl,
unsigned long key);
#endif /* IEEE1394_HIGHLEVEL_H */ #endif /* IEEE1394_HIGHLEVEL_H */
+10 -13
View File
@@ -90,6 +90,16 @@ 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);
/** /**
* hpsb_alloc_host - allocate a new host controller. * hpsb_alloc_host - allocate a new host controller.
* @drv: the driver that will manage the host controller * @drv: the driver that will manage the host controller
@@ -105,16 +115,6 @@ static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
* Return Value: a pointer to the &hpsb_host if successful, %NULL if * Return Value: a pointer to the &hpsb_host if successful, %NULL if
* no memory was available. * no memory was available.
*/ */
static DEFINE_MUTEX(host_num_alloc);
/*
* 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;
struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
struct device *dev) struct device *dev)
{ {
@@ -143,9 +143,6 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
for (i = 2; i < 16; i++) for (i = 2; i < 16; i++)
h->csr.gen_timestamp[i] = jiffies - 60 * HZ; h->csr.gen_timestamp[i] = jiffies - 60 * HZ;
for (i = 0; i < ARRAY_SIZE(h->tpool); i++)
HPSB_TPOOL_INIT(&h->tpool[i]);
atomic_set(&h->generation, 0); atomic_set(&h->generation, 0);
INIT_WORK(&h->delayed_reset, delayed_reset_bus, h); INIT_WORK(&h->delayed_reset, delayed_reset_bus, h);
+24 -31
View File
@@ -2,17 +2,19 @@
#define _IEEE1394_HOSTS_H #define _IEEE1394_HOSTS_H
#include <linux/device.h> #include <linux/device.h>
#include <linux/wait.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/timer.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/timer.h>
#include <linux/types.h>
#include <linux/workqueue.h>
#include <asm/atomic.h>
#include <asm/semaphore.h> struct pci_dev;
struct module;
#include "ieee1394_types.h" #include "ieee1394_types.h"
#include "csr.h" #include "csr.h"
struct hpsb_packet; struct hpsb_packet;
struct hpsb_iso; struct hpsb_iso;
@@ -33,7 +35,6 @@ struct hpsb_host {
int node_count; /* number of identified nodes on this bus */ int node_count; /* number of identified nodes on this bus */
int selfid_count; /* total number of SelfIDs received */ int selfid_count; /* total number of SelfIDs received */
int nodes_active; /* number of nodes with active link layer */ int nodes_active; /* number of nodes with active link layer */
u8 speed[ALL_NODES]; /* speed between each node and local node */
nodeid_t node_id; /* node ID of this host */ nodeid_t node_id; /* node ID of this host */
nodeid_t irm_id; /* ID of this bus' isochronous resource manager */ nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
@@ -53,32 +54,30 @@ struct hpsb_host {
int reset_retries; int reset_retries;
quadlet_t *topology_map; quadlet_t *topology_map;
u8 *speed_map; u8 *speed_map;
struct csr_control csr;
/* Per node tlabel pool allocation */
struct hpsb_tlabel_pool tpool[ALL_NODES];
struct hpsb_host_driver *driver;
struct pci_dev *pdev;
int id; int id;
struct hpsb_host_driver *driver;
struct pci_dev *pdev;
struct device device; struct device device;
struct class_device class_dev; struct class_device class_dev;
int update_config_rom; int update_config_rom;
struct work_struct delayed_reset; struct work_struct delayed_reset;
unsigned int config_roms; unsigned int config_roms;
struct list_head addr_space; struct list_head addr_space;
u64 low_addr_space; /* upper bound of physical DMA area */ u64 low_addr_space; /* upper bound of physical DMA area */
u64 middle_addr_space; /* upper bound of posted write area */ u64 middle_addr_space; /* upper bound of posted write area */
u8 speed[ALL_NODES]; /* speed between each node and local node */
/* per node tlabel allocation */
u8 next_tl[ALL_NODES];
struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES];
struct csr_control csr;
}; };
enum devctl_cmd { enum devctl_cmd {
/* Host is requested to reset its bus and cancel all outstanding async /* Host is requested to reset its bus and cancel all outstanding async
* requests. If arg == 1, it shall also attempt to become root on the * requests. If arg == 1, it shall also attempt to become root on the
@@ -112,7 +111,7 @@ enum devctl_cmd {
enum isoctl_cmd { enum isoctl_cmd {
/* rawiso API - see iso.h for the meanings of these commands /* rawiso API - see iso.h for the meanings of these commands
(they correspond exactly to the hpsb_iso_* API functions) * (they correspond exactly to the hpsb_iso_* API functions)
* INIT = allocate resources * INIT = allocate resources
* START = begin transmission/reception * START = begin transmission/reception
* STOP = halt transmission/reception * STOP = halt transmission/reception
@@ -160,7 +159,8 @@ struct hpsb_host_driver {
/* The hardware driver may optionally support a function that is used /* The hardware driver may optionally support a function that is used
* to set the hardware ConfigROM if the hardware supports handling * to set the hardware ConfigROM if the hardware supports handling
* reads to the ConfigROM on its own. */ * reads to the ConfigROM on its own. */
void (*set_hw_config_rom) (struct hpsb_host *host, quadlet_t *config_rom); void (*set_hw_config_rom)(struct hpsb_host *host,
quadlet_t *config_rom);
/* This function shall implement packet transmission based on /* This function shall implement packet transmission based on
* packet->type. It shall CRC both parts of the packet (unless * packet->type. It shall CRC both parts of the packet (unless
@@ -170,20 +170,21 @@ struct hpsb_host_driver {
* called. Return 0 on success, negative errno on failure. * called. Return 0 on success, negative errno on failure.
* NOTE: The function must be callable in interrupt context. * NOTE: The function must be callable in interrupt context.
*/ */
int (*transmit_packet) (struct hpsb_host *host, int (*transmit_packet)(struct hpsb_host *host,
struct hpsb_packet *packet); struct hpsb_packet *packet);
/* This function requests miscellanous services from the driver, see /* This function requests miscellanous services from the driver, see
* above for command codes and expected actions. Return -1 for unknown * above for command codes and expected actions. Return -1 for unknown
* command, though that should never happen. * command, though that should never happen.
*/ */
int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg); int (*devctl)(struct hpsb_host *host, enum devctl_cmd command, int arg);
/* ISO transmission/reception functions. Return 0 on success, -1 /* ISO transmission/reception functions. Return 0 on success, -1
* (or -EXXX errno code) on failure. If the low-level driver does not * (or -EXXX errno code) on failure. If the low-level driver does not
* support the new ISO API, set isoctl to NULL. * support the new ISO API, set isoctl to NULL.
*/ */
int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg); int (*isoctl)(struct hpsb_iso *iso, enum isoctl_cmd command,
unsigned long arg);
/* This function is mainly to redirect local CSR reads/locks to the iso /* This function is mainly to redirect local CSR reads/locks to the iso
* management registers (bus manager id, bandwidth available, channels * management registers (bus manager id, bandwidth available, channels
@@ -196,19 +197,11 @@ struct hpsb_host_driver {
quadlet_t data, quadlet_t compare); quadlet_t data, quadlet_t compare);
}; };
struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
struct device *dev); struct device *dev);
int hpsb_add_host(struct hpsb_host *host); int hpsb_add_host(struct hpsb_host *host);
void hpsb_remove_host(struct hpsb_host *h); void hpsb_remove_host(struct hpsb_host *h);
/* The following 2 functions are deprecated and will be removed when the
* raw1394/libraw1394 update is complete. */
int hpsb_update_config_rom(struct hpsb_host *host,
const quadlet_t *new_rom, size_t size, unsigned char rom_version);
int hpsb_get_config_rom(struct hpsb_host *host, quadlet_t *buffer,
size_t buffersize, size_t *rom_size, unsigned char *rom_version);
/* Updates the configuration rom image of a host. rom_version must be the /* 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 * current version, otherwise it will fail with return value -1. If this
* host does not support config-rom-update, it will return -EINVAL. * host does not support config-rom-update, it will return -EINVAL.
+5 -4
View File
@@ -1,5 +1,7 @@
/* Base file for all ieee1394 ioctl's. Linux-1394 has allocated base '#' /*
* with a range of 0x00-0x3f. */ * Base file for all ieee1394 ioctl's.
* Linux-1394 has allocated base '#' with a range of 0x00-0x3f.
*/
#ifndef __IEEE1394_IOCTL_H #ifndef __IEEE1394_IOCTL_H
#define __IEEE1394_IOCTL_H #define __IEEE1394_IOCTL_H
@@ -96,8 +98,7 @@
_IOW ('#', 0x27, struct raw1394_iso_packets) _IOW ('#', 0x27, struct raw1394_iso_packets)
#define RAW1394_IOC_ISO_XMIT_SYNC \ #define RAW1394_IOC_ISO_XMIT_SYNC \
_IO ('#', 0x28) _IO ('#', 0x28)
#define RAW1394_IOC_ISO_RECV_FLUSH \ #define RAW1394_IOC_ISO_RECV_FLUSH \
_IO ('#', 0x29) _IO ('#', 0x29)
#endif /* __IEEE1394_IOCTL_H */ #endif /* __IEEE1394_IOCTL_H */
+152 -152
View File
@@ -5,77 +5,78 @@
#ifndef _IEEE1394_IEEE1394_H #ifndef _IEEE1394_IEEE1394_H
#define _IEEE1394_IEEE1394_H #define _IEEE1394_IEEE1394_H
#define TCODE_WRITEQ 0x0 #define TCODE_WRITEQ 0x0
#define TCODE_WRITEB 0x1 #define TCODE_WRITEB 0x1
#define TCODE_WRITE_RESPONSE 0x2 #define TCODE_WRITE_RESPONSE 0x2
#define TCODE_READQ 0x4 #define TCODE_READQ 0x4
#define TCODE_READB 0x5 #define TCODE_READB 0x5
#define TCODE_READQ_RESPONSE 0x6 #define TCODE_READQ_RESPONSE 0x6
#define TCODE_READB_RESPONSE 0x7 #define TCODE_READB_RESPONSE 0x7
#define TCODE_CYCLE_START 0x8 #define TCODE_CYCLE_START 0x8
#define TCODE_LOCK_REQUEST 0x9 #define TCODE_LOCK_REQUEST 0x9
#define TCODE_ISO_DATA 0xa #define TCODE_ISO_DATA 0xa
#define TCODE_STREAM_DATA 0xa #define TCODE_STREAM_DATA 0xa
#define TCODE_LOCK_RESPONSE 0xb #define TCODE_LOCK_RESPONSE 0xb
#define RCODE_COMPLETE 0x0 #define RCODE_COMPLETE 0x0
#define RCODE_CONFLICT_ERROR 0x4 #define RCODE_CONFLICT_ERROR 0x4
#define RCODE_DATA_ERROR 0x5 #define RCODE_DATA_ERROR 0x5
#define RCODE_TYPE_ERROR 0x6 #define RCODE_TYPE_ERROR 0x6
#define RCODE_ADDRESS_ERROR 0x7 #define RCODE_ADDRESS_ERROR 0x7
#define EXTCODE_MASK_SWAP 0x1 #define EXTCODE_MASK_SWAP 0x1
#define EXTCODE_COMPARE_SWAP 0x2 #define EXTCODE_COMPARE_SWAP 0x2
#define EXTCODE_FETCH_ADD 0x3 #define EXTCODE_FETCH_ADD 0x3
#define EXTCODE_LITTLE_ADD 0x4 #define EXTCODE_LITTLE_ADD 0x4
#define EXTCODE_BOUNDED_ADD 0x5 #define EXTCODE_BOUNDED_ADD 0x5
#define EXTCODE_WRAP_ADD 0x6 #define EXTCODE_WRAP_ADD 0x6
#define ACK_COMPLETE 0x1 #define ACK_COMPLETE 0x1
#define ACK_PENDING 0x2 #define ACK_PENDING 0x2
#define ACK_BUSY_X 0x4 #define ACK_BUSY_X 0x4
#define ACK_BUSY_A 0x5 #define ACK_BUSY_A 0x5
#define ACK_BUSY_B 0x6 #define ACK_BUSY_B 0x6
#define ACK_TARDY 0xb #define ACK_TARDY 0xb
#define ACK_CONFLICT_ERROR 0xc #define ACK_CONFLICT_ERROR 0xc
#define ACK_DATA_ERROR 0xd #define ACK_DATA_ERROR 0xd
#define ACK_TYPE_ERROR 0xe #define ACK_TYPE_ERROR 0xe
#define ACK_ADDRESS_ERROR 0xf #define ACK_ADDRESS_ERROR 0xf
/* Non-standard "ACK codes" for internal use */ /* Non-standard "ACK codes" for internal use */
#define ACKX_NONE (-1) #define ACKX_NONE (-1)
#define ACKX_SEND_ERROR (-2) #define ACKX_SEND_ERROR (-2)
#define ACKX_ABORTED (-3) #define ACKX_ABORTED (-3)
#define ACKX_TIMEOUT (-4) #define ACKX_TIMEOUT (-4)
#define IEEE1394_SPEED_100 0x00
#define IEEE1394_SPEED_200 0x01
#define IEEE1394_SPEED_400 0x02
#define IEEE1394_SPEED_800 0x03
#define IEEE1394_SPEED_1600 0x04
#define IEEE1394_SPEED_3200 0x05
#define IEEE1394_SPEED_100 0x00
#define IEEE1394_SPEED_200 0x01
#define IEEE1394_SPEED_400 0x02
#define IEEE1394_SPEED_800 0x03
#define IEEE1394_SPEED_1600 0x04
#define IEEE1394_SPEED_3200 0x05
/* The current highest tested speed supported by the subsystem */ /* The current highest tested speed supported by the subsystem */
#define IEEE1394_SPEED_MAX IEEE1394_SPEED_800 #define IEEE1394_SPEED_MAX IEEE1394_SPEED_800
/* Maps speed values above to a string representation */ /* Maps speed values above to a string representation */
extern const char *hpsb_speedto_str[]; extern const char *hpsb_speedto_str[];
/* 1394a cable PHY packets */ /* 1394a cable PHY packets */
#define SELFID_PWRCL_NO_POWER 0x0 #define SELFID_PWRCL_NO_POWER 0x0
#define SELFID_PWRCL_PROVIDE_15W 0x1 #define SELFID_PWRCL_PROVIDE_15W 0x1
#define SELFID_PWRCL_PROVIDE_30W 0x2 #define SELFID_PWRCL_PROVIDE_30W 0x2
#define SELFID_PWRCL_PROVIDE_45W 0x3 #define SELFID_PWRCL_PROVIDE_45W 0x3
#define SELFID_PWRCL_USE_1W 0x4 #define SELFID_PWRCL_USE_1W 0x4
#define SELFID_PWRCL_USE_3W 0x5 #define SELFID_PWRCL_USE_3W 0x5
#define SELFID_PWRCL_USE_6W 0x6 #define SELFID_PWRCL_USE_6W 0x6
#define SELFID_PWRCL_USE_10W 0x7 #define SELFID_PWRCL_USE_10W 0x7
#define SELFID_PORT_CHILD 0x3 #define SELFID_PORT_CHILD 0x3
#define SELFID_PORT_PARENT 0x2 #define SELFID_PORT_PARENT 0x2
#define SELFID_PORT_NCONN 0x1 #define SELFID_PORT_NCONN 0x1
#define SELFID_PORT_NONE 0x0 #define SELFID_PORT_NONE 0x0
#define SELFID_SPEED_UNKNOWN 0x3 /* 1394b PHY */
#define PHYPACKET_LINKON 0x40000000 #define PHYPACKET_LINKON 0x40000000
#define PHYPACKET_PHYCONFIG_R 0x00800000 #define PHYPACKET_PHYCONFIG_R 0x00800000
@@ -91,76 +92,76 @@ extern const char *hpsb_speedto_str[];
#define EXTPHYPACKET_TYPEMASK 0xC0FC0000 #define EXTPHYPACKET_TYPEMASK 0xC0FC0000
#define PHYPACKET_PORT_SHIFT 24 #define PHYPACKET_PORT_SHIFT 24
#define PHYPACKET_GAPCOUNT_SHIFT 16 #define PHYPACKET_GAPCOUNT_SHIFT 16
/* 1394a PHY register map bitmasks */ /* 1394a PHY register map bitmasks */
#define PHY_00_PHYSICAL_ID 0xFC #define PHY_00_PHYSICAL_ID 0xFC
#define PHY_00_R 0x02 /* Root */ #define PHY_00_R 0x02 /* Root */
#define PHY_00_PS 0x01 /* Power Status*/ #define PHY_00_PS 0x01 /* Power Status*/
#define PHY_01_RHB 0x80 /* Root Hold-Off */ #define PHY_01_RHB 0x80 /* Root Hold-Off */
#define PHY_01_IBR 0x80 /* Initiate Bus Reset */ #define PHY_01_IBR 0x80 /* Initiate Bus Reset */
#define PHY_01_GAP_COUNT 0x3F #define PHY_01_GAP_COUNT 0x3F
#define PHY_02_EXTENDED 0xE0 /* 0x7 for 1394a-compliant PHY */ #define PHY_02_EXTENDED 0xE0 /* 0x7 for 1394a-compliant PHY */
#define PHY_02_TOTAL_PORTS 0x1F #define PHY_02_TOTAL_PORTS 0x1F
#define PHY_03_MAX_SPEED 0xE0 #define PHY_03_MAX_SPEED 0xE0
#define PHY_03_DELAY 0x0F #define PHY_03_DELAY 0x0F
#define PHY_04_LCTRL 0x80 /* Link Active Report Control */ #define PHY_04_LCTRL 0x80 /* Link Active Report Control */
#define PHY_04_CONTENDER 0x40 #define PHY_04_CONTENDER 0x40
#define PHY_04_JITTER 0x38 #define PHY_04_JITTER 0x38
#define PHY_04_PWR_CLASS 0x07 /* Power Class */ #define PHY_04_PWR_CLASS 0x07 /* Power Class */
#define PHY_05_WATCHDOG 0x80 #define PHY_05_WATCHDOG 0x80
#define PHY_05_ISBR 0x40 /* Initiate Short Bus Reset */ #define PHY_05_ISBR 0x40 /* Initiate Short Bus Reset */
#define PHY_05_LOOP 0x20 /* Loop Detect */ #define PHY_05_LOOP 0x20 /* Loop Detect */
#define PHY_05_PWR_FAIL 0x10 /* Cable Power Failure Detect */ #define PHY_05_PWR_FAIL 0x10 /* Cable Power Failure Detect */
#define PHY_05_TIMEOUT 0x08 /* Arbitration State Machine Timeout */ #define PHY_05_TIMEOUT 0x08 /* Arbitration State Machine Timeout */
#define PHY_05_PORT_EVENT 0x04 /* Port Event Detect */ #define PHY_05_PORT_EVENT 0x04 /* Port Event Detect */
#define PHY_05_ENAB_ACCEL 0x02 /* Enable Arbitration Acceleration */ #define PHY_05_ENAB_ACCEL 0x02 /* Enable Arbitration Acceleration */
#define PHY_05_ENAB_MULTI 0x01 /* Ena. Multispeed Packet Concatenation */ #define PHY_05_ENAB_MULTI 0x01 /* Ena. Multispeed Packet Concatenation */
#include <asm/byteorder.h> #include <asm/byteorder.h>
#ifdef __BIG_ENDIAN_BITFIELD #ifdef __BIG_ENDIAN_BITFIELD
struct selfid { struct selfid {
u32 packet_identifier:2; /* always binary 10 */ u32 packet_identifier:2; /* always binary 10 */
u32 phy_id:6; u32 phy_id:6;
/* byte */ /* byte */
u32 extended:1; /* if true is struct ext_selfid */ u32 extended:1; /* if true is struct ext_selfid */
u32 link_active:1; u32 link_active:1;
u32 gap_count:6; u32 gap_count:6;
/* byte */ /* byte */
u32 speed:2; u32 speed:2;
u32 phy_delay:2; u32 phy_delay:2;
u32 contender:1; u32 contender:1;
u32 power_class:3; u32 power_class:3;
/* byte */ /* byte */
u32 port0:2; u32 port0:2;
u32 port1:2; u32 port1:2;
u32 port2:2; u32 port2:2;
u32 initiated_reset:1; u32 initiated_reset:1;
u32 more_packets:1; u32 more_packets:1;
} __attribute__((packed)); } __attribute__((packed));
struct ext_selfid { struct ext_selfid {
u32 packet_identifier:2; /* always binary 10 */ u32 packet_identifier:2; /* always binary 10 */
u32 phy_id:6; u32 phy_id:6;
/* byte */ /* byte */
u32 extended:1; /* if false is struct selfid */ u32 extended:1; /* if false is struct selfid */
u32 seq_nr:3; u32 seq_nr:3;
u32 reserved:2; u32 reserved:2;
u32 porta:2; u32 porta:2;
/* byte */ /* byte */
u32 portb:2; u32 portb:2;
u32 portc:2; u32 portc:2;
u32 portd:2; u32 portd:2;
u32 porte:2; u32 porte:2;
/* byte */ /* byte */
u32 portf:2; u32 portf:2;
u32 portg:2; u32 portg:2;
u32 porth:2; u32 porth:2;
u32 reserved2:1; u32 reserved2:1;
u32 more_packets:1; u32 more_packets:1;
} __attribute__((packed)); } __attribute__((packed));
#elif defined __LITTLE_ENDIAN_BITFIELD /* __BIG_ENDIAN_BITFIELD */ #elif defined __LITTLE_ENDIAN_BITFIELD /* __BIG_ENDIAN_BITFIELD */
@@ -171,49 +172,48 @@ struct ext_selfid {
*/ */
struct selfid { struct selfid {
u32 phy_id:6; u32 phy_id:6;
u32 packet_identifier:2; /* always binary 10 */ u32 packet_identifier:2; /* always binary 10 */
/* byte */ /* byte */
u32 gap_count:6; u32 gap_count:6;
u32 link_active:1; u32 link_active:1;
u32 extended:1; /* if true is struct ext_selfid */ u32 extended:1; /* if true is struct ext_selfid */
/* byte */ /* byte */
u32 power_class:3; u32 power_class:3;
u32 contender:1; u32 contender:1;
u32 phy_delay:2; u32 phy_delay:2;
u32 speed:2; u32 speed:2;
/* byte */ /* byte */
u32 more_packets:1; u32 more_packets:1;
u32 initiated_reset:1; u32 initiated_reset:1;
u32 port2:2; u32 port2:2;
u32 port1:2; u32 port1:2;
u32 port0:2; u32 port0:2;
} __attribute__((packed)); } __attribute__((packed));
struct ext_selfid { struct ext_selfid {
u32 phy_id:6; u32 phy_id:6;
u32 packet_identifier:2; /* always binary 10 */ u32 packet_identifier:2; /* always binary 10 */
/* byte */ /* byte */
u32 porta:2; u32 porta:2;
u32 reserved:2; u32 reserved:2;
u32 seq_nr:3; u32 seq_nr:3;
u32 extended:1; /* if false is struct selfid */ u32 extended:1; /* if false is struct selfid */
/* byte */ /* byte */
u32 porte:2; u32 porte:2;
u32 portd:2; u32 portd:2;
u32 portc:2; u32 portc:2;
u32 portb:2; u32 portb:2;
/* byte */ /* byte */
u32 more_packets:1; u32 more_packets:1;
u32 reserved2:1; u32 reserved2:1;
u32 porth:2; u32 porth:2;
u32 portg:2; u32 portg:2;
u32 portf:2; u32 portf:2;
} __attribute__((packed)); } __attribute__((packed));
#else #else
#error What? PDP endian? #error What? PDP endian?
#endif /* __BIG_ENDIAN_BITFIELD */ #endif /* __BIG_ENDIAN_BITFIELD */
#endif /* _IEEE1394_IEEE1394_H */ #endif /* _IEEE1394_IEEE1394_H */
+5 -4
View File
@@ -35,7 +35,6 @@
#include <linux/kthread.h> #include <linux/kthread.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/semaphore.h>
#include "ieee1394_types.h" #include "ieee1394_types.h"
#include "ieee1394.h" #include "ieee1394.h"
@@ -86,7 +85,7 @@ static void dump_packet(const char *text, quadlet_t *data, int size, int speed)
printk("\n"); printk("\n");
} }
#else #else
#define dump_packet(a,b,c,d) #define dump_packet(a,b,c,d) do {} while (0)
#endif #endif
static void abort_requests(struct hpsb_host *host); static void abort_requests(struct hpsb_host *host);
@@ -355,10 +354,12 @@ static void build_speed_map(struct hpsb_host *host, int nodecount)
} }
} }
#if SELFID_SPEED_UNKNOWN != IEEE1394_SPEED_MAX
/* assume maximum speed for 1394b PHYs, nodemgr will correct it */ /* assume maximum speed for 1394b PHYs, nodemgr will correct it */
for (n = 0; n < nodecount; n++) for (n = 0; n < nodecount; n++)
if (speedcap[n] == 3) if (speedcap[n] == SELFID_SPEED_UNKNOWN)
speedcap[n] = IEEE1394_SPEED_MAX; speedcap[n] = IEEE1394_SPEED_MAX;
#endif
} }
@@ -1169,7 +1170,7 @@ static void __exit ieee1394_cleanup(void)
unregister_chrdev_region(IEEE1394_CORE_DEV, 256); unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
} }
module_init(ieee1394_init); fs_initcall(ieee1394_init); /* same as ohci1394 */
module_exit(ieee1394_cleanup); module_exit(ieee1394_cleanup);
/* Exported symbols */ /* Exported symbols */
+16 -12
View File
@@ -1,12 +1,15 @@
#ifndef _IEEE1394_CORE_H #ifndef _IEEE1394_CORE_H
#define _IEEE1394_CORE_H #define _IEEE1394_CORE_H
#include <linux/slab.h> #include <linux/device.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/skbuff.h>
#include <linux/types.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/semaphore.h>
#include "hosts.h"
#include "hosts.h"
#include "ieee1394_types.h"
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
@@ -58,7 +61,6 @@ struct hpsb_packet {
size_t header_size; size_t header_size;
size_t data_size; size_t data_size;
struct hpsb_host *host; struct hpsb_host *host;
unsigned int generation; unsigned int generation;
@@ -80,7 +82,7 @@ struct hpsb_packet {
/* Set a task for when a packet completes */ /* 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)
{ {
@@ -92,7 +94,6 @@ 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 * Generation counter for the complete 1394 subsystem. Generation gets
* incremented on every change in the subsystem (e.g. bus reset). * incremented on every change in the subsystem (e.g. bus reset).
@@ -204,10 +205,14 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
#define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15 #define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15
#define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0) #define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0)
#define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16) #define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, \
#define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_VIDEO1394 * 16) IEEE1394_MINOR_BLOCK_RAW1394 * 16)
#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16) #define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, \
#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16) IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, \
IEEE1394_MINOR_BLOCK_DV1394 * 16)
#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, \
IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
/* return the index (within a minor number block) of a file */ /* return the index (within a minor number block) of a file */
static inline unsigned char ieee1394_file_to_instance(struct file *file) static inline unsigned char ieee1394_file_to_instance(struct file *file)
@@ -223,4 +228,3 @@ extern struct class hpsb_host_class;
extern struct class *hpsb_protocol_class; extern struct class *hpsb_protocol_class;
#endif /* _IEEE1394_CORE_H */ #endif /* _IEEE1394_CORE_H */
+8 -22
View File
@@ -1,33 +1,19 @@
#ifndef _IEEE1394_HOTPLUG_H #ifndef _IEEE1394_HOTPLUG_H
#define _IEEE1394_HOTPLUG_H #define _IEEE1394_HOTPLUG_H
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mod_devicetable.h>
/* Unit spec id and sw version entry for some protocols */ /* Unit spec id and sw version entry for some protocols */
#define AVC_UNIT_SPEC_ID_ENTRY 0x0000A02D #define AVC_UNIT_SPEC_ID_ENTRY 0x0000A02D
#define AVC_SW_VERSION_ENTRY 0x00010001 #define AVC_SW_VERSION_ENTRY 0x00010001
#define CAMERA_UNIT_SPEC_ID_ENTRY 0x0000A02D #define CAMERA_UNIT_SPEC_ID_ENTRY 0x0000A02D
#define CAMERA_SW_VERSION_ENTRY 0x00000100 #define CAMERA_SW_VERSION_ENTRY 0x00000100
/* Check to make sure this all isn't already defined */ /* /include/linux/mod_devicetable.h defines:
#ifndef IEEE1394_MATCH_VENDOR_ID * IEEE1394_MATCH_VENDOR_ID
* IEEE1394_MATCH_MODEL_ID
#define IEEE1394_MATCH_VENDOR_ID 0x0001 * IEEE1394_MATCH_SPECIFIER_ID
#define IEEE1394_MATCH_MODEL_ID 0x0002 * IEEE1394_MATCH_VERSION
#define IEEE1394_MATCH_SPECIFIER_ID 0x0004 * struct ieee1394_device_id
#define IEEE1394_MATCH_VERSION 0x0008 */
#include <linux/mod_devicetable.h>
struct ieee1394_device_id {
u32 match_flags;
u32 vendor_id;
u32 model_id;
u32 specifier_id;
u32 version;
void *driver_data;
};
#endif
#endif /* _IEEE1394_HOTPLUG_H */ #endif /* _IEEE1394_HOTPLUG_H */
+65 -47
View File
@@ -9,19 +9,17 @@
* directory of the kernel sources for details. * directory of the kernel sources for details.
*/ */
#include <linux/sched.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/smp_lock.h> #include <linux/spinlock.h>
#include <linux/interrupt.h> #include <linux/wait.h>
#include <asm/bug.h>
#include <asm/errno.h> #include <asm/errno.h>
#include "ieee1394.h" #include "ieee1394.h"
#include "ieee1394_types.h" #include "ieee1394_types.h"
#include "hosts.h" #include "hosts.h"
#include "ieee1394_core.h" #include "ieee1394_core.h"
#include "highlevel.h"
#include "nodemgr.h"
#include "ieee1394_transactions.h" #include "ieee1394_transactions.h"
#define PREP_ASYNC_HEAD_ADDRESS(tc) \ #define PREP_ASYNC_HEAD_ADDRESS(tc) \
@@ -31,6 +29,13 @@
packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \ packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \
packet->header[2] = addr & 0xffffffff packet->header[2] = addr & 0xffffffff
#ifndef HPSB_DEBUG_TLABELS
static
#endif
spinlock_t hpsb_tlabel_lock = SPIN_LOCK_UNLOCKED;
static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq);
static void fill_async_readquad(struct hpsb_packet *packet, u64 addr) static void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
{ {
PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ); PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
@@ -114,9 +119,41 @@ static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
packet->tcode = TCODE_ISO_DATA; packet->tcode = TCODE_ISO_DATA;
} }
/* same as hpsb_get_tlabel, except that it returns immediately */
static int hpsb_get_tlabel_atomic(struct hpsb_packet *packet)
{
unsigned long flags, *tp;
u8 *next;
int tlabel, n = NODEID_TO_NODE(packet->node_id);
/* Broadcast transactions are complete once the request has been sent.
* Use the same transaction label for all broadcast transactions. */
if (unlikely(n == ALL_NODES)) {
packet->tlabel = 0;
return 0;
}
tp = packet->host->tl_pool[n].map;
next = &packet->host->next_tl[n];
spin_lock_irqsave(&hpsb_tlabel_lock, flags);
tlabel = find_next_zero_bit(tp, 64, *next);
if (tlabel > 63)
tlabel = find_first_zero_bit(tp, 64);
if (tlabel > 63) {
spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
return -EAGAIN;
}
__set_bit(tlabel, tp);
*next = (tlabel + 1) & 63;
spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
packet->tlabel = tlabel;
return 0;
}
/** /**
* hpsb_get_tlabel - allocate a transaction label * hpsb_get_tlabel - allocate a transaction label
* @packet: the packet who's tlabel/tpool we set * @packet: the packet whose tlabel and tl_pool we set
* *
* Every asynchronous transaction on the 1394 bus needs a transaction * Every asynchronous transaction on the 1394 bus needs a transaction
* label to match the response to the request. This label has to be * label to match the response to the request. This label has to be
@@ -130,42 +167,25 @@ static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
* Return value: Zero on success, otherwise non-zero. A non-zero return * Return value: Zero on success, otherwise non-zero. A non-zero return
* generally means there are no available tlabels. If this is called out * generally means there are no available tlabels. If this is called out
* of interrupt or atomic context, then it will sleep until can return a * of interrupt or atomic context, then it will sleep until can return a
* tlabel. * tlabel or a signal is received.
*/ */
int hpsb_get_tlabel(struct hpsb_packet *packet) int hpsb_get_tlabel(struct hpsb_packet *packet)
{ {
unsigned long flags; if (irqs_disabled() || in_atomic())
struct hpsb_tlabel_pool *tp; return hpsb_get_tlabel_atomic(packet);
int n = NODEID_TO_NODE(packet->node_id);
if (unlikely(n == ALL_NODES)) /* NB: The macro wait_event_interruptible() is called with a condition
return 0; * argument with side effect. This is only possible because the side
tp = &packet->host->tpool[n]; * effect does not occur until the condition became true, and
* wait_event_interruptible() won't evaluate the condition again after
if (irqs_disabled() || in_atomic()) { * that. */
if (down_trylock(&tp->count)) return wait_event_interruptible(tlabel_wq,
return 1; !hpsb_get_tlabel_atomic(packet));
} else {
down(&tp->count);
}
spin_lock_irqsave(&tp->lock, flags);
packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next);
if (packet->tlabel > 63)
packet->tlabel = find_first_zero_bit(tp->pool, 64);
tp->next = (packet->tlabel + 1) % 64;
/* Should _never_ happen */
BUG_ON(test_and_set_bit(packet->tlabel, tp->pool));
tp->allocations++;
spin_unlock_irqrestore(&tp->lock, flags);
return 0;
} }
/** /**
* hpsb_free_tlabel - free an allocated transaction label * hpsb_free_tlabel - free an allocated transaction label
* @packet: packet whos tlabel/tpool needs to be cleared * @packet: packet whose tlabel and tl_pool needs to be cleared
* *
* Frees the transaction label allocated with hpsb_get_tlabel(). The * Frees the transaction label allocated with hpsb_get_tlabel(). The
* tlabel has to be freed after the transaction is complete (i.e. response * tlabel has to be freed after the transaction is complete (i.e. response
@@ -176,21 +196,20 @@ int hpsb_get_tlabel(struct hpsb_packet *packet)
*/ */
void hpsb_free_tlabel(struct hpsb_packet *packet) void hpsb_free_tlabel(struct hpsb_packet *packet)
{ {
unsigned long flags; unsigned long flags, *tp;
struct hpsb_tlabel_pool *tp; int tlabel, n = NODEID_TO_NODE(packet->node_id);
int n = NODEID_TO_NODE(packet->node_id);
if (unlikely(n == ALL_NODES)) if (unlikely(n == ALL_NODES))
return; return;
tp = &packet->host->tpool[n]; tp = packet->host->tl_pool[n].map;
tlabel = packet->tlabel;
BUG_ON(tlabel > 63 || tlabel < 0);
BUG_ON(packet->tlabel > 63 || packet->tlabel < 0); spin_lock_irqsave(&hpsb_tlabel_lock, flags);
BUG_ON(!__test_and_clear_bit(tlabel, tp));
spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
spin_lock_irqsave(&tp->lock, flags); wake_up_interruptible(&tlabel_wq);
BUG_ON(!test_and_clear_bit(packet->tlabel, tp->pool));
spin_unlock_irqrestore(&tp->lock, flags);
up(&tp->count);
} }
int hpsb_packet_success(struct hpsb_packet *packet) int hpsb_packet_success(struct hpsb_packet *packet)
@@ -214,7 +233,7 @@ int hpsb_packet_success(struct hpsb_packet *packet)
packet->node_id); packet->node_id);
return -EAGAIN; return -EAGAIN;
} }
HPSB_PANIC("reached unreachable code 1 in %s", __FUNCTION__); BUG();
case ACK_BUSY_X: case ACK_BUSY_X:
case ACK_BUSY_A: case ACK_BUSY_A:
@@ -261,8 +280,7 @@ int hpsb_packet_success(struct hpsb_packet *packet)
packet->ack_code, packet->node_id, packet->tcode); packet->ack_code, packet->node_id, packet->tcode);
return -EAGAIN; return -EAGAIN;
} }
BUG();
HPSB_PANIC("reached unreachable code 2 in %s", __FUNCTION__);
} }
struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node, struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
+22 -19
View File
@@ -1,32 +1,32 @@
#ifndef _IEEE1394_TRANSACTIONS_H #ifndef _IEEE1394_TRANSACTIONS_H
#define _IEEE1394_TRANSACTIONS_H #define _IEEE1394_TRANSACTIONS_H
#include "ieee1394_core.h" #include <linux/types.h>
#include "ieee1394_types.h"
struct hpsb_packet;
struct hpsb_host;
/*
* Get and free transaction labels.
*/
int hpsb_get_tlabel(struct hpsb_packet *packet); int hpsb_get_tlabel(struct hpsb_packet *packet);
void hpsb_free_tlabel(struct hpsb_packet *packet); void hpsb_free_tlabel(struct hpsb_packet *packet);
struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node, struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
u64 addr, size_t length); u64 addr, size_t length);
struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node, struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
u64 addr, int extcode, quadlet_t *data, u64 addr, int extcode, quadlet_t *data,
quadlet_t arg); quadlet_t arg);
struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host, nodeid_t node, struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
u64 addr, int extcode, octlet_t *data, nodeid_t node, u64 addr, int extcode,
octlet_t arg); octlet_t *data, octlet_t arg);
struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
quadlet_t data) ; struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, int length,
struct hpsb_packet *hpsb_make_isopacket(struct hpsb_host *host, int channel, int tag, int sync);
int length, int channel, struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
int tag, int sync); nodeid_t node, u64 addr,
struct hpsb_packet *hpsb_make_writepacket (struct hpsb_host *host, nodeid_t node, quadlet_t *buffer, size_t length);
u64 addr, quadlet_t *buffer, size_t length);
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 sync); int length, int channel, int tag,
int sync);
/* /*
* hpsb_packet_success - Make sense of the ack and reply codes and * hpsb_packet_success - Make sense of the ack and reply codes and
@@ -40,9 +40,8 @@ struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer,
*/ */
int hpsb_packet_success(struct hpsb_packet *packet); int hpsb_packet_success(struct hpsb_packet *packet);
/* /*
* The generic read, write and lock functions. All recognize the local node ID * The generic read and write functions. All recognize the local node ID
* and act accordingly. Read and write automatically use quadlet commands if * and act accordingly. Read and write automatically use quadlet commands if
* length == 4 and and block commands otherwise (however, they do not yet * 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 * support lengths that are not a multiple of 4). You must explicitly specifiy
@@ -54,4 +53,8 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
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);
#ifdef HPSB_DEBUG_TLABELS
extern spinlock_t hpsb_tlabel_lock;
#endif
#endif /* _IEEE1394_TRANSACTIONS_H */ #endif /* _IEEE1394_TRANSACTIONS_H */

Some files were not shown because too many files have changed in this diff Show More