diff --git a/MAINTAINERS b/MAINTAINERS index 7cd2c7ad35fcde2e2735098768104bb4ea41f669..48b253ee120eb870a596c4c9a631d71beae9e524 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1082,9 +1082,21 @@ M: Gadi Oxman <gadio@netvision.net.il> L: linux-kernel@vger.kernel.org S: Maintained +IEEE 1394 ETHERNET (eth1394) +L: linux1394-devel@lists.sourceforge.net +W: http://www.linux1394.org/ +S: Orphan + +IEEE 1394 SBP2 +L: linux1394-devel@lists.sourceforge.net +W: http://www.linux1394.org/ +S: Orphan + IEEE 1394 SUBSYSTEM P: Ben Collins M: bcollins@debian.org +P: Jody McIntyre +M: scjody@steamballoon.com L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ S: Maintained @@ -1092,13 +1104,15 @@ S: Maintained IEEE 1394 OHCI DRIVER P: Ben Collins M: bcollins@debian.org +P: Jody McIntyre +M: scjody@steamballoon.com L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ S: Maintained IEEE 1394 PCILYNX DRIVER -P: Andreas Bombe -M: andreas.bombe@munich.netsurf.de +P: Jody McIntyre +M: scjody@steamballoon.com L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ S: Maintained @@ -1106,6 +1120,8 @@ S: Maintained IEEE 1394 RAW I/O DRIVER P: Ben Collins M: bcollins@debian.org +P: Dan Dennedy +M: dan@dennedy.org L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ S: Maintained diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index f2ae8128925524d36339d5a8c2be728f08c44535..78b201fb5e8ab792c622bddcc69e396039a8b772 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -5,6 +5,7 @@ menu "IEEE 1394 (FireWire) support" config IEEE1394 tristate "IEEE 1394 (FireWire) support" depends on PCI || BROKEN + select NET help IEEE 1394 describes a high performance serial bus, which is also known as FireWire(tm) or i.Link(tm) and is used for connecting all diff --git a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c index 6ba5de706fae44256cfced0dad099402a4676e9a..84ae027b021a19920dede6881f2260ddefb48978 100644 --- a/drivers/ieee1394/amdtp.c +++ b/drivers/ieee1394/amdtp.c @@ -286,7 +286,7 @@ static struct hpsb_highlevel amdtp_highlevel; #define OHCI1394_CONTEXT_DEAD 0x00000800 #define OHCI1394_CONTEXT_ACTIVE 0x00000400 -void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx, +static void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx, dma_addr_t first_cmd, int z, int cycle_match) { reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << ctx); @@ -298,13 +298,13 @@ void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx, OHCI1394_CONTEXT_RUN); } -void ohci1394_wake_it_ctx(struct ti_ohci *ohci, int ctx) +static void ohci1394_wake_it_ctx(struct ti_ohci *ohci, int ctx) { reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16, OHCI1394_CONTEXT_WAKE); } -void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous) +static void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous) { u32 control; int wait; @@ -530,7 +530,7 @@ static __inline__ int fraction_ceil(struct fraction *frac) return frac->integer + (frac->numerator > 0 ? 1 : 0); } -void packet_initialize(struct packet *p, struct packet *next) +static void packet_initialize(struct packet *p, struct packet *next) { /* Here we initialize the dma descriptor block for * transferring one iso packet. We use two descriptors per @@ -559,7 +559,7 @@ void packet_initialize(struct packet *p, struct packet *next) p->db->payload_desc.status = 0; } -struct packet_list *packet_list_alloc(struct stream *s) +static struct packet_list *packet_list_alloc(struct stream *s) { int i; struct packet_list *pl; @@ -588,7 +588,7 @@ struct packet_list *packet_list_alloc(struct stream *s) return pl; } -void packet_list_free(struct packet_list *pl, struct stream *s) +static void packet_list_free(struct packet_list *pl, struct stream *s) { int i; @@ -1010,7 +1010,7 @@ static int stream_configure(struct stream *s, int cmd, struct amdtp_ioctl *cfg) return 0; } -struct stream *stream_alloc(struct amdtp_host *host) +static struct stream *stream_alloc(struct amdtp_host *host) { struct stream *s; unsigned long flags; @@ -1062,7 +1062,7 @@ struct stream *stream_alloc(struct amdtp_host *host) return s; } -void stream_free(struct stream *s) +static void stream_free(struct stream *s) { unsigned long flags; diff --git a/drivers/ieee1394/config_roms.c b/drivers/ieee1394/config_roms.c index 530f853f03ceef8b76947eefc496f308b9e2fafe..1017fd7172486dd3058694ca22368b973f707469 100644 --- a/drivers/ieee1394/config_roms.c +++ b/drivers/ieee1394/config_roms.c @@ -67,8 +67,8 @@ int hpsb_default_host_entry(struct hpsb_host *host) ret = csr1212_associate_keyval(vend_id, text); csr1212_release_keyval(text); ret |= csr1212_attach_keyval_to_directory(root, vend_id); + csr1212_release_keyval(vend_id); if (ret != CSR1212_SUCCESS) { - csr1212_release_keyval(vend_id); csr1212_destroy_csr(host->csr.rom); return -ENOMEM; } diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c index 931464b6ce9eabd54371d64af4e515ab458efbeb..7c4330e2e875b8e41d92bfc447e3f9aca5c93bc6 100644 --- a/drivers/ieee1394/csr1212.c +++ b/drivers/ieee1394/csr1212.c @@ -87,7 +87,8 @@ static const u_int8_t csr1212_key_id_type_map[0x30] = { static inline void free_keyval(struct csr1212_keyval *kv) { - if (kv->key.type == CSR1212_KV_TYPE_LEAF) + if ((kv->key.type == CSR1212_KV_TYPE_LEAF) && + (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)) CSR1212_FREE(kv->value.leaf.data); CSR1212_FREE(kv); @@ -155,7 +156,7 @@ static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_k { struct csr1212_keyval *kv; - for (kv = kv_list; kv != NULL; kv = kv->next) { + for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next) { if (kv->offset == offset) return kv; } @@ -181,9 +182,9 @@ struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, return NULL; } - /* The keyval key id is not used for the root node, but a valid key id - * that can be used for a directory needs to be passed to - * csr1212_new_directory(). */ + /* The keyval key id is not used for the root node, but a valid key id + * that can be used for a directory needs to be passed to + * csr1212_new_directory(). */ csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR); if (!csr->root_kv) { CSR1212_FREE(csr->cache_head); @@ -709,7 +710,7 @@ void _csr1212_destroy_keyval(struct csr1212_keyval *kv) tail->next = k->value.directory.dentries_head; k->value.directory.dentries_head->prev = tail; tail = k->value.directory.dentries_tail; - } + } } free_keyval(k); k = a; @@ -796,7 +797,8 @@ static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize) return CSR1212_ENOMEM; } cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE; - cache->ext_rom->value.leaf.len = 0; + cache->ext_rom->value.leaf.len = -1; + cache->ext_rom->value.leaf.data = cache->data; /* Add cache to tail of cache list */ cache->prev = csr->cache_tail; @@ -864,20 +866,20 @@ static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir, default: case CSR1212_KV_TYPE_IMMEDIATE: case CSR1212_KV_TYPE_CSR_OFFSET: - continue; + break; case CSR1212_KV_TYPE_LEAF: case CSR1212_KV_TYPE_DIRECTORY: /* Remove from list */ - if (dkv->prev) + if (dkv->prev && (dkv->prev->next == dkv)) dkv->prev->next = dkv->next; - if (dkv->next) + if (dkv->next && (dkv->next->prev == dkv)) dkv->next->prev = dkv->prev; - if (dkv == *layout_tail) - *layout_tail = dkv->prev; + //if (dkv == *layout_tail) + // *layout_tail = dkv->prev; /* Special case: Extended ROM leafs */ if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) { - dkv->value.leaf.len = 0; /* initialize to zero */ + dkv->value.leaf.len = -1; /* Don't add Extended ROM leafs in the layout list, * they are handled differently. */ break; @@ -919,8 +921,8 @@ size_t csr1212_generate_layout_order(struct csr1212_keyval *kv) } struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache, - struct csr1212_keyval *start_kv, - int start_pos) + struct csr1212_keyval *start_kv, + int start_pos) { struct csr1212_keyval *kv = start_kv; struct csr1212_keyval *okv = start_kv; @@ -930,7 +932,10 @@ struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache * cache->layout_head = kv; while(kv && pos < cache->size) { - kv->offset = cache->offset + pos; + /* Special case: Extended ROM leafs */ + if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) { + kv->offset = cache->offset + pos; + } switch(kv->key.type) { case CSR1212_KV_TYPE_LEAF: @@ -1090,6 +1095,9 @@ int csr1212_generate_csr_image(struct csr1212_csr *csr) bi->crc_length = bi->length; bi->crc = csr1212_crc16(bi->data, bi->crc_length); + csr->root_kv->next = NULL; + csr->root_kv->prev = NULL; + agg_size = csr1212_generate_layout_order(csr->root_kv); init_offset = csr->bus_info_len; @@ -1158,6 +1166,17 @@ int csr1212_generate_csr_image(struct csr1212_csr *csr) /* Copy the data into the cache buffer */ csr1212_fill_cache(cache); + + if (cache != csr->cache_head) { + /* Set the length and CRC of the extended ROM. */ + struct csr1212_keyval_img *kvi = + (struct csr1212_keyval_img*)cache->data; + + kvi->length = CSR1212_CPU_TO_BE16(bytes_to_quads(cache->len) - 1); + kvi->crc = csr1212_crc16(kvi->data, + bytes_to_quads(cache->len) - 1); + + } } return CSR1212_SUCCESS; @@ -1174,11 +1193,6 @@ int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, u_int3 &cache->data[bytes_to_quads(offset - cache->offset)], len); return CSR1212_SUCCESS; - } else if (((offset < cache->offset) && - ((offset + len) >= cache->offset)) || - ((offset >= cache->offset) && - ((offset + len) > (cache->offset + cache->size)))) { - return CSR1212_EINVAL; } } return CSR1212_ENOENT; @@ -1227,8 +1241,8 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) return CSR1212_EINVAL; #if 0 - /* Apparently there are too many differnt wrong implementations of the - * CRC algorithm that verifying them is moot. */ + /* Apparently there are too many differnt wrong implementations of the + * CRC algorithm that verifying them is moot. */ if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) && (csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc)) return CSR1212_EINVAL; @@ -1249,10 +1263,9 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) return CSR1212_SUCCESS; } -static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir, - csr1212_quad_t ki, - u_int32_t kv_pos, - struct csr1212_csr_rom_cache *cache) +static int csr1212_parse_dir_entry(struct csr1212_keyval *dir, + csr1212_quad_t ki, + u_int32_t kv_pos) { int ret = CSR1212_SUCCESS; struct csr1212_keyval *k = NULL; @@ -1291,7 +1304,7 @@ static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir, goto fail; } - k = csr1212_find_keyval_offset(cache->layout_head, offset); + k = csr1212_find_keyval_offset(dir, offset); if (k) break; /* Found it. */ @@ -1309,11 +1322,10 @@ static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir, k->valid = 0; /* Contents not read yet so it's not valid. */ k->offset = offset; - k->prev = cache->layout_tail; - k->next = NULL; - if (cache->layout_tail) - cache->layout_tail->next = k; - cache->layout_tail = k; + k->prev = dir; + k->next = dir->next; + dir->next->prev = k; + dir->next = k; } ret = csr1212_attach_keyval_to_directory(dir, k); @@ -1325,6 +1337,7 @@ static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir, return ret; } + int csr1212_parse_keyval(struct csr1212_keyval *kv, struct csr1212_csr_rom_cache *cache) { @@ -1338,8 +1351,8 @@ int csr1212_parse_keyval(struct csr1212_keyval *kv, kvi_len = CSR1212_BE16_TO_CPU(kvi->length); #if 0 - /* Apparently there are too many differnt wrong implementations of the - * CRC algorithm that verifying them is moot. */ + /* Apparently there are too many differnt wrong implementations of the + * CRC algorithm that verifying them is moot. */ if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) && (csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) { ret = CSR1212_EINVAL; @@ -1353,22 +1366,19 @@ int csr1212_parse_keyval(struct csr1212_keyval *kv, csr1212_quad_t ki = kvi->data[i]; /* Some devices put null entries in their unit - * directories. If we come across such and entry, + * directories. If we come across such an entry, * then skip it. */ if (ki == 0x0) continue; ret = csr1212_parse_dir_entry(kv, ki, (kv->offset + - quads_to_bytes(i + 1)), - cache); + quads_to_bytes(i + 1))); } kv->value.directory.len = kvi_len; break; case CSR1212_KV_TYPE_LEAF: - if (kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) { - kv->value.leaf.data = cache->data; - } else { + if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) { kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len)); if (!kv->value.leaf.data) { @@ -1399,7 +1409,6 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) u_int32_t *cache_ptr; u_int16_t kv_len = 0; - if (!csr || !kv) return CSR1212_EINVAL; @@ -1413,7 +1422,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) if (!cache) { csr1212_quad_t q; - struct csr1212_csr_rom_cache *nc; + u_int32_t cache_size; /* Only create a new cache for Extended ROM leaves. */ if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) @@ -1425,12 +1434,20 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) return CSR1212_EIO; } - kv->value.leaf.len = quads_to_bytes(CSR1212_BE32_TO_CPU(q)>>16); + kv->value.leaf.len = CSR1212_BE32_TO_CPU(q) >> 16; + + cache_size = (quads_to_bytes(kv->value.leaf.len + 1) + + (csr->max_rom - 1)) & ~(csr->max_rom - 1); - nc = csr1212_rom_cache_malloc(kv->offset, kv->value.leaf.len); - cache->next = nc; - nc->prev = cache; - csr->cache_tail = nc; + cache = csr1212_rom_cache_malloc(kv->offset, cache_size); + if (!cache) + return CSR1212_ENOMEM; + + kv->value.leaf.data = &cache->data[1]; + csr->cache_tail->next = cache; + cache->prev = csr->cache_tail; + cache->next = NULL; + csr->cache_tail = cache; cache->filled_head = CSR1212_MALLOC(sizeof(struct csr1212_cache_region)); if (!cache->filled_head) { @@ -1443,6 +1460,10 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) cache->filled_head->next = NULL; cache->filled_head->prev = NULL; cache->data[0] = q; + + /* Don't read the entire extended ROM now. Pieces of it will + * be read when entries inside it are read. */ + return csr1212_parse_keyval(kv, cache); } cache_index = kv->offset - cache->offset; @@ -1548,6 +1569,7 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) int csr1212_parse_csr(struct csr1212_csr *csr) { static const int mr_map[] = { 4, 64, 1024, 0 }; + struct csr1212_dentry *dentry; int ret; if (!csr || !csr->ops->bus_read) @@ -1570,7 +1592,21 @@ int csr1212_parse_csr(struct csr1212_csr *csr) csr->bus_info_len; csr->root_kv->valid = 0; + csr->root_kv->next = csr->root_kv; + csr->root_kv->prev = csr->root_kv; csr1212_get_keyval(csr, csr->root_kv); + /* Scan through the Root directory finding all extended ROM regions + * and make cache regions for them */ + for (dentry = csr->root_kv->value.directory.dentries_head; + dentry; dentry = dentry->next) { + if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) { + csr1212_get_keyval(csr, dentry->kv); + + if (ret != CSR1212_SUCCESS) + return ret; + } + } + return CSR1212_SUCCESS; } diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c index 4bc2eab69e14aa0fcf1a2acb5990dc0fa9d8b242..758819d1999dd054b18f7084cb98072bdfc718a9 100644 --- a/drivers/ieee1394/dma.c +++ b/drivers/ieee1394/dma.c @@ -127,16 +127,12 @@ void dma_region_free(struct dma_region *dma) dma->dev = NULL; } - if (dma->sglist) { - vfree(dma->sglist); - dma->sglist = NULL; - } + vfree(dma->sglist); + dma->sglist = NULL; - if (dma->kvirt) { - vfree(dma->kvirt); - dma->kvirt = NULL; - dma->n_pages = 0; - } + vfree(dma->kvirt); + dma->kvirt = NULL; + dma->n_pages = 0; } /* find the scatterlist index and remaining offset corresponding to a diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index f80090084575506306986bc696b0f1f1ad2ab815..e60d4ef2f1fe9bc69c5574082f86327f6124c535 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -1277,7 +1277,7 @@ static void do_dv1394_shutdown(struct video_card *video, int free_dv_buf) error-prone code in dv1394. */ -int dv1394_mmap(struct file *file, struct vm_area_struct *vma) +static int dv1394_mmap(struct file *file, struct vm_area_struct *vma) { struct video_card *video = file_to_video_card(file); int retval = -EINVAL; @@ -2343,6 +2343,8 @@ static void dv1394_remove_host (struct hpsb_host *host) dv1394_un_init(video); } while (video != NULL); + class_simple_device_remove(MKDEV( + IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2))); devfs_remove("ieee1394/dv/host%d/NTSC", id); devfs_remove("ieee1394/dv/host%d/PAL", id); devfs_remove("ieee1394/dv/host%d", id); @@ -2359,6 +2361,9 @@ static void dv1394_add_host (struct hpsb_host *host) ohci = (struct ti_ohci *)host->hostdata; + class_simple_device_add(hpsb_protocol_class, MKDEV( + IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), + NULL, "dv1394-%d", id); devfs_mk_dir("ieee1394/dv/host%d", id); devfs_mk_dir("ieee1394/dv/host%d/NTSC", id); devfs_mk_dir("ieee1394/dv/host%d/PAL", id); diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 9b01d57486e3f578123eabf6fca75ff2d637ddcc..dccc25ad3d2bfae69d25b17ce7a0779375707e71 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -89,7 +89,7 @@ #define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__) static char version[] __devinitdata = - "$Rev: 1224 $ Ben Collins <bcollins@debian.org>"; + "$Rev: 1247 $ Ben Collins <bcollins@debian.org>"; struct fragment_info { struct list_head list; @@ -165,8 +165,7 @@ MODULE_LICENSE("GPL"); /* The max_partial_datagrams parameter is the maximum number of fragmented * datagrams per node that eth1394 will keep in memory. Providing an upper * bound allows us to limit the amount of memory that partial datagrams - * consume in the event that some partial datagrams are never completed. This - * should probably change to a sysctl item or the like if possible. + * consume in the event that some partial datagrams are never completed. */ static int max_partial_datagrams = 25; module_param(max_partial_datagrams, int, S_IRUGO | S_IWUSR); @@ -186,7 +185,7 @@ static void ether1394_header_cache_update(struct hh_cache *hh, unsigned char * haddr); static int ether1394_mac_addr(struct net_device *dev, void *p); -static inline void purge_partial_datagram(struct list_head *old); +static void purge_partial_datagram(struct list_head *old); static int ether1394_tx(struct sk_buff *skb, struct net_device *dev); static void ether1394_iso(struct hpsb_iso *iso); @@ -289,7 +288,7 @@ static int ether1394_change_mtu(struct net_device *dev, int new_mtu) return 0; } -static inline void purge_partial_datagram(struct list_head *old) +static void purge_partial_datagram(struct list_head *old) { struct partial_datagram *pd = list_entry(old, struct partial_datagram, list); struct list_head *lh, *n; @@ -449,7 +448,7 @@ static int eth1394_update(struct unit_directory *ud) if (!node_info) { kfree(node); return -ENOMEM; - } + } spin_lock_init(&node_info->pdg.lock); INIT_LIST_HEAD(&node_info->pdg.list); @@ -1187,7 +1186,7 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, lh = find_partial_datagram(pdgl, dgl); if (lh == NULL) { - if (pdg->sz == max_partial_datagrams) { + while (pdg->sz >= max_partial_datagrams) { /* remove the oldest */ purge_partial_datagram(pdgl->prev); pdg->sz--; @@ -1583,7 +1582,7 @@ static inline void ether1394_dg_complete(struct packet_task *ptask, int fail) struct sk_buff *skb = ptask->skb; struct net_device *dev = skb->dev; struct eth1394_priv *priv = netdev_priv(dev); - unsigned long flags; + unsigned long flags; /* Statistics */ spin_lock_irqsave(&priv->lock, flags); @@ -1771,7 +1770,7 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strcpy (info->driver, driver_name); - strcpy (info->version, "$Rev: 1224 $"); + strcpy (info->version, "$Rev: 1247 $"); /* FIXME XXX provide sane businfo */ strcpy (info->bus_info, "ieee1394"); } diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 24c1746c8b7346e2d1ac3a04efb199b2dc483d0a..997e1bf6297f8b1d1a6f797594bdeda16d1e7183 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c @@ -173,18 +173,6 @@ void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, un } -unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host) -{ - struct hl_host_info *hi; - - hi = hl_get_hostinfo(hl, host); - if (hi) - return hi->key; - - return 0; -} - - void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key) { struct hl_host_info *hi; @@ -206,26 +194,6 @@ void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key) } -struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key) -{ - struct hl_host_info *hi; - struct hpsb_host *host = NULL; - - if (!hl) - return NULL; - - read_lock(&hl->host_info_lock); - list_for_each_entry(hi, &hl->host_info_list, list) { - if (hi->key == key) { - host = hi->host; - break; - } - } - read_unlock(&hl->host_info_lock); - - return host; -} - static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data) { struct hpsb_highlevel *hl = __data; @@ -416,7 +384,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, } as = (struct hpsb_address_serve *) - kmalloc(sizeof(struct hpsb_address_serve), GFP_KERNEL); + kmalloc(sizeof(struct hpsb_address_serve), GFP_ATOMIC); if (as == NULL) { return 0; } diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h index 9834efc4edd45b851548950394ecd9758d27b890..b634a9bb365c9888c8fa3c736a8fa4964094ee56 100644 --- a/drivers/ieee1394/ieee1394.h +++ b/drivers/ieee1394/ieee1394.h @@ -77,6 +77,30 @@ extern const char *hpsb_speedto_str[]; #define SELFID_PORT_NONE 0x0 +/* 1394a PHY bitmasks */ +#define PHY_00_PHYSICAL_ID 0xFC +#define PHY_00_R 0x02 /* Root */ +#define PHY_00_PS 0x01 /* Power Status*/ +#define PHY_01_RHB 0x80 /* Root Hold-Off */ +#define PHY_01_IBR 0x80 /* Initiate Bus Reset */ +#define PHY_01_GAP_COUNT 0x3F +#define PHY_02_EXTENDED 0xE0 /* 0x7 for 1394a-compliant PHY */ +#define PHY_02_TOTAL_PORTS 0x1F +#define PHY_03_MAX_SPEED 0xE0 +#define PHY_03_DELAY 0x0F +#define PHY_04_LCTRL 0x80 /* Link Active Report Control */ +#define PHY_04_CONTENDER 0x40 +#define PHY_04_JITTER 0x38 +#define PHY_04_PWR_CLASS 0x07 /* Power Class */ +#define PHY_05_WATCHDOG 0x80 +#define PHY_05_ISBR 0x40 /* Initiate Short Bus Reset */ +#define PHY_05_LOOP 0x20 /* Loop Detect */ +#define PHY_05_PWR_FAIL 0x10 /* Cable Power Failure Detect */ +#define PHY_05_TIMEOUT 0x08 /* Arbitration State Machine Timeout */ +#define PHY_05_PORT_EVENT 0x04 /* Port Event Detect */ +#define PHY_05_ENAB_ACCEL 0x02 /* Enable Arbitration Acceleration */ +#define PHY_05_ENAB_MULTI 0x01 /* Ena. Multispeed Packet Concatenation */ + #include <asm/byteorder.h> #ifdef __BIG_ENDIAN_BITFIELD diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 9a3c58654267dfe800a2916272e41d4c1b41a057..1c5845f7e4ab3103675db0a54edb04c4a4adf6cb 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -56,11 +56,18 @@ static int disable_nodemgr = 0; module_param(disable_nodemgr, int, 0444); MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality."); +/* Disable Isochronous Resource Manager functionality */ +int hpsb_disable_irm = 0; +module_param_named(disable_irm, hpsb_disable_irm, bool, 0); +MODULE_PARM_DESC(disable_irm, + "Disable Isochronous Resource Manager functionality."); + /* We are GPL, so treat us special */ MODULE_LICENSE("GPL"); /* Some globals used */ const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" }; +struct class_simple *hpsb_protocol_class; #ifdef CONFIG_IEEE1394_VERBOSEDEBUG static void dump_packet(const char *text, quadlet_t *data, int size) @@ -79,6 +86,7 @@ static void dump_packet(const char *text, quadlet_t *data, int size) #define dump_packet(x,y,z) #endif +static void abort_requests(struct hpsb_host *host); static void queue_packet_complete(struct hpsb_packet *packet); @@ -512,6 +520,7 @@ int hpsb_send_packet(struct hpsb_packet *packet) if (!packet->no_waiter || packet->expect_response) { atomic_inc(&packet->refcnt); + packet->sendtime = jiffies; skb_queue_tail(&host->pending_packet_queue, packet->skb); } @@ -939,7 +948,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, } -void abort_requests(struct hpsb_host *host) +static void abort_requests(struct hpsb_host *host) { struct hpsb_packet *packet; struct sk_buff *skb; @@ -1002,7 +1011,7 @@ void abort_timedouts(unsigned long __opaque) * the stack. */ static int khpsbpkt_pid = -1, khpsbpkt_kill; static DECLARE_COMPLETION(khpsbpkt_complete); -struct sk_buff_head hpsbpkt_queue; +static struct sk_buff_head hpsbpkt_queue; static DECLARE_MUTEX_LOCKED(khpsbpkt_sig); @@ -1030,15 +1039,19 @@ static int hpsbpkt_thread(void *__hi) daemonize("khpsbpkt"); - while (!down_interruptible(&khpsbpkt_sig)) { - if (khpsbpkt_kill) + while (1) { + if (down_interruptible(&khpsbpkt_sig)) { + if (current->flags & PF_FREEZE) { + refrigerator(0); + continue; + } + printk("khpsbpkt: received unexpected signal?!\n" ); break; - - if (current->flags & PF_FREEZE) { - refrigerator(0); - continue; } + if (khpsbpkt_kill) + break; + while ((skb = skb_dequeue(&hpsbpkt_queue)) != NULL) { packet = (struct hpsb_packet *)skb->data; @@ -1054,7 +1067,6 @@ static int hpsbpkt_thread(void *__hi) complete_and_exit(&khpsbpkt_complete, 0); } - static int __init ieee1394_init(void) { int i, ret; @@ -1109,18 +1121,33 @@ static int __init ieee1394_init(void) if (ret < 0) goto release_all_bus; + hpsb_protocol_class = class_simple_create(THIS_MODULE, "ieee1394_protocol"); + if (IS_ERR(hpsb_protocol_class)) { + ret = PTR_ERR(hpsb_protocol_class); + goto release_class_host; + } + ret = init_csr(); if (ret) { HPSB_INFO("init csr failed"); ret = -ENOMEM; - goto release_class; + goto release_class_protocol; } if (disable_nodemgr) { - HPSB_INFO("nodemgr functionality disabled"); + HPSB_INFO("nodemgr and IRM functionality disabled"); + /* We shouldn't contend for IRM with nodemgr disabled, since + nodemgr implements functionality required of ieee1394a-2000 + IRMs */ + hpsb_disable_irm = 1; + return 0; } + if (hpsb_disable_irm) { + HPSB_INFO("IRM functionality disabled"); + } + ret = init_ieee1394_nodemgr(); if (ret < 0) { HPSB_INFO("init nodemgr failed"); @@ -1131,7 +1158,9 @@ static int __init ieee1394_init(void) cleanup_csr: cleanup_csr(); -release_class: +release_class_protocol: + class_simple_destroy(hpsb_protocol_class); +release_class_host: class_unregister(&hpsb_host_class); release_all_bus: for (i = 0; fw_bus_attrs[i]; i++) @@ -1160,6 +1189,7 @@ static void __exit ieee1394_cleanup(void) cleanup_csr(); + class_simple_destroy(hpsb_protocol_class); class_unregister(&hpsb_host_class); for (i = 0; fw_bus_attrs[i]; i++) bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); @@ -1191,6 +1221,7 @@ EXPORT_SYMBOL(hpsb_update_config_rom_image); /** ieee1394_core.c **/ EXPORT_SYMBOL(hpsb_speedto_str); +EXPORT_SYMBOL(hpsb_protocol_class); EXPORT_SYMBOL(hpsb_set_packet_complete_task); EXPORT_SYMBOL(hpsb_alloc_packet); EXPORT_SYMBOL(hpsb_free_packet); @@ -1203,6 +1234,7 @@ EXPORT_SYMBOL(hpsb_selfid_received); EXPORT_SYMBOL(hpsb_selfid_complete); EXPORT_SYMBOL(hpsb_packet_sent); EXPORT_SYMBOL(hpsb_packet_received); +EXPORT_SYMBOL_GPL(hpsb_disable_irm); /** ieee1394_transactions.c **/ EXPORT_SYMBOL(hpsb_get_tlabel); @@ -1217,8 +1249,6 @@ EXPORT_SYMBOL(hpsb_make_isopacket); EXPORT_SYMBOL(hpsb_read); EXPORT_SYMBOL(hpsb_write); EXPORT_SYMBOL(hpsb_lock); -EXPORT_SYMBOL(hpsb_lock64); -EXPORT_SYMBOL(hpsb_send_gasp); EXPORT_SYMBOL(hpsb_packet_success); /** highlevel.c **/ @@ -1230,28 +1260,18 @@ EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace); EXPORT_SYMBOL(hpsb_listen_channel); EXPORT_SYMBOL(hpsb_unlisten_channel); EXPORT_SYMBOL(hpsb_get_hostinfo); -EXPORT_SYMBOL(hpsb_get_host_bykey); EXPORT_SYMBOL(hpsb_create_hostinfo); EXPORT_SYMBOL(hpsb_destroy_hostinfo); EXPORT_SYMBOL(hpsb_set_hostinfo_key); -EXPORT_SYMBOL(hpsb_get_hostinfo_key); EXPORT_SYMBOL(hpsb_get_hostinfo_bykey); EXPORT_SYMBOL(hpsb_set_hostinfo); -EXPORT_SYMBOL(highlevel_read); -EXPORT_SYMBOL(highlevel_write); -EXPORT_SYMBOL(highlevel_lock); -EXPORT_SYMBOL(highlevel_lock64); EXPORT_SYMBOL(highlevel_add_host); EXPORT_SYMBOL(highlevel_remove_host); EXPORT_SYMBOL(highlevel_host_reset); /** nodemgr.c **/ -EXPORT_SYMBOL(hpsb_guid_get_entry); -EXPORT_SYMBOL(hpsb_nodeid_get_entry); EXPORT_SYMBOL(hpsb_node_fill_packet); -EXPORT_SYMBOL(hpsb_node_read); EXPORT_SYMBOL(hpsb_node_write); -EXPORT_SYMBOL(hpsb_node_lock); EXPORT_SYMBOL(hpsb_register_protocol); EXPORT_SYMBOL(hpsb_unregister_protocol); EXPORT_SYMBOL(ieee1394_bus_type); @@ -1295,27 +1315,14 @@ EXPORT_SYMBOL(hpsb_iso_recv_flush); EXPORT_SYMBOL(csr1212_create_csr); EXPORT_SYMBOL(csr1212_init_local_csr); EXPORT_SYMBOL(csr1212_new_immediate); -EXPORT_SYMBOL(csr1212_new_leaf); -EXPORT_SYMBOL(csr1212_new_csr_offset); EXPORT_SYMBOL(csr1212_new_directory); EXPORT_SYMBOL(csr1212_associate_keyval); EXPORT_SYMBOL(csr1212_attach_keyval_to_directory); -EXPORT_SYMBOL(csr1212_new_extended_immediate); -EXPORT_SYMBOL(csr1212_new_extended_leaf); -EXPORT_SYMBOL(csr1212_new_descriptor_leaf); -EXPORT_SYMBOL(csr1212_new_textual_descriptor_leaf); EXPORT_SYMBOL(csr1212_new_string_descriptor_leaf); -EXPORT_SYMBOL(csr1212_new_icon_descriptor_leaf); -EXPORT_SYMBOL(csr1212_new_modifiable_descriptor_leaf); -EXPORT_SYMBOL(csr1212_new_keyword_leaf); EXPORT_SYMBOL(csr1212_detach_keyval_from_directory); -EXPORT_SYMBOL(csr1212_disassociate_keyval); EXPORT_SYMBOL(csr1212_release_keyval); EXPORT_SYMBOL(csr1212_destroy_csr); EXPORT_SYMBOL(csr1212_read); -EXPORT_SYMBOL(csr1212_generate_positions); -EXPORT_SYMBOL(csr1212_generate_layout_order); -EXPORT_SYMBOL(csr1212_fill_cache); EXPORT_SYMBOL(csr1212_generate_csr_image); EXPORT_SYMBOL(csr1212_parse_keyval); EXPORT_SYMBOL(csr1212_parse_csr); diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index 8e4b62c23bd3f2175b858af59d130537fe377935..c4b4408e2e0506f1f21acb23402934de0af65f79 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -89,7 +89,6 @@ static inline struct hpsb_packet *driver_packet(struct list_head *l) } void abort_timedouts(unsigned long __opaque); -void abort_requests(struct hpsb_host *host); struct hpsb_packet *hpsb_alloc_packet(size_t data_size); void hpsb_free_packet(struct hpsb_packet *packet); @@ -219,9 +218,11 @@ static inline unsigned char ieee1394_file_to_instance(struct file *file) return file->f_dentry->d_inode->i_cindex; } +extern int hpsb_disable_irm; /* Our sysfs bus entry */ extern struct bus_type ieee1394_bus_type; extern struct class hpsb_host_class; +extern struct class_simple *hpsb_protocol_class; #endif /* _IEEE1394_CORE_H */ diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c index 60da23ba33ad0e93c717843d759a7958f0897987..09908b9564d8b944d5029f83b03f405846890fc4 100644 --- a/drivers/ieee1394/ieee1394_transactions.c +++ b/drivers/ieee1394/ieee1394_transactions.c @@ -566,34 +566,6 @@ int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation, return retval; } -int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation, - u64 addr, int extcode, octlet_t *data, octlet_t arg) -{ - struct hpsb_packet *packet; - int retval = 0; - - BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet - - packet = hpsb_make_lock64packet(host, node, addr, extcode, data, arg); - if (!packet) - return -ENOMEM; - - packet->generation = generation; - retval = hpsb_send_packet_and_wait(packet); - if (retval < 0) - goto hpsb_lock64_fail; - - retval = hpsb_packet_success(packet); - - if (retval == 0) - *data = (u64)packet->data[1] << 32 | packet->data[0]; - -hpsb_lock64_fail: - hpsb_free_tlabel(packet); - hpsb_free_packet(packet); - - return retval; -} int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation, quadlet_t *buffer, size_t length, u32 specifier_id, diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 21472e9bdfa678711f19c1528d1518cffb3d67f5..79ab0c97f6a2e3bf7d53aa1f25fb95ff867ef529 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -23,6 +23,7 @@ #include "ieee1394_types.h" #include "ieee1394.h" +#include "ieee1394_core.h" #include "hosts.h" #include "ieee1394_transactions.h" #include "highlevel.h" @@ -146,7 +147,7 @@ static void ne_cls_release(struct class_device *class_dev) put_device(&container_of((class_dev), struct node_entry, class_dev)->device); } -struct class nodemgr_ne_class = { +static struct class nodemgr_ne_class = { .name = "ieee1394_node", .release = ne_cls_release, }; @@ -158,7 +159,7 @@ static void ud_cls_release(struct class_device *class_dev) /* The name here is only so that unit directory hotplug works with old * style hotplug, which only ever did unit directories anyway. */ -struct class nodemgr_ud_class = { +static struct class nodemgr_ud_class = { .name = "ieee1394", .release = ud_cls_release, .hotplug = nodemgr_hotplug, @@ -831,6 +832,31 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t } +static void nodemgr_register_device(struct node_entry *ne, + struct unit_directory *ud, struct device *parent) +{ + memcpy(&ud->device, &nodemgr_dev_template_ud, + sizeof(ud->device)); + + ud->device.parent = parent; + + snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u", + ne->device.bus_id, ud->id); + + ud->class_dev.dev = &ud->device; + ud->class_dev.class = &nodemgr_ud_class; + snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u", + ne->device.bus_id, ud->id); + + device_register(&ud->device); + class_device_register(&ud->class_dev); + get_device(&ud->device); + + if (ud->vendor_oui) + device_create_file(&ud->device, &dev_attr_ud_vendor_oui); + nodemgr_create_ud_dev_files(ud); +} + /* This implementation currently only scans the config rom and its * immediate unit directories looking for software_id and @@ -840,7 +866,7 @@ static struct unit_directory *nodemgr_process_unit_directory unsigned int *id, struct unit_directory *parent) { struct unit_directory *ud; - struct unit_directory *ud_temp = NULL; + struct unit_directory *ud_child = NULL; struct csr1212_dentry *dentry; struct csr1212_keyval *kv; u8 last_key_id = 0; @@ -907,42 +933,61 @@ static struct unit_directory *nodemgr_process_unit_directory break; case CSR1212_KV_ID_DEPENDENT_INFO: - if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) { + /* Logical Unit Number */ + if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) { + if (ud->flags & UNIT_DIRECTORY_HAS_LUN) { + ud_child = kmalloc(sizeof(struct unit_directory), GFP_KERNEL); + if (!ud_child) + goto unit_directory_error; + memcpy(ud_child, ud, sizeof(struct unit_directory)); + nodemgr_register_device(ne, ud_child, &ne->device); + ud_child = NULL; + + ud->id = (*id)++; + } + ud->lun = kv->value.immediate; + ud->flags |= UNIT_DIRECTORY_HAS_LUN; + + /* Logical Unit Directory */ + } else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) { /* This should really be done in SBP2 as this is - * doing SBP2 specific parsing. */ + * doing SBP2 specific parsing. + */ + + /* first register the parent unit */ ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY; - ud_temp = nodemgr_process_unit_directory(hi, ne, kv, id, - parent); + if (ud->device.bus != &ieee1394_bus_type) + nodemgr_register_device(ne, ud, &ne->device); + + /* process the child unit */ + ud_child = nodemgr_process_unit_directory(hi, ne, kv, id, ud); - if (ud_temp == NULL) + if (ud_child == NULL) break; - - /* inherit unspecified values */ - if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) && - !(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID)) - { - ud_temp->flags |= UNIT_DIRECTORY_VENDOR_ID; - ud_temp->vendor_id = ud->vendor_id; - ud_temp->vendor_oui = ud->vendor_oui; - } + + /* inherit unspecified values so hotplug picks it up */ if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) && - !(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID)) + !(ud_child->flags & UNIT_DIRECTORY_MODEL_ID)) { - ud_temp->flags |= UNIT_DIRECTORY_MODEL_ID; - ud_temp->model_id = ud->model_id; + ud_child->flags |= UNIT_DIRECTORY_MODEL_ID; + ud_child->model_id = ud->model_id; } if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) && - !(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID)) + !(ud_child->flags & UNIT_DIRECTORY_SPECIFIER_ID)) { - ud_temp->flags |= UNIT_DIRECTORY_SPECIFIER_ID; - ud_temp->specifier_id = ud->specifier_id; + ud_child->flags |= UNIT_DIRECTORY_SPECIFIER_ID; + ud_child->specifier_id = ud->specifier_id; } if ((ud->flags & UNIT_DIRECTORY_VERSION) && - !(ud_temp->flags & UNIT_DIRECTORY_VERSION)) + !(ud_child->flags & UNIT_DIRECTORY_VERSION)) { - ud_temp->flags |= UNIT_DIRECTORY_VERSION; - ud_temp->version = ud->version; + ud_child->flags |= UNIT_DIRECTORY_VERSION; + ud_child->version = ud->version; } + + /* register the child unit */ + ud_child->flags |= UNIT_DIRECTORY_LUN_DIRECTORY; + nodemgr_register_device(ne, ud_child, &ud->device); } break; @@ -952,31 +997,10 @@ static struct unit_directory *nodemgr_process_unit_directory } last_key_id = kv->key.id; } - - memcpy(&ud->device, &nodemgr_dev_template_ud, - sizeof(ud->device)); - - if (parent) { - ud->flags |= UNIT_DIRECTORY_LUN_DIRECTORY; - ud->device.parent = &parent->device; - } else - ud->device.parent = &ne->device; - - snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u", - ne->device.bus_id, ud->id); - - ud->class_dev.dev = &ud->device; - ud->class_dev.class = &nodemgr_ud_class; - snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u", - ne->device.bus_id, ud->id); - - device_register(&ud->device); - class_device_register(&ud->class_dev); - get_device(&ud->device); - - if (ud->vendor_oui) - device_create_file(&ud->device, &dev_attr_ud_vendor_oui); - nodemgr_create_ud_dev_files(ud); + + /* do not process child units here and only if not already registered */ + if (!parent && ud->device.bus != &ieee1394_bus_type) + nodemgr_register_device(ne, ud, &ne->device); return ud; @@ -1141,6 +1165,13 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr, /* Mark the node as new, so it gets re-probed */ ne->needs_probe = 1; + } else { + /* old cache is valid, so update its generation */ + struct nodemgr_csr_info *ci = ne->csr->private; + ci->generation = generation; + /* free the partially filled now unneeded new cache */ + kfree(csr->private); + csr1212_destroy_csr(csr); } if (ne->in_limbo) @@ -1431,7 +1462,7 @@ static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles) quadlet_t bc; int status; - if (host->is_irm) + if (hpsb_disable_irm || host->is_irm) return 1; status = hpsb_read(host, LOCAL_BUS | (host->irm_id), @@ -1553,29 +1584,6 @@ static int nodemgr_host_thread(void *__hi) complete_and_exit(&hi->exited, 0); } -struct node_entry *hpsb_guid_get_entry(u64 guid) -{ - struct node_entry *ne; - - down(&nodemgr_serialize); - ne = find_entry_by_guid(guid); - up(&nodemgr_serialize); - - return ne; -} - -struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid) -{ - struct node_entry *ne; - - down(&nodemgr_serialize); - ne = find_entry_by_nodeid(host, nodeid); - up(&nodemgr_serialize); - - return ne; -} - - int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *)) { struct class *class = &hpsb_host_class; @@ -1618,16 +1626,6 @@ void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *pkt) pkt->node_id = ne->nodeid; } -int hpsb_node_read(struct node_entry *ne, u64 addr, - quadlet_t *buffer, size_t length) -{ - unsigned int generation = ne->generation; - - barrier(); - return hpsb_read(ne->host, ne->nodeid, generation, - addr, buffer, length); -} - int hpsb_node_write(struct node_entry *ne, u64 addr, quadlet_t *buffer, size_t length) { @@ -1638,16 +1636,6 @@ int hpsb_node_write(struct node_entry *ne, u64 addr, addr, buffer, length); } -int hpsb_node_lock(struct node_entry *ne, u64 addr, - int extcode, quadlet_t *data, quadlet_t arg) -{ - unsigned int generation = ne->generation; - - barrier(); - return hpsb_lock(ne->host, ne->nodeid, generation, - addr, extcode, data, arg); -} - static void nodemgr_add_host(struct hpsb_host *host) { struct host_info *hi; diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index f27ea3a257509346da6b6bfac37d716afcd861db..3a2f0c02fd081e679ebe50b32fc7e33ce405f730 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h @@ -51,6 +51,7 @@ struct bus_options { #define UNIT_DIRECTORY_VERSION 0x08 #define UNIT_DIRECTORY_HAS_LUN_DIRECTORY 0x10 #define UNIT_DIRECTORY_LUN_DIRECTORY 0x20 +#define UNIT_DIRECTORY_HAS_LUN 0x40 /* * A unit directory corresponds to a protocol supported by the @@ -82,6 +83,7 @@ struct unit_directory { struct class_device class_dev; struct csr1212_keyval *ud_kv; + u32 lun; /* logical unit number immediate value */ }; struct node_entry { diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 7c3f6e7bcdf70ff5400d64102cac7ebe1af7d2cc..11fbdaa0e5eca6227b36b0652414a1f891e40fe7 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -162,7 +162,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args) static char version[] __devinitdata = - "$Rev: 1223 $ Ben Collins <bcollins@debian.org>"; + "$Rev: 1250 $ Ben Collins <bcollins@debian.org>"; /* Module Parameters */ static int phys_dma = 1; @@ -482,7 +482,9 @@ static void ohci_initialize(struct ti_ohci *ohci) /* Put some defaults to these undefined bus options */ buf = reg_read(ohci, OHCI1394_BusOptions); - buf |= 0xE0000000; /* Enable IRMC, CMC and ISC */ + buf |= 0x60000000; /* Enable CMC and ISC */ + if (!hpsb_disable_irm) + buf |= 0x80000000; /* Enable IRMC */ buf &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */ buf &= ~0x18000000; /* Disable PMC and BMC */ reg_write(ohci, OHCI1394_BusOptions, buf); @@ -497,10 +499,12 @@ static void ohci_initialize(struct ti_ohci *ohci) reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); /* Enable cycle timer and cycle master and set the IRM - * contender bit in our self ID packets. */ - reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_CycleTimerEnable | + * contender bit in our self ID packets if appropriate. */ + reg_write(ohci, OHCI1394_LinkControlSet, + OHCI1394_LinkControl_CycleTimerEnable | OHCI1394_LinkControl_CycleMaster); - set_phy_reg_mask(ohci, 4, 0xc0); + set_phy_reg_mask(ohci, 4, PHY_04_LCTRL | + (hpsb_disable_irm ? 0 : PHY_04_CONTENDER)); /* Set up self-id dma buffer */ reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus); @@ -515,12 +519,6 @@ static void ohci_initialize(struct ti_ohci *ohci) /* Now get our max packet size */ ohci->max_packet_size = 1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1); - - if (ohci->max_packet_size < 512) { - HPSB_ERR("warning: Invalid max packet size of %d, setting to 512", - ohci->max_packet_size); - ohci->max_packet_size = 512; - } /* Don't accept phy packets into AR request context */ reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400); @@ -2545,6 +2543,10 @@ static void insert_dma_buffer(struct dma_rcv_ctx *d, int idx) idx = (idx + d->num_desc - 1 ) % d->num_desc; d->prg_cpu[idx]->branchAddress |= le32_to_cpu(0x00000001); + /* To avoid a race, ensure 1394 interface hardware sees the inserted + * context program descriptors before it sees the wakeup bit set. */ + wmb(); + /* wake up the dma context if necessary */ if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { PRINT(KERN_INFO, diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c index 4bd76bf7d479abadb20e4b37a715ffed79e9d706..76f4fda126126e9929d1f4006a972426f6d11912 100644 --- a/drivers/ieee1394/pcilynx.c +++ b/drivers/ieee1394/pcilynx.c @@ -384,7 +384,8 @@ static quadlet_t generate_own_selfid(struct ti_lynx *lynx, lsid = 0x80400000 | ((phyreg[0] & 0xfc) << 22); lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */ lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */ - lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */ + if (!hpsb_disable_irm) + lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */ /* lsid |= 1 << 11; *//* set contender (hack) */ lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */ @@ -500,7 +501,7 @@ static void send_next(struct ti_lynx *lynx, int what) pcl.async_error_next = PCL_NEXT_INVALID; pcl.pcl_status = 0; pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size; -#ifdef __BIG_ENDIAN +#ifndef __BIG_ENDIAN pcl.buffer[0].control |= PCL_BIGENDIAN; #endif pcl.buffer[0].pointer = d->header_dma; @@ -1521,10 +1522,6 @@ static int __devinit add_card(struct pci_dev *dev, int i; int error; - /* needed for i2c communication with serial eeprom */ - struct i2c_adapter i2c_adapter; - struct i2c_algo_bit_data i2c_adapter_data; - error = -ENXIO; if (pci_set_dma_mask(dev, 0xffffffff)) @@ -1697,7 +1694,7 @@ static int __devinit add_card(struct pci_dev *dev, pcl.async_error_next = PCL_NEXT_INVALID; pcl.buffer[0].control = PCL_CMD_RCV | 16; -#ifdef __BIG_ENDIAN +#ifndef __BIG_ENDIAN pcl.buffer[0].control |= PCL_BIGENDIAN; #endif pcl.buffer[1].control = PCL_LAST_BUFF | 4080; @@ -1779,26 +1776,40 @@ static int __devinit add_card(struct pci_dev *dev, | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN | LINK_CONTROL_RESET_TX | LINK_CONTROL_RESET_RX); - if (!lynx->phyic.reg_1394a) { - /* attempt to enable contender bit -FIXME- would this work - * elsewhere? */ - reg_set_bits(lynx, GPIO_CTRL_A, 0x1); - reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1); - } else { - /* set the contender and LCtrl bit in the extended PHY register - * set. (Should check that bis 0,1,2 (=0xE0) is set - * in register 2?) - */ - i = get_phy_reg(lynx, 4); - if (i != -1) set_phy_reg(lynx, 4, i | 0xc0); - } - - + if (!lynx->phyic.reg_1394a) { + if (!hpsb_disable_irm) { + /* attempt to enable contender bit -FIXME- would this + * work elsewhere? */ + reg_set_bits(lynx, GPIO_CTRL_A, 0x1); + reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1); + } + } else { + /* set the contender (if appropriate) and LCtrl bit in the + * extended PHY register set. (Should check that PHY_02_EXTENDED + * is set in register 2?) + */ + i = get_phy_reg(lynx, 4); + i |= PHY_04_LCTRL; + if (hpsb_disable_irm) + i &= !PHY_04_CONTENDER; + else + i |= PHY_04_CONTENDER; + if (i != -1) set_phy_reg(lynx, 4, i); + } + if (!skip_eeprom) { - i2c_adapter = bit_ops; + /* needed for i2c communication with serial eeprom */ + struct i2c_adapter *i2c_ad; + struct i2c_algo_bit_data i2c_adapter_data; + + error = -ENOMEM; + i2c_ad = kmalloc(sizeof(struct i2c_adapter), SLAB_KERNEL); + if (!i2c_ad) FAIL("failed to allocate I2C adapter memory"); + + memcpy(i2c_ad, &bit_ops, sizeof(struct i2c_adapter)); i2c_adapter_data = bit_data; - i2c_adapter.algo_data = &i2c_adapter_data; + i2c_ad->algo_data = &i2c_adapter_data; i2c_adapter_data.data = lynx; PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d", @@ -1808,8 +1819,9 @@ static int __devinit add_card(struct pci_dev *dev, lynx->i2c_driven_state = 0x00000070; reg_write(lynx, SERIAL_EEPROM_CONTROL, lynx->i2c_driven_state); - if (i2c_bit_add_bus(&i2c_adapter) < 0) + if (i2c_bit_add_bus(i2c_ad) < 0) { + kfree(i2c_ad); error = -ENXIO; FAIL("unable to register i2c"); } @@ -1825,13 +1837,13 @@ static int __devinit add_card(struct pci_dev *dev, #ifdef CONFIG_IEEE1394_VERBOSEDEBUG union i2c_smbus_data data; - if (i2c_smbus_xfer(&i2c_adapter, 80, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE,NULL)) + if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE,NULL)) PRINT(KERN_ERR, lynx->id,"eeprom read start has failed"); else { u16 addr; for (addr=0x00; addr < 0x100; addr++) { - if (i2c_smbus_xfer(&i2c_adapter, 80, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE,& data)) { + if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE,& data)) { PRINT(KERN_ERR, lynx->id, "unable to read i2c %x", addr); break; } @@ -1843,7 +1855,7 @@ static int __devinit add_card(struct pci_dev *dev, /* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we do it more efficiently in one transaction rather then using several reads */ - if (i2c_transfer(&i2c_adapter, msg, 2) < 0) { + if (i2c_transfer(i2c_ad, msg, 2) < 0) { PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c"); } else { int i; @@ -1863,13 +1875,15 @@ static int __devinit add_card(struct pci_dev *dev, { PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from"); } else { + kfree(i2c_ad); error = -ENXIO; FAIL("read something from serial eeprom, but it does not seem to be a valid bus info block"); } } - i2c_bit_del_bus(&i2c_adapter); + i2c_bit_del_bus(i2c_ad); + kfree(i2c_ad); } } diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 674dd23e55857e0558558d086ae4410bb2c9e156..f6fda042bb656f3c05b5ebd27cbd35ddbebae505 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -75,58 +75,60 @@ static DEFINE_SPINLOCK(host_info_lock); static atomic_t internal_generation = ATOMIC_INIT(0); static atomic_t iso_buffer_size; -static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */ +static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */ static struct hpsb_highlevel raw1394_highlevel; -static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, size_t length, u16 flags); -static int arm_write (struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, size_t length, u16 flags); -static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags); -static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags); +static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, + u64 addr, size_t length, u16 flags); +static int arm_write(struct hpsb_host *host, int nodeid, int destid, + quadlet_t * data, u64 addr, size_t length, u16 flags); +static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, + u16 flags); +static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, + u16 flags); static struct hpsb_address_ops arm_ops = { - .read = arm_read, - .write = arm_write, - .lock = arm_lock, - .lock64 = arm_lock64, + .read = arm_read, + .write = arm_write, + .lock = arm_lock, + .lock64 = arm_lock64, }; static void queue_complete_cb(struct pending_request *req); static struct pending_request *__alloc_pending_request(int flags) { - struct pending_request *req; + struct pending_request *req; - req = (struct pending_request *)kmalloc(sizeof(struct pending_request), - flags); - if (req != NULL) { - memset(req, 0, sizeof(struct pending_request)); - INIT_LIST_HEAD(&req->list); - } + req = (struct pending_request *)kmalloc(sizeof(struct pending_request), + flags); + if (req != NULL) { + memset(req, 0, sizeof(struct pending_request)); + INIT_LIST_HEAD(&req->list); + } - return req; + return req; } static inline struct pending_request *alloc_pending_request(void) { - return __alloc_pending_request(SLAB_KERNEL); + return __alloc_pending_request(SLAB_KERNEL); } static void free_pending_request(struct pending_request *req) { - if (req->ibs) { - if (atomic_dec_and_test(&req->ibs->refcount)) { - atomic_sub(req->ibs->data_size, &iso_buffer_size); - kfree(req->ibs); - } - } else if (req->free_data) { - kfree(req->data); - } - hpsb_free_packet(req->packet); - kfree(req); + if (req->ibs) { + if (atomic_dec_and_test(&req->ibs->refcount)) { + atomic_sub(req->ibs->data_size, &iso_buffer_size); + kfree(req->ibs); + } + } else if (req->free_data) { + kfree(req->data); + } + hpsb_free_packet(req->packet); + kfree(req); } /* fi->reqlists_lock must be taken */ @@ -134,494 +136,505 @@ static void __queue_complete_req(struct pending_request *req) { struct file_info *fi = req->file_info; list_del(&req->list); - list_add_tail(&req->list, &fi->req_complete); + list_add_tail(&req->list, &fi->req_complete); up(&fi->complete_sem); - wake_up_interruptible(&fi->poll_wait_complete); + wake_up_interruptible(&fi->poll_wait_complete); } static void queue_complete_req(struct pending_request *req) { - unsigned long flags; - struct file_info *fi = req->file_info; + unsigned long flags; + struct file_info *fi = req->file_info; - spin_lock_irqsave(&fi->reqlists_lock, flags); + spin_lock_irqsave(&fi->reqlists_lock, flags); __queue_complete_req(req); - spin_unlock_irqrestore(&fi->reqlists_lock, flags); + spin_unlock_irqrestore(&fi->reqlists_lock, flags); } static void queue_complete_cb(struct pending_request *req) { - struct hpsb_packet *packet = req->packet; - int rcode = (packet->header[1] >> 12) & 0xf; - - switch (packet->ack_code) { - case ACKX_NONE: - case ACKX_SEND_ERROR: - req->req.error = RAW1394_ERROR_SEND_ERROR; - break; - case ACKX_ABORTED: - req->req.error = RAW1394_ERROR_ABORTED; - break; - case ACKX_TIMEOUT: - req->req.error = RAW1394_ERROR_TIMEOUT; - break; - default: - req->req.error = (packet->ack_code << 16) | rcode; - break; - } - - if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) { - req->req.length = 0; - } - - if ((req->req.type == RAW1394_REQ_ASYNC_READ) || + struct hpsb_packet *packet = req->packet; + int rcode = (packet->header[1] >> 12) & 0xf; + + switch (packet->ack_code) { + case ACKX_NONE: + case ACKX_SEND_ERROR: + req->req.error = RAW1394_ERROR_SEND_ERROR; + break; + case ACKX_ABORTED: + req->req.error = RAW1394_ERROR_ABORTED; + break; + case ACKX_TIMEOUT: + req->req.error = RAW1394_ERROR_TIMEOUT; + break; + default: + req->req.error = (packet->ack_code << 16) | rcode; + break; + } + + if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) { + req->req.length = 0; + } + + if ((req->req.type == RAW1394_REQ_ASYNC_READ) || (req->req.type == RAW1394_REQ_ASYNC_WRITE) || (req->req.type == RAW1394_REQ_ASYNC_STREAM) || (req->req.type == RAW1394_REQ_LOCK) || (req->req.type == RAW1394_REQ_LOCK64)) - hpsb_free_tlabel(packet); + hpsb_free_tlabel(packet); - queue_complete_req(req); + queue_complete_req(req); } - static void add_host(struct hpsb_host *host) { - struct host_info *hi; - unsigned long flags; - - hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL); + struct host_info *hi; + unsigned long flags; - if (hi != NULL) { - INIT_LIST_HEAD(&hi->list); - hi->host = host; - INIT_LIST_HEAD(&hi->file_info_list); + hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL); - spin_lock_irqsave(&host_info_lock, flags); - list_add_tail(&hi->list, &host_info_list); - host_count++; - spin_unlock_irqrestore(&host_info_lock, flags); - } + if (hi != NULL) { + INIT_LIST_HEAD(&hi->list); + hi->host = host; + INIT_LIST_HEAD(&hi->file_info_list); + + spin_lock_irqsave(&host_info_lock, flags); + list_add_tail(&hi->list, &host_info_list); + host_count++; + spin_unlock_irqrestore(&host_info_lock, flags); + } - atomic_inc(&internal_generation); + atomic_inc(&internal_generation); } - static struct host_info *find_host_info(struct hpsb_host *host) { - struct host_info *hi; + struct host_info *hi; - list_for_each_entry(hi, &host_info_list, list) - if (hi->host == host) - return hi; + list_for_each_entry(hi, &host_info_list, list) + if (hi->host == host) + return hi; - return NULL; + return NULL; } static void remove_host(struct hpsb_host *host) { - struct host_info *hi; - unsigned long flags; - - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(host); - - if (hi != NULL) { - list_del(&hi->list); - host_count--; - /* - FIXME: address ranges should be removed - and fileinfo states should be initialized - (including setting generation to - internal-generation ...) - */ - } - spin_unlock_irqrestore(&host_info_lock, flags); - - if (hi == NULL) { - printk(KERN_ERR "raw1394: attempt to remove unknown host " - "0x%p\n", host); - return; - } - - kfree(hi); - - atomic_inc(&internal_generation); + struct host_info *hi; + unsigned long flags; + + spin_lock_irqsave(&host_info_lock, flags); + hi = find_host_info(host); + + if (hi != NULL) { + list_del(&hi->list); + host_count--; + /* + FIXME: address ranges should be removed + and fileinfo states should be initialized + (including setting generation to + internal-generation ...) + */ + } + spin_unlock_irqrestore(&host_info_lock, flags); + + if (hi == NULL) { + printk(KERN_ERR "raw1394: attempt to remove unknown host " + "0x%p\n", host); + return; + } + + kfree(hi); + + atomic_inc(&internal_generation); } static void host_reset(struct hpsb_host *host) { - unsigned long flags; - struct host_info *hi; - struct file_info *fi; - struct pending_request *req; - - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(host); - - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - if (fi->notification == RAW1394_NOTIFY_ON) { - req = __alloc_pending_request(SLAB_ATOMIC); - - if (req != NULL) { - req->file_info = fi; - req->req.type = RAW1394_REQ_BUS_RESET; - req->req.generation = get_hpsb_generation(host); - req->req.misc = (host->node_id << 16) - | host->node_count; - if (fi->protocol_version > 3) { - req->req.misc |= (NODEID_TO_NODE(host->irm_id) - << 8); - } - - queue_complete_req(req); - } - } - } - } - spin_unlock_irqrestore(&host_info_lock, flags); + unsigned long flags; + struct host_info *hi; + struct file_info *fi; + struct pending_request *req; + + spin_lock_irqsave(&host_info_lock, flags); + hi = find_host_info(host); + + if (hi != NULL) { + list_for_each_entry(fi, &hi->file_info_list, list) { + if (fi->notification == RAW1394_NOTIFY_ON) { + req = __alloc_pending_request(SLAB_ATOMIC); + + if (req != NULL) { + req->file_info = fi; + req->req.type = RAW1394_REQ_BUS_RESET; + req->req.generation = + get_hpsb_generation(host); + req->req.misc = (host->node_id << 16) + | host->node_count; + if (fi->protocol_version > 3) { + req->req.misc |= + (NODEID_TO_NODE + (host->irm_id) + << 8); + } + + queue_complete_req(req); + } + } + } + } + spin_unlock_irqrestore(&host_info_lock, flags); } -static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data, - size_t length) +static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data, + size_t length) { - unsigned long flags; - struct host_info *hi; - struct file_info *fi; - struct pending_request *req, *req_next; - struct iso_block_store *ibs = NULL; - LIST_HEAD(reqs); - - if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) { - HPSB_INFO("dropped iso packet"); - return; - } - - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(host); - - if (hi != NULL) { + unsigned long flags; + struct host_info *hi; + struct file_info *fi; + struct pending_request *req, *req_next; + struct iso_block_store *ibs = NULL; + LIST_HEAD(reqs); + + if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) { + HPSB_INFO("dropped iso packet"); + return; + } + + spin_lock_irqsave(&host_info_lock, flags); + hi = find_host_info(host); + + if (hi != NULL) { list_for_each_entry(fi, &hi->file_info_list, list) { - if (!(fi->listen_channels & (1ULL << channel))) - continue; - - req = __alloc_pending_request(SLAB_ATOMIC); - if (!req) break; - - if (!ibs) { - ibs = kmalloc(sizeof(struct iso_block_store) - + length, SLAB_ATOMIC); - if (!ibs) { - kfree(req); - break; - } - - atomic_add(length, &iso_buffer_size); - atomic_set(&ibs->refcount, 0); - ibs->data_size = length; - memcpy(ibs->data, data, length); - } - - atomic_inc(&ibs->refcount); - - req->file_info = fi; - req->ibs = ibs; - req->data = ibs->data; - req->req.type = RAW1394_REQ_ISO_RECEIVE; - req->req.generation = get_hpsb_generation(host); - req->req.misc = 0; - req->req.recvb = ptr2int(fi->iso_buffer); - req->req.length = min(length, fi->iso_buffer_length); - - list_add_tail(&req->list, &reqs); - } - } - spin_unlock_irqrestore(&host_info_lock, flags); + if (!(fi->listen_channels & (1ULL << channel))) + continue; + + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) + break; + + if (!ibs) { + ibs = kmalloc(sizeof(struct iso_block_store) + + length, SLAB_ATOMIC); + if (!ibs) { + kfree(req); + break; + } + + atomic_add(length, &iso_buffer_size); + atomic_set(&ibs->refcount, 0); + ibs->data_size = length; + memcpy(ibs->data, data, length); + } + + atomic_inc(&ibs->refcount); + + req->file_info = fi; + req->ibs = ibs; + req->data = ibs->data; + req->req.type = RAW1394_REQ_ISO_RECEIVE; + req->req.generation = get_hpsb_generation(host); + req->req.misc = 0; + req->req.recvb = ptr2int(fi->iso_buffer); + req->req.length = min(length, fi->iso_buffer_length); + + list_add_tail(&req->list, &reqs); + } + } + spin_unlock_irqrestore(&host_info_lock, flags); list_for_each_entry_safe(req, req_next, &reqs, list) - queue_complete_req(req); + queue_complete_req(req); } static void fcp_request(struct hpsb_host *host, int nodeid, int direction, - int cts, u8 *data, size_t length) + int cts, u8 * data, size_t length) { - unsigned long flags; - struct host_info *hi; - struct file_info *fi; - struct pending_request *req, *req_next; - struct iso_block_store *ibs = NULL; - LIST_HEAD(reqs); - - if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) { - HPSB_INFO("dropped fcp request"); - return; - } - - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(host); - - if (hi != NULL) { + unsigned long flags; + struct host_info *hi; + struct file_info *fi; + struct pending_request *req, *req_next; + struct iso_block_store *ibs = NULL; + LIST_HEAD(reqs); + + if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) { + HPSB_INFO("dropped fcp request"); + return; + } + + spin_lock_irqsave(&host_info_lock, flags); + hi = find_host_info(host); + + if (hi != NULL) { list_for_each_entry(fi, &hi->file_info_list, list) { - if (!fi->fcp_buffer) - continue; - - req = __alloc_pending_request(SLAB_ATOMIC); - if (!req) break; - - if (!ibs) { - ibs = kmalloc(sizeof(struct iso_block_store) - + length, SLAB_ATOMIC); - if (!ibs) { - kfree(req); - break; - } - - atomic_add(length, &iso_buffer_size); - atomic_set(&ibs->refcount, 0); - ibs->data_size = length; - memcpy(ibs->data, data, length); - } - - atomic_inc(&ibs->refcount); - - req->file_info = fi; - req->ibs = ibs; - req->data = ibs->data; - req->req.type = RAW1394_REQ_FCP_REQUEST; - req->req.generation = get_hpsb_generation(host); - req->req.misc = nodeid | (direction << 16); - req->req.recvb = ptr2int(fi->fcp_buffer); - req->req.length = length; - - list_add_tail(&req->list, &reqs); - } - } - spin_unlock_irqrestore(&host_info_lock, flags); + if (!fi->fcp_buffer) + continue; + + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) + break; + + if (!ibs) { + ibs = kmalloc(sizeof(struct iso_block_store) + + length, SLAB_ATOMIC); + if (!ibs) { + kfree(req); + break; + } + + atomic_add(length, &iso_buffer_size); + atomic_set(&ibs->refcount, 0); + ibs->data_size = length; + memcpy(ibs->data, data, length); + } + + atomic_inc(&ibs->refcount); + + req->file_info = fi; + req->ibs = ibs; + req->data = ibs->data; + req->req.type = RAW1394_REQ_FCP_REQUEST; + req->req.generation = get_hpsb_generation(host); + req->req.misc = nodeid | (direction << 16); + req->req.recvb = ptr2int(fi->fcp_buffer); + req->req.length = length; + + list_add_tail(&req->list, &reqs); + } + } + spin_unlock_irqrestore(&host_info_lock, flags); list_for_each_entry_safe(req, req_next, &reqs, list) - queue_complete_req(req); + queue_complete_req(req); } - -static ssize_t raw1394_read(struct file *file, char __user *buffer, size_t count, - loff_t *offset_is_ignored) +static ssize_t raw1394_read(struct file *file, char __user * buffer, + size_t count, loff_t * offset_is_ignored) { - struct file_info *fi = (struct file_info *)file->private_data; - struct list_head *lh; - struct pending_request *req; - - if (count != sizeof(struct raw1394_request)) { - return -EINVAL; - } - - if (!access_ok(VERIFY_WRITE, buffer, count)) { - return -EFAULT; - } - - if (file->f_flags & O_NONBLOCK) { - if (down_trylock(&fi->complete_sem)) { - return -EAGAIN; - } - } else { - if (down_interruptible(&fi->complete_sem)) { - return -ERESTARTSYS; - } - } - - spin_lock_irq(&fi->reqlists_lock); - lh = fi->req_complete.next; - list_del(lh); - spin_unlock_irq(&fi->reqlists_lock); - - req = list_entry(lh, struct pending_request, list); - - if (req->req.length) { - if (copy_to_user(int2ptr(req->req.recvb), req->data, - req->req.length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - } - } - __copy_to_user(buffer, &req->req, sizeof(req->req)); - - free_pending_request(req); - return sizeof(struct raw1394_request); -} + struct file_info *fi = (struct file_info *)file->private_data; + struct list_head *lh; + struct pending_request *req; + ssize_t ret; + + if (count != sizeof(struct raw1394_request)) { + return -EINVAL; + } + + if (!access_ok(VERIFY_WRITE, buffer, count)) { + return -EFAULT; + } + + if (file->f_flags & O_NONBLOCK) { + if (down_trylock(&fi->complete_sem)) { + return -EAGAIN; + } + } else { + if (down_interruptible(&fi->complete_sem)) { + return -ERESTARTSYS; + } + } + + spin_lock_irq(&fi->reqlists_lock); + lh = fi->req_complete.next; + list_del(lh); + spin_unlock_irq(&fi->reqlists_lock); + + req = list_entry(lh, struct pending_request, list); + + if (req->req.length) { + if (copy_to_user(int2ptr(req->req.recvb), req->data, + req->req.length)) { + req->req.error = RAW1394_ERROR_MEMFAULT; + } + } + if (copy_to_user(buffer, &req->req, sizeof(req->req))) { + ret = -EFAULT; + goto out; + } + ret = (ssize_t) sizeof(struct raw1394_request); + out: + free_pending_request(req); + return ret; +} static int state_opened(struct file_info *fi, struct pending_request *req) { - if (req->req.type == RAW1394_REQ_INITIALIZE) { - switch (req->req.misc) { - case RAW1394_KERNELAPI_VERSION: - case 3: - fi->state = initialized; - fi->protocol_version = req->req.misc; - req->req.error = RAW1394_ERROR_NONE; - req->req.generation = atomic_read(&internal_generation); - break; - - default: - req->req.error = RAW1394_ERROR_COMPAT; - req->req.misc = RAW1394_KERNELAPI_VERSION; - } - } else { - req->req.error = RAW1394_ERROR_STATE_ORDER; - } - - req->req.length = 0; - queue_complete_req(req); - return sizeof(struct raw1394_request); + if (req->req.type == RAW1394_REQ_INITIALIZE) { + switch (req->req.misc) { + case RAW1394_KERNELAPI_VERSION: + case 3: + fi->state = initialized; + fi->protocol_version = req->req.misc; + req->req.error = RAW1394_ERROR_NONE; + req->req.generation = atomic_read(&internal_generation); + break; + + default: + req->req.error = RAW1394_ERROR_COMPAT; + req->req.misc = RAW1394_KERNELAPI_VERSION; + } + } else { + req->req.error = RAW1394_ERROR_STATE_ORDER; + } + + req->req.length = 0; + queue_complete_req(req); + return sizeof(struct raw1394_request); } static int state_initialized(struct file_info *fi, struct pending_request *req) { - struct host_info *hi; - struct raw1394_khost_list *khl; - - if (req->req.generation != atomic_read(&internal_generation)) { - req->req.error = RAW1394_ERROR_GENERATION; - req->req.generation = atomic_read(&internal_generation); - req->req.length = 0; - queue_complete_req(req); - return sizeof(struct raw1394_request); - } - - switch (req->req.type) { - case RAW1394_REQ_LIST_CARDS: - spin_lock_irq(&host_info_lock); - khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count, - SLAB_ATOMIC); - - if (khl != NULL) { - req->req.misc = host_count; - req->data = (quadlet_t *)khl; - - list_for_each_entry(hi, &host_info_list, list) { - khl->nodes = hi->host->node_count; - strcpy(khl->name, hi->host->driver->name); - khl++; - } - } - spin_unlock_irq(&host_info_lock); - - if (khl != NULL) { - req->req.error = RAW1394_ERROR_NONE; - req->req.length = min(req->req.length, - (u32)(sizeof(struct raw1394_khost_list) - * req->req.misc)); - req->free_data = 1; - } else { - return -ENOMEM; - } - break; - - case RAW1394_REQ_SET_CARD: - spin_lock_irq(&host_info_lock); - if (req->req.misc < host_count) { + struct host_info *hi; + struct raw1394_khost_list *khl; + + if (req->req.generation != atomic_read(&internal_generation)) { + req->req.error = RAW1394_ERROR_GENERATION; + req->req.generation = atomic_read(&internal_generation); + req->req.length = 0; + queue_complete_req(req); + return sizeof(struct raw1394_request); + } + + switch (req->req.type) { + case RAW1394_REQ_LIST_CARDS: + spin_lock_irq(&host_info_lock); + khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count, + SLAB_ATOMIC); + + if (khl != NULL) { + req->req.misc = host_count; + req->data = (quadlet_t *) khl; + + list_for_each_entry(hi, &host_info_list, list) { + khl->nodes = hi->host->node_count; + strcpy(khl->name, hi->host->driver->name); + khl++; + } + } + spin_unlock_irq(&host_info_lock); + + if (khl != NULL) { + req->req.error = RAW1394_ERROR_NONE; + req->req.length = min(req->req.length, + (u32) (sizeof + (struct raw1394_khost_list) + * req->req.misc)); + req->free_data = 1; + } else { + return -ENOMEM; + } + break; + + case RAW1394_REQ_SET_CARD: + spin_lock_irq(&host_info_lock); + if (req->req.misc < host_count) { list_for_each_entry(hi, &host_info_list, list) { if (!req->req.misc--) break; } - get_device(&hi->host->device); // XXX Need to handle failure case - list_add_tail(&fi->list, &hi->file_info_list); - fi->host = hi->host; - fi->state = connected; - - req->req.error = RAW1394_ERROR_NONE; - req->req.generation = get_hpsb_generation(fi->host); - req->req.misc = (fi->host->node_id << 16) - | fi->host->node_count; - if (fi->protocol_version > 3) { - req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8; - } - } else { - req->req.error = RAW1394_ERROR_INVALID_ARG; - } + get_device(&hi->host->device); // XXX Need to handle failure case + list_add_tail(&fi->list, &hi->file_info_list); + fi->host = hi->host; + fi->state = connected; + + req->req.error = RAW1394_ERROR_NONE; + req->req.generation = get_hpsb_generation(fi->host); + req->req.misc = (fi->host->node_id << 16) + | fi->host->node_count; + if (fi->protocol_version > 3) { + req->req.misc |= + NODEID_TO_NODE(fi->host->irm_id) << 8; + } + } else { + req->req.error = RAW1394_ERROR_INVALID_ARG; + } spin_unlock_irq(&host_info_lock); - req->req.length = 0; - break; + req->req.length = 0; + break; - default: - req->req.error = RAW1394_ERROR_STATE_ORDER; - req->req.length = 0; - break; - } + default: + req->req.error = RAW1394_ERROR_STATE_ORDER; + req->req.length = 0; + break; + } - queue_complete_req(req); - return sizeof(struct raw1394_request); + queue_complete_req(req); + return sizeof(struct raw1394_request); } static void handle_iso_listen(struct file_info *fi, struct pending_request *req) { - int channel = req->req.misc; - - spin_lock_irq(&host_info_lock); - if ((channel > 63) || (channel < -64)) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - } else if (channel >= 0) { - /* allocate channel req.misc */ - if (fi->listen_channels & (1ULL << channel)) { - req->req.error = RAW1394_ERROR_ALREADY; - } else { - if (hpsb_listen_channel(&raw1394_highlevel, fi->host, channel)) { + int channel = req->req.misc; + + spin_lock_irq(&host_info_lock); + if ((channel > 63) || (channel < -64)) { + req->req.error = RAW1394_ERROR_INVALID_ARG; + } else if (channel >= 0) { + /* allocate channel req.misc */ + if (fi->listen_channels & (1ULL << channel)) { + req->req.error = RAW1394_ERROR_ALREADY; + } else { + if (hpsb_listen_channel + (&raw1394_highlevel, fi->host, channel)) { req->req.error = RAW1394_ERROR_ALREADY; } else { fi->listen_channels |= 1ULL << channel; fi->iso_buffer = int2ptr(req->req.recvb); fi->iso_buffer_length = req->req.length; } - } - } else { - /* deallocate channel (one's complement neg) req.misc */ - channel = ~channel; - - if (fi->listen_channels & (1ULL << channel)) { - hpsb_unlisten_channel(&raw1394_highlevel, fi->host, channel); - fi->listen_channels &= ~(1ULL << channel); - } else { - req->req.error = RAW1394_ERROR_INVALID_ARG; - } - } - - req->req.length = 0; - queue_complete_req(req); - spin_unlock_irq(&host_info_lock); + } + } else { + /* deallocate channel (one's complement neg) req.misc */ + channel = ~channel; + + if (fi->listen_channels & (1ULL << channel)) { + hpsb_unlisten_channel(&raw1394_highlevel, fi->host, + channel); + fi->listen_channels &= ~(1ULL << channel); + } else { + req->req.error = RAW1394_ERROR_INVALID_ARG; + } + } + + req->req.length = 0; + queue_complete_req(req); + spin_unlock_irq(&host_info_lock); } static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) { - if (req->req.misc) { - if (fi->fcp_buffer) { - req->req.error = RAW1394_ERROR_ALREADY; - } else { - fi->fcp_buffer = int2ptr(req->req.recvb); - } - } else { - if (!fi->fcp_buffer) { - req->req.error = RAW1394_ERROR_ALREADY; - } else { - fi->fcp_buffer = NULL; - } - } - - req->req.length = 0; - queue_complete_req(req); -} + if (req->req.misc) { + if (fi->fcp_buffer) { + req->req.error = RAW1394_ERROR_ALREADY; + } else { + fi->fcp_buffer = int2ptr(req->req.recvb); + } + } else { + if (!fi->fcp_buffer) { + req->req.error = RAW1394_ERROR_ALREADY; + } else { + fi->fcp_buffer = NULL; + } + } + req->req.length = 0; + queue_complete_req(req); +} static int handle_async_request(struct file_info *fi, - struct pending_request *req, int node) + struct pending_request *req, int node) { - struct hpsb_packet *packet = NULL; - u64 addr = req->req.address & 0xffffffffffffULL; + struct hpsb_packet *packet = NULL; + u64 addr = req->req.address & 0xffffffffffffULL; - switch (req->req.type) { - case RAW1394_REQ_ASYNC_READ: + switch (req->req.type) { + case RAW1394_REQ_ASYNC_READ: DBGMSG("read_request called"); - packet = hpsb_make_readpacket(fi->host, node, addr, req->req.length); + packet = + hpsb_make_readpacket(fi->host, node, addr, req->req.length); if (!packet) return -ENOMEM; @@ -631,7 +644,7 @@ static int handle_async_request(struct file_info *fi, else req->data = packet->data; - break; + break; case RAW1394_REQ_ASYNC_WRITE: DBGMSG("write_request called"); @@ -642,1105 +655,1207 @@ static int handle_async_request(struct file_info *fi, return -ENOMEM; if (req->req.length == 4) { - if (copy_from_user(&packet->header[3], int2ptr(req->req.sendb), - req->req.length)) + if (copy_from_user + (&packet->header[3], int2ptr(req->req.sendb), + req->req.length)) req->req.error = RAW1394_ERROR_MEMFAULT; } else { - if (copy_from_user(packet->data, int2ptr(req->req.sendb), - req->req.length)) + if (copy_from_user + (packet->data, int2ptr(req->req.sendb), + req->req.length)) req->req.error = RAW1394_ERROR_MEMFAULT; } req->req.length = 0; - break; + break; case RAW1394_REQ_ASYNC_STREAM: DBGMSG("stream_request called"); - packet = hpsb_make_streampacket(fi->host, NULL, req->req.length, node & 0x3f/*channel*/, - (req->req.misc >> 16) & 0x3, req->req.misc & 0xf); + packet = + hpsb_make_streampacket(fi->host, NULL, req->req.length, + node & 0x3f /*channel */ , + (req->req.misc >> 16) & 0x3, + req->req.misc & 0xf); if (!packet) return -ENOMEM; if (copy_from_user(packet->data, int2ptr(req->req.sendb), - req->req.length)) + req->req.length)) req->req.error = RAW1394_ERROR_MEMFAULT; req->req.length = 0; break; - case RAW1394_REQ_LOCK: - DBGMSG("lock_request called"); - if ((req->req.misc == EXTCODE_FETCH_ADD) - || (req->req.misc == EXTCODE_LITTLE_ADD)) { - if (req->req.length != 4) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - break; - } - } else { - if (req->req.length != 8) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - break; - } - } - - packet = hpsb_make_lockpacket(fi->host, node, addr, - req->req.misc, NULL, 0); - if (!packet) return -ENOMEM; - - if (copy_from_user(packet->data, int2ptr(req->req.sendb), - req->req.length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - break; - } - - req->data = packet->data; - req->req.length = 4; - break; - - case RAW1394_REQ_LOCK64: - DBGMSG("lock64_request called"); - if ((req->req.misc == EXTCODE_FETCH_ADD) - || (req->req.misc == EXTCODE_LITTLE_ADD)) { - if (req->req.length != 8) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - break; - } - } else { - if (req->req.length != 16) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - break; - } - } - packet = hpsb_make_lock64packet(fi->host, node, addr, - req->req.misc, NULL, 0); - if (!packet) return -ENOMEM; - - if (copy_from_user(packet->data, int2ptr(req->req.sendb), - req->req.length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - break; - } - - req->data = packet->data; - req->req.length = 8; - break; - - default: - req->req.error = RAW1394_ERROR_STATE_ORDER; - } - - req->packet = packet; - - if (req->req.error) { - req->req.length = 0; - queue_complete_req(req); - return sizeof(struct raw1394_request); - } - - hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req); - - spin_lock_irq(&fi->reqlists_lock); - list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irq(&fi->reqlists_lock); + case RAW1394_REQ_LOCK: + DBGMSG("lock_request called"); + if ((req->req.misc == EXTCODE_FETCH_ADD) + || (req->req.misc == EXTCODE_LITTLE_ADD)) { + if (req->req.length != 4) { + req->req.error = RAW1394_ERROR_INVALID_ARG; + break; + } + } else { + if (req->req.length != 8) { + req->req.error = RAW1394_ERROR_INVALID_ARG; + break; + } + } + + packet = hpsb_make_lockpacket(fi->host, node, addr, + req->req.misc, NULL, 0); + if (!packet) + return -ENOMEM; + + if (copy_from_user(packet->data, int2ptr(req->req.sendb), + req->req.length)) { + req->req.error = RAW1394_ERROR_MEMFAULT; + break; + } + + req->data = packet->data; + req->req.length = 4; + break; + + case RAW1394_REQ_LOCK64: + DBGMSG("lock64_request called"); + if ((req->req.misc == EXTCODE_FETCH_ADD) + || (req->req.misc == EXTCODE_LITTLE_ADD)) { + if (req->req.length != 8) { + req->req.error = RAW1394_ERROR_INVALID_ARG; + break; + } + } else { + if (req->req.length != 16) { + req->req.error = RAW1394_ERROR_INVALID_ARG; + break; + } + } + packet = hpsb_make_lock64packet(fi->host, node, addr, + req->req.misc, NULL, 0); + if (!packet) + return -ENOMEM; + + if (copy_from_user(packet->data, int2ptr(req->req.sendb), + req->req.length)) { + req->req.error = RAW1394_ERROR_MEMFAULT; + break; + } + + req->data = packet->data; + req->req.length = 8; + break; + + default: + req->req.error = RAW1394_ERROR_STATE_ORDER; + } + + req->packet = packet; + + if (req->req.error) { + req->req.length = 0; + queue_complete_req(req); + return sizeof(struct raw1394_request); + } + + hpsb_set_packet_complete_task(packet, + (void (*)(void *))queue_complete_cb, req); + + spin_lock_irq(&fi->reqlists_lock); + list_add_tail(&req->list, &fi->req_pending); + spin_unlock_irq(&fi->reqlists_lock); packet->generation = req->req.generation; - if (hpsb_send_packet(packet) < 0) { - req->req.error = RAW1394_ERROR_SEND_ERROR; - req->req.length = 0; - hpsb_free_tlabel(packet); - queue_complete_req(req); - } - return sizeof(struct raw1394_request); + if (hpsb_send_packet(packet) < 0) { + req->req.error = RAW1394_ERROR_SEND_ERROR; + req->req.length = 0; + hpsb_free_tlabel(packet); + queue_complete_req(req); + } + return sizeof(struct raw1394_request); } static int handle_iso_send(struct file_info *fi, struct pending_request *req, - int channel) + int channel) { - struct hpsb_packet *packet; + struct hpsb_packet *packet; packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f, - (req->req.misc >> 16) & 0x3, req->req.misc & 0xf); + (req->req.misc >> 16) & 0x3, + req->req.misc & 0xf); if (!packet) return -ENOMEM; - packet->speed_code = req->req.address & 0x3; + packet->speed_code = req->req.address & 0x3; req->packet = packet; - if (copy_from_user(packet->data, int2ptr(req->req.sendb), - req->req.length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - req->req.length = 0; - queue_complete_req(req); - return sizeof(struct raw1394_request); - } + if (copy_from_user(packet->data, int2ptr(req->req.sendb), + req->req.length)) { + req->req.error = RAW1394_ERROR_MEMFAULT; + req->req.length = 0; + queue_complete_req(req); + return sizeof(struct raw1394_request); + } - req->req.length = 0; - hpsb_set_packet_complete_task(packet, (void (*)(void*))queue_complete_req, req); + req->req.length = 0; + hpsb_set_packet_complete_task(packet, + (void (*)(void *))queue_complete_req, + req); - spin_lock_irq(&fi->reqlists_lock); - list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irq(&fi->reqlists_lock); + spin_lock_irq(&fi->reqlists_lock); + list_add_tail(&req->list, &fi->req_pending); + spin_unlock_irq(&fi->reqlists_lock); /* Update the generation of the packet just before sending. */ packet->generation = req->req.generation; - if (hpsb_send_packet(packet) < 0) { - req->req.error = RAW1394_ERROR_SEND_ERROR; - queue_complete_req(req); - } + if (hpsb_send_packet(packet) < 0) { + req->req.error = RAW1394_ERROR_SEND_ERROR; + queue_complete_req(req); + } - return sizeof(struct raw1394_request); + return sizeof(struct raw1394_request); } static int handle_async_send(struct file_info *fi, struct pending_request *req) { - struct hpsb_packet *packet; - int header_length = req->req.misc & 0xffff; - int expect_response = req->req.misc >> 16; - - if ((header_length > req->req.length) || - (header_length < 12)) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - req->req.length = 0; - queue_complete_req(req); - return sizeof(struct raw1394_request); - } - - packet = hpsb_alloc_packet(req->req.length-header_length); - req->packet = packet; - if (!packet) return -ENOMEM; - - if (copy_from_user(packet->header, int2ptr(req->req.sendb), - header_length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - req->req.length = 0; - queue_complete_req(req); - return sizeof(struct raw1394_request); - } - - if (copy_from_user(packet->data, int2ptr(req->req.sendb) + header_length, - packet->data_size)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - req->req.length = 0; - queue_complete_req(req); - return sizeof(struct raw1394_request); - } - - packet->type = hpsb_async; - packet->node_id = packet->header[0] >> 16; - packet->tcode = (packet->header[0] >> 4) & 0xf; - packet->tlabel = (packet->header[0] >> 10) &0x3f; - packet->host = fi->host; - packet->expect_response = expect_response; - packet->header_size=header_length; - packet->data_size=req->req.length-header_length; - - req->req.length = 0; - hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req); - - spin_lock_irq(&fi->reqlists_lock); - list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irq(&fi->reqlists_lock); - - /* Update the generation of the packet just before sending. */ - packet->generation = req->req.generation; - - if (hpsb_send_packet(packet) < 0) { - req->req.error = RAW1394_ERROR_SEND_ERROR; - queue_complete_req(req); - } - - return sizeof(struct raw1394_request); + struct hpsb_packet *packet; + int header_length = req->req.misc & 0xffff; + int expect_response = req->req.misc >> 16; + + if ((header_length > req->req.length) || (header_length < 12)) { + req->req.error = RAW1394_ERROR_INVALID_ARG; + req->req.length = 0; + queue_complete_req(req); + return sizeof(struct raw1394_request); + } + + packet = hpsb_alloc_packet(req->req.length - header_length); + req->packet = packet; + if (!packet) + return -ENOMEM; + + if (copy_from_user(packet->header, int2ptr(req->req.sendb), + header_length)) { + req->req.error = RAW1394_ERROR_MEMFAULT; + req->req.length = 0; + queue_complete_req(req); + return sizeof(struct raw1394_request); + } + + if (copy_from_user + (packet->data, int2ptr(req->req.sendb) + header_length, + packet->data_size)) { + req->req.error = RAW1394_ERROR_MEMFAULT; + req->req.length = 0; + queue_complete_req(req); + return sizeof(struct raw1394_request); + } + + packet->type = hpsb_async; + packet->node_id = packet->header[0] >> 16; + packet->tcode = (packet->header[0] >> 4) & 0xf; + packet->tlabel = (packet->header[0] >> 10) & 0x3f; + packet->host = fi->host; + packet->expect_response = expect_response; + packet->header_size = header_length; + packet->data_size = req->req.length - header_length; + + req->req.length = 0; + hpsb_set_packet_complete_task(packet, + (void (*)(void *))queue_complete_cb, req); + + spin_lock_irq(&fi->reqlists_lock); + list_add_tail(&req->list, &fi->req_pending); + spin_unlock_irq(&fi->reqlists_lock); + + /* Update the generation of the packet just before sending. */ + packet->generation = req->req.generation; + + if (hpsb_send_packet(packet) < 0) { + req->req.error = RAW1394_ERROR_SEND_ERROR; + queue_complete_req(req); + } + + return sizeof(struct raw1394_request); +} + +static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, + u64 addr, size_t length, u16 flags) +{ + struct pending_request *req; + struct host_info *hi; + struct file_info *fi = NULL; + struct list_head *entry; + struct arm_addr *arm_addr = NULL; + struct arm_request *arm_req = NULL; + struct arm_response *arm_resp = NULL; + int found = 0, size = 0, rcode = -1; + struct arm_request_response *arm_req_resp = NULL; + + DBGMSG("arm_read called by node: %X" + "addr: %4.4x %8.8x length: %Zu", nodeid, + (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), + length); + spin_lock(&host_info_lock); + hi = find_host_info(host); /* search address-entry */ + if (hi != NULL) { + list_for_each_entry(fi, &hi->file_info_list, list) { + entry = fi->addr_list.next; + while (entry != &(fi->addr_list)) { + arm_addr = + list_entry(entry, struct arm_addr, + addr_list); + if (((arm_addr->start) <= (addr)) + && ((arm_addr->end) >= (addr + length))) { + found = 1; + break; + } + entry = entry->next; + } + if (found) { + break; + } + } + } + rcode = -1; + if (!found) { + printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found" + " -> rcode_address_error\n"); + spin_unlock(&host_info_lock); + return (RCODE_ADDRESS_ERROR); + } else { + DBGMSG("arm_read addr_entry FOUND"); + } + if (arm_addr->rec_length < length) { + DBGMSG("arm_read blocklength too big -> rcode_data_error"); + rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */ + } + if (rcode == -1) { + if (arm_addr->access_rights & ARM_READ) { + if (!(arm_addr->client_transactions & ARM_READ)) { + memcpy(buffer, + (arm_addr->addr_space_buffer) + (addr - + (arm_addr-> + start)), + length); + DBGMSG("arm_read -> (rcode_complete)"); + rcode = RCODE_COMPLETE; + } + } else { + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + DBGMSG("arm_read -> rcode_type_error (access denied)"); + } + } + if (arm_addr->notification_options & ARM_READ) { + DBGMSG("arm_read -> entering notification-section"); + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) { + DBGMSG("arm_read -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + if (rcode == RCODE_COMPLETE) { + size = + sizeof(struct arm_request) + + sizeof(struct arm_response) + + length * sizeof(byte_t) + + sizeof(struct arm_request_response); + } else { + size = + sizeof(struct arm_request) + + sizeof(struct arm_response) + + sizeof(struct arm_request_response); + } + req->data = kmalloc(size, SLAB_ATOMIC); + if (!(req->data)) { + free_pending_request(req); + DBGMSG("arm_read -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + req->free_data = 1; + req->file_info = fi; + req->req.type = RAW1394_REQ_ARM; + req->req.generation = get_hpsb_generation(host); + req->req.misc = + (((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF)); + req->req.tag = arm_addr->arm_tag; + req->req.recvb = arm_addr->recvb; + req->req.length = size; + arm_req_resp = (struct arm_request_response *)(req->data); + arm_req = (struct arm_request *)((byte_t *) (req->data) + + (sizeof + (struct + arm_request_response))); + arm_resp = + (struct arm_response *)((byte_t *) (arm_req) + + (sizeof(struct arm_request))); + arm_req->buffer = NULL; + arm_resp->buffer = NULL; + if (rcode == RCODE_COMPLETE) { + byte_t *buf = + (byte_t *) arm_resp + sizeof(struct arm_response); + memcpy(buf, + (arm_addr->addr_space_buffer) + (addr - + (arm_addr-> + start)), + length); + arm_resp->buffer = + int2ptr((arm_addr->recvb) + + sizeof(struct arm_request_response) + + sizeof(struct arm_request) + + sizeof(struct arm_response)); + } + arm_resp->buffer_length = + (rcode == RCODE_COMPLETE) ? length : 0; + arm_resp->response_code = rcode; + arm_req->buffer_length = 0; + arm_req->generation = req->req.generation; + arm_req->extended_transaction_code = 0; + arm_req->destination_offset = addr; + arm_req->source_nodeid = nodeid; + arm_req->destination_nodeid = host->node_id; + arm_req->tlabel = (flags >> 10) & 0x3f; + arm_req->tcode = (flags >> 4) & 0x0f; + arm_req_resp->request = int2ptr((arm_addr->recvb) + + sizeof(struct + arm_request_response)); + arm_req_resp->response = + int2ptr((arm_addr->recvb) + + sizeof(struct arm_request_response) + + sizeof(struct arm_request)); + queue_complete_req(req); + } + spin_unlock(&host_info_lock); + return (rcode); +} + +static int arm_write(struct hpsb_host *host, int nodeid, int destid, + quadlet_t * data, u64 addr, size_t length, u16 flags) +{ + struct pending_request *req; + struct host_info *hi; + struct file_info *fi = NULL; + struct list_head *entry; + struct arm_addr *arm_addr = NULL; + struct arm_request *arm_req = NULL; + struct arm_response *arm_resp = NULL; + int found = 0, size = 0, rcode = -1, length_conflict = 0; + struct arm_request_response *arm_req_resp = NULL; + + DBGMSG("arm_write called by node: %X" + "addr: %4.4x %8.8x length: %Zu", nodeid, + (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), + length); + spin_lock(&host_info_lock); + hi = find_host_info(host); /* search address-entry */ + if (hi != NULL) { + list_for_each_entry(fi, &hi->file_info_list, list) { + entry = fi->addr_list.next; + while (entry != &(fi->addr_list)) { + arm_addr = + list_entry(entry, struct arm_addr, + addr_list); + if (((arm_addr->start) <= (addr)) + && ((arm_addr->end) >= (addr + length))) { + found = 1; + break; + } + entry = entry->next; + } + if (found) { + break; + } + } + } + rcode = -1; + if (!found) { + printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found" + " -> rcode_address_error\n"); + spin_unlock(&host_info_lock); + return (RCODE_ADDRESS_ERROR); + } else { + DBGMSG("arm_write addr_entry FOUND"); + } + if (arm_addr->rec_length < length) { + DBGMSG("arm_write blocklength too big -> rcode_data_error"); + length_conflict = 1; + rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */ + } + if (rcode == -1) { + if (arm_addr->access_rights & ARM_WRITE) { + if (!(arm_addr->client_transactions & ARM_WRITE)) { + memcpy((arm_addr->addr_space_buffer) + + (addr - (arm_addr->start)), data, + length); + DBGMSG("arm_write -> (rcode_complete)"); + rcode = RCODE_COMPLETE; + } + } else { + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + DBGMSG("arm_write -> rcode_type_error (access denied)"); + } + } + if (arm_addr->notification_options & ARM_WRITE) { + DBGMSG("arm_write -> entering notification-section"); + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) { + DBGMSG("arm_write -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request my be retried */ + } + size = + sizeof(struct arm_request) + sizeof(struct arm_response) + + (length) * sizeof(byte_t) + + sizeof(struct arm_request_response); + req->data = kmalloc(size, SLAB_ATOMIC); + if (!(req->data)) { + free_pending_request(req); + DBGMSG("arm_write -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + req->free_data = 1; + req->file_info = fi; + req->req.type = RAW1394_REQ_ARM; + req->req.generation = get_hpsb_generation(host); + req->req.misc = + (((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF)); + req->req.tag = arm_addr->arm_tag; + req->req.recvb = arm_addr->recvb; + req->req.length = size; + arm_req_resp = (struct arm_request_response *)(req->data); + arm_req = (struct arm_request *)((byte_t *) (req->data) + + (sizeof + (struct + arm_request_response))); + arm_resp = + (struct arm_response *)((byte_t *) (arm_req) + + (sizeof(struct arm_request))); + arm_resp->buffer = NULL; + memcpy((byte_t *) arm_resp + sizeof(struct arm_response), + data, length); + arm_req->buffer = int2ptr((arm_addr->recvb) + + sizeof(struct arm_request_response) + + sizeof(struct arm_request) + + sizeof(struct arm_response)); + arm_req->buffer_length = length; + arm_req->generation = req->req.generation; + arm_req->extended_transaction_code = 0; + arm_req->destination_offset = addr; + arm_req->source_nodeid = nodeid; + arm_req->destination_nodeid = destid; + arm_req->tlabel = (flags >> 10) & 0x3f; + arm_req->tcode = (flags >> 4) & 0x0f; + arm_resp->buffer_length = 0; + arm_resp->response_code = rcode; + arm_req_resp->request = int2ptr((arm_addr->recvb) + + sizeof(struct + arm_request_response)); + arm_req_resp->response = + int2ptr((arm_addr->recvb) + + sizeof(struct arm_request_response) + + sizeof(struct arm_request)); + queue_complete_req(req); + } + spin_unlock(&host_info_lock); + return (rcode); } -static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, size_t length, u16 flags) +static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, + u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, + u16 flags) { - struct pending_request *req; - struct host_info *hi; - struct file_info *fi = NULL; - struct list_head *entry; - struct arm_addr *arm_addr = NULL; - struct arm_request *arm_req = NULL; - struct arm_response *arm_resp = NULL; - int found=0, size=0, rcode=-1; - struct arm_request_response *arm_req_resp = NULL; - - DBGMSG("arm_read called by node: %X" - "addr: %4.4x %8.8x length: %Zu", nodeid, - (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), - length); - spin_lock(&host_info_lock); - hi = find_host_info(host); /* search address-entry */ - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - arm_addr = list_entry(entry, struct arm_addr, addr_list); - if (((arm_addr->start) <= (addr)) && - ((arm_addr->end) >= (addr+length))) { - found = 1; - break; - } - entry = entry->next; - } - if (found) { - break; - } - } - } - rcode = -1; - if (!found) { - printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found" - " -> rcode_address_error\n"); - spin_unlock(&host_info_lock); - return (RCODE_ADDRESS_ERROR); - } else { - DBGMSG("arm_read addr_entry FOUND"); - } - if (arm_addr->rec_length < length) { - DBGMSG("arm_read blocklength too big -> rcode_data_error"); - rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */ - } - if (rcode == -1) { - if (arm_addr->access_rights & ARM_READ) { - if (!(arm_addr->client_transactions & ARM_READ)) { - memcpy(buffer,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), - length); - DBGMSG("arm_read -> (rcode_complete)"); - rcode = RCODE_COMPLETE; - } - } else { - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - DBGMSG("arm_read -> rcode_type_error (access denied)"); - } - } - if (arm_addr->notification_options & ARM_READ) { - DBGMSG("arm_read -> entering notification-section"); - req = __alloc_pending_request(SLAB_ATOMIC); - if (!req) { - DBGMSG("arm_read -> rcode_conflict_error"); - spin_unlock(&host_info_lock); - return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - if (rcode == RCODE_COMPLETE) { - size = sizeof(struct arm_request)+sizeof(struct arm_response) + - length * sizeof(byte_t) + - sizeof (struct arm_request_response); - } else { - size = sizeof(struct arm_request)+sizeof(struct arm_response) + - sizeof (struct arm_request_response); - } - req->data = kmalloc(size, SLAB_ATOMIC); - if (!(req->data)) { - free_pending_request(req); - DBGMSG("arm_read -> rcode_conflict_error"); - spin_unlock(&host_info_lock); - return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - req->free_data=1; - req->file_info = fi; - req->req.type = RAW1394_REQ_ARM; - req->req.generation = get_hpsb_generation(host); - req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF)); - req->req.tag = arm_addr->arm_tag; - req->req.recvb = arm_addr->recvb; - req->req.length = size; - arm_req_resp = (struct arm_request_response *) (req->data); - arm_req = (struct arm_request *) ((byte_t *)(req->data) + - (sizeof (struct arm_request_response))); - arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + - (sizeof(struct arm_request))); - arm_req->buffer = NULL; - arm_resp->buffer = NULL; - if (rcode == RCODE_COMPLETE) { - byte_t *buf = (byte_t *)arm_resp + sizeof(struct arm_response); - memcpy (buf, - (arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), - length); - arm_resp->buffer = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response) + - sizeof (struct arm_request) + - sizeof (struct arm_response)); - } - arm_resp->buffer_length = (rcode == RCODE_COMPLETE) ? length : 0; - arm_resp->response_code = rcode; - arm_req->buffer_length = 0; - arm_req->generation = req->req.generation; - arm_req->extended_transaction_code = 0; - arm_req->destination_offset = addr; - arm_req->source_nodeid = nodeid; - arm_req->destination_nodeid = host->node_id; - arm_req->tlabel = (flags >> 10) & 0x3f; - arm_req->tcode = (flags >> 4) & 0x0f; - arm_req_resp->request = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response)); - arm_req_resp->response = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response) + - sizeof (struct arm_request)); - queue_complete_req(req); - } - spin_unlock(&host_info_lock); - return(rcode); -} + struct pending_request *req; + struct host_info *hi; + struct file_info *fi = NULL; + struct list_head *entry; + struct arm_addr *arm_addr = NULL; + struct arm_request *arm_req = NULL; + struct arm_response *arm_resp = NULL; + int found = 0, size = 0, rcode = -1; + quadlet_t old, new; + struct arm_request_response *arm_req_resp = NULL; + + if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) || + ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) { + DBGMSG("arm_lock called by node: %X " + "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X", + nodeid, (u16) ((addr >> 32) & 0xFFFF), + (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF, + be32_to_cpu(data)); + } else { + DBGMSG("arm_lock called by node: %X " + "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X", + nodeid, (u16) ((addr >> 32) & 0xFFFF), + (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF, + be32_to_cpu(data), be32_to_cpu(arg)); + } + spin_lock(&host_info_lock); + hi = find_host_info(host); /* search address-entry */ + if (hi != NULL) { + list_for_each_entry(fi, &hi->file_info_list, list) { + entry = fi->addr_list.next; + while (entry != &(fi->addr_list)) { + arm_addr = + list_entry(entry, struct arm_addr, + addr_list); + if (((arm_addr->start) <= (addr)) + && ((arm_addr->end) >= + (addr + sizeof(*store)))) { + found = 1; + break; + } + entry = entry->next; + } + if (found) { + break; + } + } + } + rcode = -1; + if (!found) { + printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found" + " -> rcode_address_error\n"); + spin_unlock(&host_info_lock); + return (RCODE_ADDRESS_ERROR); + } else { + DBGMSG("arm_lock addr_entry FOUND"); + } + if (rcode == -1) { + if (arm_addr->access_rights & ARM_LOCK) { + if (!(arm_addr->client_transactions & ARM_LOCK)) { + memcpy(&old, + (arm_addr->addr_space_buffer) + (addr - + (arm_addr-> + start)), + sizeof(old)); + switch (ext_tcode) { + case (EXTCODE_MASK_SWAP): + new = data | (old & ~arg); + break; + case (EXTCODE_COMPARE_SWAP): + if (old == arg) { + new = data; + } else { + new = old; + } + break; + case (EXTCODE_FETCH_ADD): + new = + cpu_to_be32(be32_to_cpu(data) + + be32_to_cpu(old)); + break; + case (EXTCODE_LITTLE_ADD): + new = + cpu_to_le32(le32_to_cpu(data) + + le32_to_cpu(old)); + break; + case (EXTCODE_BOUNDED_ADD): + if (old != arg) { + new = + cpu_to_be32(be32_to_cpu + (data) + + be32_to_cpu + (old)); + } else { + new = old; + } + break; + case (EXTCODE_WRAP_ADD): + if (old != arg) { + new = + cpu_to_be32(be32_to_cpu + (data) + + be32_to_cpu + (old)); + } else { + new = data; + } + break; + default: + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + printk(KERN_ERR + "raw1394: arm_lock FAILED " + "ext_tcode not allowed -> rcode_type_error\n"); + break; + } /*switch */ + if (rcode == -1) { + DBGMSG("arm_lock -> (rcode_complete)"); + rcode = RCODE_COMPLETE; + memcpy(store, &old, sizeof(*store)); + memcpy((arm_addr->addr_space_buffer) + + (addr - (arm_addr->start)), + &new, sizeof(*store)); + } + } + } else { + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + DBGMSG("arm_lock -> rcode_type_error (access denied)"); + } + } + if (arm_addr->notification_options & ARM_LOCK) { + byte_t *buf1, *buf2; + DBGMSG("arm_lock -> entering notification-section"); + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) { + DBGMSG("arm_lock -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response); /* maximum */ + req->data = kmalloc(size, SLAB_ATOMIC); + if (!(req->data)) { + free_pending_request(req); + DBGMSG("arm_lock -> rcode_conflict_error"); + spin_unlock(&host_info_lock); + return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + req->free_data = 1; + arm_req_resp = (struct arm_request_response *)(req->data); + arm_req = (struct arm_request *)((byte_t *) (req->data) + + (sizeof + (struct + arm_request_response))); + arm_resp = + (struct arm_response *)((byte_t *) (arm_req) + + (sizeof(struct arm_request))); + buf1 = (byte_t *) arm_resp + sizeof(struct arm_response); + buf2 = buf1 + 2 * sizeof(*store); + if ((ext_tcode == EXTCODE_FETCH_ADD) || + (ext_tcode == EXTCODE_LITTLE_ADD)) { + arm_req->buffer_length = sizeof(*store); + memcpy(buf1, &data, sizeof(*store)); -static int arm_write (struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, size_t length, u16 flags) -{ - struct pending_request *req; - struct host_info *hi; - struct file_info *fi = NULL; - struct list_head *entry; - struct arm_addr *arm_addr = NULL; - struct arm_request *arm_req = NULL; - struct arm_response *arm_resp = NULL; - int found=0, size=0, rcode=-1, length_conflict=0; - struct arm_request_response *arm_req_resp = NULL; - - DBGMSG("arm_write called by node: %X" - "addr: %4.4x %8.8x length: %Zu", nodeid, - (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), - length); - spin_lock(&host_info_lock); - hi = find_host_info(host); /* search address-entry */ - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - arm_addr = list_entry(entry, struct arm_addr, addr_list); - if (((arm_addr->start) <= (addr)) && - ((arm_addr->end) >= (addr+length))) { - found = 1; - break; - } - entry = entry->next; - } - if (found) { - break; - } - } - } - rcode = -1; - if (!found) { - printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found" - " -> rcode_address_error\n"); - spin_unlock(&host_info_lock); - return (RCODE_ADDRESS_ERROR); - } else { - DBGMSG("arm_write addr_entry FOUND"); - } - if (arm_addr->rec_length < length) { - DBGMSG("arm_write blocklength too big -> rcode_data_error"); - length_conflict = 1; - rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */ - } - if (rcode == -1) { - if (arm_addr->access_rights & ARM_WRITE) { - if (!(arm_addr->client_transactions & ARM_WRITE)) { - memcpy((arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), - data, length); - DBGMSG("arm_write -> (rcode_complete)"); - rcode = RCODE_COMPLETE; - } - } else { - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - DBGMSG("arm_write -> rcode_type_error (access denied)"); - } - } - if (arm_addr->notification_options & ARM_WRITE) { - DBGMSG("arm_write -> entering notification-section"); - req = __alloc_pending_request(SLAB_ATOMIC); - if (!req) { - DBGMSG("arm_write -> rcode_conflict_error"); - spin_unlock(&host_info_lock); - return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request my be retried */ - } - size = sizeof(struct arm_request)+sizeof(struct arm_response) + - (length) * sizeof(byte_t) + - sizeof (struct arm_request_response); - req->data = kmalloc(size, SLAB_ATOMIC); - if (!(req->data)) { - free_pending_request(req); - DBGMSG("arm_write -> rcode_conflict_error"); - spin_unlock(&host_info_lock); - return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - req->free_data=1; - req->file_info = fi; - req->req.type = RAW1394_REQ_ARM; - req->req.generation = get_hpsb_generation(host); - req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF)); - req->req.tag = arm_addr->arm_tag; - req->req.recvb = arm_addr->recvb; - req->req.length = size; - arm_req_resp = (struct arm_request_response *) (req->data); - arm_req = (struct arm_request *) ((byte_t *)(req->data) + - (sizeof (struct arm_request_response))); - arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + - (sizeof(struct arm_request))); - arm_resp->buffer = NULL; - memcpy ((byte_t *)arm_resp + sizeof(struct arm_response), - data, length); - arm_req->buffer = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response) + - sizeof (struct arm_request) + - sizeof (struct arm_response)); - arm_req->buffer_length = length; - arm_req->generation = req->req.generation; - arm_req->extended_transaction_code = 0; - arm_req->destination_offset = addr; - arm_req->source_nodeid = nodeid; - arm_req->destination_nodeid = destid; - arm_req->tlabel = (flags >> 10) & 0x3f; - arm_req->tcode = (flags >> 4) & 0x0f; - arm_resp->buffer_length = 0; - arm_resp->response_code = rcode; - arm_req_resp->request = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response)); - arm_req_resp->response = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response) + - sizeof (struct arm_request)); - queue_complete_req(req); - } - spin_unlock(&host_info_lock); - return(rcode); + } else { + arm_req->buffer_length = 2 * sizeof(*store); + memcpy(buf1, &arg, sizeof(*store)); + memcpy(buf1 + sizeof(*store), &data, sizeof(*store)); + } + if (rcode == RCODE_COMPLETE) { + arm_resp->buffer_length = sizeof(*store); + memcpy(buf2, &old, sizeof(*store)); + } else { + arm_resp->buffer_length = 0; + } + req->file_info = fi; + req->req.type = RAW1394_REQ_ARM; + req->req.generation = get_hpsb_generation(host); + req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) | + (ARM_LOCK & 0xFF)); + req->req.tag = arm_addr->arm_tag; + req->req.recvb = arm_addr->recvb; + req->req.length = size; + arm_req->generation = req->req.generation; + arm_req->extended_transaction_code = ext_tcode; + arm_req->destination_offset = addr; + arm_req->source_nodeid = nodeid; + arm_req->destination_nodeid = host->node_id; + arm_req->tlabel = (flags >> 10) & 0x3f; + arm_req->tcode = (flags >> 4) & 0x0f; + arm_resp->response_code = rcode; + arm_req_resp->request = int2ptr((arm_addr->recvb) + + sizeof(struct + arm_request_response)); + arm_req_resp->response = + int2ptr((arm_addr->recvb) + + sizeof(struct arm_request_response) + + sizeof(struct arm_request)); + arm_req->buffer = + int2ptr((arm_addr->recvb) + + sizeof(struct arm_request_response) + + sizeof(struct arm_request) + + sizeof(struct arm_response)); + arm_resp->buffer = + int2ptr((arm_addr->recvb) + + sizeof(struct arm_request_response) + + sizeof(struct arm_request) + + sizeof(struct arm_response) + 2 * sizeof(*store)); + queue_complete_req(req); + } + spin_unlock(&host_info_lock); + return (rcode); } -static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags) +static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, + u64 addr, octlet_t data, octlet_t arg, int ext_tcode, + u16 flags) { - struct pending_request *req; - struct host_info *hi; - struct file_info *fi = NULL; - struct list_head *entry; - struct arm_addr *arm_addr = NULL; - struct arm_request *arm_req = NULL; - struct arm_response *arm_resp = NULL; - int found=0, size=0, rcode=-1; - quadlet_t old, new; - struct arm_request_response *arm_req_resp = NULL; - - if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) || - ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) { - DBGMSG("arm_lock called by node: %X " - "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X", - nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), - ext_tcode & 0xFF , be32_to_cpu(data)); - } else { - DBGMSG("arm_lock called by node: %X " - "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X", - nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), - ext_tcode & 0xFF , be32_to_cpu(data), be32_to_cpu(arg)); - } - spin_lock(&host_info_lock); - hi = find_host_info(host); /* search address-entry */ - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - arm_addr = list_entry(entry, struct arm_addr, addr_list); - if (((arm_addr->start) <= (addr)) && - ((arm_addr->end) >= (addr+sizeof(*store)))) { - found = 1; - break; - } - entry = entry->next; - } - if (found) { - break; - } - } - } - rcode = -1; - if (!found) { - printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found" - " -> rcode_address_error\n"); - spin_unlock(&host_info_lock); - return (RCODE_ADDRESS_ERROR); - } else { - DBGMSG("arm_lock addr_entry FOUND"); - } - if (rcode == -1) { - if (arm_addr->access_rights & ARM_LOCK) { - if (!(arm_addr->client_transactions & ARM_LOCK)) { - memcpy(&old,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), - sizeof(old)); - switch (ext_tcode) { - case (EXTCODE_MASK_SWAP): - new = data | (old & ~arg); - break; - case (EXTCODE_COMPARE_SWAP): - if (old == arg) { - new = data; - } else { - new = old; - } - break; - case (EXTCODE_FETCH_ADD): - new = cpu_to_be32(be32_to_cpu(data) + be32_to_cpu(old)); - break; - case (EXTCODE_LITTLE_ADD): - new = cpu_to_le32(le32_to_cpu(data) + le32_to_cpu(old)); - break; - case (EXTCODE_BOUNDED_ADD): - if (old != arg) { - new = cpu_to_be32(be32_to_cpu(data) + - be32_to_cpu(old)); - } else { - new = old; - } - break; - case (EXTCODE_WRAP_ADD): - if (old != arg) { - new = cpu_to_be32(be32_to_cpu(data) + - be32_to_cpu(old)); - } else { - new = data; - } - break; - default: - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - printk(KERN_ERR "raw1394: arm_lock FAILED " - "ext_tcode not allowed -> rcode_type_error\n"); - break; - } /*switch*/ - if (rcode == -1) { - DBGMSG("arm_lock -> (rcode_complete)"); - rcode = RCODE_COMPLETE; - memcpy (store, &old, sizeof(*store)); - memcpy ((arm_addr->addr_space_buffer)+ - (addr-(arm_addr->start)), - &new, sizeof(*store)); - } - } - } else { - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - DBGMSG("arm_lock -> rcode_type_error (access denied)"); - } - } - if (arm_addr->notification_options & ARM_LOCK) { + struct pending_request *req; + struct host_info *hi; + struct file_info *fi = NULL; + struct list_head *entry; + struct arm_addr *arm_addr = NULL; + struct arm_request *arm_req = NULL; + struct arm_response *arm_resp = NULL; + int found = 0, size = 0, rcode = -1; + octlet_t old, new; + struct arm_request_response *arm_req_resp = NULL; + + if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) || + ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) { + DBGMSG("arm_lock64 called by node: %X " + "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ", + nodeid, (u16) ((addr >> 32) & 0xFFFF), + (u32) (addr & 0xFFFFFFFF), + ext_tcode & 0xFF, + (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF), + (u32) (be64_to_cpu(data) & 0xFFFFFFFF)); + } else { + DBGMSG("arm_lock64 called by node: %X " + "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: " + "%8.8X %8.8X ", + nodeid, (u16) ((addr >> 32) & 0xFFFF), + (u32) (addr & 0xFFFFFFFF), + ext_tcode & 0xFF, + (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF), + (u32) (be64_to_cpu(data) & 0xFFFFFFFF), + (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF), + (u32) (be64_to_cpu(arg) & 0xFFFFFFFF)); + } + spin_lock(&host_info_lock); + hi = find_host_info(host); /* search addressentry in file_info's for host */ + if (hi != NULL) { + list_for_each_entry(fi, &hi->file_info_list, list) { + entry = fi->addr_list.next; + while (entry != &(fi->addr_list)) { + arm_addr = + list_entry(entry, struct arm_addr, + addr_list); + if (((arm_addr->start) <= (addr)) + && ((arm_addr->end) >= + (addr + sizeof(*store)))) { + found = 1; + break; + } + entry = entry->next; + } + if (found) { + break; + } + } + } + rcode = -1; + if (!found) { + printk(KERN_ERR + "raw1394: arm_lock64 FAILED addr_entry not found" + " -> rcode_address_error\n"); + spin_unlock(&host_info_lock); + return (RCODE_ADDRESS_ERROR); + } else { + DBGMSG("arm_lock64 addr_entry FOUND"); + } + if (rcode == -1) { + if (arm_addr->access_rights & ARM_LOCK) { + if (!(arm_addr->client_transactions & ARM_LOCK)) { + memcpy(&old, + (arm_addr->addr_space_buffer) + (addr - + (arm_addr-> + start)), + sizeof(old)); + switch (ext_tcode) { + case (EXTCODE_MASK_SWAP): + new = data | (old & ~arg); + break; + case (EXTCODE_COMPARE_SWAP): + if (old == arg) { + new = data; + } else { + new = old; + } + break; + case (EXTCODE_FETCH_ADD): + new = + cpu_to_be64(be64_to_cpu(data) + + be64_to_cpu(old)); + break; + case (EXTCODE_LITTLE_ADD): + new = + cpu_to_le64(le64_to_cpu(data) + + le64_to_cpu(old)); + break; + case (EXTCODE_BOUNDED_ADD): + if (old != arg) { + new = + cpu_to_be64(be64_to_cpu + (data) + + be64_to_cpu + (old)); + } else { + new = old; + } + break; + case (EXTCODE_WRAP_ADD): + if (old != arg) { + new = + cpu_to_be64(be64_to_cpu + (data) + + be64_to_cpu + (old)); + } else { + new = data; + } + break; + default: + printk(KERN_ERR + "raw1394: arm_lock64 FAILED " + "ext_tcode not allowed -> rcode_type_error\n"); + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + break; + } /*switch */ + if (rcode == -1) { + DBGMSG + ("arm_lock64 -> (rcode_complete)"); + rcode = RCODE_COMPLETE; + memcpy(store, &old, sizeof(*store)); + memcpy((arm_addr->addr_space_buffer) + + (addr - (arm_addr->start)), + &new, sizeof(*store)); + } + } + } else { + rcode = RCODE_TYPE_ERROR; /* function not allowed */ + DBGMSG + ("arm_lock64 -> rcode_type_error (access denied)"); + } + } + if (arm_addr->notification_options & ARM_LOCK) { byte_t *buf1, *buf2; - DBGMSG("arm_lock -> entering notification-section"); - req = __alloc_pending_request(SLAB_ATOMIC); - if (!req) { - DBGMSG("arm_lock -> rcode_conflict_error"); - spin_unlock(&host_info_lock); - return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - size = sizeof(struct arm_request)+sizeof(struct arm_response) + - 3 * sizeof(*store) + - sizeof (struct arm_request_response); /* maximum */ - req->data = kmalloc(size, SLAB_ATOMIC); - if (!(req->data)) { - free_pending_request(req); - DBGMSG("arm_lock -> rcode_conflict_error"); - spin_unlock(&host_info_lock); - return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - req->free_data=1; - arm_req_resp = (struct arm_request_response *) (req->data); - arm_req = (struct arm_request *) ((byte_t *)(req->data) + - (sizeof (struct arm_request_response))); - arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + - (sizeof(struct arm_request))); - buf1 = (byte_t *)arm_resp + sizeof(struct arm_response); + DBGMSG("arm_lock64 -> entering notification-section"); + req = __alloc_pending_request(SLAB_ATOMIC); + if (!req) { + spin_unlock(&host_info_lock); + DBGMSG("arm_lock64 -> rcode_conflict_error"); + return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response); /* maximum */ + req->data = kmalloc(size, SLAB_ATOMIC); + if (!(req->data)) { + free_pending_request(req); + spin_unlock(&host_info_lock); + DBGMSG("arm_lock64 -> rcode_conflict_error"); + return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. + The request may be retried */ + } + req->free_data = 1; + arm_req_resp = (struct arm_request_response *)(req->data); + arm_req = (struct arm_request *)((byte_t *) (req->data) + + (sizeof + (struct + arm_request_response))); + arm_resp = + (struct arm_response *)((byte_t *) (arm_req) + + (sizeof(struct arm_request))); + buf1 = (byte_t *) arm_resp + sizeof(struct arm_response); buf2 = buf1 + 2 * sizeof(*store); - if ((ext_tcode == EXTCODE_FETCH_ADD) || - (ext_tcode == EXTCODE_LITTLE_ADD)) { - arm_req->buffer_length = sizeof(*store); - memcpy (buf1, &data, sizeof(*store)); - - } else { - arm_req->buffer_length = 2 * sizeof(*store); - memcpy (buf1, &arg, sizeof(*store)); - memcpy (buf1 + sizeof(*store), &data, sizeof(*store)); - } - if (rcode == RCODE_COMPLETE) { - arm_resp->buffer_length = sizeof(*store); - memcpy (buf2, &old, sizeof(*store)); - } else { - arm_resp->buffer_length = 0; - } - req->file_info = fi; - req->req.type = RAW1394_REQ_ARM; - req->req.generation = get_hpsb_generation(host); - req->req.misc = ( (((sizeof(*store)) << 16) & (0xFFFF0000)) | - (ARM_LOCK & 0xFF)); - req->req.tag = arm_addr->arm_tag; - req->req.recvb = arm_addr->recvb; - req->req.length = size; - arm_req->generation = req->req.generation; - arm_req->extended_transaction_code = ext_tcode; - arm_req->destination_offset = addr; - arm_req->source_nodeid = nodeid; - arm_req->destination_nodeid = host->node_id; - arm_req->tlabel = (flags >> 10) & 0x3f; - arm_req->tcode = (flags >> 4) & 0x0f; - arm_resp->response_code = rcode; - arm_req_resp->request = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response)); - arm_req_resp->response = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response) + - sizeof (struct arm_request)); - arm_req->buffer = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response) + - sizeof (struct arm_request) + - sizeof (struct arm_response)); - arm_resp->buffer = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response) + - sizeof (struct arm_request) + - sizeof (struct arm_response) + - 2* sizeof (*store)); - queue_complete_req(req); - } - spin_unlock(&host_info_lock); - return(rcode); -} + if ((ext_tcode == EXTCODE_FETCH_ADD) || + (ext_tcode == EXTCODE_LITTLE_ADD)) { + arm_req->buffer_length = sizeof(*store); + memcpy(buf1, &data, sizeof(*store)); -static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags) -{ - struct pending_request *req; - struct host_info *hi; - struct file_info *fi = NULL; - struct list_head *entry; - struct arm_addr *arm_addr = NULL; - struct arm_request *arm_req = NULL; - struct arm_response *arm_resp = NULL; - int found=0, size=0, rcode=-1; - octlet_t old, new; - struct arm_request_response *arm_req_resp = NULL; - - if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) || - ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) { - DBGMSG("arm_lock64 called by node: %X " - "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ", - nodeid, (u16) ((addr >>32) & 0xFFFF), - (u32) (addr & 0xFFFFFFFF), - ext_tcode & 0xFF , - (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF), - (u32) (be64_to_cpu(data) & 0xFFFFFFFF)); - } else { - DBGMSG("arm_lock64 called by node: %X " - "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: " - "%8.8X %8.8X ", - nodeid, (u16) ((addr >>32) & 0xFFFF), - (u32) (addr & 0xFFFFFFFF), - ext_tcode & 0xFF , - (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF), - (u32) (be64_to_cpu(data) & 0xFFFFFFFF), - (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF), - (u32) (be64_to_cpu(arg) & 0xFFFFFFFF)); - } - spin_lock(&host_info_lock); - hi = find_host_info(host); /* search addressentry in file_info's for host */ - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - arm_addr = list_entry(entry, struct arm_addr, addr_list); - if (((arm_addr->start) <= (addr)) && - ((arm_addr->end) >= (addr+sizeof(*store)))) { - found = 1; - break; - } - entry = entry->next; - } - if (found) { - break; - } - } - } - rcode = -1; - if (!found) { - printk(KERN_ERR "raw1394: arm_lock64 FAILED addr_entry not found" - " -> rcode_address_error\n"); - spin_unlock(&host_info_lock); - return (RCODE_ADDRESS_ERROR); - } else { - DBGMSG("arm_lock64 addr_entry FOUND"); - } - if (rcode == -1) { - if (arm_addr->access_rights & ARM_LOCK) { - if (!(arm_addr->client_transactions & ARM_LOCK)) { - memcpy(&old,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)), - sizeof(old)); - switch (ext_tcode) { - case (EXTCODE_MASK_SWAP): - new = data | (old & ~arg); - break; - case (EXTCODE_COMPARE_SWAP): - if (old == arg) { - new = data; - } else { - new = old; - } - break; - case (EXTCODE_FETCH_ADD): - new = cpu_to_be64(be64_to_cpu(data) + be64_to_cpu(old)); - break; - case (EXTCODE_LITTLE_ADD): - new = cpu_to_le64(le64_to_cpu(data) + le64_to_cpu(old)); - break; - case (EXTCODE_BOUNDED_ADD): - if (old != arg) { - new = cpu_to_be64(be64_to_cpu(data) + - be64_to_cpu(old)); - } else { - new = old; - } - break; - case (EXTCODE_WRAP_ADD): - if (old != arg) { - new = cpu_to_be64(be64_to_cpu(data) + - be64_to_cpu(old)); - } else { - new = data; - } - break; - default: - printk(KERN_ERR "raw1394: arm_lock64 FAILED " - "ext_tcode not allowed -> rcode_type_error\n"); - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - break; - } /*switch*/ - if (rcode == -1) { - DBGMSG("arm_lock64 -> (rcode_complete)"); - rcode = RCODE_COMPLETE; - memcpy (store, &old, sizeof(*store)); - memcpy ((arm_addr->addr_space_buffer)+ - (addr-(arm_addr->start)), - &new, sizeof(*store)); - } - } - } else { - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - DBGMSG("arm_lock64 -> rcode_type_error (access denied)"); - } - } - if (arm_addr->notification_options & ARM_LOCK) { - byte_t *buf1, *buf2; - DBGMSG("arm_lock64 -> entering notification-section"); - req = __alloc_pending_request(SLAB_ATOMIC); - if (!req) { - spin_unlock(&host_info_lock); - DBGMSG("arm_lock64 -> rcode_conflict_error"); - return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - size = sizeof(struct arm_request)+sizeof(struct arm_response) + - 3 * sizeof(*store) + - sizeof (struct arm_request_response); /* maximum */ - req->data = kmalloc(size, SLAB_ATOMIC); - if (!(req->data)) { - free_pending_request(req); - spin_unlock(&host_info_lock); - DBGMSG("arm_lock64 -> rcode_conflict_error"); - return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - req->free_data=1; - arm_req_resp = (struct arm_request_response *) (req->data); - arm_req = (struct arm_request *) ((byte_t *)(req->data) + - (sizeof (struct arm_request_response))); - arm_resp = (struct arm_response *) ((byte_t *)(arm_req) + - (sizeof(struct arm_request))); - buf1 = (byte_t *)arm_resp + sizeof(struct arm_response); - buf2 = buf1 + 2 * sizeof(*store); - if ((ext_tcode == EXTCODE_FETCH_ADD) || - (ext_tcode == EXTCODE_LITTLE_ADD)) { - arm_req->buffer_length = sizeof(*store); - memcpy (buf1, &data, sizeof(*store)); - - } else { - arm_req->buffer_length = 2 * sizeof(*store); - memcpy (buf1, &arg, sizeof(*store)); - memcpy (buf1 + sizeof(*store), &data, sizeof(*store)); - } - if (rcode == RCODE_COMPLETE) { - arm_resp->buffer_length = sizeof(*store); - memcpy (buf2, &old, sizeof(*store)); - } else { - arm_resp->buffer_length = 0; - } - req->file_info = fi; - req->req.type = RAW1394_REQ_ARM; - req->req.generation = get_hpsb_generation(host); - req->req.misc = ( (((sizeof(*store)) << 16) & (0xFFFF0000)) | - (ARM_LOCK & 0xFF)); - req->req.tag = arm_addr->arm_tag; - req->req.recvb = arm_addr->recvb; - req->req.length = size; - arm_req->generation = req->req.generation; - arm_req->extended_transaction_code = ext_tcode; - arm_req->destination_offset = addr; - arm_req->source_nodeid = nodeid; - arm_req->destination_nodeid = host->node_id; - arm_req->tlabel = (flags >> 10) & 0x3f; - arm_req->tcode = (flags >> 4) & 0x0f; - arm_resp->response_code = rcode; - arm_req_resp->request = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response)); - arm_req_resp->response = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response) + - sizeof (struct arm_request)); - arm_req->buffer = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response) + - sizeof (struct arm_request) + - sizeof (struct arm_response)); - arm_resp->buffer = int2ptr((arm_addr->recvb) + - sizeof (struct arm_request_response) + - sizeof (struct arm_request) + - sizeof (struct arm_response) + - 2* sizeof (*store)); - queue_complete_req(req); - } - spin_unlock(&host_info_lock); - return(rcode); + } else { + arm_req->buffer_length = 2 * sizeof(*store); + memcpy(buf1, &arg, sizeof(*store)); + memcpy(buf1 + sizeof(*store), &data, sizeof(*store)); + } + if (rcode == RCODE_COMPLETE) { + arm_resp->buffer_length = sizeof(*store); + memcpy(buf2, &old, sizeof(*store)); + } else { + arm_resp->buffer_length = 0; + } + req->file_info = fi; + req->req.type = RAW1394_REQ_ARM; + req->req.generation = get_hpsb_generation(host); + req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) | + (ARM_LOCK & 0xFF)); + req->req.tag = arm_addr->arm_tag; + req->req.recvb = arm_addr->recvb; + req->req.length = size; + arm_req->generation = req->req.generation; + arm_req->extended_transaction_code = ext_tcode; + arm_req->destination_offset = addr; + arm_req->source_nodeid = nodeid; + arm_req->destination_nodeid = host->node_id; + arm_req->tlabel = (flags >> 10) & 0x3f; + arm_req->tcode = (flags >> 4) & 0x0f; + arm_resp->response_code = rcode; + arm_req_resp->request = int2ptr((arm_addr->recvb) + + sizeof(struct + arm_request_response)); + arm_req_resp->response = + int2ptr((arm_addr->recvb) + + sizeof(struct arm_request_response) + + sizeof(struct arm_request)); + arm_req->buffer = + int2ptr((arm_addr->recvb) + + sizeof(struct arm_request_response) + + sizeof(struct arm_request) + + sizeof(struct arm_response)); + arm_resp->buffer = + int2ptr((arm_addr->recvb) + + sizeof(struct arm_request_response) + + sizeof(struct arm_request) + + sizeof(struct arm_response) + 2 * sizeof(*store)); + queue_complete_req(req); + } + spin_unlock(&host_info_lock); + return (rcode); } static int arm_register(struct file_info *fi, struct pending_request *req) { - int retval; - struct arm_addr *addr; - struct host_info *hi; - struct file_info *fi_hlp = NULL; - struct list_head *entry; - struct arm_addr *arm_addr = NULL; - int same_host, another_host; - unsigned long flags; - - DBGMSG("arm_register called " - "addr(Offset): %8.8x %8.8x length: %u " - "rights: %2.2X notify: %2.2X " - "max_blk_len: %4.4X", - (u32) ((req->req.address >>32) & 0xFFFF), - (u32) (req->req.address & 0xFFFFFFFF), - req->req.length, ((req->req.misc >> 8) & 0xFF), - (req->req.misc & 0xFF),((req->req.misc >> 16) & 0xFFFF)); - /* check addressrange */ - if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) || - (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) != 0)) { - req->req.length = 0; - return (-EINVAL); - } - /* addr-list-entry for fileinfo */ - addr = (struct arm_addr *)kmalloc(sizeof(struct arm_addr), SLAB_KERNEL); - if (!addr) { - req->req.length = 0; - return (-ENOMEM); - } - /* allocation of addr_space_buffer */ - addr->addr_space_buffer = (u8 *)vmalloc(req->req.length); - if (!(addr->addr_space_buffer)) { - kfree(addr); - req->req.length = 0; - return (-ENOMEM); - } - /* initialization of addr_space_buffer */ - if ((req->req.sendb)== (unsigned long)NULL) { - /* init: set 0 */ - memset(addr->addr_space_buffer, 0,req->req.length); - } else { - /* init: user -> kernel */ - if (copy_from_user(addr->addr_space_buffer,int2ptr(req->req.sendb), - req->req.length)) { - vfree(addr->addr_space_buffer); - kfree(addr); - return (-EFAULT); - } - } - INIT_LIST_HEAD(&addr->addr_list); - addr->arm_tag = req->req.tag; - addr->start = req->req.address; - addr->end = req->req.address + req->req.length; - addr->access_rights = (u8) (req->req.misc & 0x0F); - addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F); - addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F); - addr->access_rights |= addr->client_transactions; - addr->notification_options |= addr->client_transactions; - addr->recvb = req->req.recvb; - addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF); - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(fi->host); - same_host = 0; - another_host = 0; - /* same host with address-entry containing same addressrange ? */ - list_for_each_entry(fi_hlp, &hi->file_info_list, list) { - entry = fi_hlp->addr_list.next; - while (entry != &(fi_hlp->addr_list)) { - arm_addr = list_entry(entry, struct arm_addr, addr_list); - if ( (arm_addr->start == addr->start) && - (arm_addr->end == addr->end)) { - DBGMSG("same host ownes same " - "addressrange -> EALREADY"); - same_host = 1; - break; - } - entry = entry->next; - } - if (same_host) { - break; - } - } - if (same_host) { - /* addressrange occupied by same host */ - vfree(addr->addr_space_buffer); - kfree(addr); - spin_unlock_irqrestore(&host_info_lock, flags); - return (-EALREADY); - } - /* another host with valid address-entry containing same addressrange */ - list_for_each_entry(hi, &host_info_list, list) { - if (hi->host != fi->host) { - list_for_each_entry(fi_hlp, &hi->file_info_list, list) { - entry = fi_hlp->addr_list.next; - while (entry != &(fi_hlp->addr_list)) { - arm_addr = list_entry(entry, struct arm_addr, addr_list); - if ( (arm_addr->start == addr->start) && - (arm_addr->end == addr->end)) { - DBGMSG("another host ownes same " - "addressrange"); - another_host = 1; - break; - } - entry = entry->next; - } - if (another_host) { - break; - } - } - } - } - if (another_host) { - DBGMSG("another hosts entry is valid -> SUCCESS"); - if (copy_to_user(int2ptr(req->req.recvb), - &addr->start,sizeof(u64))) { - printk(KERN_ERR "raw1394: arm_register failed " - " address-range-entry is invalid -> EFAULT !!!\n"); - vfree(addr->addr_space_buffer); - kfree(addr); - spin_unlock_irqrestore(&host_info_lock, flags); - return (-EFAULT); - } - free_pending_request(req); /* immediate success or fail */ - /* INSERT ENTRY */ - list_add_tail(&addr->addr_list, &fi->addr_list); - spin_unlock_irqrestore(&host_info_lock, flags); - return sizeof(struct raw1394_request); - } - retval = hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops, req->req.address, - req->req.address + req->req.length); - if (retval) { - /* INSERT ENTRY */ - list_add_tail(&addr->addr_list, &fi->addr_list); - } else { - DBGMSG("arm_register failed errno: %d \n",retval); - vfree(addr->addr_space_buffer); - kfree(addr); - spin_unlock_irqrestore(&host_info_lock, flags); - return (-EALREADY); - } - spin_unlock_irqrestore(&host_info_lock, flags); - free_pending_request(req); /* immediate success or fail */ - return sizeof(struct raw1394_request); + int retval; + struct arm_addr *addr; + struct host_info *hi; + struct file_info *fi_hlp = NULL; + struct list_head *entry; + struct arm_addr *arm_addr = NULL; + int same_host, another_host; + unsigned long flags; + + DBGMSG("arm_register called " + "addr(Offset): %8.8x %8.8x length: %u " + "rights: %2.2X notify: %2.2X " + "max_blk_len: %4.4X", + (u32) ((req->req.address >> 32) & 0xFFFF), + (u32) (req->req.address & 0xFFFFFFFF), + req->req.length, ((req->req.misc >> 8) & 0xFF), + (req->req.misc & 0xFF), ((req->req.misc >> 16) & 0xFFFF)); + /* check addressrange */ + if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) || + (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) != + 0)) { + req->req.length = 0; + return (-EINVAL); + } + /* addr-list-entry for fileinfo */ + addr = (struct arm_addr *)kmalloc(sizeof(struct arm_addr), SLAB_KERNEL); + if (!addr) { + req->req.length = 0; + return (-ENOMEM); + } + /* allocation of addr_space_buffer */ + addr->addr_space_buffer = (u8 *) vmalloc(req->req.length); + if (!(addr->addr_space_buffer)) { + kfree(addr); + req->req.length = 0; + return (-ENOMEM); + } + /* initialization of addr_space_buffer */ + if ((req->req.sendb) == (unsigned long)NULL) { + /* init: set 0 */ + memset(addr->addr_space_buffer, 0, req->req.length); + } else { + /* init: user -> kernel */ + if (copy_from_user + (addr->addr_space_buffer, int2ptr(req->req.sendb), + req->req.length)) { + vfree(addr->addr_space_buffer); + kfree(addr); + return (-EFAULT); + } + } + INIT_LIST_HEAD(&addr->addr_list); + addr->arm_tag = req->req.tag; + addr->start = req->req.address; + addr->end = req->req.address + req->req.length; + addr->access_rights = (u8) (req->req.misc & 0x0F); + addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F); + addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F); + addr->access_rights |= addr->client_transactions; + addr->notification_options |= addr->client_transactions; + addr->recvb = req->req.recvb; + addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF); + spin_lock_irqsave(&host_info_lock, flags); + hi = find_host_info(fi->host); + same_host = 0; + another_host = 0; + /* same host with address-entry containing same addressrange ? */ + list_for_each_entry(fi_hlp, &hi->file_info_list, list) { + entry = fi_hlp->addr_list.next; + while (entry != &(fi_hlp->addr_list)) { + arm_addr = + list_entry(entry, struct arm_addr, addr_list); + if ((arm_addr->start == addr->start) + && (arm_addr->end == addr->end)) { + DBGMSG("same host ownes same " + "addressrange -> EALREADY"); + same_host = 1; + break; + } + entry = entry->next; + } + if (same_host) { + break; + } + } + if (same_host) { + /* addressrange occupied by same host */ + vfree(addr->addr_space_buffer); + kfree(addr); + spin_unlock_irqrestore(&host_info_lock, flags); + return (-EALREADY); + } + /* another host with valid address-entry containing same addressrange */ + list_for_each_entry(hi, &host_info_list, list) { + if (hi->host != fi->host) { + list_for_each_entry(fi_hlp, &hi->file_info_list, list) { + entry = fi_hlp->addr_list.next; + while (entry != &(fi_hlp->addr_list)) { + arm_addr = + list_entry(entry, struct arm_addr, + addr_list); + if ((arm_addr->start == addr->start) + && (arm_addr->end == addr->end)) { + DBGMSG + ("another host ownes same " + "addressrange"); + another_host = 1; + break; + } + entry = entry->next; + } + if (another_host) { + break; + } + } + } + } + if (another_host) { + DBGMSG("another hosts entry is valid -> SUCCESS"); + if (copy_to_user(int2ptr(req->req.recvb), + &addr->start, sizeof(u64))) { + printk(KERN_ERR "raw1394: arm_register failed " + " address-range-entry is invalid -> EFAULT !!!\n"); + vfree(addr->addr_space_buffer); + kfree(addr); + spin_unlock_irqrestore(&host_info_lock, flags); + return (-EFAULT); + } + free_pending_request(req); /* immediate success or fail */ + /* INSERT ENTRY */ + list_add_tail(&addr->addr_list, &fi->addr_list); + spin_unlock_irqrestore(&host_info_lock, flags); + return sizeof(struct raw1394_request); + } + retval = + hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops, + req->req.address, + req->req.address + req->req.length); + if (retval) { + /* INSERT ENTRY */ + list_add_tail(&addr->addr_list, &fi->addr_list); + } else { + DBGMSG("arm_register failed errno: %d \n", retval); + vfree(addr->addr_space_buffer); + kfree(addr); + spin_unlock_irqrestore(&host_info_lock, flags); + return (-EALREADY); + } + spin_unlock_irqrestore(&host_info_lock, flags); + free_pending_request(req); /* immediate success or fail */ + return sizeof(struct raw1394_request); } static int arm_unregister(struct file_info *fi, struct pending_request *req) { - int found = 0; - int retval = 0; - struct list_head *entry; - struct arm_addr *addr = NULL; - struct host_info *hi; - struct file_info *fi_hlp = NULL; - struct arm_addr *arm_addr = NULL; - int another_host; - unsigned long flags; - - DBGMSG("arm_Unregister called addr(Offset): " - "%8.8x %8.8x", - (u32) ((req->req.address >>32) & 0xFFFF), - (u32) (req->req.address & 0xFFFFFFFF)); - spin_lock_irqsave(&host_info_lock, flags); - /* get addr */ - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - addr = list_entry(entry, struct arm_addr, addr_list); - if (addr->start == req->req.address) { - found = 1; - break; - } - entry = entry->next; - } - if (!found) { - DBGMSG("arm_Unregister addr not found"); - spin_unlock_irqrestore(&host_info_lock, flags); - return (-EINVAL); - } - DBGMSG("arm_Unregister addr found"); - another_host = 0; - /* another host with valid address-entry containing - same addressrange */ - list_for_each_entry(hi, &host_info_list, list) { - if (hi->host != fi->host) { - list_for_each_entry(fi_hlp, &hi->file_info_list, list) { - entry = fi_hlp->addr_list.next; - while (entry != &(fi_hlp->addr_list)) { - arm_addr = list_entry(entry, - struct arm_addr, addr_list); - if (arm_addr->start == - addr->start) { - DBGMSG("another host ownes " - "same addressrange"); - another_host = 1; - break; - } - entry = entry->next; - } - if (another_host) { - break; - } - } - } - } - if (another_host) { - DBGMSG("delete entry from list -> success"); - list_del(&addr->addr_list); - vfree(addr->addr_space_buffer); - kfree(addr); - free_pending_request(req); /* immediate success or fail */ - spin_unlock_irqrestore(&host_info_lock, flags); - return sizeof(struct raw1394_request); - } - 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); - return (-EINVAL); - } - DBGMSG("delete entry from list -> success"); - list_del(&addr->addr_list); - spin_unlock_irqrestore(&host_info_lock, flags); - vfree(addr->addr_space_buffer); - kfree(addr); - free_pending_request(req); /* immediate success or fail */ - return sizeof(struct raw1394_request); + int found = 0; + int retval = 0; + struct list_head *entry; + struct arm_addr *addr = NULL; + struct host_info *hi; + struct file_info *fi_hlp = NULL; + struct arm_addr *arm_addr = NULL; + int another_host; + unsigned long flags; + + DBGMSG("arm_Unregister called addr(Offset): " + "%8.8x %8.8x", + (u32) ((req->req.address >> 32) & 0xFFFF), + (u32) (req->req.address & 0xFFFFFFFF)); + spin_lock_irqsave(&host_info_lock, flags); + /* get addr */ + entry = fi->addr_list.next; + while (entry != &(fi->addr_list)) { + addr = list_entry(entry, struct arm_addr, addr_list); + if (addr->start == req->req.address) { + found = 1; + break; + } + entry = entry->next; + } + if (!found) { + DBGMSG("arm_Unregister addr not found"); + spin_unlock_irqrestore(&host_info_lock, flags); + return (-EINVAL); + } + DBGMSG("arm_Unregister addr found"); + another_host = 0; + /* another host with valid address-entry containing + same addressrange */ + list_for_each_entry(hi, &host_info_list, list) { + if (hi->host != fi->host) { + list_for_each_entry(fi_hlp, &hi->file_info_list, list) { + entry = fi_hlp->addr_list.next; + while (entry != &(fi_hlp->addr_list)) { + arm_addr = list_entry(entry, + struct arm_addr, + addr_list); + if (arm_addr->start == addr->start) { + DBGMSG("another host ownes " + "same addressrange"); + another_host = 1; + break; + } + entry = entry->next; + } + if (another_host) { + break; + } + } + } + } + if (another_host) { + DBGMSG("delete entry from list -> success"); + list_del(&addr->addr_list); + vfree(addr->addr_space_buffer); + kfree(addr); + free_pending_request(req); /* immediate success or fail */ + spin_unlock_irqrestore(&host_info_lock, flags); + return sizeof(struct raw1394_request); + } + 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); + return (-EINVAL); + } + DBGMSG("delete entry from list -> success"); + list_del(&addr->addr_list); + spin_unlock_irqrestore(&host_info_lock, flags); + vfree(addr->addr_space_buffer); + kfree(addr); + free_pending_request(req); /* immediate success or fail */ + return sizeof(struct raw1394_request); } /* Copy data from ARM buffer(s) to user buffer. */ static int arm_get_buf(struct file_info *fi, struct pending_request *req) { - struct arm_addr *arm_addr = NULL; + struct arm_addr *arm_addr = NULL; unsigned long flags; unsigned long offset; @@ -1749,8 +1864,7 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req) DBGMSG("arm_get_buf " "addr(Offset): %04X %08X length: %u", (u32) ((req->req.address >> 32) & 0xFFFF), - (u32) (req->req.address & 0xFFFFFFFF), - (u32) req->req.length); + (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length); spin_lock_irqsave(&host_info_lock, flags); entry = fi->addr_list.next; @@ -1761,13 +1875,18 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req) if (req->req.address + req->req.length <= arm_addr->end) { offset = req->req.address - arm_addr->start; - DBGMSG("arm_get_buf copy_to_user( %08X, %p, %u )", - (u32) req->req.recvb, - arm_addr->addr_space_buffer+offset, - (u32) req->req.length); - - if (copy_to_user(int2ptr(req->req.recvb), arm_addr->addr_space_buffer+offset, req->req.length)) { - spin_unlock_irqrestore(&host_info_lock, flags); + DBGMSG + ("arm_get_buf copy_to_user( %08X, %p, %u )", + (u32) req->req.recvb, + arm_addr->addr_space_buffer + offset, + (u32) req->req.length); + + if (copy_to_user + (int2ptr(req->req.recvb), + arm_addr->addr_space_buffer + offset, + req->req.length)) { + spin_unlock_irqrestore(&host_info_lock, + flags); return (-EFAULT); } @@ -1789,11 +1908,10 @@ static int arm_get_buf(struct file_info *fi, struct pending_request *req) return (-EINVAL); } - /* Copy data from user buffer to ARM buffer(s). */ static int arm_set_buf(struct file_info *fi, struct pending_request *req) { - struct arm_addr *arm_addr = NULL; + struct arm_addr *arm_addr = NULL; unsigned long flags; unsigned long offset; @@ -1802,9 +1920,7 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req) DBGMSG("arm_set_buf " "addr(Offset): %04X %08X length: %u", (u32) ((req->req.address >> 32) & 0xFFFF), - (u32) (req->req.address & 0xFFFFFFFF), - (u32) req->req.length); - + (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length); spin_lock_irqsave(&host_info_lock, flags); entry = fi->addr_list.next; @@ -1815,18 +1931,23 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req) if (req->req.address + req->req.length <= arm_addr->end) { offset = req->req.address - arm_addr->start; - DBGMSG("arm_set_buf copy_from_user( %p, %08X, %u )", - arm_addr->addr_space_buffer+offset, - (u32) req->req.sendb, - (u32) req->req.length); - - if (copy_from_user(arm_addr->addr_space_buffer+offset, int2ptr(req->req.sendb), req->req.length)) { - spin_unlock_irqrestore(&host_info_lock, flags); + DBGMSG + ("arm_set_buf copy_from_user( %p, %08X, %u )", + arm_addr->addr_space_buffer + offset, + (u32) req->req.sendb, + (u32) req->req.length); + + if (copy_from_user + (arm_addr->addr_space_buffer + offset, + int2ptr(req->req.sendb), + req->req.length)) { + spin_unlock_irqrestore(&host_info_lock, + flags); return (-EFAULT); } spin_unlock_irqrestore(&host_info_lock, flags); - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ return sizeof(struct raw1394_request); } else { DBGMSG("arm_set_buf request exceeded mapping"); @@ -1842,96 +1963,100 @@ static int arm_set_buf(struct file_info *fi, struct pending_request *req) static int reset_notification(struct file_info *fi, struct pending_request *req) { - DBGMSG("reset_notification called - switch %s ", - (req->req.misc == RAW1394_NOTIFY_OFF)?"OFF":"ON"); - if ((req->req.misc == RAW1394_NOTIFY_OFF) || - (req->req.misc == RAW1394_NOTIFY_ON)) { - fi->notification=(u8)req->req.misc; - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - return sizeof(struct raw1394_request); - } - /* error EINVAL (22) invalid argument */ - return (-EINVAL); + DBGMSG("reset_notification called - switch %s ", + (req->req.misc == RAW1394_NOTIFY_OFF) ? "OFF" : "ON"); + if ((req->req.misc == RAW1394_NOTIFY_OFF) || + (req->req.misc == RAW1394_NOTIFY_ON)) { + fi->notification = (u8) req->req.misc; + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + return sizeof(struct raw1394_request); + } + /* error EINVAL (22) invalid argument */ + return (-EINVAL); } static int write_phypacket(struct file_info *fi, struct pending_request *req) { - struct hpsb_packet *packet = NULL; - int retval=0; - quadlet_t data; - - data = be32_to_cpu((u32)req->req.sendb); - DBGMSG("write_phypacket called - quadlet 0x%8.8x ",data); - packet = hpsb_make_phypacket (fi->host, data); - if (!packet) return -ENOMEM; - req->req.length=0; - req->packet=packet; - hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req); - spin_lock_irq(&fi->reqlists_lock); - list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irq(&fi->reqlists_lock); - packet->generation = req->req.generation; - retval = hpsb_send_packet(packet); - DBGMSG("write_phypacket send_packet called => retval: %d ", retval); - if (retval < 0) { - req->req.error = RAW1394_ERROR_SEND_ERROR; - req->req.length = 0; - queue_complete_req(req); - } - return sizeof(struct raw1394_request); + struct hpsb_packet *packet = NULL; + int retval = 0; + quadlet_t data; + + data = be32_to_cpu((u32) req->req.sendb); + DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data); + packet = hpsb_make_phypacket(fi->host, data); + if (!packet) + return -ENOMEM; + req->req.length = 0; + req->packet = packet; + hpsb_set_packet_complete_task(packet, + (void (*)(void *))queue_complete_cb, req); + spin_lock_irq(&fi->reqlists_lock); + list_add_tail(&req->list, &fi->req_pending); + spin_unlock_irq(&fi->reqlists_lock); + packet->generation = req->req.generation; + retval = hpsb_send_packet(packet); + DBGMSG("write_phypacket send_packet called => retval: %d ", retval); + if (retval < 0) { + req->req.error = RAW1394_ERROR_SEND_ERROR; + req->req.length = 0; + queue_complete_req(req); + } + return sizeof(struct raw1394_request); } static int get_config_rom(struct file_info *fi, struct pending_request *req) { - int ret=sizeof(struct raw1394_request); - quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL); - int status; - - if (!data) return -ENOMEM; - - status = csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET, - data, req->req.length); - if (copy_to_user(int2ptr(req->req.recvb), data, - req->req.length)) - ret = -EFAULT; - if (copy_to_user(int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len, - sizeof(fi->host->csr.rom->cache_head->len))) - ret = -EFAULT; + int ret = sizeof(struct raw1394_request); + quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL); + int status; + + if (!data) + return -ENOMEM; + + status = + csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET, + data, req->req.length); + if (copy_to_user(int2ptr(req->req.recvb), data, req->req.length)) + ret = -EFAULT; + if (copy_to_user + (int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len, + sizeof(fi->host->csr.rom->cache_head->len))) + ret = -EFAULT; if (copy_to_user(int2ptr(req->req.address), &fi->host->csr.generation, sizeof(fi->host->csr.generation))) - ret = -EFAULT; - if (copy_to_user(int2ptr(req->req.sendb), &status, - sizeof(status))) - ret = -EFAULT; - kfree(data); - if (ret >= 0) { - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - } - return ret; + ret = -EFAULT; + if (copy_to_user(int2ptr(req->req.sendb), &status, sizeof(status))) + ret = -EFAULT; + kfree(data); + if (ret >= 0) { + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + } + return ret; } static int update_config_rom(struct file_info *fi, struct pending_request *req) { - int ret=sizeof(struct raw1394_request); - quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL); - if (!data) return -ENOMEM; - if (copy_from_user(data,int2ptr(req->req.sendb), - req->req.length)) { - ret= -EFAULT; - } else { - int status = hpsb_update_config_rom(fi->host, - data, req->req.length, - (unsigned char) req->req.misc); - if (copy_to_user(int2ptr(req->req.recvb), - &status, sizeof(status))) - ret = -ENOMEM; - } - kfree(data); - if (ret >= 0) { - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + int ret = sizeof(struct raw1394_request); + quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL); + if (!data) + return -ENOMEM; + if (copy_from_user(data, int2ptr(req->req.sendb), req->req.length)) { + ret = -EFAULT; + } else { + int status = hpsb_update_config_rom(fi->host, + data, req->req.length, + (unsigned char)req->req. + misc); + if (copy_to_user + (int2ptr(req->req.recvb), &status, sizeof(status))) + ret = -ENOMEM; + } + kfree(data); + if (ret >= 0) { + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ fi->cfgrom_upd = 1; - } - return ret; + } + return ret; } static int modify_config_rom(struct file_info *fi, struct pending_request *req) @@ -1943,23 +2068,32 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req) int ret = 0; if (req->req.misc == ~0) { - if (req->req.length == 0) return -EINVAL; + if (req->req.length == 0) + return -EINVAL; /* Find an unused slot */ - for (dr = 0; dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr]; dr++); + for (dr = 0; + dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr]; + dr++) ; - if (dr == RAW1394_MAX_USER_CSR_DIRS) return -ENOMEM; + if (dr == RAW1394_MAX_USER_CSR_DIRS) + return -ENOMEM; - fi->csr1212_dirs[dr] = csr1212_new_directory(CSR1212_KV_ID_VENDOR); - if (!fi->csr1212_dirs[dr]) return -ENOMEM; + fi->csr1212_dirs[dr] = + csr1212_new_directory(CSR1212_KV_ID_VENDOR); + if (!fi->csr1212_dirs[dr]) + return -ENOMEM; } else { dr = req->req.misc; - if (!fi->csr1212_dirs[dr]) return -EINVAL; + if (!fi->csr1212_dirs[dr]) + return -EINVAL; /* Delete old stuff */ - for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head; + for (dentry = + fi->csr1212_dirs[dr]->value.directory.dentries_head; dentry; dentry = dentry->next) { - csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv, + csr1212_detach_keyval_from_directory(fi->host->csr.rom-> + root_kv, dentry->kv); } @@ -1980,7 +2114,8 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req) return -ENOMEM; } - cache->filled_head = kmalloc(sizeof(struct csr1212_cache_region), GFP_KERNEL); + cache->filled_head = + kmalloc(sizeof(struct csr1212_cache_region), GFP_KERNEL); if (!cache->filled_head) { csr1212_release_keyval(fi->csr1212_dirs[dr]); fi->csr1212_dirs[dr] = NULL; @@ -1994,11 +2129,11 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req) csr1212_release_keyval(fi->csr1212_dirs[dr]); fi->csr1212_dirs[dr] = NULL; CSR1212_FREE(cache); - ret= -EFAULT; + ret = -EFAULT; } else { cache->len = req->req.length; cache->filled_head->offset_start = 0; - cache->filled_head->offset_end = cache->size -1; + cache->filled_head->offset_end = cache->size - 1; cache->layout_head = cache->layout_tail = fi->csr1212_dirs[dr]; @@ -2010,17 +2145,20 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req) } /* attach top level items to the root directory */ - for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head; + for (dentry = + fi->csr1212_dirs[dr]->value.directory.dentries_head; ret == CSR1212_SUCCESS && dentry; dentry = dentry->next) { - ret = csr1212_attach_keyval_to_directory(fi->host->csr.rom->root_kv, - dentry->kv); + ret = + csr1212_attach_keyval_to_directory(fi->host->csr. + rom->root_kv, + dentry->kv); } if (ret == CSR1212_SUCCESS) { ret = hpsb_update_config_rom_image(fi->host); if (ret >= 0 && copy_to_user(int2ptr(req->req.recvb), - &dr, sizeof(dr))) { + &dr, sizeof(dr))) { ret = -ENOMEM; } } @@ -2034,9 +2172,11 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req) free_pending_request(req); return sizeof(struct raw1394_request); } else { - for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head; + for (dentry = + fi->csr1212_dirs[dr]->value.directory.dentries_head; dentry; dentry = dentry->next) { - csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv, + csr1212_detach_keyval_from_directory(fi->host->csr.rom-> + root_kv, dentry->kv); } csr1212_release_keyval(fi->csr1212_dirs[dr]); @@ -2047,133 +2187,132 @@ static int modify_config_rom(struct file_info *fi, struct pending_request *req) static int state_connected(struct file_info *fi, struct pending_request *req) { - int node = req->req.address >> 48; + int node = req->req.address >> 48; - req->req.error = RAW1394_ERROR_NONE; + req->req.error = RAW1394_ERROR_NONE; - switch (req->req.type) { + switch (req->req.type) { - case RAW1394_REQ_ECHO: - queue_complete_req(req); - return sizeof(struct raw1394_request); + case RAW1394_REQ_ECHO: + queue_complete_req(req); + return sizeof(struct raw1394_request); - case RAW1394_REQ_ISO_SEND: - return handle_iso_send(fi, req, node); + case RAW1394_REQ_ISO_SEND: + return handle_iso_send(fi, req, node); - case RAW1394_REQ_ARM_REGISTER: - return arm_register(fi, req); + case RAW1394_REQ_ARM_REGISTER: + return arm_register(fi, req); - case RAW1394_REQ_ARM_UNREGISTER: - return arm_unregister(fi, req); + case RAW1394_REQ_ARM_UNREGISTER: + return arm_unregister(fi, req); - case RAW1394_REQ_ARM_SET_BUF: - return arm_set_buf(fi, req); + case RAW1394_REQ_ARM_SET_BUF: + return arm_set_buf(fi, req); - case RAW1394_REQ_ARM_GET_BUF: - return arm_get_buf(fi, req); + case RAW1394_REQ_ARM_GET_BUF: + return arm_get_buf(fi, req); - case RAW1394_REQ_RESET_NOTIFY: - return reset_notification(fi, req); + case RAW1394_REQ_RESET_NOTIFY: + return reset_notification(fi, req); - case RAW1394_REQ_ISO_LISTEN: - handle_iso_listen(fi, req); - return sizeof(struct raw1394_request); + case RAW1394_REQ_ISO_LISTEN: + handle_iso_listen(fi, req); + return sizeof(struct raw1394_request); - case RAW1394_REQ_FCP_LISTEN: - handle_fcp_listen(fi, req); - return sizeof(struct raw1394_request); + case RAW1394_REQ_FCP_LISTEN: + handle_fcp_listen(fi, req); + return sizeof(struct raw1394_request); - case RAW1394_REQ_RESET_BUS: - if (req->req.misc == RAW1394_LONG_RESET) { - DBGMSG("busreset called (type: LONG)"); - hpsb_reset_bus(fi->host, LONG_RESET); - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - return sizeof(struct raw1394_request); - } - if (req->req.misc == RAW1394_SHORT_RESET) { - DBGMSG("busreset called (type: SHORT)"); - hpsb_reset_bus(fi->host, SHORT_RESET); - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - return sizeof(struct raw1394_request); - } - /* error EINVAL (22) invalid argument */ - return (-EINVAL); - case RAW1394_REQ_GET_ROM: - return get_config_rom(fi, req); + case RAW1394_REQ_RESET_BUS: + if (req->req.misc == RAW1394_LONG_RESET) { + DBGMSG("busreset called (type: LONG)"); + hpsb_reset_bus(fi->host, LONG_RESET); + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + return sizeof(struct raw1394_request); + } + if (req->req.misc == RAW1394_SHORT_RESET) { + DBGMSG("busreset called (type: SHORT)"); + hpsb_reset_bus(fi->host, SHORT_RESET); + free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ + return sizeof(struct raw1394_request); + } + /* error EINVAL (22) invalid argument */ + return (-EINVAL); + case RAW1394_REQ_GET_ROM: + return get_config_rom(fi, req); - case RAW1394_REQ_UPDATE_ROM: - return update_config_rom(fi, req); + case RAW1394_REQ_UPDATE_ROM: + return update_config_rom(fi, req); case RAW1394_REQ_MODIFY_ROM: return modify_config_rom(fi, req); - } - - if (req->req.generation != get_hpsb_generation(fi->host)) { - req->req.error = RAW1394_ERROR_GENERATION; - req->req.generation = get_hpsb_generation(fi->host); - req->req.length = 0; - queue_complete_req(req); - return sizeof(struct raw1394_request); - } - - switch (req->req.type) { - case RAW1394_REQ_PHYPACKET: - return write_phypacket(fi, req); - case RAW1394_REQ_ASYNC_SEND: - return handle_async_send(fi, req); - } - - if (req->req.length == 0) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - queue_complete_req(req); - return sizeof(struct raw1394_request); - } - - return handle_async_request(fi, req, node); -} + } + + if (req->req.generation != get_hpsb_generation(fi->host)) { + req->req.error = RAW1394_ERROR_GENERATION; + req->req.generation = get_hpsb_generation(fi->host); + req->req.length = 0; + queue_complete_req(req); + return sizeof(struct raw1394_request); + } + + switch (req->req.type) { + case RAW1394_REQ_PHYPACKET: + return write_phypacket(fi, req); + case RAW1394_REQ_ASYNC_SEND: + return handle_async_send(fi, req); + } + + if (req->req.length == 0) { + req->req.error = RAW1394_ERROR_INVALID_ARG; + queue_complete_req(req); + return sizeof(struct raw1394_request); + } + return handle_async_request(fi, req, node); +} -static ssize_t raw1394_write(struct file *file, const char __user *buffer, size_t count, - loff_t *offset_is_ignored) +static ssize_t raw1394_write(struct file *file, const char __user * buffer, + size_t count, loff_t * offset_is_ignored) { - struct file_info *fi = (struct file_info *)file->private_data; - struct pending_request *req; - ssize_t retval = 0; - - if (count != sizeof(struct raw1394_request)) { - return -EINVAL; - } - - req = alloc_pending_request(); - if (req == NULL) { - return -ENOMEM; - } - req->file_info = fi; - - if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) { - free_pending_request(req); - return -EFAULT; - } - - switch (fi->state) { - case opened: - retval = state_opened(fi, req); - break; - - case initialized: - retval = state_initialized(fi, req); - break; - - case connected: - retval = state_connected(fi, req); - break; - } - - if (retval < 0) { - free_pending_request(req); - } - - return retval; + struct file_info *fi = (struct file_info *)file->private_data; + struct pending_request *req; + ssize_t retval = 0; + + if (count != sizeof(struct raw1394_request)) { + return -EINVAL; + } + + req = alloc_pending_request(); + if (req == NULL) { + return -ENOMEM; + } + req->file_info = fi; + + if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) { + free_pending_request(req); + return -EFAULT; + } + + switch (fi->state) { + case opened: + retval = state_opened(fi, req); + break; + + case initialized: + retval = state_initialized(fi, req); + break; + + case connected: + retval = state_connected(fi, req); + break; + } + + if (retval < 0) { + free_pending_request(req); + } + + return retval; } /* rawiso operations */ @@ -2185,8 +2324,8 @@ static inline int __rawiso_event_in_queue(struct file_info *fi) struct pending_request *req; list_for_each_entry(req, &fi->req_complete, list) - if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) - return 1; + if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) + return 1; return 0; } @@ -2200,7 +2339,8 @@ static void queue_rawiso_event(struct file_info *fi) /* only one ISO activity event may be in the queue */ if (!__rawiso_event_in_queue(fi)) { - struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC); + struct pending_request *req = + __alloc_pending_request(SLAB_ATOMIC); if (req) { req->file_info = fi; @@ -2220,11 +2360,11 @@ static void queue_rawiso_event(struct file_info *fi) static void rawiso_activity_cb(struct hpsb_iso *iso) { unsigned long flags; - struct host_info *hi; + struct host_info *hi; struct file_info *fi; - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(iso->host); + spin_lock_irqsave(&host_info_lock, flags); + hi = find_host_info(iso->host); if (hi != NULL) { list_for_each_entry(fi, &hi->file_info_list, list) { @@ -2237,7 +2377,8 @@ static void rawiso_activity_cb(struct hpsb_iso *iso) } /* helper function - gather all the kernel iso status bits for returning to user-space */ -static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_status *stat) +static void raw1394_iso_fill_status(struct hpsb_iso *iso, + struct raw1394_iso_status *stat) { stat->config.data_buf_size = iso->buf_size; stat->config.buf_packets = iso->buf_packets; @@ -2249,7 +2390,7 @@ static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_sta stat->xmit_cycle = iso->xmit_cycle; } -static int raw1394_iso_xmit_init(struct file_info *fi, void __user *uaddr) +static int raw1394_iso_xmit_init(struct file_info *fi, void __user * uaddr) { struct raw1394_iso_status stat; @@ -2281,7 +2422,7 @@ static int raw1394_iso_xmit_init(struct file_info *fi, void __user *uaddr) return 0; } -static int raw1394_iso_recv_init(struct file_info *fi, void __user *uaddr) +static int raw1394_iso_recv_init(struct file_info *fi, void __user * uaddr) { struct raw1394_iso_status stat; @@ -2295,7 +2436,7 @@ static int raw1394_iso_recv_init(struct file_info *fi, void __user *uaddr) stat.config.data_buf_size, stat.config.buf_packets, stat.config.channel, - stat.config.dma_mode, + stat.config.dma_mode, stat.config.irq_interval, rawiso_activity_cb); if (!fi->iso_handle) @@ -2309,7 +2450,7 @@ static int raw1394_iso_recv_init(struct file_info *fi, void __user *uaddr) return 0; } -static int raw1394_iso_get_status(struct file_info *fi, void __user *uaddr) +static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr) { struct raw1394_iso_status stat; struct hpsb_iso *iso = fi->iso_handle; @@ -2325,7 +2466,7 @@ static int raw1394_iso_get_status(struct file_info *fi, void __user *uaddr) } /* copy N packet_infos out of the ringbuffer into user-supplied array */ -static int raw1394_iso_recv_packets(struct file_info *fi, void __user *uaddr) +static int raw1394_iso_recv_packets(struct file_info *fi, void __user * uaddr) { struct raw1394_iso_packets upackets; unsigned int packet = fi->iso_handle->first_packet; @@ -2339,14 +2480,15 @@ static int raw1394_iso_recv_packets(struct file_info *fi, void __user *uaddr) /* ensure user-supplied buffer is accessible and big enough */ if (verify_area(VERIFY_WRITE, upackets.infos, - upackets.n_packets * sizeof(struct raw1394_iso_packet_info))) + upackets.n_packets * + sizeof(struct raw1394_iso_packet_info))) return -EFAULT; /* copy the packet_infos out */ for (i = 0; i < upackets.n_packets; i++) { if (__copy_to_user(&upackets.infos[i], - &fi->iso_handle->infos[packet], - sizeof(struct raw1394_iso_packet_info))) + &fi->iso_handle->infos[packet], + sizeof(struct raw1394_iso_packet_info))) return -EFAULT; packet = (packet + 1) % fi->iso_handle->buf_packets; @@ -2356,7 +2498,7 @@ static int raw1394_iso_recv_packets(struct file_info *fi, void __user *uaddr) } /* copy N packet_infos from user to ringbuffer, and queue them for transmission */ -static int raw1394_iso_send_packets(struct file_info *fi, void __user *uaddr) +static int raw1394_iso_send_packets(struct file_info *fi, void __user * uaddr) { struct raw1394_iso_packets upackets; int i, rv; @@ -2369,7 +2511,8 @@ static int raw1394_iso_send_packets(struct file_info *fi, void __user *uaddr) /* ensure user-supplied buffer is accessible and big enough */ if (verify_area(VERIFY_READ, upackets.infos, - upackets.n_packets * sizeof(struct raw1394_iso_packet_info))) + upackets.n_packets * + sizeof(struct raw1394_iso_packet_info))) return -EFAULT; /* copy the infos structs in and queue the packets */ @@ -2377,7 +2520,7 @@ static int raw1394_iso_send_packets(struct file_info *fi, void __user *uaddr) struct raw1394_iso_packet_info info; if (__copy_from_user(&info, &upackets.infos[i], - sizeof(struct raw1394_iso_packet_info))) + sizeof(struct raw1394_iso_packet_info))) return -EFAULT; rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset, @@ -2410,14 +2553,15 @@ static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) } /* ioctl is only used for rawiso operations */ -static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int raw1394_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { struct file_info *fi = file->private_data; void __user *argp = (void __user *)arg; - switch(fi->iso_state) { + switch (fi->iso_state) { case RAW1394_ISO_INACTIVE: - switch(cmd) { + switch (cmd) { case RAW1394_IOC_ISO_XMIT_INIT: return raw1394_iso_xmit_init(fi, argp); case RAW1394_IOC_ISO_RECV_INIT: @@ -2427,34 +2571,42 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cm } break; case RAW1394_ISO_RECV: - switch(cmd) { - case RAW1394_IOC_ISO_RECV_START: { - /* copy args from user-space */ - int args[3]; - if (copy_from_user(&args[0], argp, sizeof(args))) - return -EFAULT; - return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]); - } + switch (cmd) { + case RAW1394_IOC_ISO_RECV_START:{ + /* copy args from user-space */ + int args[3]; + if (copy_from_user + (&args[0], argp, sizeof(args))) + return -EFAULT; + return hpsb_iso_recv_start(fi->iso_handle, + args[0], args[1], + args[2]); + } case RAW1394_IOC_ISO_XMIT_RECV_STOP: hpsb_iso_stop(fi->iso_handle); return 0; case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL: - return hpsb_iso_recv_listen_channel(fi->iso_handle, arg); + return hpsb_iso_recv_listen_channel(fi->iso_handle, + arg); case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL: - return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg); - case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: { - /* copy the u64 from user-space */ - u64 mask; - if (copy_from_user(&mask, argp, sizeof(mask))) - return -EFAULT; - return hpsb_iso_recv_set_channel_mask(fi->iso_handle, mask); - } + return hpsb_iso_recv_unlisten_channel(fi->iso_handle, + arg); + case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{ + /* copy the u64 from user-space */ + u64 mask; + if (copy_from_user(&mask, argp, sizeof(mask))) + return -EFAULT; + return hpsb_iso_recv_set_channel_mask(fi-> + iso_handle, + mask); + } case RAW1394_IOC_ISO_GET_STATUS: return raw1394_iso_get_status(fi, argp); case RAW1394_IOC_ISO_RECV_PACKETS: return raw1394_iso_recv_packets(fi, argp); case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS: - return hpsb_iso_recv_release_packets(fi->iso_handle, arg); + return hpsb_iso_recv_release_packets(fi->iso_handle, + arg); case RAW1394_IOC_ISO_RECV_FLUSH: return hpsb_iso_recv_flush(fi->iso_handle); case RAW1394_IOC_ISO_SHUTDOWN: @@ -2466,14 +2618,16 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cm } break; case RAW1394_ISO_XMIT: - switch(cmd) { - case RAW1394_IOC_ISO_XMIT_START: { - /* copy two ints from user-space */ - int args[2]; - if (copy_from_user(&args[0], argp, sizeof(args))) - return -EFAULT; - return hpsb_iso_xmit_start(fi->iso_handle, args[0], args[1]); - } + switch (cmd) { + case RAW1394_IOC_ISO_XMIT_START:{ + /* copy two ints from user-space */ + int args[2]; + if (copy_from_user + (&args[0], argp, sizeof(args))) + return -EFAULT; + return hpsb_iso_xmit_start(fi->iso_handle, + args[0], args[1]); + } case RAW1394_IOC_ISO_XMIT_SYNC: return hpsb_iso_xmit_sync(fi->iso_handle); case RAW1394_IOC_ISO_XMIT_RECV_STOP: @@ -2498,270 +2652,303 @@ static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cm return -EINVAL; } -static unsigned int raw1394_poll(struct file *file, poll_table *pt) +static unsigned int raw1394_poll(struct file *file, poll_table * pt) { - struct file_info *fi = file->private_data; - unsigned int mask = POLLOUT | POLLWRNORM; + struct file_info *fi = file->private_data; + unsigned int mask = POLLOUT | POLLWRNORM; - poll_wait(file, &fi->poll_wait_complete, pt); + poll_wait(file, &fi->poll_wait_complete, pt); - spin_lock_irq(&fi->reqlists_lock); - if (!list_empty(&fi->req_complete)) { - mask |= POLLIN | POLLRDNORM; - } - spin_unlock_irq(&fi->reqlists_lock); + spin_lock_irq(&fi->reqlists_lock); + if (!list_empty(&fi->req_complete)) { + mask |= POLLIN | POLLRDNORM; + } + spin_unlock_irq(&fi->reqlists_lock); - return mask; + return mask; } static int raw1394_open(struct inode *inode, struct file *file) { - struct file_info *fi; + struct file_info *fi; - fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL); - if (fi == NULL) - return -ENOMEM; + fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL); + if (fi == NULL) + return -ENOMEM; - memset(fi, 0, sizeof(struct file_info)); - fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */ + memset(fi, 0, sizeof(struct file_info)); + fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */ - INIT_LIST_HEAD(&fi->list); - fi->state = opened; - INIT_LIST_HEAD(&fi->req_pending); - INIT_LIST_HEAD(&fi->req_complete); - sema_init(&fi->complete_sem, 0); - spin_lock_init(&fi->reqlists_lock); - init_waitqueue_head(&fi->poll_wait_complete); - INIT_LIST_HEAD(&fi->addr_list); + INIT_LIST_HEAD(&fi->list); + fi->state = opened; + INIT_LIST_HEAD(&fi->req_pending); + INIT_LIST_HEAD(&fi->req_complete); + sema_init(&fi->complete_sem, 0); + spin_lock_init(&fi->reqlists_lock); + init_waitqueue_head(&fi->poll_wait_complete); + INIT_LIST_HEAD(&fi->addr_list); - file->private_data = fi; + file->private_data = fi; - return 0; + return 0; } static int raw1394_release(struct inode *inode, struct file *file) { - struct file_info *fi = file->private_data; - struct list_head *lh; - struct pending_request *req; - int done = 0, i, fail = 0; - int retval = 0; - struct list_head *entry; - struct arm_addr *addr = NULL; - struct host_info *hi; - struct file_info *fi_hlp = NULL; - struct arm_addr *arm_addr = NULL; - int another_host; + struct file_info *fi = file->private_data; + struct list_head *lh; + struct pending_request *req; + int done = 0, i, fail = 0; + int retval = 0; + struct list_head *entry; + struct arm_addr *addr = NULL; + struct host_info *hi; + struct file_info *fi_hlp = NULL; + struct arm_addr *arm_addr = NULL; + int another_host; int csr_mod = 0; if (fi->iso_state != RAW1394_ISO_INACTIVE) raw1394_iso_shutdown(fi); - for (i = 0; i < 64; i++) { - if (fi->listen_channels & (1ULL << i)) { - hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i); - } - } - - spin_lock_irq(&host_info_lock); - fi->listen_channels = 0; - spin_unlock_irq(&host_info_lock); - - fail = 0; - /* set address-entries invalid */ - spin_lock_irq(&host_info_lock); - - while (!list_empty(&fi->addr_list)) { - another_host = 0; - lh = fi->addr_list.next; - addr = list_entry(lh, struct arm_addr, addr_list); - /* another host with valid address-entry containing - same addressrange? */ - list_for_each_entry(hi, &host_info_list, list) { - if (hi->host != fi->host) { - list_for_each_entry(fi_hlp, &hi->file_info_list, list) { - entry = fi_hlp->addr_list.next; - while (entry != &(fi_hlp->addr_list)) { - arm_addr = list_entry(entry, - struct arm_addr, addr_list); - if (arm_addr->start == - addr->start) { - DBGMSG("raw1394_release: " - "another host ownes " - "same addressrange"); - another_host = 1; - break; - } - entry = entry->next; - } - if (another_host) { - break; - } - } - } - } - if (!another_host) { - DBGMSG("raw1394_release: call hpsb_arm_unregister"); - retval = hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, addr->start); - if (!retval) { - ++fail; - printk(KERN_ERR "raw1394_release arm_Unregister failed\n"); - } - } - DBGMSG("raw1394_release: delete addr_entry from list"); - list_del(&addr->addr_list); - vfree(addr->addr_space_buffer); - kfree(addr); - } /* while */ - spin_unlock_irq(&host_info_lock); - if (fail > 0) { - printk(KERN_ERR "raw1394: during addr_list-release " - "error(s) occurred \n"); - } - - while (!done) { - spin_lock_irq(&fi->reqlists_lock); - - while (!list_empty(&fi->req_complete)) { - lh = fi->req_complete.next; - list_del(lh); - - req = list_entry(lh, struct pending_request, list); - - free_pending_request(req); - } - - if (list_empty(&fi->req_pending)) done = 1; - - spin_unlock_irq(&fi->reqlists_lock); - - if (!done) down_interruptible(&fi->complete_sem); - } + for (i = 0; i < 64; i++) { + if (fi->listen_channels & (1ULL << i)) { + hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i); + } + } + + spin_lock_irq(&host_info_lock); + fi->listen_channels = 0; + spin_unlock_irq(&host_info_lock); + + fail = 0; + /* set address-entries invalid */ + spin_lock_irq(&host_info_lock); + + while (!list_empty(&fi->addr_list)) { + another_host = 0; + lh = fi->addr_list.next; + addr = list_entry(lh, struct arm_addr, addr_list); + /* another host with valid address-entry containing + same addressrange? */ + list_for_each_entry(hi, &host_info_list, list) { + if (hi->host != fi->host) { + list_for_each_entry(fi_hlp, &hi->file_info_list, + list) { + entry = fi_hlp->addr_list.next; + while (entry != &(fi_hlp->addr_list)) { + arm_addr = list_entry(entry, struct + arm_addr, + addr_list); + if (arm_addr->start == + addr->start) { + DBGMSG + ("raw1394_release: " + "another host ownes " + "same addressrange"); + another_host = 1; + break; + } + entry = entry->next; + } + if (another_host) { + break; + } + } + } + } + if (!another_host) { + DBGMSG("raw1394_release: call hpsb_arm_unregister"); + retval = + hpsb_unregister_addrspace(&raw1394_highlevel, + fi->host, addr->start); + if (!retval) { + ++fail; + printk(KERN_ERR + "raw1394_release arm_Unregister failed\n"); + } + } + DBGMSG("raw1394_release: delete addr_entry from list"); + list_del(&addr->addr_list); + vfree(addr->addr_space_buffer); + kfree(addr); + } /* while */ + spin_unlock_irq(&host_info_lock); + if (fail > 0) { + printk(KERN_ERR "raw1394: during addr_list-release " + "error(s) occurred \n"); + } + + while (!done) { + spin_lock_irq(&fi->reqlists_lock); + + while (!list_empty(&fi->req_complete)) { + lh = fi->req_complete.next; + list_del(lh); + + req = list_entry(lh, struct pending_request, list); + + free_pending_request(req); + } + + if (list_empty(&fi->req_pending)) + done = 1; + + spin_unlock_irq(&fi->reqlists_lock); + + if (!done) + down_interruptible(&fi->complete_sem); + } /* Remove any sub-trees left by user space programs */ for (i = 0; i < RAW1394_MAX_USER_CSR_DIRS; i++) { struct csr1212_dentry *dentry; - if (!fi->csr1212_dirs[i]) continue; - for (dentry = fi->csr1212_dirs[i]->value.directory.dentries_head; - dentry; dentry = dentry->next) { - csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv, dentry->kv); + if (!fi->csr1212_dirs[i]) + continue; + for (dentry = + fi->csr1212_dirs[i]->value.directory.dentries_head; dentry; + dentry = dentry->next) { + csr1212_detach_keyval_from_directory(fi->host->csr.rom-> + root_kv, + dentry->kv); } csr1212_release_keyval(fi->csr1212_dirs[i]); fi->csr1212_dirs[i] = NULL; csr_mod = 1; } - if ((csr_mod || fi->cfgrom_upd) && hpsb_update_config_rom_image(fi->host) < 0) - HPSB_ERR("Failed to generate Configuration ROM image for host %d", fi->host->id); + if ((csr_mod || fi->cfgrom_upd) + && hpsb_update_config_rom_image(fi->host) < 0) + HPSB_ERR + ("Failed to generate Configuration ROM image for host %d", + fi->host->id); - if (fi->state == connected) { - spin_lock_irq(&host_info_lock); - list_del(&fi->list); - spin_unlock_irq(&host_info_lock); + if (fi->state == connected) { + spin_lock_irq(&host_info_lock); + list_del(&fi->list); + spin_unlock_irq(&host_info_lock); put_device(&fi->host->device); - } + } - kfree(fi); + kfree(fi); - return 0; + return 0; } - /*** HOTPLUG STUFF **********************************************************/ /* * Export information about protocols/devices supported by this driver. */ static struct ieee1394_device_id raw1394_id_table[] = { { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = AVC_SW_VERSION_ENTRY & 0xffffff - }, + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = AVC_SW_VERSION_ENTRY & 0xffffff}, + { + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = CAMERA_SW_VERSION_ENTRY & 0xffffff}, { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = CAMERA_SW_VERSION_ENTRY & 0xffffff - }, - { } + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff}, + { + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff}, + {} }; MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table); static struct hpsb_protocol_driver raw1394_driver = { - .name = "raw1394 Driver", - .id_table = raw1394_id_table, - .driver = { - .name = "raw1394", - .bus = &ieee1394_bus_type, - }, + .name = "raw1394 Driver", + .id_table = raw1394_id_table, + .driver = { + .name = "raw1394", + .bus = &ieee1394_bus_type, + }, }; - /******************************************************************************/ - static struct hpsb_highlevel raw1394_highlevel = { - .name = RAW1394_DEVICE_NAME, - .add_host = add_host, - .remove_host = remove_host, - .host_reset = host_reset, - .iso_receive = iso_receive, - .fcp_request = fcp_request, + .name = RAW1394_DEVICE_NAME, + .add_host = add_host, + .remove_host = remove_host, + .host_reset = host_reset, + .iso_receive = iso_receive, + .fcp_request = fcp_request, }; static struct cdev raw1394_cdev; static struct file_operations raw1394_fops = { - .owner = THIS_MODULE, - .read = raw1394_read, - .write = raw1394_write, - .mmap = raw1394_mmap, - .ioctl = raw1394_ioctl, - .poll = raw1394_poll, - .open = raw1394_open, - .release = raw1394_release, + .owner = THIS_MODULE, + .read = raw1394_read, + .write = raw1394_write, + .mmap = raw1394_mmap, + .ioctl = raw1394_ioctl, + .poll = raw1394_poll, + .open = raw1394_open, + .release = raw1394_release, }; static int __init init_raw1394(void) { - int ret; + int ret = 0; hpsb_register_highlevel(&raw1394_highlevel); - devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), - S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME); + if (IS_ERR(class_simple_device_add(hpsb_protocol_class, MKDEV( + IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), + NULL, RAW1394_DEVICE_NAME))) { + ret = -EFAULT; + goto out_unreg; + } + + devfs_mk_cdev(MKDEV( + IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), + S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME); cdev_init(&raw1394_cdev, &raw1394_fops); raw1394_cdev.owner = THIS_MODULE; kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME); ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1); if (ret) { - HPSB_ERR("raw1394 failed to register minor device block"); - devfs_remove(RAW1394_DEVICE_NAME); - hpsb_unregister_highlevel(&raw1394_highlevel); - return ret; - } + HPSB_ERR("raw1394 failed to register minor device block"); + goto out_dev; + } - HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME); + HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME); ret = hpsb_register_protocol(&raw1394_driver); if (ret) { HPSB_ERR("raw1394: failed to register protocol"); cdev_del(&raw1394_cdev); - devfs_remove(RAW1394_DEVICE_NAME); - hpsb_unregister_highlevel(&raw1394_highlevel); - return ret; + goto out_dev; } - return 0; + goto out; + +out_dev: + devfs_remove(RAW1394_DEVICE_NAME); + class_simple_device_remove(MKDEV( + IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)); +out_unreg: + hpsb_unregister_highlevel(&raw1394_highlevel); +out: + return ret; } static void __exit cleanup_raw1394(void) { + class_simple_device_remove(MKDEV( + IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16)); hpsb_unregister_protocol(&raw1394_driver); cdev_del(&raw1394_cdev); - devfs_remove(RAW1394_DEVICE_NAME); - hpsb_unregister_highlevel(&raw1394_highlevel); + devfs_remove(RAW1394_DEVICE_NAME); + hpsb_unregister_highlevel(&raw1394_highlevel); } module_init(init_raw1394); diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 125eb6c64f6ab5894ea51abd2a652c58030e90e7..68dca3fb29519849502ec48ba6736b0410c76e26 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -64,7 +64,10 @@ #include <asm/system.h> #include <asm/scatterlist.h> -#include "../scsi/scsi.h" +#include <scsi/scsi.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_dbg.h> +#include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include "csr1212.h" @@ -224,12 +227,12 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id u32 status); static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, - u32 scsi_status, Scsi_Cmnd *SCpnt, - void (*done)(Scsi_Cmnd *)); + u32 scsi_status, struct scsi_cmnd *SCpnt, + void (*done)(struct scsi_cmnd *)); -static Scsi_Host_Template scsi_driver_template; +static struct scsi_host_template scsi_driver_template; -const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; +static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; static void sbp2_host_reset(struct hpsb_host *host); @@ -373,7 +376,7 @@ static void sbp2_free_packet(struct hpsb_packet *packet) /* This is much like hpsb_node_write(), except it ignores the response * subaction and returns immediately. Can be used from interrupts. */ -int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr, +static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr, quadlet_t *buffer, size_t length) { struct hpsb_packet *packet; @@ -520,8 +523,8 @@ static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_ */ static struct sbp2_command_info *sbp2util_allocate_command_orb( struct scsi_id_instance_data *scsi_id, - Scsi_Cmnd *Current_SCpnt, - void (*Current_done)(Scsi_Cmnd *)) + struct scsi_cmnd *Current_SCpnt, + void (*Current_done)(struct scsi_cmnd *)) { struct list_head *lh; struct sbp2_command_info *command = NULL; @@ -1521,8 +1524,9 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, SBP2_DEBUG("sbp2_management_agent_addr = %x", (unsigned int) management_agent_addr); - } else + } else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) { scsi_id->sbp2_device_type_and_lun = kv->value.immediate; + } break; case SBP2_COMMAND_SET_SPEC_ID_KEY: @@ -1613,6 +1617,8 @@ static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, scsi_id->sbp2_unit_characteristics = unit_characteristics; scsi_id->sbp2_firmware_revision = firmware_revision; scsi_id->workarounds = workarounds; + if (ud->flags & UNIT_DIRECTORY_HAS_LUN) + scsi_id->sbp2_device_type_and_lun = ud->lun; } } @@ -1700,14 +1706,14 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, unsigned int scsi_use_sg, unsigned int scsi_request_bufflen, void *scsi_request_buffer, - unsigned char scsi_dir) + enum dma_data_direction dma_dir) + { struct sbp2scsi_host_info *hi = scsi_id->hi; struct scatterlist *sgpnt = (struct scatterlist *) scsi_request_buffer; struct sbp2_command_orb *command_orb = &command->command_orb; struct sbp2_unrestricted_page_table *scatter_gather_element = &command->scatter_gather_element[0]; - int dma_dir = scsi_to_pci_dma_dir (scsi_dir); u32 sg_count, sg_len, orb_direction; dma_addr_t sg_addr; int i; @@ -1730,22 +1736,22 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, * Get the direction of the transfer. If the direction is unknown, then use our * goofy table as a back-up. */ - switch (scsi_dir) { - case SCSI_DATA_NONE: + switch (dma_dir) { + case DMA_NONE: orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER; break; - case SCSI_DATA_WRITE: + case DMA_TO_DEVICE: orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA; break; - case SCSI_DATA_READ: + case DMA_FROM_DEVICE: orb_direction = ORB_DIRECTION_READ_FROM_MEDIA; break; - case SCSI_DATA_UNKNOWN: + case DMA_BIDIRECTIONAL: default: SBP2_ERR("SCSI data transfer direction not specified. " "Update the SBP2 direction table in sbp2.h if " "necessary for your application"); - print_command (scsi_cmd); + __scsi_print_command(scsi_cmd); orb_direction = sbp2scsi_direction_table[*scsi_cmd]; break; } @@ -2031,7 +2037,8 @@ static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, * This function is called in order to begin a regular SBP-2 command. */ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, - Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) + struct scsi_cmnd *SCpnt, + void (*done)(struct scsi_cmnd *)) { unchar *cmd = (unchar *) SCpnt->cmnd; unsigned int request_bufflen = SCpnt->request_bufflen; @@ -2040,7 +2047,7 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, SBP2_DEBUG("sbp2_send_command"); #if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP) printk("[scsi command]\n "); - print_command (cmd); + scsi_print_command(SCpnt); #endif SBP2_DEBUG("SCSI transfer size = %x", request_bufflen); SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg); @@ -2233,7 +2240,7 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense * response data translations for the SCSI stack */ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, - Scsi_Cmnd *SCpnt) + struct scsi_cmnd *SCpnt) { u8 *scsi_buf = SCpnt->request_buffer; u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun); @@ -2312,7 +2319,7 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest struct sbp2scsi_host_info *hi; struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp; u32 id; - Scsi_Cmnd *SCpnt = NULL; + struct scsi_cmnd *SCpnt = NULL; u32 scsi_status = SBP2_SCSI_STATUS_GOOD; struct sbp2_command_info *command; @@ -2454,7 +2461,8 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int dest * This routine is the main request entry routine for doing I/O. It is * called from the scsi stack directly. */ -static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, + void (*done)(struct scsi_cmnd *)) { struct scsi_id_instance_data *scsi_id = (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; @@ -2550,9 +2558,8 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id PCI_DMA_BIDIRECTIONAL); sbp2util_mark_command_completed(scsi_id, command); if (command->Current_SCpnt) { - void (*done)(Scsi_Cmnd *) = command->Current_done; command->Current_SCpnt->result = status << 16; - done (command->Current_SCpnt); + command->Current_done(command->Current_SCpnt); } } @@ -2565,8 +2572,8 @@ static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id * This can be called in interrupt context. */ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, - u32 scsi_status, Scsi_Cmnd *SCpnt, - void (*done)(Scsi_Cmnd *)) + u32 scsi_status, struct scsi_cmnd *SCpnt, + void (*done)(struct scsi_cmnd *)) { unsigned long flags; @@ -2611,8 +2618,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, * Debug stuff */ #if CONFIG_IEEE1394_SBP2_DEBUG >= 1 - print_command (SCpnt->cmnd); - print_sense("bh", SCpnt); + scsi_print_command(SCpnt); + scsi_print_sense("bh", SCpnt); #endif break; @@ -2620,7 +2627,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, case SBP2_SCSI_STATUS_SELECTION_TIMEOUT: SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT"); SCpnt->result = DID_NO_CONNECT << 16; - print_command (SCpnt->cmnd); + scsi_print_command(SCpnt); break; case SBP2_SCSI_STATUS_CONDITION_MET: @@ -2628,7 +2635,7 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, case SBP2_SCSI_STATUS_COMMAND_TERMINATED: SBP2_ERR("Bad SCSI status = %x", scsi_status); SCpnt->result = DID_ERROR << 16; - print_command (SCpnt->cmnd); + scsi_print_command(SCpnt); break; default: @@ -2688,7 +2695,7 @@ static int sbp2scsi_slave_configure (struct scsi_device *sdev) * Called by scsi stack when something has really gone wrong. Usually * called when a command has timed-out for some reason. */ -static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) +static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) { struct scsi_id_instance_data *scsi_id = (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; @@ -2696,7 +2703,7 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) struct sbp2_command_info *command; SBP2_ERR("aborting sbp2 command"); - print_command (SCpnt->cmnd); + scsi_print_command(SCpnt); if (scsi_id) { @@ -2717,9 +2724,8 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) PCI_DMA_BIDIRECTIONAL); sbp2util_mark_command_completed(scsi_id, command); if (command->Current_SCpnt) { - void (*done)(Scsi_Cmnd *) = command->Current_done; command->Current_SCpnt->result = DID_ABORT << 16; - done (command->Current_SCpnt); + command->Current_done(command->Current_SCpnt); } } @@ -2736,7 +2742,7 @@ static int sbp2scsi_abort (Scsi_Cmnd *SCpnt) /* * Called by scsi stack when something has really gone wrong. */ -static int sbp2scsi_reset (Scsi_Cmnd *SCpnt) +static int sbp2scsi_reset(struct scsi_cmnd *SCpnt) { struct scsi_id_instance_data *scsi_id = (struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; @@ -2789,7 +2795,7 @@ MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); MODULE_LICENSE("GPL"); /* SCSI host template */ -static Scsi_Host_Template scsi_driver_template = { +static struct scsi_host_template scsi_driver_template = { .module = THIS_MODULE, .name = "SBP-2 IEEE-1394", .proc_name = SBP2_DEVICE_NAME, diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 94b59f80bf90d43255001847e4054d94728289e6..a84b039a05b9430ee42074e3b4fbe15d7cd8f584 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -324,8 +324,8 @@ struct sbp2_command_info { struct list_head list; struct sbp2_command_orb command_orb ____cacheline_aligned; dma_addr_t command_orb_dma ____cacheline_aligned; - Scsi_Cmnd *Current_SCpnt; - void (*Current_done)(Scsi_Cmnd *); + struct scsi_cmnd *Current_SCpnt; + void (*Current_done)(struct scsi_cmnd *); /* Also need s/g structure for each sbp2 command */ struct sbp2_unrestricted_page_table scatter_gather_element[SG_ALL] ____cacheline_aligned; @@ -434,8 +434,8 @@ static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_ static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_instance_data *scsi_id, dma_addr_t orb); static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt); static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id, - Scsi_Cmnd *Current_SCpnt, - void (*Current_done)(Scsi_Cmnd *)); + struct scsi_cmnd *Current_SCpnt, + void (*Current_done)(struct scsi_cmnd *)); static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command); @@ -466,14 +466,16 @@ static int sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, unsigned int scsi_use_sg, unsigned int scsi_request_bufflen, void *scsi_request_buffer, - unsigned char scsi_dir); + enum dma_data_direction dma_dir); static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, struct sbp2_command_info *command); static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, - Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)); + struct scsi_cmnd *SCpnt, + void (*done)(struct scsi_cmnd *)); static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data); static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd); -static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *SCpnt); +static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, + struct scsi_cmnd *SCpnt); static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, struct unit_directory *ud); static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id); diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 3acc962296b13a4bb725a9a814944ad4fc3b13fd..2d9ec57b96514bcd1c630b1c267c80df1e061c17 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -16,14 +16,25 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * NOTES: + * + * jds -- add private data to file to keep track of iso contexts associated + * with each open -- so release won't kill all iso transfers. + * + * Damien Douxchamps: Fix failure when the number of DMA pages per frame is + * one. + * + * ioctl return codes: + * EFAULT is only for invalid address for the argp + * EINVAL for out of range values + * EBUSY when trying to use an already used resource + * ESRCH when trying to free/stop a not used resource + * EAGAIN for resource allocation failure that could perhaps succeed later + * ENOTTY for unsupported ioctl request + * */ -/* jds -- add private data to file to keep track of iso contexts associated - with each open -- so release won't kill all iso transfers */ - -/* Damien Douxchamps: Fix failure when the number of DMA pages per frame is - one */ - #include <linux/config.h> #include <linux/kernel.h> #include <linux/list.h> @@ -146,8 +157,8 @@ printk(level "video1394: " fmt "\n" , ## args) #define PRINT(level, card, fmt, args...) \ printk(level "video1394_%d: " fmt "\n" , card , ## args) -void wakeup_dma_ir_ctx(unsigned long l); -void wakeup_dma_it_ctx(unsigned long l); +static void wakeup_dma_ir_ctx(unsigned long l); +static void wakeup_dma_it_ctx(unsigned long l); static struct hpsb_highlevel video1394_highlevel; @@ -487,7 +498,7 @@ find_ctx(struct list_head *list, int type, int channel) return NULL; } -void wakeup_dma_ir_ctx(unsigned long l) +static void wakeup_dma_ir_ctx(unsigned long l) { struct dma_iso_ctx *d = (struct dma_iso_ctx *) l; int i; @@ -560,7 +571,7 @@ static inline void put_timestamp(struct ti_ohci *ohci, struct dma_iso_ctx * d, #endif } -void wakeup_dma_it_ctx(unsigned long l) +static void wakeup_dma_it_ctx(unsigned long l) { struct dma_iso_ctx *d = (struct dma_iso_ctx *) l; struct ti_ohci *ohci = d->ohci; @@ -723,7 +734,12 @@ static int __video1394_ioctl(struct file *file, /* if channel < 0, find lowest available one */ if (v.channel < 0) { mask = (u64)0x1; - for (i=0; i<ISO_CHANNELS; i++) { + for (i=0; ; i++) { + if (i == ISO_CHANNELS) { + PRINT(KERN_ERR, ohci->host->id, + "No free channel found"); + return EAGAIN; + } if (!(ohci->ISO_channel_usage & mask)) { v.channel = i; PRINT(KERN_INFO, ohci->host->id, "Found free channel %d", i); @@ -731,42 +747,40 @@ static int __video1394_ioctl(struct file *file, } mask = mask << 1; } - } - - if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) { + } else if (v.channel >= ISO_CHANNELS) { PRINT(KERN_ERR, ohci->host->id, "Iso channel %d out of bounds", v.channel); - return -EFAULT; + return -EINVAL; + } else { + mask = (u64)0x1<<v.channel; } - mask = (u64)0x1<<v.channel; - printk("mask: %08X%08X usage: %08X%08X\n", - (u32)(mask>>32),(u32)(mask&0xffffffff), - (u32)(ohci->ISO_channel_usage>>32), - (u32)(ohci->ISO_channel_usage&0xffffffff)); + PRINT(KERN_INFO, ohci->host->id, "mask: %08X%08X usage: %08X%08X\n", + (u32)(mask>>32),(u32)(mask&0xffffffff), + (u32)(ohci->ISO_channel_usage>>32), + (u32)(ohci->ISO_channel_usage&0xffffffff)); if (ohci->ISO_channel_usage & mask) { PRINT(KERN_ERR, ohci->host->id, "Channel %d is already taken", v.channel); - return -EFAULT; + return -EBUSY; } - ohci->ISO_channel_usage |= mask; if (v.buf_size == 0 || v.buf_size > VIDEO1394_MAX_SIZE) { PRINT(KERN_ERR, ohci->host->id, "Invalid %d length buffer requested",v.buf_size); - return -EFAULT; + return -EINVAL; } if (v.nb_buffers == 0 || v.nb_buffers > VIDEO1394_MAX_SIZE) { PRINT(KERN_ERR, ohci->host->id, "Invalid %d buffers requested",v.nb_buffers); - return -EFAULT; + return -EINVAL; } if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) { PRINT(KERN_ERR, ohci->host->id, "%d buffers of size %d bytes is too big", v.nb_buffers, v.buf_size); - return -EFAULT; + return -EINVAL; } if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) { @@ -777,7 +791,7 @@ static int __video1394_ioctl(struct file *file, if (d == NULL) { PRINT(KERN_ERR, ohci->host->id, "Couldn't allocate ir context"); - return -EFAULT; + return -EAGAIN; } initialize_dma_ir_ctx(d, v.sync_tag, v.flags); @@ -798,7 +812,7 @@ static int __video1394_ioctl(struct file *file, if (d == NULL) { PRINT(KERN_ERR, ohci->host->id, "Couldn't allocate it context"); - return -EFAULT; + return -EAGAIN; } initialize_dma_it_ctx(d, v.sync_tag, v.syt_offset, v.flags); @@ -814,8 +828,12 @@ static int __video1394_ioctl(struct file *file, v.channel); } - if (copy_to_user(argp, &v, sizeof(v))) + if (copy_to_user((void *)arg, &v, sizeof(v))) { + /* FIXME : free allocated dma resources */ return -EFAULT; + } + + ohci->ISO_channel_usage |= mask; return 0; } @@ -829,16 +847,16 @@ static int __video1394_ioctl(struct file *file, if (copy_from_user(&channel, argp, sizeof(int))) return -EFAULT; - if (channel<0 || channel>(ISO_CHANNELS-1)) { + if (channel < 0 || channel >= ISO_CHANNELS) { PRINT(KERN_ERR, ohci->host->id, "Iso channel %d out of bound", channel); - return -EFAULT; + return -EINVAL; } mask = (u64)0x1<<channel; if (!(ohci->ISO_channel_usage & mask)) { PRINT(KERN_ERR, ohci->host->id, "Channel %d is not being used", channel); - return -EFAULT; + return -ESRCH; } /* Mark this channel as unused */ @@ -849,7 +867,7 @@ static int __video1394_ioctl(struct file *file, else d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel); - if (d == NULL) return -EFAULT; + if (d == NULL) return -ESRCH; PRINT(KERN_INFO, ohci->host->id, "Iso context %d " "stop talking on channel %d", d->ctx, channel); free_dma_iso_ctx(d); @@ -870,7 +888,7 @@ static int __video1394_ioctl(struct file *file, if ((v.buffer<0) || (v.buffer>d->num_desc)) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); - return -EFAULT; + return -EINVAL; } spin_lock_irqsave(&d->lock,flags); @@ -879,7 +897,7 @@ static int __video1394_ioctl(struct file *file, PRINT(KERN_ERR, ohci->host->id, "Buffer %d is already used",v.buffer); spin_unlock_irqrestore(&d->lock,flags); - return -EFAULT; + return -EBUSY; } d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; @@ -933,7 +951,7 @@ static int __video1394_ioctl(struct file *file, if ((v.buffer<0) || (v.buffer>d->num_desc)) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); - return -EFAULT; + return -EINVAL; } /* @@ -976,7 +994,7 @@ static int __video1394_ioctl(struct file *file, PRINT(KERN_ERR, ohci->host->id, "Buffer %d is not queued",v.buffer); spin_unlock_irqrestore(&d->lock, flags); - return -EFAULT; + return -ESRCH; } /* set time of buffer */ @@ -1015,7 +1033,7 @@ static int __video1394_ioctl(struct file *file, if ((v.buffer<0) || (v.buffer>d->num_desc)) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); - return -EFAULT; + return -EINVAL; } if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) { @@ -1044,7 +1062,7 @@ static int __video1394_ioctl(struct file *file, spin_unlock_irqrestore(&d->lock,flags); if (psizes) kfree(psizes); - return -EFAULT; + return -EBUSY; } if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) { @@ -1118,7 +1136,7 @@ static int __video1394_ioctl(struct file *file, if ((v.buffer<0) || (v.buffer>d->num_desc)) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); - return -EFAULT; + return -EINVAL; } switch(d->buffer_status[v.buffer]) { @@ -1144,11 +1162,11 @@ static int __video1394_ioctl(struct file *file, default: PRINT(KERN_ERR, ohci->host->id, "Buffer %d is not queued",v.buffer); - return -EFAULT; + return -ESRCH; } } default: - return -EINVAL; + return -ENOTTY; } } @@ -1170,7 +1188,7 @@ static long video1394_ioctl(struct file *file, unsigned int cmd, unsigned long a * But e.g. pte_alloc() does not work in modules ... :-( */ -int video1394_mmap(struct file *file, struct vm_area_struct *vma) +static int video1394_mmap(struct file *file, struct vm_area_struct *vma) { struct file_ctx *ctx = (struct file_ctx *)file->private_data; int res = -EINVAL; @@ -1269,6 +1287,16 @@ static struct ieee1394_device_id video1394_id_table[] = { .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, .version = CAMERA_SW_VERSION_ENTRY & 0xffffff }, + { + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff + }, + { + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, + .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, + .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff + }, { } }; @@ -1304,6 +1332,9 @@ static void video1394_add_host (struct hpsb_host *host) hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id); minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id; + class_simple_device_add(hpsb_protocol_class, MKDEV( + IEEE1394_MAJOR, minor), + NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id); devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor), S_IFCHR | S_IRUSR | S_IWUSR, "%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id); @@ -1314,9 +1345,12 @@ static void video1394_remove_host (struct hpsb_host *host) { struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host); - if (ohci) + if (ohci) { + class_simple_device_remove(MKDEV(IEEE1394_MAJOR, + IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id)); devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id); - + } + return; }