diff options
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/core-card.c | 75 | ||||
-rw-r--r-- | drivers/firewire/core-cdev.c | 113 | ||||
-rw-r--r-- | drivers/firewire/core-topology.c | 17 | ||||
-rw-r--r-- | drivers/firewire/core-transaction.c | 19 | ||||
-rw-r--r-- | drivers/firewire/core.h | 9 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 39 | ||||
-rw-r--r-- | drivers/firewire/sbp2.c | 9 |
7 files changed, 155 insertions, 126 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index e4864e8..7083bcc 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -38,15 +38,14 @@ #include "core.h" -int fw_compute_block_crc(u32 *block) +int fw_compute_block_crc(__be32 *block) { - __be32 be32_block[256]; - int i, length; + int length; + u16 crc; - length = (*block >> 16) & 0xff; - for (i = 0; i < length; i++) - be32_block[i] = cpu_to_be32(block[i + 1]); - *block |= crc_itu_t(0, (u8 *) be32_block, length * 4); + length = (be32_to_cpu(block[0]) >> 16) & 0xff; + crc = crc_itu_t(0, (u8 *)&block[1], length * 4); + *block |= cpu_to_be32(crc); return length; } @@ -57,6 +56,8 @@ static LIST_HEAD(card_list); static LIST_HEAD(descriptor_list); static int descriptor_count; +static __be32 tmp_config_rom[256]; + #define BIB_CRC(v) ((v) << 0) #define BIB_CRC_LENGTH(v) ((v) << 16) #define BIB_INFO_LENGTH(v) ((v) << 24) @@ -72,11 +73,10 @@ static int descriptor_count; #define BIB_CMC ((1) << 30) #define BIB_IMC ((1) << 31) -static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) +static size_t generate_config_rom(struct fw_card *card, __be32 *config_rom) { struct fw_descriptor *desc; - static u32 config_rom[256]; - int i, j, length; + int i, j, k, length; /* * Initialize contents of config rom buffer. On the OHCI @@ -87,40 +87,39 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) * the version stored in the OHCI registers. */ - memset(config_rom, 0, sizeof(config_rom)); - config_rom[0] = BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0); - config_rom[1] = 0x31333934; - - config_rom[2] = + config_rom[0] = cpu_to_be32( + BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0)); + config_rom[1] = cpu_to_be32(0x31333934); + config_rom[2] = cpu_to_be32( BIB_LINK_SPEED(card->link_speed) | BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | BIB_MAX_ROM(2) | BIB_MAX_RECEIVE(card->max_receive) | - BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC; - config_rom[3] = card->guid >> 32; - config_rom[4] = card->guid; + BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC); + config_rom[3] = cpu_to_be32(card->guid >> 32); + config_rom[4] = cpu_to_be32(card->guid); /* Generate root directory. */ - i = 5; - config_rom[i++] = 0; - config_rom[i++] = 0x0c0083c0; /* node capabilities */ - j = i + descriptor_count; + config_rom[6] = cpu_to_be32(0x0c0083c0); /* node capabilities */ + i = 7; + j = 7 + descriptor_count; /* Generate root directory entries for descriptors. */ list_for_each_entry (desc, &descriptor_list, link) { if (desc->immediate > 0) - config_rom[i++] = desc->immediate; - config_rom[i] = desc->key | (j - i); + config_rom[i++] = cpu_to_be32(desc->immediate); + config_rom[i] = cpu_to_be32(desc->key | (j - i)); i++; j += desc->length; } /* Update root directory length. */ - config_rom[5] = (i - 5 - 1) << 16; + config_rom[5] = cpu_to_be32((i - 5 - 1) << 16); /* End of root directory, now copy in descriptors. */ list_for_each_entry (desc, &descriptor_list, link) { - memcpy(&config_rom[i], desc->data, desc->length * 4); + for (k = 0; k < desc->length; k++) + config_rom[i + k] = cpu_to_be32(desc->data[k]); i += desc->length; } @@ -131,20 +130,17 @@ static u32 *generate_config_rom(struct fw_card *card, size_t *config_rom_length) for (i = 0; i < j; i += length + 1) length = fw_compute_block_crc(config_rom + i); - *config_rom_length = j; - - return config_rom; + return j; } static void update_config_roms(void) { struct fw_card *card; - u32 *config_rom; size_t length; list_for_each_entry (card, &card_list, link) { - config_rom = generate_config_rom(card, &length); - card->driver->set_config_rom(card, config_rom, length); + length = generate_config_rom(card, tmp_config_rom); + card->driver->set_config_rom(card, tmp_config_rom, length); } } @@ -211,11 +207,8 @@ static const char gap_count_table[] = { void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) { - int scheduled; - fw_card_get(card); - scheduled = schedule_delayed_work(&card->work, delay); - if (!scheduled) + if (!schedule_delayed_work(&card->work, delay)) fw_card_put(card); } @@ -435,7 +428,6 @@ EXPORT_SYMBOL(fw_card_initialize); int fw_card_add(struct fw_card *card, u32 max_receive, u32 link_speed, u64 guid) { - u32 *config_rom; size_t length; int ret; @@ -445,8 +437,8 @@ int fw_card_add(struct fw_card *card, mutex_lock(&card_mutex); - config_rom = generate_config_rom(card, &length); - ret = card->driver->enable(card, config_rom, length); + length = generate_config_rom(card, tmp_config_rom); + ret = card->driver->enable(card, tmp_config_rom, length); if (ret == 0) list_add_tail(&card->link, &card_list); @@ -465,7 +457,8 @@ EXPORT_SYMBOL(fw_card_add); * shutdown still need to be provided by the card driver. */ -static int dummy_enable(struct fw_card *card, u32 *config_rom, size_t length) +static int dummy_enable(struct fw_card *card, + const __be32 *config_rom, size_t length) { BUG(); return -1; @@ -478,7 +471,7 @@ static int dummy_update_phy_reg(struct fw_card *card, int address, } static int dummy_set_config_rom(struct fw_card *card, - u32 *config_rom, size_t length) + const __be32 *config_rom, size_t length) { /* * We take the card out of card_list before setting the dummy diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 5089331..231e6ee 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -130,9 +130,22 @@ struct iso_resource { struct iso_resource_event *e_alloc, *e_dealloc; }; -static void schedule_iso_resource(struct iso_resource *); static void release_iso_resource(struct client *, struct client_resource *); +static void schedule_iso_resource(struct iso_resource *r, unsigned long delay) +{ + client_get(r->client); + if (!schedule_delayed_work(&r->work, delay)) + client_put(r->client); +} + +static void schedule_if_iso_resource(struct client_resource *resource) +{ + if (resource->release == release_iso_resource) + schedule_iso_resource(container_of(resource, + struct iso_resource, resource), 0); +} + /* * dequeue_event() just kfree()'s the event, so the event has to be * the first field in a struct XYZ_event. @@ -166,7 +179,7 @@ struct iso_interrupt_event { struct iso_resource_event { struct event event; - struct fw_cdev_event_iso_resource resource; + struct fw_cdev_event_iso_resource iso_resource; }; static inline void __user *u64_to_uptr(__u64 value) @@ -314,11 +327,8 @@ static void for_each_client(struct fw_device *device, static int schedule_reallocations(int id, void *p, void *data) { - struct client_resource *r = p; + schedule_if_iso_resource(p); - if (r->release == release_iso_resource) - schedule_iso_resource(container_of(r, - struct iso_resource, resource)); return 0; } @@ -414,9 +424,7 @@ static int add_client_resource(struct client *client, &resource->handle); if (ret >= 0) { client_get(client); - if (resource->release == release_iso_resource) - schedule_iso_resource(container_of(resource, - struct iso_resource, resource)); + schedule_if_iso_resource(resource); } spin_unlock_irqrestore(&client->lock, flags); @@ -428,26 +436,26 @@ static int add_client_resource(struct client *client, static int release_client_resource(struct client *client, u32 handle, client_resource_release_fn_t release, - struct client_resource **resource) + struct client_resource **return_resource) { - struct client_resource *r; + struct client_resource *resource; spin_lock_irq(&client->lock); if (client->in_shutdown) - r = NULL; + resource = NULL; else - r = idr_find(&client->resource_idr, handle); - if (r && r->release == release) + resource = idr_find(&client->resource_idr, handle); + if (resource && resource->release == release) idr_remove(&client->resource_idr, handle); spin_unlock_irq(&client->lock); - if (!(r && r->release == release)) + if (!(resource && resource->release == release)) return -EINVAL; - if (resource) - *resource = r; + if (return_resource) + *return_resource = resource; else - r->release(client, r); + resource->release(client, resource); client_put(client); @@ -699,6 +707,7 @@ static int ioctl_send_response(struct client *client, void *buffer) struct fw_cdev_send_response *request = buffer; struct client_resource *resource; struct inbound_transaction_resource *r; + int ret = 0; if (release_client_resource(client, request->handle, release_request, &resource) < 0) @@ -708,13 +717,17 @@ static int ioctl_send_response(struct client *client, void *buffer) resource); if (request->length < r->length) r->length = request->length; - if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) - return -EFAULT; + + if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) { + ret = -EFAULT; + goto out; + } fw_send_response(client->device->card, r->request, request->rcode); + out: kfree(r); - return 0; + return ret; } static int ioctl_initiate_bus_reset(struct client *client, void *buffer) @@ -1028,8 +1041,7 @@ static void iso_resource_work(struct work_struct *work) /* Allow 1000ms grace period for other reallocations. */ if (todo == ISO_RES_ALLOC && time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) { - if (schedule_delayed_work(&r->work, DIV_ROUND_UP(HZ, 3))) - client_get(client); + schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3)); skip = true; } else { /* We could be called twice within the same generation. */ @@ -1097,12 +1109,12 @@ static void iso_resource_work(struct work_struct *work) e = r->e_dealloc; r->e_dealloc = NULL; } - e->resource.handle = r->resource.handle; - e->resource.channel = channel; - e->resource.bandwidth = bandwidth; + e->iso_resource.handle = r->resource.handle; + e->iso_resource.channel = channel; + e->iso_resource.bandwidth = bandwidth; queue_event(client, &e->event, - &e->resource, sizeof(e->resource), NULL, 0); + &e->iso_resource, sizeof(e->iso_resource), NULL, 0); if (free) { cancel_delayed_work(&r->work); @@ -1114,13 +1126,6 @@ static void iso_resource_work(struct work_struct *work) client_put(client); } -static void schedule_iso_resource(struct iso_resource *r) -{ - client_get(r->client); - if (!schedule_delayed_work(&r->work, 0)) - client_put(r->client); -} - static void release_iso_resource(struct client *client, struct client_resource *resource) { @@ -1129,7 +1134,7 @@ static void release_iso_resource(struct client *client, spin_lock_irq(&client->lock); r->todo = ISO_RES_DEALLOC; - schedule_iso_resource(r); + schedule_iso_resource(r, 0); spin_unlock_irq(&client->lock); } @@ -1162,10 +1167,10 @@ static int init_iso_resource(struct client *client, r->e_alloc = e1; r->e_dealloc = e2; - e1->resource.closure = request->closure; - e1->resource.type = FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED; - e2->resource.closure = request->closure; - e2->resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED; + e1->iso_resource.closure = request->closure; + e1->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED; + e2->iso_resource.closure = request->closure; + e2->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED; if (todo == ISO_RES_ALLOC) { r->resource.release = release_iso_resource; @@ -1175,7 +1180,7 @@ static int init_iso_resource(struct client *client, } else { r->resource.release = NULL; r->resource.handle = -1; - schedule_iso_resource(r); + schedule_iso_resource(r, 0); } request->handle = r->resource.handle; @@ -1295,7 +1300,23 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { static int dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) { - char buffer[256]; + char buffer[sizeof(union { + struct fw_cdev_get_info _00; + struct fw_cdev_send_request _01; + struct fw_cdev_allocate _02; + struct fw_cdev_deallocate _03; + struct fw_cdev_send_response _04; + struct fw_cdev_initiate_bus_reset _05; + struct fw_cdev_add_descriptor _06; + struct fw_cdev_remove_descriptor _07; + struct fw_cdev_create_iso_context _08; + struct fw_cdev_queue_iso _09; + struct fw_cdev_start_iso _0a; + struct fw_cdev_stop_iso _0b; + struct fw_cdev_get_cycle_timer _0c; + struct fw_cdev_allocate_iso_resource _0d; + struct fw_cdev_send_stream_packet _13; + })]; int ret; if (_IOC_TYPE(cmd) != '#' || @@ -1390,10 +1411,10 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma) static int shutdown_resource(int id, void *p, void *data) { - struct client_resource *r = p; + struct client_resource *resource = p; struct client *client = data; - r->release(client, r); + resource->release(client, resource); client_put(client); return 0; @@ -1402,7 +1423,7 @@ static int shutdown_resource(int id, void *p, void *data) static int fw_device_op_release(struct inode *inode, struct file *file) { struct client *client = file->private_data; - struct event *e, *next_e; + struct event *event, *next_event; mutex_lock(&client->device->client_list_mutex); list_del(&client->link); @@ -1423,8 +1444,8 @@ static int fw_device_op_release(struct inode *inode, struct file *file) idr_remove_all(&client->resource_idr); idr_destroy(&client->resource_idr); - list_for_each_entry_safe(e, next_e, &client->event_list, link) - kfree(e); + list_for_each_entry_safe(event, next_event, &client->event_list, link) + kfree(event); client_put(client); diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index d373d17..93ec64c 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -28,9 +28,9 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/spinlock.h> -#include <linux/string.h> #include <asm/atomic.h> +#include <asm/byteorder.h> #include <asm/system.h> #include "core.h" @@ -510,13 +510,16 @@ static void update_tree(struct fw_card *card, struct fw_node *root) static void update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count) { - int node_count; + int node_count = (card->root_node->node_id & 0x3f) + 1; + __be32 *map = card->topology_map; + + *map++ = cpu_to_be32((self_id_count + 2) << 16); + *map++ = cpu_to_be32(be32_to_cpu(card->topology_map[1]) + 1); + *map++ = cpu_to_be32((node_count << 16) | self_id_count); + + while (self_id_count--) + *map++ = cpu_to_be32p(self_ids++); - card->topology_map[1]++; - node_count = (card->root_node->node_id & 0x3f) + 1; - card->topology_map[2] = (node_count << 16) | self_id_count; - card->topology_map[0] = (self_id_count + 2) << 16; - memcpy(&card->topology_map[3], self_ids, self_id_count * 4); fw_compute_block_crc(card->topology_map); } diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index da628c7..842739d 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -218,12 +218,15 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, packet->header_length = 16; packet->payload_length = 0; break; + + default: + WARN(1, KERN_ERR "wrong tcode %d", tcode); } common: packet->speed = speed; packet->generation = generation; packet->ack = 0; - packet->payload_bus = 0; + packet->payload_mapped = false; } /** @@ -595,11 +598,10 @@ void fw_fill_response(struct fw_packet *response, u32 *request_header, break; default: - BUG(); - return; + WARN(1, KERN_ERR "wrong tcode %d", tcode); } - response->payload_bus = 0; + response->payload_mapped = false; } EXPORT_SYMBOL(fw_fill_response); @@ -810,8 +812,7 @@ static void handle_topology_map(struct fw_card *card, struct fw_request *request int speed, unsigned long long offset, void *payload, size_t length, void *callback_data) { - int i, start, end; - __be32 *map; + int start; if (!TCODE_IS_READ_REQUEST(tcode)) { fw_send_response(card, request, RCODE_TYPE_ERROR); @@ -824,11 +825,7 @@ static void handle_topology_map(struct fw_card *card, struct fw_request *request } start = (offset - topology_map_region.start) / 4; - end = start + length / 4; - map = payload; - - for (i = 0; i < length / 4; i++) - map[i] = cpu_to_be32(card->topology_map[start + i]); + memcpy(payload, &card->topology_map[start], length); fw_send_response(card, request, RCODE_COMPLETE); } diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 7ff6e75..ed3b1a7 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -40,7 +40,8 @@ struct fw_card_driver { * enable the PHY or set the link_on bit and initiate a bus * reset. */ - int (*enable)(struct fw_card *card, u32 *config_rom, size_t length); + int (*enable)(struct fw_card *card, + const __be32 *config_rom, size_t length); int (*update_phy_reg)(struct fw_card *card, int address, int clear_bits, int set_bits); @@ -48,10 +49,10 @@ struct fw_card_driver { /* * Update the config rom for an enabled card. This function * should change the config rom that is presented on the bus - * an initiate a bus reset. + * and initiate a bus reset. */ int (*set_config_rom)(struct fw_card *card, - u32 *config_rom, size_t length); + const __be32 *config_rom, size_t length); void (*send_request)(struct fw_card *card, struct fw_packet *packet); void (*send_response)(struct fw_card *card, struct fw_packet *packet); @@ -93,7 +94,7 @@ int fw_card_add(struct fw_card *card, u32 max_receive, u32 link_speed, u64 guid); void fw_core_remove_card(struct fw_card *card); int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); -int fw_compute_block_crc(u32 *block); +int fw_compute_block_crc(__be32 *block); void fw_schedule_bm_work(struct fw_card *card, unsigned long delay); static inline struct fw_card *fw_card_get(struct fw_card *card) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 94260aa..ae4556f 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -205,7 +205,7 @@ struct fw_ohci { dma_addr_t config_rom_bus; __be32 *next_config_rom; dma_addr_t next_config_rom_bus; - u32 next_header; + __be32 next_header; struct ar_context ar_request_ctx; struct ar_context ar_response_ctx; @@ -997,7 +997,8 @@ static int at_context_queue_packet(struct context *ctx, packet->ack = RCODE_SEND_ERROR; return -1; } - packet->payload_bus = payload_bus; + packet->payload_bus = payload_bus; + packet->payload_mapped = true; d[2].req_count = cpu_to_le16(packet->payload_length); d[2].data_address = cpu_to_le32(payload_bus); @@ -1025,7 +1026,7 @@ static int at_context_queue_packet(struct context *ctx, */ if (ohci->generation != packet->generation || reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) { - if (packet->payload_length > 0) + if (packet->payload_mapped) dma_unmap_single(ohci->card.device, payload_bus, packet->payload_length, DMA_TO_DEVICE); packet->ack = RCODE_GENERATION; @@ -1061,7 +1062,7 @@ static int handle_at_packet(struct context *context, /* This packet was cancelled, just continue. */ return 1; - if (packet->payload_bus) + if (packet->payload_mapped) dma_unmap_single(ohci->card.device, packet->payload_bus, packet->payload_length, DMA_TO_DEVICE); @@ -1357,8 +1358,9 @@ static void bus_reset_tasklet(unsigned long data) */ reg_write(ohci, OHCI1394_BusOptions, be32_to_cpu(ohci->config_rom[2])); - ohci->config_rom[0] = cpu_to_be32(ohci->next_header); - reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->next_header); + ohci->config_rom[0] = ohci->next_header; + reg_write(ohci, OHCI1394_ConfigROMhdr, + be32_to_cpu(ohci->next_header)); } #ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA @@ -1477,7 +1479,17 @@ static int software_reset(struct fw_ohci *ohci) return -EBUSY; } -static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) +static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length) +{ + size_t size = length * 4; + + memcpy(dest, src, size); + if (size < CONFIG_ROM_SIZE) + memset(&dest[length], 0, CONFIG_ROM_SIZE - size); +} + +static int ohci_enable(struct fw_card *card, + const __be32 *config_rom, size_t length) { struct fw_ohci *ohci = fw_ohci(card); struct pci_dev *dev = to_pci_dev(card->device); @@ -1579,8 +1591,7 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) if (ohci->next_config_rom == NULL) return -ENOMEM; - memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE); - fw_memcpy_to_be32(ohci->next_config_rom, config_rom, length * 4); + copy_config_rom(ohci->next_config_rom, config_rom, length); } else { /* * In the suspend case, config_rom is NULL, which @@ -1590,7 +1601,7 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) ohci->next_config_rom_bus = ohci->config_rom_bus; } - ohci->next_header = be32_to_cpu(ohci->next_config_rom[0]); + ohci->next_header = ohci->next_config_rom[0]; ohci->next_config_rom[0] = 0; reg_write(ohci, OHCI1394_ConfigROMhdr, 0); reg_write(ohci, OHCI1394_BusOptions, @@ -1624,7 +1635,7 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length) } static int ohci_set_config_rom(struct fw_card *card, - u32 *config_rom, size_t length) + const __be32 *config_rom, size_t length) { struct fw_ohci *ohci; unsigned long flags; @@ -1673,9 +1684,7 @@ static int ohci_set_config_rom(struct fw_card *card, ohci->next_config_rom = next_config_rom; ohci->next_config_rom_bus = next_config_rom_bus; - memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE); - fw_memcpy_to_be32(ohci->next_config_rom, config_rom, - length * 4); + copy_config_rom(ohci->next_config_rom, config_rom, length); ohci->next_header = config_rom[0]; ohci->next_config_rom[0] = 0; @@ -1729,7 +1738,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) if (packet->ack != 0) goto out; - if (packet->payload_bus) + if (packet->payload_mapped) dma_unmap_single(ohci->card.device, packet->payload_bus, packet->payload_length, DMA_TO_DEVICE); diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 98dbbda..d485cdd 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -820,20 +820,25 @@ static void sbp2_release_target(struct kref *kref) fw_device_put(device); } -static struct workqueue_struct *sbp2_wq; +static void sbp2_target_get(struct sbp2_target *tgt) +{ + kref_get(&tgt->kref); +} static void sbp2_target_put(struct sbp2_target *tgt) { kref_put(&tgt->kref, sbp2_release_target); } +static struct workqueue_struct *sbp2_wq; + /* * Always get the target's kref when scheduling work on one its units. * Each workqueue job is responsible to call sbp2_target_put() upon return. */ static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay) { - kref_get(&lu->tgt->kref); + sbp2_target_get(lu->tgt); if (!queue_delayed_work(sbp2_wq, &lu->work, delay)) sbp2_target_put(lu->tgt); } |