Skip to content

Commit e24c2d9

Browse files
davem330gregkh
authored andcommitted
[PATCH] PCI: DMA bursting advice
After seeing, at best, "guesses" as to the following kind of information in several drivers, I decided that we really need a way for platforms to specifically give advice in this area for what works best with their PCI controller implementation. Basically, this new interface gives DMA bursting advice on PCI. There are three forms of the advice: 1) Burst as much as possible, it is not necessary to end bursts on some particular boundary for best performance. 2) Burst on some byte count multiple. A DMA burst to some multiple of number of bytes may be done, but it is important to end the burst on an exact multiple for best performance. The best example of this I am aware of are the PPC64 PCI controllers, where if you end a burst mid-cacheline then chip has to refetch the data and the IOMMU translations which hurts performance a lot. 3) Burst on a single byte count multiple. Bursts shall end exactly on the next multiple boundary for best performance. Sparc64 and Alpha's PCI controllers operate this way. They disconnect any device which tries to burst across a cacheline boundary. Actually, newer sparc64 PCI controllers do not have this behavior. That is why the "pdev" is passed into the interface, so I can add code later to check which PCI controller the system is using and give advice accordingly. Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2311b1f commit e24c2d9

File tree

16 files changed

+174
-0
lines changed

16 files changed

+174
-0
lines changed

include/asm-alpha/pci.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,23 @@ pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr,
223223
/* Nothing to do. */
224224
}
225225

226+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
227+
enum pci_dma_burst_strategy *strat,
228+
unsigned long *strategy_parameter)
229+
{
230+
unsigned long cacheline_size;
231+
u8 byte;
232+
233+
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
234+
if (byte == 0)
235+
cacheline_size = 1024;
236+
else
237+
cacheline_size = (int) byte * 4;
238+
239+
*strat = PCI_DMA_BURST_BOUNDARY;
240+
*strategy_parameter = cacheline_size;
241+
}
242+
226243
/* TODO: integrate with include/asm-generic/pci.h ? */
227244
static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
228245
{

include/asm-arm/pci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ static inline void pcibios_penalize_isa_irq(int irq)
4242
#define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME)
4343
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL))
4444

45+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
46+
enum pci_dma_burst_strategy *strat,
47+
unsigned long *strategy_parameter)
48+
{
49+
*strat = PCI_DMA_BURST_INFINITY;
50+
*strategy_parameter = ~0UL;
51+
}
52+
4553
#define HAVE_PCI_MMAP
4654
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
4755
enum pci_mmap_state mmap_state, int write_combine);

include/asm-frv/pci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
5757
*/
5858
#define PCI_DMA_BUS_IS_PHYS (1)
5959

60+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
61+
enum pci_dma_burst_strategy *strat,
62+
unsigned long *strategy_parameter)
63+
{
64+
*strat = PCI_DMA_BURST_INFINITY;
65+
*strategy_parameter = ~0UL;
66+
}
67+
6068
/*
6169
* These are pretty much arbitary with the CoMEM implementation.
6270
* We have the whole address space to ourselves.

include/asm-i386/pci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ static inline void pcibios_add_platform_entries(struct pci_dev *dev)
9999
{
100100
}
101101

102+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
103+
enum pci_dma_burst_strategy *strat,
104+
unsigned long *strategy_parameter)
105+
{
106+
*strat = PCI_DMA_BURST_INFINITY;
107+
*strategy_parameter = ~0UL;
108+
}
109+
102110
#endif /* __KERNEL__ */
103111

104112
/* implement the pci_ DMA API in terms of the generic device dma_ one */

include/asm-ia64/pci.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,23 @@ extern int pcibios_prep_mwi (struct pci_dev *);
8282
#define sg_dma_len(sg) ((sg)->dma_length)
8383
#define sg_dma_address(sg) ((sg)->dma_address)
8484

