Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 128124
b: refs/heads/master
c: a3a798c
h: refs/heads/master
v: v3
  • Loading branch information
Linus Torvalds committed Jan 9, 2009
1 parent c25a64d commit e0c38db
Show file tree
Hide file tree
Showing 61 changed files with 1,114 additions and 1,454 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d97c0defba25a959a990f6d4759f43075540832e
refs/heads/master: a3a798c88a14b35e5d4ca30716dbc9eb9a1ddfe2
96 changes: 44 additions & 52 deletions trunk/Documentation/crypto/async-tx-api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
3.6 Constraints
3.7 Example

4 DRIVER DEVELOPER NOTES
4 DMAENGINE DRIVER DEVELOPER NOTES
4.1 Conformance points
4.2 "My application needs finer control of hardware channels"
4.2 "My application needs exclusive control of hardware channels"

5 SOURCE

Expand Down Expand Up @@ -150,6 +150,7 @@ ops_run_* and ops_complete_* routines in drivers/md/raid5.c for more
implementation examples.

4 DRIVER DEVELOPMENT NOTES

4.1 Conformance points:
There are a few conformance points required in dmaengine drivers to
accommodate assumptions made by applications using the async_tx API:
Expand All @@ -158,58 +159,49 @@ accommodate assumptions made by applications using the async_tx API:
3/ Use async_tx_run_dependencies() in the descriptor clean up path to
handle submission of dependent operations

4.2 "My application needs finer control of hardware channels"
This requirement seems to arise from cases where a DMA engine driver is
trying to support device-to-memory DMA. The dmaengine and async_tx
implementations were designed for offloading memory-to-memory
operations; however, there are some capabilities of the dmaengine layer
that can be used for platform-specific channel management.
Platform-specific constraints can be handled by registering the
application as a 'dma_client' and implementing a 'dma_event_callback' to
apply a filter to the available channels in the system. Before showing
how to implement a custom dma_event callback some background of
dmaengine's client support is required.

The following routines in dmaengine support multiple clients requesting
use of a channel:
- dma_async_client_register(struct dma_client *client)
- dma_async_client_chan_request(struct dma_client *client)

dma_async_client_register takes a pointer to an initialized dma_client
structure. It expects that the 'event_callback' and 'cap_mask' fields
are already initialized.

dma_async_client_chan_request triggers dmaengine to notify the client of
all channels that satisfy the capability mask. It is up to the client's
event_callback routine to track how many channels the client needs and
how many it is currently using. The dma_event_callback routine returns a
dma_state_client code to let dmaengine know the status of the
allocation.

Below is the example of how to extend this functionality for
platform-specific filtering of the available channels beyond the
standard capability mask:

static enum dma_state_client
my_dma_client_callback(struct dma_client *client,
struct dma_chan *chan, enum dma_state state)
{
struct dma_device *dma_dev;
struct my_platform_specific_dma *plat_dma_dev;

dma_dev = chan->device;
plat_dma_dev = container_of(dma_dev,
struct my_platform_specific_dma,
dma_dev);

if (!plat_dma_dev->platform_specific_capability)
return DMA_DUP;

. . .
}
4.2 "My application needs exclusive control of hardware channels"
Primarily this requirement arises from cases where a DMA engine driver
is being used to support device-to-memory operations. A channel that is
performing these operations cannot, for many platform specific reasons,
be shared. For these cases the dma_request_channel() interface is
provided.

The interface is:
struct dma_chan *dma_request_channel(dma_cap_mask_t mask,
dma_filter_fn filter_fn,
void *filter_param);

Where dma_filter_fn is defined as:
typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param);

When the optional 'filter_fn' parameter is set to NULL
dma_request_channel simply returns the first channel that satisfies the
capability mask. Otherwise, when the mask parameter is insufficient for
specifying the necessary channel, the filter_fn routine can be used to
disposition the available channels in the system. The filter_fn routine
is called once for each free channel in the system. Upon seeing a
suitable channel filter_fn returns DMA_ACK which flags that channel to
be the return value from dma_request_channel. A channel allocated via
this interface is exclusive to the caller, until dma_release_channel()
is called.

The DMA_PRIVATE capability flag is used to tag dma devices that should
not be used by the general-purpose allocator. It can be set at
initialization time if it is known that a channel will always be
private. Alternatively, it is set when dma_request_channel() finds an
unused "public" channel.

A couple caveats to note when implementing a driver and consumer:
1/ Once a channel has been privately allocated it will no longer be
considered by the general-purpose allocator even after a call to
dma_release_channel().
2/ Since capabilities are specified at the device level a dma_device
with multiple channels will either have all channels public, or all
channels private.

5 SOURCE
include/linux/dmaengine.h: core header file for DMA drivers and clients

