diff options
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r-- | drivers/ieee1394/csr1212.c | 2 | ||||
-rw-r--r-- | drivers/ieee1394/dv1394.c | 23 | ||||
-rw-r--r-- | drivers/ieee1394/eth1394.c | 2 | ||||
-rw-r--r-- | drivers/ieee1394/hosts.c | 4 | ||||
-rw-r--r-- | drivers/ieee1394/nodemgr.c | 293 | ||||
-rw-r--r-- | drivers/ieee1394/nodemgr.h | 2 | ||||
-rw-r--r-- | drivers/ieee1394/raw1394-private.h | 1 | ||||
-rw-r--r-- | drivers/ieee1394/raw1394.c | 241 | ||||
-rw-r--r-- | drivers/ieee1394/sbp2.c | 218 | ||||
-rw-r--r-- | drivers/ieee1394/sbp2.h | 33 | ||||
-rw-r--r-- | drivers/ieee1394/video1394.c | 13 |
11 files changed, 374 insertions, 458 deletions
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c index 9f95337139e..5e38a68b8af 100644 --- a/drivers/ieee1394/csr1212.c +++ b/drivers/ieee1394/csr1212.c @@ -84,7 +84,7 @@ static const u8 csr1212_key_id_type_map[0x30] = { #define quads_to_bytes(_q) ((_q) * sizeof(u32)) -#define bytes_to_quads(_b) (((_b) + sizeof(u32) - 1) / sizeof(u32)) +#define bytes_to_quads(_b) DIV_ROUND_UP(_b, sizeof(u32)) static void free_keyval(struct csr1212_keyval *kv) { diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index b6eb2cf2591..c19f2326715 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c @@ -918,7 +918,7 @@ static int do_dv1394_init(struct video_card *video, struct dv1394_init *init) /* default SYT offset is 3 cycles */ init->syt_offset = 3; - if ( (init->channel > 63) || (init->channel < 0) ) + if (init->channel > 63) init->channel = 63; chan_mask = (u64)1 << init->channel; @@ -1270,8 +1270,14 @@ static int dv1394_mmap(struct file *file, struct vm_area_struct *vma) struct video_card *video = file_to_video_card(file); int retval = -EINVAL; - /* serialize mmap */ - mutex_lock(&video->mtx); + /* + * We cannot use the blocking variant mutex_lock here because .mmap + * is called with mmap_sem held, while .ioctl, .read, .write acquire + * video->mtx and subsequently call copy_to/from_user which will + * grab mmap_sem in case of a page fault. + */ + if (!mutex_trylock(&video->mtx)) + return -EAGAIN; if ( ! video_card_initialized(video) ) { retval = do_dv1394_init_default(video); @@ -1828,9 +1834,6 @@ static int dv1394_release(struct inode *inode, struct file *file) /* OK to free the DMA buffer, no more mappings can exist */ do_dv1394_shutdown(video, 1); - /* clean up async I/O users */ - dv1394_fasync(-1, file, 0); - /* give someone else a turn */ clear_bit(0, &video->open); @@ -2296,10 +2299,10 @@ static void dv1394_add_host(struct hpsb_host *host) ohci = (struct ti_ohci *)host->hostdata; - device_create_drvdata(hpsb_protocol_class, NULL, - MKDEV(IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), NULL, - "dv1394-%d", id); + device_create(hpsb_protocol_class, NULL, + MKDEV(IEEE1394_MAJOR, + IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), + NULL, "dv1394-%d", id); dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT); diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index b166b3575fa..20128692b33 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -1361,7 +1361,7 @@ static unsigned int ether1394_encapsulate_prep(unsigned int max_payload, hdr->ff.dgl = dgl; adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF]; } - return (dg_size + adj_max_payload - 1) / adj_max_payload; + return DIV_ROUND_UP(dg_size, adj_max_payload); } static unsigned int ether1394_encapsulate(struct sk_buff *skb, diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index 8dd09d85041..237d0c9d69c 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c @@ -155,11 +155,11 @@ struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device)); h->device.parent = dev; set_dev_node(&h->device, dev_to_node(dev)); - snprintf(h->device.bus_id, BUS_ID_SIZE, "fw-host%d", h->id); + dev_set_name(&h->device, "fw-host%d", h->id); h->host_dev.parent = &h->device; h->host_dev.class = &hpsb_host_class; - snprintf(h->host_dev.bus_id, BUS_ID_SIZE, "fw-host%d", h->id); + dev_set_name(&h->host_dev, "fw-host%d", h->id); if (device_register(&h->device)) goto fail; diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 16240a78965..9e39f73282e 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -154,9 +154,6 @@ struct host_info { static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env); -static void nodemgr_resume_ne(struct node_entry *ne); -static void nodemgr_remove_ne(struct node_entry *ne); -static struct node_entry *find_entry_by_guid(u64 guid); struct bus_type ieee1394_bus_type = { .name = "ieee1394", @@ -385,27 +382,6 @@ static ssize_t fw_get_ignore_driver(struct device *dev, struct device_attribute static DEVICE_ATTR(ignore_driver, S_IWUSR | S_IRUGO, fw_get_ignore_driver, fw_set_ignore_driver); -static ssize_t fw_set_destroy_node(struct bus_type *bus, const char *buf, size_t count) -{ - struct node_entry *ne; - u64 guid = (u64)simple_strtoull(buf, NULL, 16); - - ne = find_entry_by_guid(guid); - - if (ne == NULL || !ne->in_limbo) - return -EINVAL; - - nodemgr_remove_ne(ne); - - return count; -} -static ssize_t fw_get_destroy_node(struct bus_type *bus, char *buf) -{ - return sprintf(buf, "You can destroy in_limbo nodes by writing their GUID to this file\n"); -} -static BUS_ATTR(destroy_node, S_IWUSR | S_IRUGO, fw_get_destroy_node, fw_set_destroy_node); - - static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, size_t count) { @@ -442,7 +418,6 @@ static BUS_ATTR(ignore_drivers, S_IWUSR | S_IRUGO, fw_get_ignore_drivers, fw_set struct bus_attribute *const fw_bus_attrs[] = { - &bus_attr_destroy_node, &bus_attr_rescan, &bus_attr_ignore_drivers, NULL @@ -734,10 +709,10 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv) static DEFINE_MUTEX(nodemgr_serialize_remove_uds); -static int __match_ne(struct device *dev, void *data) +static int match_ne(struct device *dev, void *data) { struct unit_directory *ud; - struct node_entry *ne = (struct node_entry *)data; + struct node_entry *ne = data; ud = container_of(dev, struct unit_directory, unit_dev); return ud->ne == ne; @@ -754,8 +729,7 @@ static void nodemgr_remove_uds(struct node_entry *ne) */ mutex_lock(&nodemgr_serialize_remove_uds); for (;;) { - dev = class_find_device(&nodemgr_ud_class, NULL, ne, - __match_ne); + dev = class_find_device(&nodemgr_ud_class, NULL, ne, match_ne); if (!dev) break; ud = container_of(dev, struct unit_directory, unit_dev); @@ -785,7 +759,7 @@ static void nodemgr_remove_ne(struct node_entry *ne) put_device(dev); } -static int __nodemgr_remove_host_dev(struct device *dev, void *data) +static int remove_host_dev(struct device *dev, void *data) { if (dev->bus == &ieee1394_bus_type) nodemgr_remove_ne(container_of(dev, struct node_entry, @@ -795,7 +769,7 @@ static int __nodemgr_remove_host_dev(struct device *dev, void *data) static void nodemgr_remove_host_dev(struct device *dev) { - WARN_ON(device_for_each_child(dev, NULL, __nodemgr_remove_host_dev)); + device_for_each_child(dev, NULL, remove_host_dev); sysfs_remove_link(&dev->kobj, "irm_id"); sysfs_remove_link(&dev->kobj, "busmgr_id"); sysfs_remove_link(&dev->kobj, "host_id"); @@ -830,11 +804,10 @@ static void nodemgr_update_bus_options(struct node_entry *ne) } -static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr *csr, - struct host_info *hi, nodeid_t nodeid, - unsigned int generation) +static struct node_entry *nodemgr_create_node(octlet_t guid, + struct csr1212_csr *csr, struct hpsb_host *host, + nodeid_t nodeid, unsigned int generation) { - struct hpsb_host *host = hi->host; struct node_entry *ne; ne = kzalloc(sizeof(*ne), GFP_KERNEL); @@ -853,13 +826,11 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr memcpy(&ne->device, &nodemgr_dev_template_ne, sizeof(ne->device)); ne->device.parent = &host->device; - snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx", - (unsigned long long)(ne->guid)); + dev_set_name(&ne->device, "%016Lx", (unsigned long long)(ne->guid)); ne->node_dev.parent = &ne->device; ne->node_dev.class = &nodemgr_ne_class; - snprintf(ne->node_dev.bus_id, BUS_ID_SIZE, "%016Lx", - (unsigned long long)(ne->guid)); + dev_set_name(&ne->node_dev, "%016Lx", (unsigned long long)(ne->guid)); if (device_register(&ne->device)) goto fail_devreg; @@ -888,10 +859,10 @@ fail_alloc: return NULL; } -static int __match_ne_guid(struct device *dev, void *data) +static int match_ne_guid(struct device *dev, void *data) { struct node_entry *ne; - u64 *guid = (u64 *)data; + u64 *guid = data; ne = container_of(dev, struct node_entry, node_dev); return ne->guid == *guid; @@ -902,8 +873,7 @@ static struct node_entry *find_entry_by_guid(u64 guid) struct device *dev; struct node_entry *ne; - dev = class_find_device(&nodemgr_ne_class, NULL, &guid, - __match_ne_guid); + dev = class_find_device(&nodemgr_ne_class, NULL, &guid, match_ne_guid); if (!dev) return NULL; ne = container_of(dev, struct node_entry, node_dev); @@ -912,21 +882,21 @@ static struct node_entry *find_entry_by_guid(u64 guid) return ne; } -struct match_nodeid_param { +struct match_nodeid_parameter { struct hpsb_host *host; nodeid_t nodeid; }; -static int __match_ne_nodeid(struct device *dev, void *data) +static int match_ne_nodeid(struct device *dev, void *data) { int found = 0; struct node_entry *ne; - struct match_nodeid_param *param = (struct match_nodeid_param *)data; + struct match_nodeid_parameter *p = data; if (!dev) goto ret; ne = container_of(dev, struct node_entry, node_dev); - if (ne->host == param->host && ne->nodeid == param->nodeid) + if (ne->host == p->host && ne->nodeid == p->nodeid) found = 1; ret: return found; @@ -937,13 +907,12 @@ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, { struct device *dev; struct node_entry *ne; - struct match_nodeid_param param; + struct match_nodeid_parameter p; - param.host = host; - param.nodeid = nodeid; + p.host = host; + p.nodeid = nodeid; - dev = class_find_device(&nodemgr_ne_class, NULL, ¶m, - __match_ne_nodeid); + dev = class_find_device(&nodemgr_ne_class, NULL, &p, match_ne_nodeid); if (!dev) return NULL; ne = container_of(dev, struct node_entry, node_dev); @@ -961,13 +930,11 @@ static void nodemgr_register_device(struct node_entry *ne, ud->device.parent = parent; - snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u", - ne->device.bus_id, ud->id); + dev_set_name(&ud->device, "%s-%u", dev_name(&ne->device), ud->id); ud->unit_dev.parent = &ud->device; ud->unit_dev.class = &nodemgr_ud_class; - snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u", - ne->device.bus_id, ud->id); + dev_set_name(&ud->unit_dev, "%s-%u", dev_name(&ne->device), ud->id); if (device_register(&ud->device)) goto fail_devreg; @@ -982,7 +949,7 @@ static void nodemgr_register_device(struct node_entry *ne, fail_classdevreg: device_unregister(&ud->device); fail_devreg: - HPSB_ERR("Failed to create unit %s", ud->device.bus_id); + HPSB_ERR("Failed to create unit %s", dev_name(&ud->device)); } @@ -990,7 +957,7 @@ fail_devreg: * immediate unit directories looking for software_id and * software_version entries, in order to get driver autoloading working. */ static struct unit_directory *nodemgr_process_unit_directory - (struct host_info *hi, struct node_entry *ne, struct csr1212_keyval *ud_kv, + (struct node_entry *ne, struct csr1212_keyval *ud_kv, unsigned int *id, struct unit_directory *parent) { struct unit_directory *ud; @@ -1083,7 +1050,7 @@ static struct unit_directory *nodemgr_process_unit_directory nodemgr_register_device(ne, ud, &ne->device); /* process the child unit */ - ud_child = nodemgr_process_unit_directory(hi, ne, kv, id, ud); + ud_child = nodemgr_process_unit_directory(ne, kv, id, ud); if (ud_child == NULL) break; @@ -1137,7 +1104,7 @@ unit_directory_error: } -static void nodemgr_process_root_directory(struct host_info *hi, struct node_entry *ne) +static void nodemgr_process_root_directory(struct node_entry *ne) { unsigned int ud_id = 0; struct csr1212_dentry *dentry; @@ -1157,7 +1124,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent break; case CSR1212_KV_ID_UNIT: - nodemgr_process_unit_directory(hi, ne, kv, &ud_id, NULL); + nodemgr_process_unit_directory(ne, kv, &ud_id, NULL); break; case CSR1212_KV_ID_DESCRIPTOR: @@ -1273,8 +1240,7 @@ void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver) * the to take whatever actions required. */ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr, - struct host_info *hi, nodeid_t nodeid, - unsigned int generation) + nodeid_t nodeid, unsigned int generation) { if (ne->nodeid != nodeid) { HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT, @@ -1305,19 +1271,23 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr, csr1212_destroy_csr(csr); } - if (ne->in_limbo) - nodemgr_resume_ne(ne); - /* Mark the node current */ ne->generation = generation; -} + if (ne->in_limbo) { + device_remove_file(&ne->device, &dev_attr_ne_in_limbo); + ne->in_limbo = false; + HPSB_DEBUG("Node reactivated: " + "ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", + NODE_BUS_ARGS(ne->host, ne->nodeid), + (unsigned long long)ne->guid); + } +} -static void nodemgr_node_scan_one(struct host_info *hi, +static void nodemgr_node_scan_one(struct hpsb_host *host, nodeid_t nodeid, int generation) { - struct hpsb_host *host = hi->host; struct node_entry *ne; octlet_t guid; struct csr1212_csr *csr; @@ -1373,16 +1343,15 @@ static void nodemgr_node_scan_one(struct host_info *hi, } if (!ne) - nodemgr_create_node(guid, csr, hi, nodeid, generation); + nodemgr_create_node(guid, csr, host, nodeid, generation); else - nodemgr_update_node(ne, csr, hi, nodeid, generation); + nodemgr_update_node(ne, csr, nodeid, generation); } -static void nodemgr_node_scan(struct host_info *hi, int generation) +static void nodemgr_node_scan(struct hpsb_host *host, int generation) { int count; - struct hpsb_host *host = hi->host; struct selfid *sid = (struct selfid *)host->topology_map; nodeid_t nodeid = LOCAL_BUS; @@ -1395,89 +1364,26 @@ static void nodemgr_node_scan(struct host_info *hi, int generation) nodeid++; continue; } - nodemgr_node_scan_one(hi, nodeid++, generation); - } -} - -static int __nodemgr_driver_suspend(struct device *dev, void *data) -{ - struct unit_directory *ud; - struct device_driver *drv; - struct node_entry *ne = (struct node_entry *)data; - int error; - - ud = container_of(dev, struct unit_directory, unit_dev); - if (ud->ne == ne) { - drv = get_driver(ud->device.driver); - if (drv) { - error = 1; /* release if suspend is not implemented */ - if (drv->suspend) { - down(&ud->device.sem); - error = drv->suspend(&ud->device, PMSG_SUSPEND); - up(&ud->device.sem); - } - if (error) - device_release_driver(&ud->device); - put_driver(drv); - } - } - - return 0; -} - -static int __nodemgr_driver_resume(struct device *dev, void *data) -{ - struct unit_directory *ud; - struct device_driver *drv; - struct node_entry *ne = (struct node_entry *)data; - - ud = container_of(dev, struct unit_directory, unit_dev); - if (ud->ne == ne) { - drv = get_driver(ud->device.driver); - if (drv) { - if (drv->resume) { - down(&ud->device.sem); - drv->resume(&ud->device); - up(&ud->device.sem); - } - put_driver(drv); - } + nodemgr_node_scan_one(host, nodeid++, generation); } - - return 0; } -static void nodemgr_suspend_ne(struct node_entry *ne) +static void nodemgr_pause_ne(struct node_entry *ne) { - HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", + HPSB_DEBUG("Node paused: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); - ne->in_limbo = 1; + ne->in_limbo = true; WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo)); - - class_for_each_device(&nodemgr_ud_class, NULL, ne, - __nodemgr_driver_suspend); -} - - -static void nodemgr_resume_ne(struct node_entry *ne) -{ - ne->in_limbo = 0; - device_remove_file(&ne->device, &dev_attr_ne_in_limbo); - - class_for_each_device(&nodemgr_ud_class, NULL, ne, - __nodemgr_driver_resume); - HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", - NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); } -static int __nodemgr_update_pdrv(struct device *dev, void *data) +static int update_pdrv(struct device *dev, void *data) { struct unit_directory *ud; struct device_driver *drv; struct hpsb_protocol_driver *pdrv; - struct node_entry *ne = (struct node_entry *)data; + struct node_entry *ne = data; int error; ud = container_of(dev, struct unit_directory, unit_dev); @@ -1503,11 +1409,9 @@ static int __nodemgr_update_pdrv(struct device *dev, void *data) static void nodemgr_update_pdrv(struct node_entry *ne) { - class_for_each_device(&nodemgr_ud_class, NULL, ne, - __nodemgr_update_pdrv); + class_for_each_device(&nodemgr_ud_class, NULL, ne, update_pdrv); } - /* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3. This * seems like an optional service but in the end it is practically mandatory * as a consequence of these clauses. @@ -1535,11 +1439,12 @@ static void nodemgr_irm_write_bc(struct node_entry *ne, int generation) } -static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation) +static void nodemgr_probe_ne(struct hpsb_host *host, struct node_entry *ne, + int generation) { struct device *dev; - if (ne->host != hi->host || ne->in_limbo) + if (ne->host != host || ne->in_limbo) return; dev = get_device(&ne->device); @@ -1554,40 +1459,40 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge * down to the drivers. Otherwise, this is a dead node and we * suspend it. */ if (ne->needs_probe) - nodemgr_process_root_directory(hi, ne); + nodemgr_process_root_directory(ne); else if (ne->generation == generation) nodemgr_update_pdrv(ne); else - nodemgr_suspend_ne(ne); + nodemgr_pause_ne(ne); put_device(dev); } -struct probe_param { - struct host_info *hi; +struct node_probe_parameter { + struct hpsb_host *host; int generation; bool probe_now; }; static int node_probe(struct device *dev, void *data) { - struct probe_param *p = data; + struct node_probe_parameter *p = data; struct node_entry *ne; - if (p->generation != get_hpsb_generation(p->hi->host)) + if (p->generation != get_hpsb_generation(p->host)) return -EAGAIN; ne = container_of(dev, struct node_entry, node_dev); if (ne->needs_probe == p->probe_now) - nodemgr_probe_ne(p->hi, ne, p->generation); + nodemgr_probe_ne(p->host, ne, p->generation); return 0; } -static void nodemgr_node_probe(struct host_info *hi, int generation) +static int nodemgr_node_probe(struct hpsb_host *host, int generation) { - struct probe_param p; + struct node_probe_parameter p; - p.hi = hi; + p.host = host; p.generation = generation; /* * Do some processing of the nodes we've probed. This pulls them @@ -1604,11 +1509,11 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) */ p.probe_now = false; if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0) - return; + return 0; p.probe_now = true; if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0) - return; + return 0; /* * Now let's tell the bus to rescan our devices. This may seem * like overhead, but the driver-model core will only scan a @@ -1620,6 +1525,27 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) */ if (bus_rescan_devices(&ieee1394_bus_type) != 0) HPSB_DEBUG("bus_rescan_devices had an error"); + + return 1; +} + +static int remove_nodes_in_limbo(struct device *dev, void *data) +{ + struct node_entry *ne; + + if (dev->bus != &ieee1394_bus_type) + return 0; + + ne = container_of(dev, struct node_entry, device); + if (ne->in_limbo) + nodemgr_remove_ne(ne); + + return 0; +} + +static void nodemgr_remove_nodes_in_limbo(struct hpsb_host *host) +{ + device_for_each_child(&host->device, NULL, remove_nodes_in_limbo); } static int nodemgr_send_resume_packet(struct hpsb_host *host) @@ -1730,10 +1656,9 @@ static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles) return 1; } -static int nodemgr_host_thread(void *__hi) +static int nodemgr_host_thread(void *data) { - struct host_info *hi = (struct host_info *)__hi; - struct hpsb_host *host = hi->host; + struct hpsb_host *host = data; unsigned int g, generation = 0; int i, reset_cycles = 0; @@ -1787,36 +1712,48 @@ static int nodemgr_host_thread(void *__hi) * entries. This does not do the sysfs stuff, since that * would trigger uevents and such, which is a bad idea at * this point. */ - nodemgr_node_scan(hi, generation); + nodemgr_node_scan(host, generation); /* This actually does the full probe, with sysfs * registration. */ - nodemgr_node_probe(hi, generation); + if (!nodemgr_node_probe(host, generation)) + continue; /* Update some of our sysfs symlinks */ nodemgr_update_host_dev_links(host); + + /* Sleep 3 seconds */ + for (i = 3000/200; i; i--) { + msleep_interruptible(200); + if (kthread_should_stop()) + goto exit; + + if (generation != get_hpsb_generation(host)) + break; + } + /* Remove nodes which are gone, unless a bus reset happened */ + if (!i) + nodemgr_remove_nodes_in_limbo(host); } exit: HPSB_VERBOSE("NodeMgr: Exiting thread"); return 0; } -struct host_iter_param { +struct per_host_parameter { void *data; int (*cb)(struct hpsb_host *, void *); }; -static int __nodemgr_for_each_host(struct device *dev, void *data) +static int per_host(struct device *dev, void *data) { struct hpsb_host *host; - struct host_iter_param *hip = (struct host_iter_param *)data; - int error = 0; + struct per_host_parameter *p = data; host = container_of(dev, struct hpsb_host, host_dev); - error = hip->cb(host, hip->data); - - return error; + return p->cb(host, p->data); } + /** * nodemgr_for_each_host - call a function for each IEEE 1394 host * @data: an address to supply to the callback @@ -1831,15 +1768,11 @@ static int __nodemgr_for_each_host(struct device *dev, void *data) */ int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)) { - struct host_iter_param hip; - int error; - - hip.cb = cb; - hip.data = data; - error = class_for_each_device(&hpsb_host_class, NULL, &hip, - __nodemgr_for_each_host); + struct per_host_parameter p; - return error; + p.cb = cb; + p.data = data; + return class_for_each_device(&hpsb_host_class, NULL, &p, per_host); } /* The following two convenience functions use a struct node_entry @@ -1893,7 +1826,7 @@ static void nodemgr_add_host(struct hpsb_host *host) return; } hi->host = host; - hi->thread = kthread_run(nodemgr_host_thread, hi, "knodemgrd_%d", + hi->thread = kthread_run(nodemgr_host_thread, host, "knodemgrd_%d", host->id); if (IS_ERR(hi->thread)) { HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id); diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index 6eb26465a84..4f287a3561b 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h @@ -110,7 +110,7 @@ struct node_entry { struct device node_dev; /* Means this node is not attached anymore */ - int in_limbo; + bool in_limbo; struct csr1212_csr *csr; }; diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h index a06aaad5b44..7a225a40598 100644 --- a/drivers/ieee1394/raw1394-private.h +++ b/drivers/ieee1394/raw1394-private.h @@ -22,6 +22,7 @@ enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0, struct file_info { struct list_head list; + struct mutex state_mutex; enum { opened, initialized, connected } state; unsigned int protocol_version; diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 6fa9e4a2184..bf7e761c12b 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -34,6 +34,7 @@ #include <linux/fs.h> #include <linux/poll.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/vmalloc.h> @@ -2267,6 +2268,9 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, return -EFAULT; } + if (!mutex_trylock(&fi->state_mutex)) + return -EAGAIN; + switch (fi->state) { case opened: retval = state_opened(fi, req); @@ -2281,6 +2285,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, break; } + mutex_unlock(&fi->state_mutex); + if (retval < 0) { free_pending_request(req); } else { @@ -2541,109 +2547,121 @@ static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr) static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) { struct file_info *fi = file->private_data; + int ret; + + if (!mutex_trylock(&fi->state_mutex)) + return -EAGAIN; if (fi->iso_state == RAW1394_ISO_INACTIVE) - return -EINVAL; + ret = -EINVAL; + else + ret = dma_region_mmap(&fi->iso_handle->data_buf, file, vma); + + mutex_unlock(&fi->state_mutex); - return dma_region_mmap(&fi->iso_handle->data_buf, file, vma); + return ret; } -/* ioctl is only used for rawiso operations */ -static long do_raw1394_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +static long raw1394_ioctl_inactive(struct file_info *fi, unsigned int cmd, + void __user *argp) +{ + switch (cmd) { + case RAW1394_IOC_ISO_XMIT_INIT: + return raw1394_iso_xmit_init(fi, argp); + case RAW1394_IOC_ISO_RECV_INIT: + return raw1394_iso_recv_init(fi, argp); + default: + return -EINVAL; + } +} + +static long raw1394_ioctl_recv(struct file_info *fi, unsigned int cmd, + unsigned long arg) { - struct file_info *fi = file->private_data; void __user *argp = (void __user *)arg; - switch (fi->iso_state) { - case RAW1394_ISO_INACTIVE: - switch (cmd) { - case RAW1394_IOC_ISO_XMIT_INIT: - return raw1394_iso_xmit_init(fi, argp); - case RAW1394_IOC_ISO_RECV_INIT: - return raw1394_iso_recv_init(fi, argp); - default: - break; + switch (cmd) { + case RAW1394_IOC_ISO_RECV_START:{ + 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]); } - 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]); - } - 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); - 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); - } - 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); - case RAW1394_IOC_ISO_RECV_FLUSH: - return hpsb_iso_recv_flush(fi->iso_handle); - case RAW1394_IOC_ISO_SHUTDOWN: - raw1394_iso_shutdown(fi); - return 0; - case RAW1394_IOC_ISO_QUEUE_ACTIVITY: - queue_rawiso_event(fi); - return 0; + 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); + 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:{ + u64 mask; + + if (copy_from_user(&mask, argp, sizeof(mask))) + return -EFAULT; + return hpsb_iso_recv_set_channel_mask(fi->iso_handle, + mask); } - 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]); - } - case RAW1394_IOC_ISO_XMIT_SYNC: - return hpsb_iso_xmit_sync(fi->iso_handle); - case RAW1394_IOC_ISO_XMIT_RECV_STOP: - hpsb_iso_stop(fi->iso_handle); - return 0; - case RAW1394_IOC_ISO_GET_STATUS: - return raw1394_iso_get_status(fi, argp); - case RAW1394_IOC_ISO_XMIT_PACKETS: - return raw1394_iso_send_packets(fi, argp); - case RAW1394_IOC_ISO_SHUTDOWN: - raw1394_iso_shutdown(fi); - return 0; - case RAW1394_IOC_ISO_QUEUE_ACTIVITY: - queue_rawiso_event(fi); - return 0; + 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); + case RAW1394_IOC_ISO_RECV_FLUSH: + return hpsb_iso_recv_flush(fi->iso_handle); + case RAW1394_IOC_ISO_SHUTDOWN: + raw1394_iso_shutdown(fi); + return 0; + case RAW1394_IOC_ISO_QUEUE_ACTIVITY: + queue_rawiso_event(fi); + return 0; + default: + return -EINVAL; + } +} + +static long raw1394_ioctl_xmit(struct file_info *fi, unsigned int cmd, + void __user *argp) +{ + switch (cmd) { + case RAW1394_IOC_ISO_XMIT_START:{ + 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]); } - break; + case RAW1394_IOC_ISO_XMIT_SYNC: + return hpsb_iso_xmit_sync(fi->iso_handle); + case RAW1394_IOC_ISO_XMIT_RECV_STOP: + hpsb_iso_stop(fi->iso_handle); + return 0; + case RAW1394_IOC_ISO_GET_STATUS: + return raw1394_iso_get_status(fi, argp); + case RAW1394_IOC_ISO_XMIT_PACKETS: + return raw1394_iso_send_packets(fi, argp); + case RAW1394_IOC_ISO_SHUTDOWN: + raw1394_iso_shutdown(fi); + return 0; + case RAW1394_IOC_ISO_QUEUE_ACTIVITY: + queue_rawiso_event(fi); + return 0; default: - break; + return -EINVAL; } +} + +/* ioctl is only used for rawiso operations */ +static long raw1394_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct file_info *fi = file->private_data; + void __user *argp = (void __user *)arg; + long ret; /* state-independent commands */ switch(cmd) { @@ -2653,16 +2671,26 @@ static long do_raw1394_ioctl(struct file *file, unsigned int cmd, break; } - return -EINVAL; -} + if (!mutex_trylock(&fi->state_mutex)) + return -EAGAIN; + + switch (fi->iso_state) { + case RAW1394_ISO_INACTIVE: + ret = raw1394_ioctl_inactive(fi, cmd, argp); + break; + case RAW1394_ISO_RECV: + ret = raw1394_ioctl_recv(fi, cmd, arg); + break; + case RAW1394_ISO_XMIT: + ret = raw1394_ioctl_xmit(fi, cmd, argp); + break; + default: + ret = -EINVAL; + break; + } + + mutex_unlock(&fi->state_mutex); -static long raw1394_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - long ret; - lock_kernel(); - ret = do_raw1394_ioctl(file, cmd, arg); - unlock_kernel(); return ret; } @@ -2700,7 +2728,7 @@ static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd, !copy_from_user(&infos32, &arg->infos, sizeof infos32)) { infos = compat_ptr(infos32); if (!copy_to_user(&dst->infos, &infos, sizeof infos)) - err = do_raw1394_ioctl(file, cmd, (unsigned long)dst); + err = raw1394_ioctl(file, cmd, (unsigned long)dst); } return err; } @@ -2724,7 +2752,6 @@ static long raw1394_compat_ioctl(struct file *file, void __user *argp = (void __user *)arg; long err; - lock_kernel(); switch (cmd) { /* These requests have same format as long as 'int' has same size. */ case RAW1394_IOC_ISO_RECV_INIT: @@ -2741,7 +2768,7 @@ static long raw1394_compat_ioctl(struct file *file, case RAW1394_IOC_ISO_GET_STATUS: case RAW1394_IOC_ISO_SHUTDOWN: case RAW1394_IOC_ISO_QUEUE_ACTIVITY: - err = do_raw1394_ioctl(file, cmd, arg); + err = raw1394_ioctl(file, cmd, arg); break; /* These request have different format. */ case RAW1394_IOC_ISO_RECV_PACKETS32: @@ -2757,7 +2784,6 @@ static long raw1394_compat_ioctl(struct file *file, err = -EINVAL; break; } - unlock_kernel(); return err; } @@ -2791,6 +2817,7 @@ static int raw1394_open(struct inode *inode, struct file *file) fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */ INIT_LIST_HEAD(&fi->list); + mutex_init(&fi->state_mutex); fi->state = opened; INIT_LIST_HEAD(&fi->req_pending); INIT_LIST_HEAD(&fi->req_complete); @@ -3010,10 +3037,10 @@ static int __init init_raw1394(void) hpsb_register_highlevel(&raw1394_highlevel); if (IS_ERR - (device_create_drvdata( - hpsb_protocol_class, NULL, - MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), - NULL, RAW1394_DEVICE_NAME))) { + (device_create(hpsb_protocol_class, NULL, + MKDEV(IEEE1394_MAJOR, + IEEE1394_MINOR_BLOCK_RAW1394 * 16), + NULL, RAW1394_DEVICE_NAME))) { ret = -EFAULT; goto out_unreg; } diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 1d6ad343553..c52f6e6e8af 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -526,26 +526,41 @@ static void sbp2util_write_doorbell(struct work_struct *work) static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu) { - struct sbp2_fwhost_info *hi = lu->hi; struct sbp2_command_info *cmd; + struct device *dmadev = lu->hi->host->device.parent; int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS; for (i = 0; i < orbs; i++) { cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) - return -ENOMEM; - cmd->command_orb_dma = dma_map_single(hi->host->device.parent, - &cmd->command_orb, - sizeof(struct sbp2_command_orb), - DMA_TO_DEVICE); - cmd->sge_dma = dma_map_single(hi->host->device.parent, - &cmd->scatter_gather_element, - sizeof(cmd->scatter_gather_element), - DMA_TO_DEVICE); + goto failed_alloc; + + cmd->command_orb_dma = + dma_map_single(dmadev, &cmd->command_orb, + sizeof(struct sbp2_command_orb), + DMA_TO_DEVICE); + if (dma_mapping_error(dmadev, cmd->command_orb_dma)) + goto failed_orb; + + cmd->sge_dma = + dma_map_single(dmadev, &cmd->scatter_gather_element, + sizeof(cmd->scatter_gather_element), + DMA_TO_DEVICE); + if (dma_mapping_error(dmadev, cmd->sge_dma)) + goto failed_sge; + INIT_LIST_HEAD(&cmd->list); list_add_tail(&cmd->list, &lu->cmd_orb_completed); } return 0; + +failed_sge: + dma_unmap_single(dmadev, cmd->command_orb_dma, + sizeof(struct sbp2_command_orb), DMA_TO_DEVICE); +failed_orb: + kfree(cmd); +failed_alloc: + return -ENOMEM; } static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu, @@ -641,24 +656,11 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb( static void sbp2util_mark_command_completed(struct sbp2_lu *lu, struct sbp2_command_info *cmd) { - struct hpsb_host *host = lu->ud->ne->host; - - if (cmd->cmd_dma) { - if (cmd->dma_type == CMD_DMA_SINGLE) - dma_unmap_single(host->device.parent, cmd->cmd_dma, - cmd->dma_size, cmd->dma_dir); - else if (cmd->dma_type == CMD_DMA_PAGE) - dma_unmap_page(host->device.parent, cmd->cmd_dma, - cmd->dma_size, cmd->dma_dir); - /* XXX: Check for CMD_DMA_NONE bug */ - cmd->dma_type = CMD_DMA_NONE; - cmd->cmd_dma = 0; - } - if (cmd->sge_buffer) { - dma_unmap_sg(host->device.parent, cmd->sge_buffer, - cmd->dma_size, cmd->dma_dir); - cmd->sge_buffer = NULL; - } + if (scsi_sg_count(cmd->Current_SCpnt)) + dma_unmap_sg(lu->ud->ne->host->device.parent, + scsi_sglist(cmd->Current_SCpnt), + scsi_sg_count(cmd->Current_SCpnt), + cmd->Current_SCpnt->sc_data_direction); list_move_tail(&cmd->list, &lu->cmd_orb_completed); } @@ -823,6 +825,10 @@ static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) #endif } + if (dma_get_max_seg_size(hi->host->device.parent) > SBP2_MAX_SEG_SIZE) + BUG_ON(dma_set_max_seg_size(hi->host->device.parent, + SBP2_MAX_SEG_SIZE)); + /* Prevent unloading of the 1394 host */ if (!try_module_get(hi->host->driver->owner)) { SBP2_ERR("failed to get a reference on 1394 host driver"); @@ -1494,84 +1500,65 @@ static int sbp2_agent_reset(struct sbp2_lu *lu, int wait) return 0; } -static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, - struct sbp2_fwhost_info *hi, - struct sbp2_command_info *cmd, - unsigned int scsi_use_sg, - struct scatterlist *sg, - u32 orb_direction, - enum dma_data_direction dma_dir) +static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, + struct sbp2_fwhost_info *hi, + struct sbp2_command_info *cmd, + unsigned int sg_count, + struct scatterlist *sg, + u32 orb_direction, + enum dma_data_direction dma_dir) { - cmd->dma_dir = dma_dir; + struct device *dmadev = hi->host->device.parent; + struct sbp2_unrestricted_page_table *pt; + int i, n; + + n = dma_map_sg(dmadev, sg, sg_count, dma_dir); + if (n == 0) + return -ENOMEM; + orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); orb->misc |= ORB_SET_DIRECTION(orb_direction); /* special case if only one element (and less than 64KB in size) */ - if (scsi_use_sg == 1 && sg->length <= SBP2_MAX_SG_ELEMENT_LENGTH) { - - cmd->dma_size = sg->length; - cmd->dma_type = CMD_DMA_PAGE; - cmd->cmd_dma = dma_map_page(hi->host->device.parent, - sg_page(sg), sg->offset, - cmd->dma_size, cmd->dma_dir); - - orb->data_descriptor_lo = cmd->cmd_dma; - orb->misc |= ORB_SET_DATA_SIZE(cmd->dma_size); - + if (n == 1) { + orb->misc |= ORB_SET_DATA_SIZE(sg_dma_len(sg)); + orb->data_descriptor_lo = sg_dma_address(sg); } else { - struct sbp2_unrestricted_page_table *sg_element = - &cmd->scatter_gather_element[0]; - u32 sg_count, sg_len; - dma_addr_t sg_addr; - int i, count = dma_map_sg(hi->host->device.parent, sg, - scsi_use_sg, dma_dir); - - cmd->dma_size = scsi_use_sg; - cmd->sge_buffer = sg; - - /* use page tables (s/g) */ - orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); - orb->data_descriptor_lo = cmd->sge_dma; + pt = &cmd->scatter_gather_element[0]; - /* loop through and fill out our SBP-2 page tables - * (and split up anything too large) */ - for (i = 0, sg_count = 0; i < count; i++, sg = sg_next(sg)) { - sg_len = sg_dma_len(sg); - sg_addr = sg_dma_address(sg); - while (sg_len) { - sg_element[sg_count].segment_base_lo = sg_addr; - if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) { - sg_element[sg_count].length_segment_base_hi = - PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH); - sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH; - sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH; - } else { - sg_element[sg_count].length_segment_base_hi = - PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len); - sg_len = 0; - } - sg_count++; - } + dma_sync_single_for_cpu(dmadev, cmd->sge_dma, + sizeof(cmd->scatter_gather_element), + DMA_TO_DEVICE); + + for_each_sg(sg, sg, n, i) { + pt[i].high = cpu_to_be32(sg_dma_len(sg) << 16); + pt[i].low = cpu_to_be32(sg_dma_address(sg)); } - orb->misc |= ORB_SET_DATA_SIZE(sg_count); + orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1) | + ORB_SET_DATA_SIZE(n); + orb->data_descriptor_lo = cmd->sge_dma; - sbp2util_cpu_to_be32_buffer(sg_element, - (sizeof(struct sbp2_unrestricted_page_table)) * - sg_count); + dma_sync_single_for_device(dmadev, cmd->sge_dma, + sizeof(cmd->scatter_gather_element), + DMA_TO_DEVICE); } + return 0; } -static void sbp2_create_command_orb(struct sbp2_lu *lu, - struct sbp2_command_info *cmd, - struct scsi_cmnd *SCpnt) +static int sbp2_create_command_orb(struct sbp2_lu *lu, + struct sbp2_command_info *cmd, + struct scsi_cmnd *SCpnt) { - struct sbp2_fwhost_info *hi = lu->hi; + struct device *dmadev = lu->hi->host->device.parent; struct sbp2_command_orb *orb = &cmd->command_orb; - u32 orb_direction; unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt); enum dma_data_direction dma_dir = SCpnt->sc_data_direction; + u32 orb_direction; + int ret; + dma_sync_single_for_cpu(dmadev, cmd->command_orb_dma, + sizeof(struct sbp2_command_orb), DMA_TO_DEVICE); /* * Set-up our command ORB. * @@ -1602,15 +1589,21 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu, orb->data_descriptor_hi = 0x0; orb->data_descriptor_lo = 0x0; orb->misc |= ORB_SET_DIRECTION(1); - } else - sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_sg_count(SCpnt), - scsi_sglist(SCpnt), - orb_direction, dma_dir); - + ret = 0; + } else { + ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd, + scsi_sg_count(SCpnt), + scsi_sglist(SCpnt), + orb_direction, dma_dir); + } sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb)); memset(orb->cdb, 0, sizeof(orb->cdb)); memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len); + + dma_sync_single_for_device(dmadev, cmd->command_orb_dma, + sizeof(struct sbp2_command_orb), DMA_TO_DEVICE); + return ret; } static void sbp2_link_orb_command(struct sbp2_lu *lu, @@ -1624,14 +1617,6 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu, size_t length; unsigned long flags; - dma_sync_single_for_device(hi->host->device.parent, - cmd->command_orb_dma, - sizeof(struct sbp2_command_orb), - DMA_TO_DEVICE); - dma_sync_single_for_device(hi->host->device.parent, cmd->sge_dma, - sizeof(cmd->scatter_gather_element), - DMA_TO_DEVICE); - /* check to see if there are any previous orbs to use */ spin_lock_irqsave(&lu->cmd_orb_lock, flags); last_orb = lu->last_orb; @@ -1699,9 +1684,10 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt, if (!cmd) return -EIO; - sbp2_create_command_orb(lu, cmd, SCpnt); - sbp2_link_orb_command(lu, cmd); + if (sbp2_create_command_orb(lu, cmd, SCpnt)) + return -ENOMEM; + sbp2_link_orb_command(lu, cmd); return 0; } @@ -1789,13 +1775,6 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, else cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo); if (cmd) { - dma_sync_single_for_cpu(hi->host->device.parent, - cmd->command_orb_dma, - sizeof(struct sbp2_command_orb), - DMA_TO_DEVICE); - dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma, - sizeof(cmd->scatter_gather_element), - DMA_TO_DEVICE); /* Grab SCSI command pointers and check status. */ /* * FIXME: If the src field in the status is 1, the ORB DMA must @@ -1912,7 +1891,6 @@ done: static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status) { - struct sbp2_fwhost_info *hi = lu->hi; struct list_head *lh; struct sbp2_command_info *cmd; unsigned long flags; @@ -1921,13 +1899,6 @@ static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status) while (!list_empty(&lu->cmd_orb_inuse)) { lh = lu->cmd_orb_inuse.next; cmd = list_entry(lh, struct sbp2_command_info, list); - dma_sync_single_for_cpu(hi->host->device.parent, - cmd->command_orb_dma, - sizeof(struct sbp2_command_orb), - DMA_TO_DEVICE); - dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma, - sizeof(cmd->scatter_gather_element), - DMA_TO_DEVICE); sbp2util_mark_command_completed(lu, cmd); if (cmd->Current_SCpnt) { cmd->Current_SCpnt->result = status << 16; @@ -2033,6 +2004,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) sdev->start_stop_pwr_cond = 1; if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); + + blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE); return 0; } @@ -2049,7 +2022,6 @@ static void sbp2scsi_slave_destroy(struct scsi_device *sdev) static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) { struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0]; - struct sbp2_fwhost_info *hi = lu->hi; struct sbp2_command_info *cmd; unsigned long flags; @@ -2063,14 +2035,6 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) spin_lock_irqsave(&lu->cmd_orb_lock, flags); cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt); if (cmd) { - dma_sync_single_for_cpu(hi->host->device.parent, - cmd->command_orb_dma, - sizeof(struct sbp2_command_orb), - DMA_TO_DEVICE); - dma_sync_single_for_cpu(hi->host->device.parent, - cmd->sge_dma, - sizeof(cmd->scatter_gather_element), - DMA_TO_DEVICE); sbp2util_mark_command_completed(lu, cmd); if (cmd->Current_SCpnt) { cmd->Current_SCpnt->result = DID_ABORT << 16; diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index 875428bc8d2..c5036f1cc5b 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h @@ -139,13 +139,10 @@ struct sbp2_logout_orb { u32 status_fifo_lo; } __attribute__((packed)); -#define PAGE_TABLE_SET_SEGMENT_BASE_HI(v) ((v) & 0xffff) -#define PAGE_TABLE_SET_SEGMENT_LENGTH(v) (((v) & 0xffff) << 16) - struct sbp2_unrestricted_page_table { - u32 length_segment_base_hi; - u32 segment_base_lo; -} __attribute__((packed)); + __be32 high; + __be32 low; +}; #define RESP_STATUS_REQUEST_COMPLETE 0x0 #define RESP_STATUS_TRANSPORT_FAILURE 0x1 @@ -216,15 +213,18 @@ struct sbp2_status_block { #define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e #define SBP2_SW_VERSION_ENTRY 0x00010483 - /* - * SCSI specific definitions + * The default maximum s/g segment size of a FireWire controller is + * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to + * be quadlet-aligned, we set the length limit to 0xffff & ~3. */ +#define SBP2_MAX_SEG_SIZE 0xfffc -#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 -/* There is no real limitation of the queue depth (i.e. length of the linked +/* + * There is no real limitation of the queue depth (i.e. length of the linked * list of command ORBs) at the target. The chosen depth is merely an - * implementation detail of the sbp2 driver. */ + * implementation detail of the sbp2 driver. + */ #define SBP2_MAX_CMDS 8 #define SBP2_SCSI_STATUS_GOOD 0x0 @@ -240,12 +240,6 @@ struct sbp2_status_block { * Representations of commands and devices */ -enum sbp2_dma_types { - CMD_DMA_NONE, - CMD_DMA_PAGE, - CMD_DMA_SINGLE -}; - /* Per SCSI command */ struct sbp2_command_info { struct list_head list; @@ -258,11 +252,6 @@ struct sbp2_command_info { struct sbp2_unrestricted_page_table scatter_gather_element[SG_ALL] __attribute__((aligned(8))); dma_addr_t sge_dma; - void *sge_buffer; - dma_addr_t cmd_dma; - enum sbp2_dma_types dma_type; - unsigned long dma_size; - enum dma_data_direction dma_dir; }; /* Per FireWire host */ diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 25db6e67fa4..679a918a5cc 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c @@ -893,7 +893,7 @@ static long video1394_ioctl(struct file *file, if (unlikely(d == NULL)) return -EFAULT; - if (unlikely((v.buffer<0) || (v.buffer>=d->num_desc - 1))) { + if (unlikely(v.buffer >= d->num_desc - 1)) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EINVAL; @@ -959,7 +959,7 @@ static long video1394_ioctl(struct file *file, if (unlikely(d == NULL)) return -EFAULT; - if (unlikely((v.buffer<0) || (v.buffer>d->num_desc - 1))) { + if (unlikely(v.buffer > d->num_desc - 1)) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EINVAL; @@ -1030,7 +1030,7 @@ static long video1394_ioctl(struct file *file, d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); if (d == NULL) return -EFAULT; - if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) { + if (v.buffer >= d->num_desc - 1) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EINVAL; @@ -1137,7 +1137,7 @@ static long video1394_ioctl(struct file *file, d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); if (d == NULL) return -EFAULT; - if ((v.buffer<0) || (v.buffer>=d->num_desc-1)) { + if (v.buffer >= d->num_desc - 1) { PRINT(KERN_ERR, ohci->host->id, "Buffer %d out of range",v.buffer); return -EINVAL; @@ -1341,9 +1341,8 @@ 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; - device_create_drvdata(hpsb_protocol_class, NULL, - MKDEV(IEEE1394_MAJOR, minor), NULL, - "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id); + device_create(hpsb_protocol_class, NULL, MKDEV(IEEE1394_MAJOR, minor), + NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id); } |