85+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
86+
enum pci_dma_burst_strategy *strat,
87+
unsigned long *strategy_parameter)
88+
{
89+
unsigned long cacheline_size;
90+
u8 byte;
91+
92+
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
93+
if (byte == 0)
94+
cacheline_size = 1024;
95+
else
96+
cacheline_size = (int) byte * 4;
97+
98+
*strat = PCI_DMA_BURST_MULTIPLE;
99+
*strategy_parameter = cacheline_size;
100+
}
101+
85102
#define HAVE_PCI_MMAP
86103
extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
87104
enum pci_mmap_state mmap_state, int write_combine);

include/asm-mips/pci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,14 @@ extern void pci_dac_dma_sync_single_for_cpu(struct pci_dev *pdev,
130130
extern void pci_dac_dma_sync_single_for_device(struct pci_dev *pdev,
131131
dma64_addr_t dma_addr, size_t len, int direction);
132132

133+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
134+
enum pci_dma_burst_strategy *strat,
135+
unsigned long *strategy_parameter)
136+
{
137+
*strat = PCI_DMA_BURST_INFINITY;
138+
*strategy_parameter = ~0UL;
139+
}
140+
133141
extern void pcibios_resource_to_bus(struct pci_dev *dev,
134142
struct pci_bus_region *region, struct resource *res);
135143

include/asm-parisc/pci.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,23 @@ extern inline void pcibios_register_hba(struct pci_hba_data *x)
230230
/* export the pci_ DMA API in terms of the dma_ one */
231231
#include <asm-generic/pci-dma-compat.h>
232232

233+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
234+
enum pci_dma_burst_strategy *strat,
235+
unsigned long *strategy_parameter)
236+
{
237+
unsigned long cacheline_size;
238+
u8 byte;
239+
240+
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
241+
if (byte == 0)
242+
cacheline_size = 1024;
243+
else
244+
cacheline_size = (int) byte * 4;
245+
246+
*strat = PCI_DMA_BURST_MULTIPLE;
247+
*strategy_parameter = cacheline_size;
248+
}
249+
233250
extern void
234251
pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
235252
struct resource *res);

include/asm-ppc/pci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ extern unsigned long pci_bus_to_phys(unsigned int ba, int busnr);
6969
#define pci_unmap_len(PTR, LEN_NAME) (0)
7070
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
7171

72+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
73+
enum pci_dma_burst_strategy *strat,
74+
unsigned long *strategy_parameter)
75+
{
76+
*strat = PCI_DMA_BURST_INFINITY;
77+
*strategy_parameter = ~0UL;
78+
}
79+
7280
/*
7381
* At present there are very few 32-bit PPC machines that can have
7482
* memory above the 4GB point, and we don't support that.

include/asm-ppc64/pci.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,23 @@ static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask)
7878
return 0;
7979
}
8080

81+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
82+
enum pci_dma_burst_strategy *strat,
83+
unsigned long *strategy_parameter)
84+
{
85+
unsigned long cacheline_size;
86+
u8 byte;
87+
88+
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
89+
if (byte == 0)
90+
cacheline_size = 1024;
91+
else
92+
cacheline_size = (int) byte * 4;
93+
94+
*strat = PCI_DMA_BURST_MULTIPLE;
95+
*strategy_parameter = cacheline_size;
96+
}
97+
8198
extern int pci_domain_nr(struct pci_bus *bus);
8299

83100
/* Decide whether to display the domain number in /proc */

include/asm-sh/pci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ static inline void pcibios_penalize_isa_irq(int irq)
9696
#define sg_dma_address(sg) (virt_to_bus((sg)->dma_address))
9797
#define sg_dma_len(sg) ((sg)->length)
9898

99+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
100+
enum pci_dma_burst_strategy *strat,
101+
unsigned long *strategy_parameter)
102+
{
103+
*strat = PCI_DMA_BURST_INFINITY;
104+
*strategy_parameter = ~0UL;
105+
}
106+
99107
/* Board-specific fixup routines. */
100108
extern void pcibios_fixup(void);
101109
extern void pcibios_fixup_irqs(void);

