diff options
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/core-card.c | 42 | ||||
-rw-r--r-- | drivers/firewire/core-cdev.c | 12 | ||||
-rw-r--r-- | drivers/firewire/core-device.c | 6 | ||||
-rw-r--r-- | drivers/firewire/core-topology.c | 9 | ||||
-rw-r--r-- | drivers/firewire/core-transaction.c | 48 | ||||
-rw-r--r-- | drivers/firewire/net.c | 14 | ||||
-rw-r--r-- | drivers/firewire/sbp2.c | 13 |
7 files changed, 98 insertions, 46 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 54be88167c60..6ac5ff20a2fe 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -616,6 +616,15 @@ static struct fw_iso_context *dummy_allocate_iso_context(struct fw_card *card, return ERR_PTR(-ENODEV); } +static u32 dummy_read_csr(struct fw_card *card, int csr_offset) +{ + return 0; +} + +static void dummy_write_csr(struct fw_card *card, int csr_offset, u32 value) +{ +} + static int dummy_start_iso(struct fw_iso_context *ctx, s32 cycle, u32 sync, u32 tags) { @@ -649,6 +658,8 @@ static const struct fw_card_driver dummy_driver_template = { .send_response = dummy_send_response, .cancel_packet = dummy_cancel_packet, .enable_phys_dma = dummy_enable_phys_dma, + .read_csr = dummy_read_csr, + .write_csr = dummy_write_csr, .allocate_iso_context = dummy_allocate_iso_context, .start_iso = dummy_start_iso, .set_iso_channels = dummy_set_iso_channels, @@ -668,6 +679,7 @@ EXPORT_SYMBOL_GPL(fw_card_release); void fw_core_remove_card(struct fw_card *card) { struct fw_card_driver dummy_driver = dummy_driver_template; + unsigned long flags; card->driver->update_phy_reg(card, 4, PHY_LINK_ACTIVE | PHY_CONTENDER, 0); @@ -682,7 +694,9 @@ void fw_core_remove_card(struct fw_card *card) dummy_driver.stop_iso = card->driver->stop_iso; card->driver = &dummy_driver; + spin_lock_irqsave(&card->lock, flags); fw_destroy_nodes(card); + spin_unlock_irqrestore(&card->lock, flags); /* Wait for all users, especially device workqueue jobs, to finish. */ fw_card_put(card); @@ -691,3 +705,31 @@ void fw_core_remove_card(struct fw_card *card) WARN_ON(!list_empty(&card->transaction_list)); } EXPORT_SYMBOL(fw_core_remove_card); + +/** + * fw_card_read_cycle_time: read from Isochronous Cycle Timer Register of 1394 OHCI in MMIO region + * for controller card. + * @card: The instance of card for 1394 OHCI controller. + * @cycle_time: The mutual reference to value of cycle time for the read operation. + * + * Read value from Isochronous Cycle Timer Register of 1394 OHCI in MMIO region for the given + * controller card. This function accesses the region without any lock primitives or IRQ mask. + * When returning successfully, the content of @value argument has value aligned to host endianness, + * formetted by CYCLE_TIME CSR Register of IEEE 1394 std. + * + * Context: Any context. + * Return: + * * 0 - Read successfully. + * * -ENODEV - The controller is unavailable due to being removed or unbound. + */ +int fw_card_read_cycle_time(struct fw_card *card, u32 *cycle_time) +{ + if (card->driver->read_csr == dummy_read_csr) + return -ENODEV; + + // It's possible to switch to dummy driver between the above and the below. This is the best + // effort to return -ENODEV. + *cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME); + return 0; +} +EXPORT_SYMBOL_GPL(fw_card_read_cycle_time); diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 9f89c17730b1..9c89f7d53e99 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1211,12 +1211,14 @@ static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg) struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2; struct fw_card *card = client->device->card; struct timespec64 ts = {0, 0}; - u32 cycle_time; + u32 cycle_time = 0; int ret = 0; local_irq_disable(); - cycle_time = card->driver->read_csr(card, CSR_CYCLE_TIME); + ret = fw_card_read_cycle_time(card, &cycle_time); + if (ret < 0) + goto end; switch (a->clk_id) { case CLOCK_REALTIME: ktime_get_real_ts64(&ts); break; @@ -1225,7 +1227,7 @@ static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg) default: ret = -EINVAL; } - +end: local_irq_enable(); a->tv_sec = ts.tv_sec; @@ -1500,6 +1502,7 @@ static void outbound_phy_packet_callback(struct fw_packet *packet, { struct outbound_phy_packet_event *e = container_of(packet, struct outbound_phy_packet_event, p); + struct client *e_client; switch (status) { /* expected: */ @@ -1516,9 +1519,10 @@ static void outbound_phy_packet_callback(struct fw_packet *packet, } e->phy_packet.data[0] = packet->timestamp; + e_client = e->client; queue_event(e->client, &e->event, &e->phy_packet, sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0); - client_put(e->client); + client_put(e_client); } static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg) diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 90ed8fdaba75..adddd8c45d0c 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -372,8 +372,7 @@ static ssize_t rom_index_show(struct device *dev, struct fw_device *device = fw_device(dev->parent); struct fw_unit *unit = fw_unit(dev); - return snprintf(buf, PAGE_SIZE, "%d\n", - (int)(unit->directory - device->config_rom)); + return sysfs_emit(buf, "%td\n", unit->directory - device->config_rom); } static struct device_attribute fw_unit_attributes[] = { @@ -403,8 +402,7 @@ static ssize_t guid_show(struct device *dev, int ret; down_read(&fw_device_rwsem); - ret = snprintf(buf, PAGE_SIZE, "0x%08x%08x\n", - device->config_rom[3], device->config_rom[4]); + ret = sysfs_emit(buf, "0x%08x%08x\n", device->config_rom[3], device->config_rom[4]); up_read(&fw_device_rwsem); return ret; diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index b63d55f5ebd3..f40c81534381 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -375,16 +375,13 @@ static void report_found_node(struct fw_card *card, card->bm_retries = 0; } +/* Must be called with card->lock held */ void fw_destroy_nodes(struct fw_card *card) { - unsigned long flags; - - spin_lock_irqsave(&card->lock, flags); card->color++; if (card->local_node != NULL) for_each_fw_node(card, card->local_node, report_lost_node); card->local_node = NULL; - spin_unlock_irqrestore(&card->lock, flags); } static void move_tree(struct fw_node *node0, struct fw_node *node1, int port) @@ -510,6 +507,8 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, struct fw_node *local_node; unsigned long flags; + spin_lock_irqsave(&card->lock, flags); + /* * If the selfID buffer is not the immediate successor of the * previously processed one, we cannot reliably compare the @@ -521,8 +520,6 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation, card->bm_retries = 0; } - spin_lock_irqsave(&card->lock, flags); - card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated; card->node_id = node_id; /* diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index ac487c96bb71..af498d767702 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -73,24 +73,25 @@ static int try_cancel_split_timeout(struct fw_transaction *t) static int close_transaction(struct fw_transaction *transaction, struct fw_card *card, int rcode) { - struct fw_transaction *t; + struct fw_transaction *t = NULL, *iter; unsigned long flags; spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(t, &card->transaction_list, link) { - if (t == transaction) { - if (!try_cancel_split_timeout(t)) { + list_for_each_entry(iter, &card->transaction_list, link) { + if (iter == transaction) { + if (!try_cancel_split_timeout(iter)) { spin_unlock_irqrestore(&card->lock, flags); goto timed_out; } - list_del_init(&t->link); - card->tlabel_mask &= ~(1ULL << t->tlabel); + list_del_init(&iter->link); + card->tlabel_mask &= ~(1ULL << iter->tlabel); + t = iter; break; } } spin_unlock_irqrestore(&card->lock, flags); - if (&t->link != &card->transaction_list) { + if (t) { t->callback(card, rcode, NULL, 0, t->callback_data); return 0; } @@ -619,6 +620,7 @@ struct fw_request { struct fw_packet response; u32 request_header[4]; int ack; + u32 timestamp; u32 length; u32 data[]; }; @@ -788,6 +790,7 @@ static struct fw_request *allocate_request(struct fw_card *card, request->response.ack = 0; request->response.callback = free_response_callback; request->ack = p->ack; + request->timestamp = p->timestamp; request->length = length; if (data) memcpy(request->data, data, length); @@ -832,6 +835,22 @@ int fw_get_request_speed(struct fw_request *request) } EXPORT_SYMBOL(fw_get_request_speed); +/** + * fw_request_get_timestamp: Get timestamp of the request. + * @request: The opaque pointer to request structure. + * + * Get timestamp when 1394 OHCI controller receives the asynchronous request subaction. The + * timestamp consists of the low order 3 bits of second field and the full 13 bits of count + * field of isochronous cycle time register. + * + * Returns: timestamp of the request. + */ +u32 fw_request_get_timestamp(const struct fw_request *request) +{ + return request->timestamp; +} +EXPORT_SYMBOL_GPL(fw_request_get_timestamp); + static void handle_exclusive_region_request(struct fw_card *card, struct fw_packet *p, struct fw_request *request, @@ -935,7 +954,7 @@ EXPORT_SYMBOL(fw_core_handle_request); void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) { - struct fw_transaction *t; + struct fw_transaction *t = NULL, *iter; unsigned long flags; u32 *data; size_t data_length; @@ -947,20 +966,21 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) rcode = HEADER_GET_RCODE(p->header[1]); spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(t, &card->transaction_list, link) { - if (t->node_id == source && t->tlabel == tlabel) { - if (!try_cancel_split_timeout(t)) { + list_for_each_entry(iter, &card->transaction_list, link) { + if (iter->node_id == source && iter->tlabel == tlabel) { + if (!try_cancel_split_timeout(iter)) { spin_unlock_irqrestore(&card->lock, flags); goto timed_out; } - list_del_init(&t->link); - card->tlabel_mask &= ~(1ULL << t->tlabel); + list_del_init(&iter->link); + card->tlabel_mask &= ~(1ULL << iter->tlabel); + t = iter; break; } } spin_unlock_irqrestore(&card->lock, flags); - if (&t->link == &card->transaction_list) { + if (!t) { timed_out: fw_notice(card, "unsolicited response (source %x, tlabel %x)\n", source, tlabel); diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index dcc141068128..af22be84034b 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -202,15 +202,6 @@ struct fwnet_packet_task { }; /* - * Get fifo address embedded in hwaddr - */ -static __u64 fwnet_hwaddr_fifo(union fwnet_hwaddr *ha) -{ - return (u64)get_unaligned_be16(&ha->uc.fifo_hi) << 32 - | get_unaligned_be32(&ha->uc.fifo_lo); -} - -/* * saddr == NULL means use device source address. * daddr == NULL means leave destination address (eg unresolved arp). */ @@ -1306,7 +1297,7 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net) max_payload = peer->max_payload; datagram_label_ptr = &peer->datagram_label; - ptask->fifo_addr = fwnet_hwaddr_fifo(ha); + ptask->fifo_addr = get_unaligned_be48(ha->uc.fifo); ptask->generation = generation; ptask->dest_node = dest_node; ptask->speed = peer->speed; @@ -1494,8 +1485,7 @@ static int fwnet_probe(struct fw_unit *unit, ha.uc.uniq_id = cpu_to_be64(card->guid); ha.uc.max_rec = dev->card->max_receive; ha.uc.sspd = dev->card->link_speed; - ha.uc.fifo_hi = cpu_to_be16(dev->local_fifo >> 32); - ha.uc.fifo_lo = cpu_to_be32(dev->local_fifo & 0xffffffff); + put_unaligned_be48(dev->local_fifo, ha.uc.fifo); dev_addr_set(net, ha.u); memset(net->broadcast, -1, net->addr_len); diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 85cd379fd383..60051c0cabea 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -408,7 +408,7 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request, void *payload, size_t length, void *callback_data) { struct sbp2_logical_unit *lu = callback_data; - struct sbp2_orb *orb; + struct sbp2_orb *orb = NULL, *iter; struct sbp2_status status; unsigned long flags; @@ -433,17 +433,18 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request, /* Lookup the orb corresponding to this status write. */ spin_lock_irqsave(&lu->tgt->lock, flags); - list_for_each_entry(orb, &lu->orb_list, link) { + list_for_each_entry(iter, &lu->orb_list, link) { if (STATUS_GET_ORB_HIGH(status) == 0 && - STATUS_GET_ORB_LOW(status) == orb->request_bus) { - orb->rcode = RCODE_COMPLETE; - list_del(&orb->link); + STATUS_GET_ORB_LOW(status) == iter->request_bus) { + iter->rcode = RCODE_COMPLETE; + list_del(&iter->link); + orb = iter; break; } } spin_unlock_irqrestore(&lu->tgt->lock, flags); - if (&orb->link != &lu->orb_list) { + if (orb) { orb->callback(orb, &status); kref_put(&orb->kref, free_orb); /* orb callback reference */ } else { |