include/linux/dmaengine.h: core header file for DMA drivers and api users
drivers/dma/dmaengine.c: offload engine channel management routines
drivers/dma/: location for offload engine drivers
include/linux/async_tx.h: core header file for the async_tx api
Expand Down
1 change: 1 addition & 0 deletions trunk/Documentation/dmaengine.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
See Documentation/crypto/async-tx-api.txt
15 changes: 3 additions & 12 deletions trunk/arch/avr32/mach-at32ap/at32ap700x.c
Original file line number Diff line number Diff line change
Expand Up @@ -1305,7 +1305,7 @@ struct platform_device *__init
at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
{
struct platform_device *pdev;
struct dw_dma_slave *dws;
struct dw_dma_slave *dws = &data->dma_slave;
u32 pioa_mask;
u32 piob_mask;

Expand All @@ -1324,22 +1324,13 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data)
ARRAY_SIZE(atmel_mci0_resource)))
goto fail;

if (data->dma_slave)
dws = kmemdup(to_dw_dma_slave(data->dma_slave),
sizeof(struct dw_dma_slave), GFP_KERNEL);
else
dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL);

dws->slave.dev = &pdev->dev;
dws->slave.dma_dev = &dw_dmac0_device.dev;
dws->slave.reg_width = DMA_SLAVE_WIDTH_32BIT;
dws->dma_dev = &dw_dmac0_device.dev;
dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT;
dws->cfg_hi = (DWC_CFGH_SRC_PER(0)
| DWC_CFGH_DST_PER(1));
dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL
| DWC_CFGL_HS_SRC_POL);

data->dma_slave = &dws->slave;

