On Tue, 2 Oct 2007 09:44:13 -0700 Greg KH <gregkh@xxxxxxx> wrote: > On Tue, Oct 02, 2007 at 09:25:34AM -0600, Matthew Wilcox wrote: > > On Tue, Oct 02, 2007 at 05:23:39PM +0200, Kay Sievers wrote: > > > Just looking at the number of devices, it seems that allocating it > > > dynamically would be the better deal. We allocate the name of every > > > kobject dynamically today, so I guess it's fine to do that with the > > > DMA data too. > > > > But we don't need to allocate it dynamically. We can embed it in the > > pci_dev, eisa_dev, zorro_dev, mca_dev and parisc_device. > > But then you run into the issue that James pointed out originally. > > Anyway, I don't care which, let's see some patches :) How about this (based on James' proposal)? - Currently, there are only max_segment_size and segment_boundary_mask in struct device_dma_parameters (I'll add segment_boundary_mask support later after I finish the iommu part). We'll move more dma stuff in struct device (like dma_mask) to struct device_dma_parameters later (needs some cleanups before that). - New accessors for the dma parameters are added. So we can easily change where to place struct device_dma_parameters in the future. - the default max_segment_size is set to 64K, same to the block layer's default value. diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 37c00f6..c93ebe8 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1392,6 +1392,13 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask) } #endif +#ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE +int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) +{ + return dma_set_max_seg_size(&dev->dev, size); +} +#endif + /** * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count * @dev: PCI device to query @@ -1624,6 +1631,7 @@ EXPORT_SYMBOL(pci_clear_mwi); EXPORT_SYMBOL_GPL(pci_intx); EXPORT_SYMBOL(pci_set_dma_mask); EXPORT_SYMBOL(pci_set_consistent_dma_mask); +EXPORT_SYMBOL(pci_set_dma_max_seg_size); EXPORT_SYMBOL(pci_assign_resource); EXPORT_SYMBOL(pci_find_parent_resource); EXPORT_SYMBOL(pci_select_bars); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 171ca71..2a18134 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -948,8 +948,11 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) set_dev_node(&dev->dev, pcibus_to_node(bus)); dev->dev.dma_mask = &dev->dma_mask; + dev->dev.dma_parms = &dev->dma_parms; dev->dev.coherent_dma_mask = 0xffffffffull; + pci_set_dma_max_seg_size(dev, 65536); + /* Fix up broken headers */ pci_fixup_device(pci_fixup_header, dev); diff --git a/include/linux/device.h b/include/linux/device.h index 3a38d1f..3c24932 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -404,6 +404,15 @@ extern int devres_release_group(struct device *dev, void *id); extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp); extern void devm_kfree(struct device *dev, void *p); +struct device_dma_parameters { + /* + * a low level driver may set these to teach IOMMU code about + * sg limitations. + */ + unsigned int max_segment_size; + unsigned long segment_boundary_mask; +}; + struct device { struct klist klist_children; struct klist_node knode_parent; /* node in sibling list */ @@ -439,6 +448,8 @@ struct device { 64 bit addresses for consistent allocations such descriptors. */ + struct device_dma_parameters *dma_parms; + struct list_head dma_pools; /* dma pools (if dma'ble) */ struct dma_coherent_mem *dma_mem; /* internal for coherent mem diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index 2dc21cb..02854c8 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h @@ -43,6 +43,21 @@ static inline int valid_dma_direction(int dma_direction) extern u64 dma_get_required_mask(struct device *dev); +static inline unsigned int dma_get_max_seg_size(struct device *dev) +{ + return dev->dma_parms ? dev->dma_parms->max_segment_size : 65536; +} + +static inline unsigned int dma_set_max_seg_size(struct device *dev, + unsigned int size) +{ + if (dev->dma_parms) { + dev->dma_parms->max_segment_size = size; + return 0; + } else + return -EIO; +} + /* flags for the coherent memory api */ #define DMA_MEMORY_MAP 0x01 #define DMA_MEMORY_IO 0x02 diff --git a/include/linux/pci.h b/include/linux/pci.h index 038a0dc..1d630b5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -151,6 +151,8 @@ struct pci_dev { this if your device has broken DMA or supports 64-bit transfers. */ + struct device_dma_parameters dma_parms; + pci_power_t current_state; /* Current operating state. In ACPI-speak, this is D0-D3, D0 being fully functional, and D3 being off. */ @@ -554,6 +556,7 @@ void pci_intx(struct pci_dev *dev, int enable); void pci_msi_off(struct pci_dev *dev); int pci_set_dma_mask(struct pci_dev *dev, u64 mask); int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); +int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size); int pcix_get_max_mmrbc(struct pci_dev *dev); int pcix_get_mmrbc(struct pci_dev *dev); int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc); @@ -739,6 +742,7 @@ static inline void pci_set_master(struct pci_dev *dev) { } static inline int pci_enable_device(struct pci_dev *dev) { return -EIO; } static inline void pci_disable_device(struct pci_dev *dev) { } static inline int pci_set_dma_mask(struct pci_dev *dev, u64 mask) { return -EIO; } +static inline int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) { return -EIO; } static inline int pci_assign_resource(struct pci_dev *dev, int i) { return -EBUSY;} static inline int __pci_register_driver(struct pci_driver *drv, struct module *owner) { return 0;} static inline int pci_register_driver(struct pci_driver *drv) { return 0;} - To unsubscribe from this list: send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html