[PATCH] I2O: new sysfs attributes and Adaptec specific block device access and 64-bit DMA support
Changes: - Added Bus-OSM which could be used by user space programs to reset a channel on the controller - Make ioctl's in Config-OSM obsolete in prefer for sysfs attributes and move those to its own file - Added sysfs attribute for firmware read and write access for I2O controllers - Added special handling of firmware read and write access for Adaptec controllers - Added vendor id and product id as sysfs-attribute to Executive classes - Added automatic notification of LCT change handling to Exec-OSM - Added flushing function to Block-OSM for later barrier implementation - Use PRIVATE messages for Block access on Adaptec controllers, which are faster then BLOCK class access - Cleaned up support for Promise controller - New messages are now detected using the IRQ status register as suggested by the I2O spec - Added i2o_dma_high() and i2o_dma_low() functions - Added facility for SG tablesize calculation when using 32-bit and 64-bit DMA addresses - Added i2o_dma_map_single() and i2o_dma_map_sg() which could build the SG list for 32-bit as well as 64-bit DMA addresses Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:

committed by
Linus Torvalds

parent
f88e119c4b
commit
f10378fff6
@@ -32,6 +32,10 @@ typedef unsigned int u32;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
* Vendors
|
||||
*/
|
||||
#define I2O_VENDOR_DPT 0x001b
|
||||
|
||||
/*
|
||||
* I2O Control IOCTLs and structures
|
||||
@@ -333,7 +337,7 @@ typedef struct _i2o_status_block {
|
||||
#define I2O_CLASS_ATE_PERIPHERAL 0x061
|
||||
#define I2O_CLASS_FLOPPY_CONTROLLER 0x070
|
||||
#define I2O_CLASS_FLOPPY_DEVICE 0x071
|
||||
#define I2O_CLASS_BUS_ADAPTER_PORT 0x080
|
||||
#define I2O_CLASS_BUS_ADAPTER 0x080
|
||||
#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090
|
||||
#define I2O_CLASS_PEER_TRANSPORT 0x091
|
||||
#define I2O_CLASS_END 0xfff
|
||||
|
@@ -157,7 +157,8 @@ struct i2o_controller {
|
||||
|
||||
void __iomem *in_port; /* Inbout port address */
|
||||
void __iomem *out_port; /* Outbound port address */
|
||||
void __iomem *irq_mask; /* Interrupt register address */
|
||||
void __iomem *irq_status; /* Interrupt status register address */
|
||||
void __iomem *irq_mask; /* Interrupt mask register address */
|
||||
|
||||
/* Dynamic LCT related data */
|
||||
|
||||
@@ -242,15 +243,6 @@ extern int i2o_msg_post_wait_mem(struct i2o_controller *, u32, unsigned long,
|
||||
extern void i2o_msg_nop(struct i2o_controller *, u32);
|
||||
static inline void i2o_flush_reply(struct i2o_controller *, u32);
|
||||
|
||||
/* DMA handling functions */
|
||||
static inline int i2o_dma_alloc(struct device *, struct i2o_dma *, size_t,
|
||||
unsigned int);
|
||||
static inline void i2o_dma_free(struct device *, struct i2o_dma *);
|
||||
int i2o_dma_realloc(struct device *, struct i2o_dma *, size_t, unsigned int);
|
||||
|
||||
static inline int i2o_dma_map(struct device *, struct i2o_dma *);
|
||||
static inline void i2o_dma_unmap(struct device *, struct i2o_dma *);
|
||||
|
||||
/* IOP functions */
|
||||
extern int i2o_status_get(struct i2o_controller *);
|
||||
|
||||
@@ -275,6 +267,16 @@ static inline u32 i2o_ptr_high(void *ptr)
|
||||
{
|
||||
return (u32) ((u64) ptr >> 32);
|
||||
};
|
||||
|
||||
static inline u32 i2o_dma_low(dma_addr_t dma_addr)
|
||||
{
|
||||
return (u32) (u64) dma_addr;
|
||||
};
|
||||
|
||||
static inline u32 i2o_dma_high(dma_addr_t dma_addr)
|
||||
{
|
||||
return (u32) ((u64) dma_addr >> 32);
|
||||
};
|
||||
#else
|
||||
static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr)
|
||||
{
|
||||
@@ -305,8 +307,246 @@ static inline u32 i2o_ptr_high(void *ptr)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
static inline u32 i2o_dma_low(dma_addr_t dma_addr)
|
||||
{
|
||||
return (u32) dma_addr;
|
||||
};
|
||||
|
||||
static inline u32 i2o_dma_high(dma_addr_t dma_addr)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* i2o_sg_tablesize - Calculate the maximum number of elements in a SGL
|
||||
* @c: I2O controller for which the calculation should be done
|
||||
* @body_size: maximum body size used for message in 32-bit words.
|
||||
*
|
||||
* Return the maximum number of SG elements in a SG list.
|
||||
*/
|
||||
static inline u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size)
|
||||
{
|
||||
i2o_status_block *sb = c->status_block.virt;
|
||||
u16 sg_count =
|
||||
(sb->inbound_frame_size - sizeof(struct i2o_message) / 4) -
|
||||
body_size;
|
||||
|
||||
if (c->pae_support) {
|
||||
/*
|
||||
* for 64-bit a SG attribute element must be added and each
|
||||
* SG element needs 12 bytes instead of 8.
|
||||
*/
|
||||
sg_count -= 2;
|
||||
sg_count /= 3;
|
||||
} else
|
||||
sg_count /= 2;
|
||||
|
||||
if (c->short_req && (sg_count > 8))
|
||||
sg_count = 8;
|
||||
|
||||
return sg_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* i2o_dma_map_single - Map pointer to controller and fill in I2O message.
|
||||
* @c: I2O controller
|
||||
* @ptr: pointer to the data which should be mapped
|
||||
* @size: size of data in bytes
|
||||
* @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
|
||||
* @sg_ptr: pointer to the SG list inside the I2O message
|
||||
*
|
||||
* This function does all necessary DMA handling and also writes the I2O
|
||||
* SGL elements into the I2O message. For details on DMA handling see also
|
||||
* dma_map_single(). The pointer sg_ptr will only be set to the end of the
|
||||
* SG list if the allocation was successful.
|
||||
*
|
||||
* Returns DMA address which must be checked for failures using
|
||||
* dma_mapping_error().
|
||||
*/
|
||||
static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
|
||||
size_t size,
|
||||
enum dma_data_direction direction,
|
||||
u32 __iomem ** sg_ptr)
|
||||
{
|
||||
u32 sg_flags;
|
||||
u32 __iomem *mptr = *sg_ptr;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
switch (direction) {
|
||||
case DMA_TO_DEVICE:
|
||||
sg_flags = 0xd4000000;
|
||||
break;
|
||||
case DMA_FROM_DEVICE:
|
||||
sg_flags = 0xd0000000;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction);
|
||||
if (!dma_mapping_error(dma_addr)) {
|
||||
#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
|
||||
if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
|
||||
writel(0x7C020002, mptr++);
|
||||
writel(PAGE_SIZE, mptr++);
|
||||
}
|
||||
#endif
|
||||
|
||||
writel(sg_flags | size, mptr++);
|
||||
writel(i2o_dma_low(dma_addr), mptr++);
|
||||
#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
|
||||
if ((sizeof(dma_addr_t) > 4) && c->pae_support)
|
||||
writel(i2o_dma_high(dma_addr), mptr++);
|
||||
#endif
|
||||
*sg_ptr = mptr;
|
||||
}
|
||||
return dma_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* i2o_dma_map_sg - Map a SG List to controller and fill in I2O message.
|
||||
* @c: I2O controller
|
||||
* @sg: SG list to be mapped
|
||||
* @sg_count: number of elements in the SG list
|
||||
* @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
|
||||
* @sg_ptr: pointer to the SG list inside the I2O message
|
||||
*
|
||||
* This function does all necessary DMA handling and also writes the I2O
|
||||
* SGL elements into the I2O message. For details on DMA handling see also
|
||||
* dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG
|
||||
* list if the allocation was successful.
|
||||
*
|
||||
* Returns 0 on failure or 1 on success.
|
||||
*/
|
||||
static inline int i2o_dma_map_sg(struct i2o_controller *c,
|
||||
struct scatterlist *sg, int sg_count,
|
||||
enum dma_data_direction direction,
|
||||
u32 __iomem ** sg_ptr)
|
||||
{
|
||||
u32 sg_flags;
|
||||
u32 __iomem *mptr = *sg_ptr;
|
||||
|
||||
switch (direction) {
|
||||
case DMA_TO_DEVICE:
|
||||
sg_flags = 0x14000000;
|
||||
break;
|
||||
case DMA_FROM_DEVICE:
|
||||
sg_flags = 0x10000000;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction);
|
||||
if (!sg_count)
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
|
||||
if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
|
||||
writel(0x7C020002, mptr++);
|
||||
writel(PAGE_SIZE, mptr++);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (sg_count-- > 0) {
|
||||
if (!sg_count)
|
||||
sg_flags |= 0xC0000000;
|
||||
writel(sg_flags | sg_dma_len(sg), mptr++);
|
||||
writel(i2o_dma_low(sg_dma_address(sg)), mptr++);
|
||||
#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
|
||||
if ((sizeof(dma_addr_t) > 4) && c->pae_support)
|
||||
writel(i2o_dma_high(sg_dma_address(sg)), mptr++);
|
||||
#endif
|
||||
sg++;
|
||||
}
|
||||
*sg_ptr = mptr;
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* i2o_dma_alloc - Allocate DMA memory
|
||||
* @dev: struct device pointer to the PCI device of the I2O controller
|
||||
* @addr: i2o_dma struct which should get the DMA buffer
|
||||
* @len: length of the new DMA memory
|
||||
* @gfp_mask: GFP mask
|
||||
*
|
||||
* Allocate a coherent DMA memory and write the pointers into addr.
|
||||
*
|
||||
* Returns 0 on success or -ENOMEM on failure.
|
||||
*/
|
||||
static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
|
||||
size_t len, unsigned int gfp_mask)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
int dma_64 = 0;
|
||||
|
||||
if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) {
|
||||
dma_64 = 1;
|
||||
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
|
||||
|
||||
if ((sizeof(dma_addr_t) > 4) && dma_64)
|
||||
if (pci_set_dma_mask(pdev, DMA_64BIT_MASK))
|
||||
printk(KERN_WARNING "i2o: unable to set 64-bit DMA");
|
||||
|
||||
if (!addr->virt)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(addr->virt, 0, len);
|
||||
addr->len = len;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* i2o_dma_free - Free DMA memory
|
||||
* @dev: struct device pointer to the PCI device of the I2O controller
|
||||
* @addr: i2o_dma struct which contains the DMA buffer
|
||||
*
|
||||
* Free a coherent DMA memory and set virtual address of addr to NULL.
|
||||
*/
|
||||
static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
|
||||
{
|
||||
if (addr->virt) {
|
||||
if (addr->phys)
|
||||
dma_free_coherent(dev, addr->len, addr->virt,
|
||||
addr->phys);
|
||||
else
|
||||
kfree(addr->virt);
|
||||
addr->virt = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* i2o_dma_realloc - Realloc DMA memory
|
||||
* @dev: struct device pointer to the PCI device of the I2O controller
|
||||
* @addr: pointer to a i2o_dma struct DMA buffer
|
||||
* @len: new length of memory
|
||||
* @gfp_mask: GFP mask
|
||||
*
|
||||
* If there was something allocated in the addr, free it first. If len > 0
|
||||
* than try to allocate it and write the addresses back to the addr
|
||||
* structure. If len == 0 set the virtual address to NULL.
|
||||
*
|
||||
* Returns the 0 on success or negative error code on failure.
|
||||
*/
|
||||
static inline int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr,
|
||||
size_t len, unsigned int gfp_mask)
|
||||
{
|
||||
i2o_dma_free(dev, addr);
|
||||
|
||||
if (len)
|
||||
return i2o_dma_alloc(dev, addr, len, gfp_mask);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/* I2O driver (OSM) functions */
|
||||
extern int i2o_driver_register(struct i2o_driver *);
|
||||
extern void i2o_driver_unregister(struct i2o_driver *);
|
||||
@@ -375,10 +615,11 @@ extern int i2o_device_claim_release(struct i2o_device *);
|
||||
/* Exec OSM functions */
|
||||
extern int i2o_exec_lct_get(struct i2o_controller *);
|
||||
|
||||
/* device / driver conversion functions */
|
||||
/* device / driver / kobject conversion functions */
|
||||
#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver)
|
||||
#define to_i2o_device(dev) container_of(dev, struct i2o_device, device)
|
||||
#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device)
|
||||
#define kobj_to_i2o_device(kobj) to_i2o_device(container_of(kobj, struct device, kobj))
|
||||
|
||||
/**
|
||||
* i2o_msg_get - obtain an I2O message from the IOP
|
||||
@@ -466,8 +707,10 @@ static inline struct i2o_message __iomem *i2o_msg_out_to_virt(struct
|
||||
i2o_controller *c,
|
||||
u32 m)
|
||||
{
|
||||
BUG_ON(m < c->out_queue.phys
|
||||
|| m >= c->out_queue.phys + c->out_queue.len);
|
||||
if (unlikely
|
||||
(m < c->out_queue.phys
|
||||
|| m >= c->out_queue.phys + c->out_queue.len))
|
||||
return NULL;
|
||||
|
||||
return c->out_queue.virt + (m - c->out_queue.phys);
|
||||
};
|
||||
@@ -532,48 +775,6 @@ static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* i2o_dma_map - Map the memory to DMA
|
||||
* @dev: struct device pointer to the PCI device of the I2O controller
|
||||
* @addr: i2o_dma struct which should be mapped
|
||||
*
|
||||
* Map the memory in addr->virt to coherent DMA memory and write the
|
||||
* physical address into addr->phys.
|
||||
*
|
||||
* Returns 0 on success or -ENOMEM on failure.
|
||||
*/
|
||||
static inline int i2o_dma_map(struct device *dev, struct i2o_dma *addr)
|
||||
{
|
||||
if (!addr->virt)
|
||||
return -EFAULT;
|
||||
|
||||
if (!addr->phys)
|
||||
addr->phys = dma_map_single(dev, addr->virt, addr->len,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (!addr->phys)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* i2o_dma_unmap - Unmap the DMA memory
|
||||
* @dev: struct device pointer to the PCI device of the I2O controller
|
||||
* @addr: i2o_dma struct which should be unmapped
|
||||
*
|
||||
* Unmap the memory in addr->virt from DMA memory.
|
||||
*/
|
||||
static inline void i2o_dma_unmap(struct device *dev, struct i2o_dma *addr)
|
||||
{
|
||||
if (!addr->virt)
|
||||
return;
|
||||
|
||||
if (addr->phys) {
|
||||
dma_unmap_single(dev, addr->phys, addr->len, DMA_BIDIRECTIONAL);
|
||||
addr->phys = 0;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Endian handling wrapped into the macro - keeps the core code
|
||||
* cleaner.
|
||||
@@ -725,6 +926,14 @@ extern void i2o_debug_state(struct i2o_controller *c);
|
||||
#define I2O_CMD_SCSI_ABORT 0x83
|
||||
#define I2O_CMD_SCSI_BUSRESET 0x27
|
||||
|
||||
/*
|
||||
* Bus Adapter Class
|
||||
*/
|
||||
#define I2O_CMD_BUS_ADAPTER_RESET 0x85
|
||||
#define I2O_CMD_BUS_RESET 0x87
|
||||
#define I2O_CMD_BUS_SCAN 0x89
|
||||
#define I2O_CMD_BUS_QUIESCE 0x8b
|
||||
|
||||
/*
|
||||
* Random Block Storage Class
|
||||
*/
|
||||
@@ -948,7 +1157,7 @@ extern void i2o_debug_state(struct i2o_controller *c);
|
||||
|
||||
/* request queue sizes */
|
||||
#define I2O_MAX_SECTORS 1024
|
||||
#define I2O_MAX_SEGMENTS 128
|
||||
#define I2O_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS
|
||||
|
||||
#define I2O_REQ_MEMPOOL_SIZE 32
|
||||
|
||||
|
Reference in New Issue
Block a user