if (platform_device_add_data(pdev, data,
sizeof(struct mci_platform_data)))
goto fail;
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/parisc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name`

drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/

PALO := $(shell if which palo; then : ; \
PALO := $(shell if (which palo 2>&1); then : ; \
elif [ -x /sbin/palo ]; then echo /sbin/palo; \
fi)

Expand Down
37 changes: 12 additions & 25 deletions trunk/arch/parisc/include/asm/byteorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@
#include <asm/types.h>
#include <linux/compiler.h>

#ifdef __GNUC__
#define __BIG_ENDIAN
#define __SWAB_64_THRU_32__

static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
{
__asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */
"shd %%r0, %0, 8, %0" /* shift 000000ab -> 00ba */
: "=r" (x)
: "0" (x));
return x;
}
#define __arch_swab16 __arch_swab16

static __inline__ __attribute_const__ __u32 ___arch__swab24(__u32 x)
static inline __attribute_const__ __u32 __arch_swab24(__u32 x)
{
__asm__("shd %0, %0, 8, %0\n\t" /* shift xabcxabc -> cxab */
"dep %0, 15, 8, %0\n\t" /* deposit cxab -> cbab */
Expand All @@ -25,7 +27,7 @@ static __inline__ __attribute_const__ __u32 ___arch__swab24(__u32 x)
return x;
}

static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
{
unsigned int temp;
__asm__("shd %0, %0, 16, %1\n\t" /* shift abcdabcd -> cdab */
Expand All @@ -35,7 +37,7 @@ static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
: "0" (x));
return x;
}

#define __arch_swab32 __arch_swab32

#if BITS_PER_LONG > 32
/*
Expand All @@ -48,7 +50,8 @@ static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
** HSHR 67452301 -> *6*4*2*0 into %0
** OR %0 | %1 -> 76543210 into %0 (all done!)
*/
static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x) {
static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
{
__u64 temp;
__asm__("permh,3210 %0, %0\n\t"
"hshl %0, 8, %1\n\t"
Expand All @@ -58,25 +61,9 @@ static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x) {
: "0" (x));
return x;
}
#define __arch__swab64(x) ___arch__swab64(x)
#define __BYTEORDER_HAS_U64__
#elif !defined(__STRICT_ANSI__)
static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x)
{
__u32 t1 = ___arch__swab32((__u32) x);
__u32 t2 = ___arch__swab32((__u32) (x >> 32));
return (((__u64) t1 << 32) | t2);
}
#define __arch__swab64(x) ___arch__swab64(x)
#define __BYTEORDER_HAS_U64__
#endif

#define __arch__swab16(x) ___arch__swab16(x)
#define __arch__swab24(x) ___arch__swab24(x)
#define __arch__swab32(x) ___arch__swab32(x)

#endif /* __GNUC__ */
#define __arch_swab64 __arch_swab64
#endif /* BITS_PER_LONG > 32 */

#include <linux/byteorder/big_endian.h>
#include <linux/byteorder.h>

#endif /* _PARISC_BYTEORDER_H */
2 changes: 1 addition & 1 deletion trunk/arch/parisc/include/asm/checksum.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
#endif
: "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len)
: "0" (sum), "1" (saddr), "2" (daddr), "3" (len), "r" (proto)
: "r19", "r20", "r21", "r22");
: "r19", "r20", "r21", "r22", "memory");
return csum_fold(sum);
}

Expand Down
12 changes: 3 additions & 9 deletions trunk/arch/parisc/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
#include <linux/types.h>
#include <asm/pgtable.h>

extern unsigned long parisc_vmerge_boundary;
extern unsigned long parisc_vmerge_max_size;

#define BIO_VMERGE_BOUNDARY parisc_vmerge_boundary
#define BIO_VMERGE_MAX_SIZE parisc_vmerge_max_size

#define virt_to_phys(a) ((unsigned long)__pa(a))
#define phys_to_virt(a) __va(a)
#define virt_to_bus virt_to_phys
Expand Down Expand Up @@ -182,9 +176,9 @@ static inline void __raw_writeq(unsigned long long b, volatile void __iomem *add

/* readb can never be const, so use __fswab instead of le*_to_cpu */
#define readb(addr) __raw_readb(addr)
#define readw(addr) __fswab16(__raw_readw(addr))
#define readl(addr) __fswab32(__raw_readl(addr))
#define readq(addr) __fswab64(__raw_readq(addr))
#define readw(addr) le16_to_cpu(__raw_readw(addr))
#define readl(addr) le32_to_cpu(__raw_readl(addr))
#define readq(addr) le64_to_cpu(__raw_readq(addr))
#define writeb(b, addr) __raw_writeb(b, addr)
#define writew(b, addr) __raw_writew(cpu_to_le16(b), addr)
#define writel(b, addr) __raw_writel(cpu_to_le32(b), addr)
Expand Down
13 changes: 9 additions & 4 deletions trunk/arch/parisc/include/asm/mmu_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,21 @@ destroy_context(struct mm_struct *mm)
mm->context = 0;
}

static inline void load_context(mm_context_t context)
static inline unsigned long __space_to_prot(mm_context_t context)
{
mtsp(context, 3);
#if SPACEID_SHIFT == 0
mtctl(context << 1,8);
return context << 1;
#else
mtctl(context >> (SPACEID_SHIFT - 1),8);
return context >> (SPACEID_SHIFT - 1);
#endif
}

static inline void load_context(mm_context_t context)
{
mtsp(context, 3);
mtctl(__space_to_prot(context), 8);
}

static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
{

Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/parisc/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <asm/ptrace.h>
#include <asm/types.h>
#include <asm/system.h>
#include <asm/percpu.h>
#endif /* __ASSEMBLY__ */

#define KERNEL_STACK_SIZE (4*PAGE_SIZE)
Expand Down Expand Up @@ -109,8 +110,7 @@ struct cpuinfo_parisc {
};

extern struct system_cpuinfo_parisc boot_cpu_data;
extern struct cpuinfo_parisc cpu_data[NR_CPUS];
#define current_cpu_data cpu_data[smp_processor_id()]
DECLARE_PER_CPU(struct cpuinfo_parisc, cpu_data);

#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF)

Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/parisc/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,6 @@ unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned lo
#define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user

int fixup_exception(struct pt_regs *regs);

#endif /* __PARISC_UACCESS_H */
40 changes: 34 additions & 6 deletions trunk/arch/parisc/kernel/drivers.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,38 @@ static int parisc_generic_match(struct device *dev, struct device_driver *drv)
return match_device(to_parisc_driver(drv), to_parisc_device(dev));
}

static ssize_t make_modalias(struct device *dev, char *buf)
{
const struct parisc_device *padev = to_parisc_device(dev);
const struct parisc_device_id *id = &padev->id;

return sprintf(buf, "parisc:t%02Xhv%04Xrev%02Xsv%08X\n",
(u8)id->hw_type, (u16)id->hversion, (u8)id->hversion_rev,
(u32)id->sversion);
}

static int parisc_uevent(struct device *dev, struct kobj_uevent_env *env)
{
const struct parisc_device *padev;
char modalias[40];

if (!dev)
return -ENODEV;

padev = to_parisc_device(dev);
if (!padev)
return -ENODEV;

if (add_uevent_var(env, "PARISC_NAME=%s", padev->name))
return -ENOMEM;

make_modalias(dev, modalias);
if (add_uevent_var(env, "MODALIAS=%s", modalias))
return -ENOMEM;

return 0;
}

#define pa_dev_attr(name, field, format_string) \
static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
Expand All @@ -566,12 +598,7 @@ pa_dev_attr_id(sversion, "0x%05x\n");

static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct parisc_device *padev = to_parisc_device(dev);
struct parisc_device_id *id = &padev->id;

return sprintf(buf, "parisc:t%02Xhv%04Xrev%02Xsv%08X\n",
(u8)id->hw_type, (u16)id->hversion, (u8)id->hversion_rev,
(u32)id->sversion);
return make_modalias(dev, buf);
}

static struct device_attribute parisc_device_attrs[] = {
Expand All @@ -587,6 +614,7 @@ static struct device_attribute parisc_device_attrs[] = {
struct bus_type parisc_bus_type = {
.name = "parisc",
.match = parisc_generic_match,
.uevent = parisc_uevent,
.dev_attrs = parisc_device_attrs,
.probe = parisc_driver_probe,
.remove = parisc_driver_remove,
Expand Down
Loading

0 comments on commit e0c38db

Please sign in to comment.