include/asm-sh64/pci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ static inline void pcibios_penalize_isa_irq(int irq)
8686
#define sg_dma_address(sg) ((sg)->dma_address)
8787
#define sg_dma_len(sg) ((sg)->length)
8888

89+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
90+
enum pci_dma_burst_strategy *strat,
91+
unsigned long *strategy_parameter)
92+
{
93+
*strat = PCI_DMA_BURST_INFINITY;
94+
*strategy_parameter = ~0UL;
95+
}
96+
8997
/* Board-specific fixup routines. */
9098
extern void pcibios_fixup(void);
9199
extern void pcibios_fixup_irqs(void);

include/asm-sparc/pci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,14 @@ extern inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
144144

145145
#define pci_dac_dma_supported(dev, mask) (0)
146146

147+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
148+
enum pci_dma_burst_strategy *strat,
149+
unsigned long *strategy_parameter)
150+
{
151+
*strat = PCI_DMA_BURST_INFINITY;
152+
*strategy_parameter = ~0UL;
153+
}
154+
147155
static inline void pcibios_add_platform_entries(struct pci_dev *dev)
148156
{
149157
}

include/asm-sparc64/pci.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,23 @@ static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
220220
return (dma_addr == PCI_DMA_ERROR_CODE);
221221
}
222222

223+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
224+
enum pci_dma_burst_strategy *strat,
225+
unsigned long *strategy_parameter)
226+
{
227+
unsigned long cacheline_size;
228+
u8 byte;
229+
230+
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);
231+
if (byte == 0)
232+
cacheline_size = 1024;
233+
else
234+
cacheline_size = (int) byte * 4;
235+
236+
*strat = PCI_DMA_BURST_BOUNDARY;
237+
*strategy_parameter = cacheline_size;
238+
}
239+
223240
/* Return the index of the PCI controller for device PDEV. */
224241

225242
extern int pci_domain_nr(struct pci_bus *bus);

include/asm-v850/pci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ extern void
8181
pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
8282
dma_addr_t dma_addr);
8383

84+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
85+
enum pci_dma_burst_strategy *strat,
86+
unsigned long *strategy_parameter)
87+
{
88+
*strat = PCI_DMA_BURST_INFINITY;
89+
*strategy_parameter = ~0UL;
90+
}
91+
8492
static inline void pcibios_add_platform_entries(struct pci_dev *dev)
8593
{
8694
}

include/asm-x86_64/pci.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@ pci_dac_dma_sync_single_for_device(struct pci_dev *pdev, dma64_addr_t dma_addr,
123123
flush_write_buffers();
124124
}
125125

126+
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
127+
enum pci_dma_burst_strategy *strat,
128+
unsigned long *strategy_parameter)
129+
{
130+
*strat = PCI_DMA_BURST_INFINITY;
131+
*strategy_parameter = ~0UL;
132+
}
133+
126134
#define HAVE_PCI_MMAP
127135
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
128136
enum pci_mmap_state mmap_state, int write_combine);

include/linux/pci.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,15 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
874874
#define pci_pool_alloc(pool, flags, handle) dma_pool_alloc(pool, flags, handle)
875875
#define pci_pool_free(pool, vaddr, addr) dma_pool_free(pool, vaddr, addr)
876876

877+
enum pci_dma_burst_strategy {
878+
PCI_DMA_BURST_INFINITY, /* make bursts as large as possible,
879+
strategy_parameter is N/A */
880+
PCI_DMA_BURST_BOUNDARY, /* disconnect at every strategy_parameter
881+
byte boundaries */
882+
PCI_DMA_BURST_MULTIPLE, /* disconnect at some multiple of
883+
strategy_parameter byte boundaries */
884+
};
885+
877886
#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
878887
extern struct pci_dev *isa_bridge;
879888
#endif

0 commit comments

Comments
 (0)