Commit 072152fc authored by Ben Collins's avatar Ben Collins

[IEEE1394]: Per-host address space patch from Steve.

parent 5c0b7f26
......@@ -77,6 +77,25 @@ enum {
static struct hpsb_highlevel cmp_highlevel;
static void cmp_add_host(struct hpsb_host *host);
static void cmp_host_reset(struct hpsb_host *host);
static int pcr_read(struct hpsb_host *host, int nodeid, quadlet_t *buf,
u64 addr, size_t length, u16 flags);
static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 flags);
static struct hpsb_highlevel cmp_highlevel = {
.name = "cmp",
.add_host = cmp_add_host,
.host_reset = cmp_host_reset,
};
static struct hpsb_address_ops pcr_ops = {
.read = pcr_read,
.lock = pcr_lock,
};
struct cmp_pcr *
cmp_register_opcr(struct hpsb_host *host, int opcr_number, int payload,
void (*update)(struct cmp_pcr *pcr, void *data),
......@@ -137,6 +156,10 @@ static void cmp_add_host(struct hpsb_host *host)
return;
}
hpsb_register_addrspace(&cmp_highlevel, host, &pcr_ops,
CSR_REGISTER_BASE + CSR_PCR_MAP,
CSR_REGISTER_BASE + CSR_PCR_MAP_END);
ch->host = host;
ch->u.ompr.rate = IEEE1394_SPEED_100;
ch->u.ompr.bcast_channel_base = 63;
......@@ -258,17 +281,6 @@ static int pcr_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
}
static struct hpsb_highlevel cmp_highlevel = {
.name = "cmp",
.add_host = cmp_add_host,
.host_reset = cmp_host_reset,
};
static struct hpsb_address_ops pcr_ops = {
.read = pcr_read,
.lock = pcr_lock,
};
/* Module interface */
MODULE_AUTHOR("Kristian Hogsberg <hogsberg@users.sf.net>");
......@@ -283,10 +295,6 @@ static int __init cmp_init_module (void)
{
hpsb_register_highlevel (&cmp_highlevel);
hpsb_register_addrspace(&cmp_highlevel, &pcr_ops,
CSR_REGISTER_BASE + CSR_PCR_MAP,
CSR_REGISTER_BASE + CSR_PCR_MAP_END);
HPSB_INFO("Loaded CMP driver");
return 0;
......
......@@ -35,6 +35,43 @@ static int fcp = 1;
module_param(fcp, int, 0444);
MODULE_PARM_DESC(fcp, "Map FCP registers (default = 1, disable = 0).");
static void add_host(struct hpsb_host *host);
static void host_reset(struct hpsb_host *host);
static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
u64 addr, size_t length, u16 fl);
static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
quadlet_t *data, u64 addr, size_t length, u16 flags);
static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
u64 addr, size_t length, u16 flags);
static int write_regs(struct hpsb_host *host, int nodeid, int destid,
quadlet_t *data, u64 addr, size_t length, u16 flags);
static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl);
static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store,
u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl);
static struct hpsb_highlevel csr_highlevel = {
.name = "standard registers",
.add_host = add_host,
.host_reset = host_reset,
};
static struct hpsb_address_ops map_ops = {
.read = read_maps,
};
static struct hpsb_address_ops fcp_ops = {
.write = write_fcp,
};
static struct hpsb_address_ops reg_ops = {
.read = read_regs,
.write = write_regs,
.lock = lock_regs,
.lock64 = lock64_regs,
};
static u16 csr_crc16(unsigned *data, int length)
{
int check=0, i;
......@@ -125,6 +162,24 @@ static inline void calculate_expire(struct csr_control *csr)
static void add_host(struct hpsb_host *host)
{
hpsb_register_addrspace(&csr_highlevel, host, &reg_ops,
CSR_REGISTER_BASE,
CSR_REGISTER_BASE + CSR_CONFIG_ROM);
hpsb_register_addrspace(&csr_highlevel, host, &map_ops,
CSR_REGISTER_BASE + CSR_CONFIG_ROM,
CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
if (fcp) {
hpsb_register_addrspace(&csr_highlevel, host, &fcp_ops,
CSR_REGISTER_BASE + CSR_FCP_COMMAND,
CSR_REGISTER_BASE + CSR_FCP_END);
}
hpsb_register_addrspace(&csr_highlevel, host, &map_ops,
CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP,
CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END);
hpsb_register_addrspace(&csr_highlevel, host, &map_ops,
CSR_REGISTER_BASE + CSR_SPEED_MAP,
CSR_REGISTER_BASE + CSR_SPEED_MAP_END);
host->csr.lock = SPIN_LOCK_UNLOCKED;
host->csr.rom_size = host->driver->get_rom(host, &host->csr.rom);
......@@ -684,48 +739,10 @@ static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
}
static struct hpsb_highlevel csr_highlevel = {
.name = "standard registers",
.add_host = add_host,
.host_reset = host_reset,
};
static struct hpsb_address_ops map_ops = {
.read = read_maps,
};
static struct hpsb_address_ops fcp_ops = {
.write = write_fcp,
};
static struct hpsb_address_ops reg_ops = {
.read = read_regs,
.write = write_regs,
.lock = lock_regs,
.lock64 = lock64_regs,
};
void init_csr(void)
{
hpsb_register_highlevel(&csr_highlevel);
hpsb_register_addrspace(&csr_highlevel, &reg_ops, CSR_REGISTER_BASE,
CSR_REGISTER_BASE + CSR_CONFIG_ROM);
hpsb_register_addrspace(&csr_highlevel, &map_ops,
CSR_REGISTER_BASE + CSR_CONFIG_ROM,
CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
if (fcp) {
hpsb_register_addrspace(&csr_highlevel, &fcp_ops,
CSR_REGISTER_BASE + CSR_FCP_COMMAND,
CSR_REGISTER_BASE + CSR_FCP_END);
}
hpsb_register_addrspace(&csr_highlevel, &map_ops,
CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP,
CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END);
hpsb_register_addrspace(&csr_highlevel, &map_ops,
CSR_REGISTER_BASE + CSR_SPEED_MAP,
CSR_REGISTER_BASE + CSR_SPEED_MAP_END);
}
void cleanup_csr(void)
......
......@@ -168,6 +168,26 @@ static void ether1394_iso(struct hpsb_iso *iso);
static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
static int ether1394_ethtool_ioctl(struct net_device *dev, void *useraddr);
static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
quadlet_t *data, u64 addr, size_t len, u16 flags);
static void ether1394_add_host (struct hpsb_host *host);
static void ether1394_remove_host (struct hpsb_host *host);
static void ether1394_host_reset (struct hpsb_host *host);
/* Function for incoming 1394 packets */
static struct hpsb_address_ops addr_ops = {
.write = ether1394_write,
};
/* Ieee1394 highlevel driver functions */
static struct hpsb_highlevel eth1394_highlevel = {
.name = driver_name,
.add_host = ether1394_add_host,
.remove_host = ether1394_remove_host,
.host_reset = ether1394_host_reset,
};
static void eth1394_iso_shutdown(struct eth1394_priv *priv)
{
priv->bc_state = ETHER1394_BC_CLOSED;
......@@ -420,6 +440,10 @@ static void ether1394_add_host (struct hpsb_host *host)
struct eth1394_priv *priv;
static int version_printed = 0;
hpsb_register_addrspace(&eth1394_highlevel, host, &addr_ops,
ETHER1394_REGION_ADDR,
ETHER1394_REGION_ADDR_END);
if (version_printed++ == 0)
ETH1394_PRINT_G (KERN_INFO, "%s\n", version);
......@@ -1619,18 +1643,6 @@ static int ether1394_ethtool_ioctl(struct net_device *dev, void *useraddr)
return 0;
}
/* Function for incoming 1394 packets */
static struct hpsb_address_ops addr_ops = {
.write = ether1394_write,
};
/* Ieee1394 highlevel driver functions */
static struct hpsb_highlevel eth1394_highlevel = {
.name = driver_name,
.add_host = ether1394_add_host,
.remove_host = ether1394_remove_host,
.host_reset = ether1394_host_reset,
};
static int __init ether1394_init_module (void)
{
......@@ -1640,9 +1652,6 @@ static int __init ether1394_init_module (void)
/* Register ourselves as a highlevel driver */
hpsb_register_highlevel(&eth1394_highlevel);
hpsb_register_addrspace(&eth1394_highlevel, &addr_ops, ETHER1394_REGION_ADDR,
ETHER1394_REGION_ADDR_END);
return 0;
}
......
......@@ -41,7 +41,6 @@ struct hl_host_info {
static LIST_HEAD(hl_drivers);
static rwlock_t hl_drivers_lock = RW_LOCK_UNLOCKED;
static LIST_HEAD(addr_space);
static rwlock_t addr_space_lock = RW_LOCK_UNLOCKED;
/* addr_space list will have zero and max already included as bounds */
......@@ -288,7 +287,7 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
nodemgr_for_each_host(hl, highlevel_for_each_host_unreg);
}
int hpsb_register_addrspace(struct hpsb_highlevel *hl,
int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
struct hpsb_address_ops *ops, u64 start, u64 end)
{
struct hpsb_address_serve *as;
......@@ -314,7 +313,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl,
as->end = end;
write_lock_irqsave(&addr_space_lock, flags);
entry = addr_space.next;
entry = host->addr_space.next;
while (list_entry(entry, struct hpsb_address_serve, as_list)->end
<= start) {
......@@ -336,7 +335,8 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl,
return retval;
}
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start)
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
u64 start)
{
int retval = 0;
struct hpsb_address_serve *as;
......@@ -350,7 +350,7 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start)
while (entry != &hl->addr_list) {
as = list_entry(entry, struct hpsb_address_serve, addr_list);
entry = entry->next;
if (as->start == start) {
if (as->start == start && as->host == host) {
list_del(&as->as_list);
list_del(&as->addr_list);
kfree(as);
......@@ -398,6 +398,8 @@ void highlevel_add_host(struct hpsb_host *host)
struct list_head *entry;
struct hpsb_highlevel *hl;
init_hpsb_highlevel(host);
read_lock(&hl_drivers_lock);
list_for_each(entry, &hl_drivers) {
hl = list_entry(entry, struct hpsb_highlevel, hl_list);
......@@ -411,6 +413,9 @@ void highlevel_remove_host(struct hpsb_host *host)
{
struct list_head *entry;
struct hpsb_highlevel *hl;
struct list_head *lh, *next;
struct hpsb_address_serve *as;
unsigned long flags;
read_lock(&hl_drivers_lock);
list_for_each(entry, &hl_drivers) {
......@@ -422,6 +427,17 @@ void highlevel_remove_host(struct hpsb_host *host)
}
}
read_unlock(&hl_drivers_lock);
/* Free up 1394 address space left behind by high level drivers. */
write_lock_irqsave(&addr_space_lock, flags);
list_for_each_safe (lh, next, &host->addr_space) {
as = list_entry(lh, struct hpsb_address_serve, as_list);
if (!list_empty(&as->addr_list)) {
list_del(&as->addr_list);
kfree(as);
}
}
write_unlock_irqrestore(&addr_space_lock, flags);
}
void highlevel_host_reset(struct hpsb_host *host)
......@@ -490,7 +506,7 @@ int highlevel_read(struct hpsb_host *host, int nodeid, void *data,
read_lock(&addr_space_lock);
entry = addr_space.next;
entry = host->addr_space.next;
as = list_entry(entry, struct hpsb_address_serve, as_list);
while (as->start <= addr) {
......@@ -536,7 +552,7 @@ int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
read_lock(&addr_space_lock);
entry = addr_space.next;
entry = host->addr_space.next;
as = list_entry(entry, struct hpsb_address_serve, as_list);
while (as->start <= addr) {
......@@ -582,7 +598,7 @@ int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
read_lock(&addr_space_lock);
entry = addr_space.next;
entry = host->addr_space.next;
as = list_entry(entry, struct hpsb_address_serve, as_list);
while (as->start <= addr) {
......@@ -615,7 +631,7 @@ int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
read_lock(&addr_space_lock);
entry = addr_space.next;
entry = host->addr_space.next;
as = list_entry(entry, struct hpsb_address_serve, as_list);
while (as->start <= addr) {
......@@ -640,7 +656,7 @@ int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
return rcode;
}
void init_hpsb_highlevel(void)
void init_hpsb_highlevel(struct hpsb_host *host)
{
INIT_LIST_HEAD(&dummy_zero_addr.as_list);
INIT_LIST_HEAD(&dummy_zero_addr.addr_list);
......@@ -652,6 +668,6 @@ void init_hpsb_highlevel(void)
dummy_zero_addr.start = dummy_zero_addr.end = 0;
dummy_max_addr.start = dummy_max_addr.end = ((u64) 1) << 48;
list_add_tail(&dummy_zero_addr.as_list, &addr_space);
list_add_tail(&dummy_max_addr.as_list, &addr_space);
list_add_tail(&dummy_zero_addr.as_list, &host->addr_space);
list_add_tail(&dummy_max_addr.as_list, &host->addr_space);
}
......@@ -10,6 +10,8 @@ struct hpsb_address_serve {
struct hpsb_address_ops *op;
struct hpsb_host *host;
/* first address handled and first address behind, quadlet aligned */
u64 start, end;
};
......@@ -137,10 +139,11 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
* It returns true for successful allocation. There is no unregister function,
* all address spaces are deallocated together with the hpsb_highlevel.
*/
int hpsb_register_addrspace(struct hpsb_highlevel *hl,
int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
struct hpsb_address_ops *ops, u64 start, u64 end);
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start);
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
u64 start);
/*
* Enable or disable receving a certain isochronous channel through the
......@@ -179,6 +182,6 @@ int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *d
struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key);
/* Initialize the highlevel system */
void init_hpsb_highlevel(void);
void init_hpsb_highlevel(struct hpsb_host *host);
#endif /* IEEE1394_HIGHLEVEL_H */
......@@ -89,6 +89,8 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
INIT_LIST_HEAD(&h->pending_packets);
spin_lock_init(&h->pending_pkt_lock);
INIT_LIST_HEAD(&h->addr_space);
for (i = 0; i < ARRAY_SIZE(h->tpool); i++)
HPSB_TPOOL_INIT(&h->tpool[i]);
......
......@@ -69,6 +69,8 @@ struct hpsb_host {
int id;
struct device device;
struct list_head addr_space;
};
......
......@@ -1009,7 +1009,6 @@ static int __init ieee1394_init(void)
bus_register(&ieee1394_bus_type);
init_hpsb_highlevel();
init_csr();
if (!disable_nodemgr)
......
......@@ -1696,7 +1696,7 @@ static int arm_register(struct file_info *fi, struct pending_request *req)
spin_unlock_irqrestore(&host_info_lock, flags);
return sizeof(struct raw1394_request);
}
retval = hpsb_register_addrspace(&raw1394_highlevel, &arm_ops, req->req.address,
retval = hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops, req->req.address,
req->req.address + req->req.length);
if (retval) {
/* INSERT ENTRY */
......@@ -1783,7 +1783,7 @@ static int arm_unregister(struct file_info *fi, struct pending_request *req)
spin_unlock_irqrestore(&host_info_lock, flags);
return sizeof(struct raw1394_request);
}
retval = hpsb_unregister_addrspace(&raw1394_highlevel, addr->start);
retval = hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, addr->start);
if (!retval) {
printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n");
spin_unlock_irqrestore(&host_info_lock, flags);
......@@ -2551,7 +2551,7 @@ static int raw1394_release(struct inode *inode, struct file *file)
}
if (!another_host) {
DBGMSG("raw1394_release: call hpsb_arm_unregister");
retval = hpsb_unregister_addrspace(&raw1394_highlevel, addr->start);
retval = hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, addr->start);
if (!retval) {
++fail;
printk(KERN_ERR "raw1394_release arm_Unregister failed\n");
......
......@@ -712,6 +712,18 @@ static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host)
return NULL;
}
/* Register our sbp2 status address space... */
hpsb_register_addrspace(&sbp2_highlevel, host, &sbp2_ops,
SBP2_STATUS_FIFO_ADDRESS,
SBP2_STATUS_FIFO_ADDRESS +
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1));
/* Handle data movement if physical dma is not enabled/supported
* on host controller */
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
hpsb_register_addrspace(&sbp2_highlevel, host, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL);
#endif
hi = hpsb_create_hostinfo(&sbp2_highlevel, host, sizeof(*hi));
if (!hi) {
SBP2_ERR("failed to allocate hostinfo");
......@@ -2881,17 +2893,6 @@ static int sbp2_module_init(void)
/* Register our high level driver with 1394 stack */
hpsb_register_highlevel(&sbp2_highlevel);
/* Register our sbp2 status address space... */
hpsb_register_addrspace(&sbp2_highlevel, &sbp2_ops, SBP2_STATUS_FIFO_ADDRESS,
SBP2_STATUS_FIFO_ADDRESS +
SBP2_STATUS_FIFO_ENTRY_TO_OFFSET(SBP2SCSI_MAX_SCSI_IDS+1));
/* Handle data movement if physical dma is not enabled/supported
* on host controller */
#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
hpsb_register_addrspace(&sbp2_highlevel, &sbp2_physdma_ops, 0x0ULL, 0xfffffffcULL);
#endif
hpsb_register_protocol(&sbp2_driver);
return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment