diff options
| -rw-r--r-- | drivers/firewire/core-card.c | 41 | ||||
| -rw-r--r-- | drivers/firewire/core-cdev.c | 50 | ||||
| -rw-r--r-- | drivers/firewire/ohci.c | 4 | ||||
| -rw-r--r-- | drivers/mtd/ubi/cdev.c | 1 | ||||
| -rw-r--r-- | include/linux/firewire-cdev.h | 4 |
5 files changed, 70 insertions, 30 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 7083bcc1b9c7..5045156c5313 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c | |||
| @@ -57,6 +57,8 @@ static LIST_HEAD(descriptor_list); | |||
| 57 | static int descriptor_count; | 57 | static int descriptor_count; |
| 58 | 58 | ||
| 59 | static __be32 tmp_config_rom[256]; | 59 | static __be32 tmp_config_rom[256]; |
| 60 | /* ROM header, bus info block, root dir header, capabilities = 7 quadlets */ | ||
| 61 | static size_t config_rom_length = 1 + 4 + 1 + 1; | ||
| 60 | 62 | ||
| 61 | #define BIB_CRC(v) ((v) << 0) | 63 | #define BIB_CRC(v) ((v) << 0) |
| 62 | #define BIB_CRC_LENGTH(v) ((v) << 16) | 64 | #define BIB_CRC_LENGTH(v) ((v) << 16) |
| @@ -73,7 +75,7 @@ static __be32 tmp_config_rom[256]; | |||
| 73 | #define BIB_CMC ((1) << 30) | 75 | #define BIB_CMC ((1) << 30) |
| 74 | #define BIB_IMC ((1) << 31) | 76 | #define BIB_IMC ((1) << 31) |
| 75 | 77 | ||
| 76 | static size_t generate_config_rom(struct fw_card *card, __be32 *config_rom) | 78 | static void generate_config_rom(struct fw_card *card, __be32 *config_rom) |
| 77 | { | 79 | { |
| 78 | struct fw_descriptor *desc; | 80 | struct fw_descriptor *desc; |
| 79 | int i, j, k, length; | 81 | int i, j, k, length; |
| @@ -130,23 +132,30 @@ static size_t generate_config_rom(struct fw_card *card, __be32 *config_rom) | |||
| 130 | for (i = 0; i < j; i += length + 1) | 132 | for (i = 0; i < j; i += length + 1) |
| 131 | length = fw_compute_block_crc(config_rom + i); | 133 | length = fw_compute_block_crc(config_rom + i); |
| 132 | 134 | ||
| 133 | return j; | 135 | WARN_ON(j != config_rom_length); |
| 134 | } | 136 | } |
| 135 | 137 | ||
| 136 | static void update_config_roms(void) | 138 | static void update_config_roms(void) |
| 137 | { | 139 | { |
| 138 | struct fw_card *card; | 140 | struct fw_card *card; |
| 139 | size_t length; | ||
| 140 | 141 | ||
| 141 | list_for_each_entry (card, &card_list, link) { | 142 | list_for_each_entry (card, &card_list, link) { |
| 142 | length = generate_config_rom(card, tmp_config_rom); | 143 | generate_config_rom(card, tmp_config_rom); |
| 143 | card->driver->set_config_rom(card, tmp_config_rom, length); | 144 | card->driver->set_config_rom(card, tmp_config_rom, |
| 145 | config_rom_length); | ||
| 144 | } | 146 | } |
| 145 | } | 147 | } |
| 146 | 148 | ||
| 149 | static size_t required_space(struct fw_descriptor *desc) | ||
| 150 | { | ||
| 151 | /* descriptor + entry into root dir + optional immediate entry */ | ||
| 152 | return desc->length + 1 + (desc->immediate > 0 ? 1 : 0); | ||
| 153 | } | ||
| 154 | |||
| 147 | int fw_core_add_descriptor(struct fw_descriptor *desc) | 155 | int fw_core_add_descriptor(struct fw_descriptor *desc) |
| 148 | { | 156 | { |
| 149 | size_t i; | 157 | size_t i; |
| 158 | int ret; | ||
| 150 | 159 | ||
| 151 | /* | 160 | /* |
| 152 | * Check descriptor is valid; the length of all blocks in the | 161 | * Check descriptor is valid; the length of all blocks in the |
| @@ -162,15 +171,21 @@ int fw_core_add_descriptor(struct fw_descriptor *desc) | |||
| 162 | 171 | ||
| 163 | mutex_lock(&card_mutex); | 172 | mutex_lock(&card_mutex); |
| 164 | 173 | ||
| 165 | list_add_tail(&desc->link, &descriptor_list); | 174 | if (config_rom_length + required_space(desc) > 256) { |
| 166 | descriptor_count++; | 175 | ret = -EBUSY; |
| 167 | if (desc->immediate > 0) | 176 | } else { |
| 177 | list_add_tail(&desc->link, &descriptor_list); | ||
| 178 | config_rom_length += required_space(desc); | ||
| 168 | descriptor_count++; | 179 | descriptor_count++; |
| 169 | update_config_roms(); | 180 | if (desc->immediate > 0) |
| 181 | descriptor_count++; | ||
| 182 | update_config_roms(); | ||
| 183 | ret = 0; | ||
| 184 | } | ||
| 170 | 185 | ||
| 171 | mutex_unlock(&card_mutex); | 186 | mutex_unlock(&card_mutex); |
| 172 | 187 | ||
| 173 | return 0; | 188 | return ret; |
| 174 | } | 189 | } |
| 175 | EXPORT_SYMBOL(fw_core_add_descriptor); | 190 | EXPORT_SYMBOL(fw_core_add_descriptor); |
| 176 | 191 | ||
| @@ -179,6 +194,7 @@ void fw_core_remove_descriptor(struct fw_descriptor *desc) | |||
| 179 | mutex_lock(&card_mutex); | 194 | mutex_lock(&card_mutex); |
| 180 | 195 | ||
| 181 | list_del(&desc->link); | 196 | list_del(&desc->link); |
| 197 | config_rom_length -= required_space(desc); | ||
| 182 | descriptor_count--; | 198 | descriptor_count--; |
| 183 | if (desc->immediate > 0) | 199 | if (desc->immediate > 0) |
| 184 | descriptor_count--; | 200 | descriptor_count--; |
| @@ -428,7 +444,6 @@ EXPORT_SYMBOL(fw_card_initialize); | |||
| 428 | int fw_card_add(struct fw_card *card, | 444 | int fw_card_add(struct fw_card *card, |
| 429 | u32 max_receive, u32 link_speed, u64 guid) | 445 | u32 max_receive, u32 link_speed, u64 guid) |
| 430 | { | 446 | { |
| 431 | size_t length; | ||
| 432 | int ret; | 447 | int ret; |
| 433 | 448 | ||
| 434 | card->max_receive = max_receive; | 449 | card->max_receive = max_receive; |
| @@ -437,8 +452,8 @@ int fw_card_add(struct fw_card *card, | |||
| 437 | 452 | ||
| 438 | mutex_lock(&card_mutex); | 453 | mutex_lock(&card_mutex); |
| 439 | 454 | ||
| 440 | length = generate_config_rom(card, tmp_config_rom); | 455 | generate_config_rom(card, tmp_config_rom); |
| 441 | ret = card->driver->enable(card, tmp_config_rom, length); | 456 | ret = card->driver->enable(card, tmp_config_rom, config_rom_length); |
| 442 | if (ret == 0) | 457 | if (ret == 0) |
| 443 | list_add_tail(&card->link, &card_list); | 458 | list_add_tail(&card->link, &card_list); |
| 444 | 459 | ||
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index e6d63849e78e..4eeaed57e219 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/preempt.h> | 35 | #include <linux/preempt.h> |
| 36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
| 37 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
| 38 | #include <linux/string.h> | ||
| 38 | #include <linux/time.h> | 39 | #include <linux/time.h> |
| 39 | #include <linux/uaccess.h> | 40 | #include <linux/uaccess.h> |
| 40 | #include <linux/vmalloc.h> | 41 | #include <linux/vmalloc.h> |
| @@ -595,13 +596,20 @@ static int ioctl_send_request(struct client *client, void *buffer) | |||
| 595 | client->device->max_speed); | 596 | client->device->max_speed); |
| 596 | } | 597 | } |
| 597 | 598 | ||
| 599 | static inline bool is_fcp_request(struct fw_request *request) | ||
| 600 | { | ||
| 601 | return request == NULL; | ||
| 602 | } | ||
| 603 | |||
| 598 | static void release_request(struct client *client, | 604 | static void release_request(struct client *client, |
| 599 | struct client_resource *resource) | 605 | struct client_resource *resource) |
| 600 | { | 606 | { |
| 601 | struct inbound_transaction_resource *r = container_of(resource, | 607 | struct inbound_transaction_resource *r = container_of(resource, |
| 602 | struct inbound_transaction_resource, resource); | 608 | struct inbound_transaction_resource, resource); |
| 603 | 609 | ||
| 604 | if (r->request) | 610 | if (is_fcp_request(r->request)) |
| 611 | kfree(r->data); | ||
| 612 | else | ||
| 605 | fw_send_response(client->device->card, r->request, | 613 | fw_send_response(client->device->card, r->request, |
| 606 | RCODE_CONFLICT_ERROR); | 614 | RCODE_CONFLICT_ERROR); |
| 607 | kfree(r); | 615 | kfree(r); |
| @@ -616,6 +624,7 @@ static void handle_request(struct fw_card *card, struct fw_request *request, | |||
| 616 | struct address_handler_resource *handler = callback_data; | 624 | struct address_handler_resource *handler = callback_data; |
| 617 | struct inbound_transaction_resource *r; | 625 | struct inbound_transaction_resource *r; |
| 618 | struct inbound_transaction_event *e; | 626 | struct inbound_transaction_event *e; |
| 627 | void *fcp_frame = NULL; | ||
| 619 | int ret; | 628 | int ret; |
| 620 | 629 | ||
| 621 | r = kmalloc(sizeof(*r), GFP_ATOMIC); | 630 | r = kmalloc(sizeof(*r), GFP_ATOMIC); |
| @@ -627,6 +636,18 @@ static void handle_request(struct fw_card *card, struct fw_request *request, | |||
| 627 | r->data = payload; | 636 | r->data = payload; |
| 628 | r->length = length; | 637 | r->length = length; |
| 629 | 638 | ||
| 639 | if (is_fcp_request(request)) { | ||
| 640 | /* | ||
| 641 | * FIXME: Let core-transaction.c manage a | ||
| 642 | * single reference-counted copy? | ||
| 643 | */ | ||
| 644 | fcp_frame = kmemdup(payload, length, GFP_ATOMIC); | ||
| 645 | if (fcp_frame == NULL) | ||
| 646 | goto failed; | ||
| 647 | |||
| 648 | r->data = fcp_frame; | ||
| 649 | } | ||
| 650 | |||
| 630 | r->resource.release = release_request; | 651 | r->resource.release = release_request; |
| 631 | ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC); | 652 | ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC); |
| 632 | if (ret < 0) | 653 | if (ret < 0) |
| @@ -640,13 +661,15 @@ static void handle_request(struct fw_card *card, struct fw_request *request, | |||
| 640 | e->request.closure = handler->closure; | 661 | e->request.closure = handler->closure; |
| 641 | 662 | ||
| 642 | queue_event(handler->client, &e->event, | 663 | queue_event(handler->client, &e->event, |
| 643 | &e->request, sizeof(e->request), payload, length); | 664 | &e->request, sizeof(e->request), r->data, length); |
| 644 | return; | 665 | return; |
| 645 | 666 | ||
| 646 | failed: | 667 | failed: |
| 647 | kfree(r); | 668 | kfree(r); |
| 648 | kfree(e); | 669 | kfree(e); |
| 649 | if (request) | 670 | kfree(fcp_frame); |
| 671 | |||
| 672 | if (!is_fcp_request(request)) | ||
| 650 | fw_send_response(card, request, RCODE_CONFLICT_ERROR); | 673 | fw_send_response(card, request, RCODE_CONFLICT_ERROR); |
| 651 | } | 674 | } |
| 652 | 675 | ||
| @@ -717,18 +740,17 @@ static int ioctl_send_response(struct client *client, void *buffer) | |||
| 717 | 740 | ||
| 718 | r = container_of(resource, struct inbound_transaction_resource, | 741 | r = container_of(resource, struct inbound_transaction_resource, |
| 719 | resource); | 742 | resource); |
| 720 | if (r->request) { | 743 | if (is_fcp_request(r->request)) |
| 721 | if (request->length < r->length) | 744 | goto out; |
| 722 | r->length = request->length; | 745 | |
| 723 | if (copy_from_user(r->data, u64_to_uptr(request->data), | 746 | if (request->length < r->length) |
| 724 | r->length)) { | 747 | r->length = request->length; |
| 725 | ret = -EFAULT; | 748 | if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) { |
| 726 | kfree(r->request); | 749 | ret = -EFAULT; |
| 727 | goto out; | 750 | kfree(r->request); |
| 728 | } | 751 | goto out; |
| 729 | fw_send_response(client->device->card, r->request, | ||
| 730 | request->rcode); | ||
| 731 | } | 752 | } |
| 753 | fw_send_response(client->device->card, r->request, request->rcode); | ||
| 732 | out: | 754 | out: |
| 733 | kfree(r); | 755 | kfree(r); |
| 734 | 756 | ||
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index a61571c63c59..2345d4103fe6 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
| @@ -2420,6 +2420,7 @@ static void ohci_pmac_off(struct pci_dev *dev) | |||
| 2420 | 2420 | ||
| 2421 | #define PCI_VENDOR_ID_AGERE PCI_VENDOR_ID_ATT | 2421 | #define PCI_VENDOR_ID_AGERE PCI_VENDOR_ID_ATT |
| 2422 | #define PCI_DEVICE_ID_AGERE_FW643 0x5901 | 2422 | #define PCI_DEVICE_ID_AGERE_FW643 0x5901 |
| 2423 | #define PCI_DEVICE_ID_TI_TSB43AB23 0x8024 | ||
| 2423 | 2424 | ||
| 2424 | static int __devinit pci_probe(struct pci_dev *dev, | 2425 | static int __devinit pci_probe(struct pci_dev *dev, |
| 2425 | const struct pci_device_id *ent) | 2426 | const struct pci_device_id *ent) |
| @@ -2488,7 +2489,8 @@ static int __devinit pci_probe(struct pci_dev *dev, | |||
| 2488 | #if !defined(CONFIG_X86_32) | 2489 | #if !defined(CONFIG_X86_32) |
| 2489 | /* dual-buffer mode is broken with descriptor addresses above 2G */ | 2490 | /* dual-buffer mode is broken with descriptor addresses above 2G */ |
| 2490 | if (dev->vendor == PCI_VENDOR_ID_TI && | 2491 | if (dev->vendor == PCI_VENDOR_ID_TI && |
| 2491 | dev->device == PCI_DEVICE_ID_TI_TSB43AB22) | 2492 | (dev->device == PCI_DEVICE_ID_TI_TSB43AB22 || |
| 2493 | dev->device == PCI_DEVICE_ID_TI_TSB43AB23)) | ||
| 2492 | ohci->use_dualbuffer = false; | 2494 | ohci->use_dualbuffer = false; |
| 2493 | #endif | 2495 | #endif |
| 2494 | 2496 | ||
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index f237ddbb2713..111ea41c4ecd 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c | |||
| @@ -853,7 +853,6 @@ static long ubi_cdev_ioctl(struct file *file, unsigned int cmd, | |||
| 853 | break; | 853 | break; |
| 854 | } | 854 | } |
| 855 | 855 | ||
| 856 | req.name[req.name_len] = '\0'; | ||
| 857 | err = verify_mkvol_req(ubi, &req); | 856 | err = verify_mkvol_req(ubi, &req); |
| 858 | if (err) | 857 | if (err) |
| 859 | break; | 858 | break; |
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index 1f716d9f714b..520ecf86cbb3 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h | |||
| @@ -380,7 +380,7 @@ struct fw_cdev_initiate_bus_reset { | |||
| 380 | * @immediate: If non-zero, immediate key to insert before pointer | 380 | * @immediate: If non-zero, immediate key to insert before pointer |
| 381 | * @key: Upper 8 bits of root directory pointer | 381 | * @key: Upper 8 bits of root directory pointer |
| 382 | * @data: Userspace pointer to contents of descriptor block | 382 | * @data: Userspace pointer to contents of descriptor block |
| 383 | * @length: Length of descriptor block data, in bytes | 383 | * @length: Length of descriptor block data, in quadlets |
| 384 | * @handle: Handle to the descriptor, written by the kernel | 384 | * @handle: Handle to the descriptor, written by the kernel |
| 385 | * | 385 | * |
| 386 | * Add a descriptor block and optionally a preceding immediate key to the local | 386 | * Add a descriptor block and optionally a preceding immediate key to the local |
| @@ -394,6 +394,8 @@ struct fw_cdev_initiate_bus_reset { | |||
| 394 | * If not 0, the @immediate field specifies an immediate key which will be | 394 | * If not 0, the @immediate field specifies an immediate key which will be |
| 395 | * inserted before the root directory pointer. | 395 | * inserted before the root directory pointer. |
| 396 | * | 396 | * |
| 397 | * @immediate, @key, and @data array elements are CPU-endian quadlets. | ||
| 398 | * | ||
| 397 | * If successful, the kernel adds the descriptor and writes back a handle to the | 399 | * If successful, the kernel adds the descriptor and writes back a handle to the |
| 398 | * kernel-side object to be used for later removal of the descriptor block and | 400 | * kernel-side object to be used for later removal of the descriptor block and |
| 399 | * immediate key. | 401 | * immediate key. |
