GIT acc23b54573d7d85fefe472ed8ba38dcca246583 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git commit Author: Stefan Richter Date: Sat May 19 12:29:37 2007 +0200 ieee1394: add comments in struct hpsb_packet to clarify who is supposed to set what Signed-off-by: Stefan Richter commit f5eab334ac9b88844a22ddc2e7da9c9d5efac2ad Author: Stefan Richter Date: Fri May 11 23:04:08 2007 +0200 firewire: fw-sbp2: remove unused struct member cleanup after support of single-buffer requests was dropped Signed-off-by: Stefan Richter Signed-off-by: Kristian Hoegsberg commit 9b42bc5f3c6f487eacf67e0c15e4bba2428b452c Author: Jan Engelhardt Date: Mon Apr 30 13:29:32 2007 +0200 Use menuconfig objects II - IEEE1394 Make a "menuconfig" out of the Kconfig objects "menu, ..., endmenu", so that the user can disable all the options in that menu at once instead of having to disable each option separately. Follows Stefan's suggestion as per http://lkml.org/lkml/2007/4/28/108 Signed-off-by: Jan Engelhardt Signed-off-by: Andrew Morton Signed-off-by: Stefan Richter commit 461d0b710cd44dc90c55868928eb385b06e86bb1 Author: Stefan Richter Date: Thu May 3 20:24:19 2007 +0200 ieee1394: ohci1394: remove dead CONFIG variable spotted by Robert P. J. Day Signed-off-by: Stefan Richter commit b59f74e660f8064fceb733148aec76334108175c Author: Petr Vandrovec Date: Mon May 7 04:14:47 2007 +0200 ieee1394: raw1394: Add ioctl() for 32bit userland on 64bit kernel Add compat_ioctl. Although all structures are more or less same, raw1394_iso_packets got pointer inside, and raw1394_cycle_timer got unwanted padding in the middle. I did not add any translation for ioctls passing array of integers around as integers seem to have same size (32 bits) on all architectures supported by Linux. Signed-off-by: Petr Vandrovec Acked-by: Dan Dennedy Signed-off-by: Stefan Richter (split into 3 patches) commit 44273c6a648a09570bc5a3258049c8079e3eb8b7 Author: Petr Vandrovec Date: Mon May 7 04:14:47 2007 +0200 ieee1394: raw1394: Fix write() for 32bit userland on 64bit kernel * write(fd, buf, 52) from 32bit app was returning 56. Most of callers did not care, but some (arm registration) did, and anyway it looks bad if request for writing 52 bytes returns 56. And returning sizeof anything in 'int' is not good as well. So all functions now return '0' instead of sizeof(struct raw1394_request) on success, and write() itself provides correct return value (it just returns value it was asked to write on success as raw1394 does not do any partial writes at all). * Related to this was problem that write() could have returned 0 when kernel state would become corrupted and moved to different state than opened/initialized/connected. Now it returns -EBADFD which seemed appropriate. Signed-off-by: Petr Vandrovec Acked-by: Dan Dennedy Signed-off-by: Stefan Richter (split into 3 patches) commit 36354ea205745107709b012bc2350d9922ca3a58 Author: Petr Vandrovec Date: Mon May 7 04:14:47 2007 +0200 ieee1394: raw1394: Fix read() for 32bit userland on 64bit kernel read() always failed with -EFAULT. This was happening due to raw1394_compat_read copying data to wrong location - access_ok always failed as 'r' is kernel address, not user. Whole function just tried to copy data from 'r' to 'r', which is not good. Signed-off-by: Petr Vandrovec Acked-by: Dan Dennedy Signed-off-by: Stefan Richter (split into 3 patches) commit 95608355f5a36781d08757ecea209ce76b4eead0 Author: Petr Vandrovec Date: Sun May 13 22:14:44 2007 -0700 ieee1394: raw1394: Fix async send While playing with libiec61883 I've noticed that async_send is broken because it was doing copy_from_user(...., packet->data_size) before packet->data_size was set to any useful value. It got broken when packet->allocated_data_size got introduced, as hpsb_alloc_packet does not set packet->data_size anymore. (Regression in 2.6.22-rc1) Signed-off-by: Petr Vandrovec Signed-off-by: Stefan Richter commit 60b27f38f3ff9a325fbc044ddfc869bdb46b59ea Author: Stefan Richter Date: Sat May 5 17:25:51 2007 +0200 ieee1394: eth1394: handle tlabel exhaustion When eth1394 was unable to acquire a transaction label, it just dropped outgoing packets without attempt to resend them later. The transmit queue is now halted if no tlabel is available to ->hard_start_xmit(). A workqueue job is then scheduled to catch the moment when ieee1394 recycled the next lot of tlabels. Fixes http://bugzilla.kernel.org/show_bug.cgi?id=8402 Signed-off-by: Stefan Richter commit 6527285b4eaf23e112e88220b3111827916a7dff Author: Stefan Richter Date: Sat May 5 17:19:09 2007 +0200 ieee1394: eth1394: remove bogus netif_wake_queue When we are within hard_start_xmit, the queue is already awake. Signed-off-by: Stefan Richter commit 54b0b6c8bdda632b1556a99562e34d9bda64eec1 Author: Stefan Richter Date: Sat May 5 17:18:12 2007 +0200 ieee1394: sbp2: include workqueue.h Signed-off-by: Stefan Richter drivers/firewire/fw-sbp2.c | 6 - drivers/ieee1394/Kconfig | 8 +- drivers/ieee1394/eth1394.c | 84 ++++++++++++++----- drivers/ieee1394/eth1394.h | 4 + drivers/ieee1394/ieee1394_core.h | 10 ++ drivers/ieee1394/ohci1394.c | 51 ++--------- drivers/ieee1394/raw1394.c | 172 ++++++++++++++++++++++++++++++-------- drivers/ieee1394/sbp2.c | 1 8 files changed, 225 insertions(+), 111 deletions(-) diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 6830041..3ac252d 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c @@ -207,7 +207,6 @@ struct sbp2_command_orb { struct sbp2_pointer page_table[SG_ALL]; dma_addr_t page_table_bus; - dma_addr_t request_buffer_bus; }; /* @@ -882,11 +881,6 @@ complete_command_orb(struct sbp2_orb *ba dma_unmap_single(device->card->device, orb->page_table_bus, sizeof(orb->page_table_bus), DMA_TO_DEVICE); - if (orb->request_buffer_bus != 0) - dma_unmap_single(device->card->device, orb->request_buffer_bus, - sizeof(orb->request_buffer_bus), - DMA_FROM_DEVICE); - orb->cmd->result = result; orb->done(orb->cmd); kfree(orb); diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index 8012b3b..a16b73c 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -1,5 +1,9 @@ -menu "IEEE 1394 (FireWire) support" +menuconfig IEEE1394_SUPPORT + bool "IEEE 1394 (FireWire) support" depends on PCI || BROKEN + default y + +if IEEE1394_SUPPORT source "drivers/firewire/Kconfig" @@ -147,4 +151,4 @@ config IEEE1394_RAWIO To compile this driver as a module, say M here: the module will be called raw1394. -endmenu +endif # IEEE1394_SUPPORT diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 2296d43..d6b19c2 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -47,6 +47,7 @@ #include #include #include #include +#include #include #include @@ -235,6 +236,9 @@ static int ether1394_open(struct net_dev /* This is called after an "ifdown" */ static int ether1394_stop(struct net_device *dev) { + /* flush priv->wake */ + flush_scheduled_work(); + netif_stop_queue(dev); return 0; } @@ -531,6 +535,37 @@ static void ether1394_init_dev(struct ne } /* + * Wake the queue up after commonly encountered transmit failure conditions are + * hopefully over. Currently only tlabel exhaustion is accounted for. + */ +static void ether1394_wake_queue(struct work_struct *work) +{ + struct eth1394_priv *priv; + struct hpsb_packet *packet; + + priv = container_of(work, struct eth1394_priv, wake); + packet = hpsb_alloc_packet(0); + + /* This is really bad, but unjam the queue anyway. */ + if (!packet) + goto out; + + packet->host = priv->host; + packet->node_id = priv->wake_node; + /* + * A transaction label is all we really want. If we get one, it almost + * always means we can get a lot more because the ieee1394 core recycled + * a whole batch of tlabels, at last. + */ + if (hpsb_get_tlabel(packet) == 0) + hpsb_free_tlabel(packet); + + hpsb_free_packet(packet); +out: + netif_wake_queue(priv->wake_dev); +} + +/* * This function is called every time a card is found. It is generally called * when the module is installed. This is where we add all of our ethernet * devices. One for each host. @@ -574,6 +609,8 @@ #endif spin_lock_init(&priv->lock); priv->host = host; priv->local_fifo = fifo_addr; + INIT_WORK(&priv->wake, ether1394_wake_queue); + priv->wake_dev = dev; hi = hpsb_create_hostinfo(ð1394_highlevel, host, sizeof(*hi)); if (hi == NULL) { @@ -1390,22 +1427,17 @@ static int ether1394_prep_write_packet(s u64 addr, void *data, int tx_len) { p->node_id = node; - p->data = NULL; - p->tcode = TCODE_WRITEB; - p->header[1] = host->node_id << 16 | addr >> 32; - p->header[2] = addr & 0xffffffff; + if (hpsb_get_tlabel(p)) + return -EAGAIN; + p->tcode = TCODE_WRITEB; p->header_size = 16; p->expect_response = 1; - - if (hpsb_get_tlabel(p)) { - ETH1394_PRINT_G(KERN_ERR, "Out of tlabels\n"); - return -1; - } p->header[0] = p->node_id << 16 | p->tlabel << 10 | 1 << 8 | TCODE_WRITEB << 4; - + p->header[1] = host->node_id << 16 | addr >> 32; + p->header[2] = addr & 0xffffffff; p->header[3] = tx_len << 16; p->data_size = (tx_len + 3) & ~3; p->data = data; @@ -1451,7 +1483,7 @@ static int ether1394_send_packet(struct packet = ether1394_alloc_common_packet(priv->host); if (!packet) - return -1; + return -ENOMEM; if (ptask->tx_type == ETH1394_GASP) { int length = tx_len + 2 * sizeof(quadlet_t); @@ -1462,7 +1494,7 @@ static int ether1394_send_packet(struct ptask->addr, ptask->skb->data, tx_len)) { hpsb_free_packet(packet); - return -1; + return -EAGAIN; } ptask->packet = packet; @@ -1471,7 +1503,7 @@ static int ether1394_send_packet(struct if (hpsb_send_packet(packet) < 0) { ether1394_free_packet(packet); - return -1; + return -EIO; } return 0; @@ -1514,13 +1546,18 @@ static void ether1394_complete_cb(void * ptask->outstanding_pkts--; if (ptask->outstanding_pkts > 0 && !fail) { - int tx_len; + int tx_len, err; /* Add the encapsulation header to the fragment */ tx_len = ether1394_encapsulate(ptask->skb, ptask->max_payload, &ptask->hdr); - if (ether1394_send_packet(ptask, tx_len)) + err = ether1394_send_packet(ptask, tx_len); + if (err) { + if (err == -EAGAIN) + ETH1394_PRINT_G(KERN_ERR, "Out of tlabels\n"); + ether1394_dg_complete(ptask, 1); + } } else { ether1394_dg_complete(ptask, fail); } @@ -1633,10 +1670,18 @@ #endif /* Add the encapsulation header to the fragment */ tx_len = ether1394_encapsulate(skb, max_payload, &ptask->hdr); dev->trans_start = jiffies; - if (ether1394_send_packet(ptask, tx_len)) - goto fail; + if (ether1394_send_packet(ptask, tx_len)) { + if (dest_node == (LOCAL_BUS | ALL_NODES)) + goto fail; + + /* Most failures of ether1394_send_packet are recoverable. */ + netif_stop_queue(dev); + priv->wake_node = dest_node; + schedule_work(&priv->wake); + kmem_cache_free(packet_task_cache, ptask); + return NETDEV_TX_BUSY; + } - netif_wake_queue(dev); return NETDEV_TX_OK; fail: if (ptask) @@ -1650,9 +1695,6 @@ fail: priv->stats.tx_errors++; spin_unlock_irqrestore(&priv->lock, flags); - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); - /* * FIXME: According to a patch from 2003-02-26, "returning non-zero * causes serious problems" here, allegedly. Before that patch, diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h index a3439ee..4f3e2dd 100644 --- a/drivers/ieee1394/eth1394.h +++ b/drivers/ieee1394/eth1394.h @@ -66,6 +66,10 @@ struct eth1394_priv { int bc_dgl; /* Outgoing broadcast datagram label */ struct list_head ip_node_list; /* List of IP capable nodes */ struct unit_directory *ud_list[ALL_NODES]; /* Cached unit dir list */ + + struct work_struct wake; /* Wake up after xmit failure */ + struct net_device *wake_dev; /* Stupid backlink for .wake */ + nodeid_t wake_node; /* Destination of failed xmit */ }; diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index ad52652..11fd324 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h @@ -37,7 +37,7 @@ struct hpsb_packet { hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete } __attribute__((packed)) state; - /* These are core internal. */ + /* These are core-internal. */ signed char tlabel; signed char ack_code; unsigned char tcode; @@ -62,11 +62,15 @@ struct hpsb_packet { /* Store jiffies for implementing bus timeouts. */ unsigned long sendtime; - /* Sizes are in bytes. *data can be DMA-mapped. */ + /* Core-internal. */ size_t allocated_data_size; /* as allocated */ + + /* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */ size_t data_size; /* as filled in */ size_t header_size; /* as filled in, not counting the CRC */ - quadlet_t *data; + + /* Buffers */ + quadlet_t *data; /* can be DMA-mapped */ quadlet_t header[5]; quadlet_t embedded_data[0]; /* keep as last member */ }; diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 5dadfd2..a75b144 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -138,19 +138,6 @@ #else #define DBGMSG(fmt, args...) do {} while (0) #endif -#ifdef CONFIG_IEEE1394_OHCI_DMA_DEBUG -#define OHCI_DMA_ALLOC(fmt, args...) \ - HPSB_ERR("%s(%s)alloc(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \ - ++global_outstanding_dmas, ## args) -#define OHCI_DMA_FREE(fmt, args...) \ - HPSB_ERR("%s(%s)free(%d): "fmt, OHCI1394_DRIVER_NAME, __FUNCTION__, \ - --global_outstanding_dmas, ## args) -static int global_outstanding_dmas = 0; -#else -#define OHCI_DMA_ALLOC(fmt, args...) do {} while (0) -#define OHCI_DMA_FREE(fmt, args...) do {} while (0) -#endif - /* print general (card independent) information */ #define PRINT_G(level, fmt, args...) \ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) @@ -733,7 +720,6 @@ #endif pci_map_single(ohci->dev, packet->data, packet->data_size, PCI_DMA_TODEVICE)); - OHCI_DMA_ALLOC("single, block transmit packet"); d->prg_cpu[idx]->end.branchAddress = 0; d->prg_cpu[idx]->end.status = 0; @@ -783,7 +769,6 @@ #endif d->prg_cpu[idx]->end.address = cpu_to_le32( pci_map_single(ohci->dev, packet->data, packet->data_size, PCI_DMA_TODEVICE)); - OHCI_DMA_ALLOC("single, iso transmit packet"); d->prg_cpu[idx]->end.branchAddress = 0; d->prg_cpu[idx]->end.status = 0; @@ -2869,12 +2854,10 @@ #endif list_del_init(&packet->driver_list); hpsb_packet_sent(ohci->host, packet, ack); - if (datasize) { + if (datasize) pci_unmap_single(ohci->dev, cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address), datasize, PCI_DMA_TODEVICE); - OHCI_DMA_FREE("single Xmit data packet"); - } d->sent_ind = (d->sent_ind+1)%d->num_desc; d->free_prgs++; @@ -2913,23 +2896,19 @@ static void free_dma_rcv_ctx(struct dma_ if (d->buf_cpu) { for (i=0; inum_desc; i++) - if (d->buf_cpu[i] && d->buf_bus[i]) { + if (d->buf_cpu[i] && d->buf_bus[i]) pci_free_consistent( ohci->dev, d->buf_size, d->buf_cpu[i], d->buf_bus[i]); - OHCI_DMA_FREE("consistent dma_rcv buf[%d]", i); - } kfree(d->buf_cpu); kfree(d->buf_bus); } if (d->prg_cpu) { for (i=0; inum_desc; i++) - if (d->prg_cpu[i] && d->prg_bus[i]) { - pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]); - OHCI_DMA_FREE("consistent dma_rcv prg[%d]", i); - } + if (d->prg_cpu[i] && d->prg_bus[i]) + pci_pool_free(d->prg_pool, d->prg_cpu[i], + d->prg_bus[i]); pci_pool_destroy(d->prg_pool); - OHCI_DMA_FREE("dma_rcv prg pool"); kfree(d->prg_cpu); kfree(d->prg_bus); } @@ -2998,13 +2977,10 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, } num_allocs++; - OHCI_DMA_ALLOC("dma_rcv prg pool"); - for (i=0; inum_desc; i++) { d->buf_cpu[i] = pci_alloc_consistent(ohci->dev, d->buf_size, d->buf_bus+i); - OHCI_DMA_ALLOC("consistent dma_rcv buf[%d]", i); if (d->buf_cpu[i] != NULL) { memset(d->buf_cpu[i], 0, d->buf_size); @@ -3016,7 +2992,6 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, } d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i); - OHCI_DMA_ALLOC("pool dma_rcv prg[%d]", i); if (d->prg_cpu[i] != NULL) { memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd)); @@ -3057,12 +3032,10 @@ static void free_dma_trm_ctx(struct dma_ if (d->prg_cpu) { for (i=0; inum_desc; i++) - if (d->prg_cpu[i] && d->prg_bus[i]) { - pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]); - OHCI_DMA_FREE("pool dma_trm prg[%d]", i); - } + if (d->prg_cpu[i] && d->prg_bus[i]) + pci_pool_free(d->prg_pool, d->prg_cpu[i], + d->prg_bus[i]); pci_pool_destroy(d->prg_pool); - OHCI_DMA_FREE("dma_trm prg pool"); kfree(d->prg_cpu); kfree(d->prg_bus); } @@ -3108,11 +3081,8 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, } num_allocs++; - OHCI_DMA_ALLOC("dma_rcv prg pool"); - for (i = 0; i < d->num_desc; i++) { d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i); - OHCI_DMA_ALLOC("pool dma_trm prg[%d]", i); if (d->prg_cpu[i] != NULL) { memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg)); @@ -3294,7 +3264,6 @@ #endif ohci->csr_config_rom_cpu = pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN, &ohci->csr_config_rom_bus); - OHCI_DMA_ALLOC("consistent csr_config_rom"); if (ohci->csr_config_rom_cpu == NULL) FAIL(-ENOMEM, "Failed to allocate buffer config rom"); ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER; @@ -3303,8 +3272,6 @@ #endif ohci->selfid_buf_cpu = pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, &ohci->selfid_buf_bus); - OHCI_DMA_ALLOC("consistent selfid_buf"); - if (ohci->selfid_buf_cpu == NULL) FAIL(-ENOMEM, "Failed to allocate DMA buffer for self-id packets"); ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER; @@ -3490,13 +3457,11 @@ static void ohci1394_pci_remove(struct p pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, ohci->selfid_buf_cpu, ohci->selfid_buf_bus); - OHCI_DMA_FREE("consistent selfid_buf"); case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER: pci_free_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN, ohci->csr_config_rom_cpu, ohci->csr_config_rom_bus); - OHCI_DMA_FREE("consistent csr_config_rom"); case OHCI_INIT_HAVE_IOMAPPING: iounmap(ohci->registers); diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index d382500..151a48f 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c @@ -459,7 +459,7 @@ #define P(x) __put_user(r->x, &cr->x) static int raw1394_compat_read(const char __user *buf, struct raw1394_request *r) { - struct compat_raw1394_req __user *cr = (typeof(cr)) r; + struct compat_raw1394_req __user *cr = (typeof(cr)) buf; if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) || P(type) || P(error) || @@ -587,7 +587,7 @@ static int state_opened(struct file_info req->req.length = 0; queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; } static int state_initialized(struct file_info *fi, struct pending_request *req) @@ -601,7 +601,7 @@ static int state_initialized(struct file req->req.generation = atomic_read(&internal_generation); req->req.length = 0; queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; } switch (req->req.type) { @@ -673,7 +673,7 @@ out_set_card: } queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; } static void handle_iso_listen(struct file_info *fi, struct pending_request *req) @@ -865,7 +865,7 @@ static int handle_async_request(struct f if (req->req.error) { req->req.length = 0; queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; } hpsb_set_packet_complete_task(packet, @@ -883,7 +883,7 @@ static int handle_async_request(struct f hpsb_free_tlabel(packet); queue_complete_req(req); } - return sizeof(struct raw1394_request); + return 0; } static int handle_iso_send(struct file_info *fi, struct pending_request *req, @@ -907,7 +907,7 @@ static int handle_iso_send(struct file_i req->req.error = RAW1394_ERROR_MEMFAULT; req->req.length = 0; queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; } req->req.length = 0; @@ -927,7 +927,7 @@ static int handle_iso_send(struct file_i queue_complete_req(req); } - return sizeof(struct raw1394_request); + return 0; } static int handle_async_send(struct file_info *fi, struct pending_request *req) @@ -936,16 +936,18 @@ static int handle_async_send(struct file struct hpsb_packet *packet; int header_length = req->req.misc & 0xffff; int expect_response = req->req.misc >> 16; + size_t data_size; if (header_length > req->req.length || header_length < 12 || header_length > FIELD_SIZEOF(struct hpsb_packet, header)) { req->req.error = RAW1394_ERROR_INVALID_ARG; req->req.length = 0; queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; } - packet = hpsb_alloc_packet(req->req.length - header_length); + data_size = req->req.length - header_length; + packet = hpsb_alloc_packet(data_size); req->packet = packet; if (!packet) return -ENOMEM; @@ -955,16 +957,16 @@ static int handle_async_send(struct file req->req.error = RAW1394_ERROR_MEMFAULT; req->req.length = 0; queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; } if (copy_from_user (packet->data, int2ptr(req->req.sendb) + header_length, - packet->data_size)) { + data_size)) { req->req.error = RAW1394_ERROR_MEMFAULT; req->req.length = 0; queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; } packet->type = hpsb_async; @@ -974,7 +976,7 @@ static int handle_async_send(struct file packet->host = fi->host; packet->expect_response = expect_response; packet->header_size = header_length; - packet->data_size = req->req.length - header_length; + packet->data_size = data_size; req->req.length = 0; hpsb_set_packet_complete_task(packet, @@ -992,7 +994,7 @@ static int handle_async_send(struct file queue_complete_req(req); } - return sizeof(struct raw1394_request); + return 0; } static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, @@ -1867,7 +1869,7 @@ static int arm_register(struct file_info spin_lock_irqsave(&host_info_lock, flags); list_add_tail(&addr->addr_list, &fi->addr_list); spin_unlock_irqrestore(&host_info_lock, flags); - return sizeof(struct raw1394_request); + return 0; } retval = hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops, @@ -1885,7 +1887,7 @@ static int arm_register(struct file_info return (-EALREADY); } free_pending_request(req); /* immediate success or fail */ - return sizeof(struct raw1394_request); + return 0; } static int arm_unregister(struct file_info *fi, struct pending_request *req) @@ -1953,7 +1955,7 @@ static int arm_unregister(struct file_in vfree(addr->addr_space_buffer); kfree(addr); free_pending_request(req); /* immediate success or fail */ - return sizeof(struct raw1394_request); + return 0; } retval = hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, @@ -1969,7 +1971,7 @@ static int arm_unregister(struct file_in vfree(addr->addr_space_buffer); kfree(addr); free_pending_request(req); /* immediate success or fail */ - return sizeof(struct raw1394_request); + return 0; } /* Copy data from ARM buffer(s) to user buffer. */ @@ -2011,7 +2013,7 @@ static int arm_get_buf(struct file_info * queue no response, and therefore nobody * will free it. */ free_pending_request(req); - return sizeof(struct raw1394_request); + return 0; } else { DBGMSG("arm_get_buf request exceeded mapping"); spin_unlock_irqrestore(&host_info_lock, flags); @@ -2063,7 +2065,7 @@ static int arm_set_buf(struct file_info * queue no response, and therefore nobody * will free it. */ free_pending_request(req); - return sizeof(struct raw1394_request); + return 0; } else { DBGMSG("arm_set_buf request exceeded mapping"); spin_unlock_irqrestore(&host_info_lock, flags); @@ -2084,7 +2086,7 @@ static int reset_notification(struct fil (req->req.misc == RAW1394_NOTIFY_ON)) { fi->notification = (u8) req->req.misc; free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - return sizeof(struct raw1394_request); + return 0; } /* error EINVAL (22) invalid argument */ return (-EINVAL); @@ -2117,12 +2119,12 @@ static int write_phypacket(struct file_i req->req.length = 0; queue_complete_req(req); } - return sizeof(struct raw1394_request); + return 0; } static int get_config_rom(struct file_info *fi, struct pending_request *req) { - int ret = sizeof(struct raw1394_request); + int ret = 0; quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL); int status; @@ -2152,7 +2154,7 @@ static int get_config_rom(struct file_in static int update_config_rom(struct file_info *fi, struct pending_request *req) { - int ret = sizeof(struct raw1394_request); + int ret = 0; quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL); if (!data) return -ENOMEM; @@ -2219,7 +2221,7 @@ static int modify_config_rom(struct file hpsb_update_config_rom_image(fi->host); free_pending_request(req); - return sizeof(struct raw1394_request); + return 0; } } @@ -2284,7 +2286,7 @@ static int modify_config_rom(struct file /* we have to free the request, because we queue no response, * and therefore nobody will free it */ free_pending_request(req); - return sizeof(struct raw1394_request); + return 0; } else { for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head; @@ -2309,7 +2311,7 @@ static int state_connected(struct file_i case RAW1394_REQ_ECHO: queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; case RAW1394_REQ_ISO_SEND: print_old_iso_deprecation(); @@ -2333,24 +2335,24 @@ static int state_connected(struct file_i case RAW1394_REQ_ISO_LISTEN: print_old_iso_deprecation(); handle_iso_listen(fi, req); - return sizeof(struct raw1394_request); + return 0; case RAW1394_REQ_FCP_LISTEN: handle_fcp_listen(fi, req); - return sizeof(struct raw1394_request); + return 0; case RAW1394_REQ_RESET_BUS: if (req->req.misc == RAW1394_LONG_RESET) { DBGMSG("busreset called (type: LONG)"); hpsb_reset_bus(fi->host, LONG_RESET); free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - return sizeof(struct raw1394_request); + return 0; } if (req->req.misc == RAW1394_SHORT_RESET) { DBGMSG("busreset called (type: SHORT)"); hpsb_reset_bus(fi->host, SHORT_RESET); free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - return sizeof(struct raw1394_request); + return 0; } /* error EINVAL (22) invalid argument */ return (-EINVAL); @@ -2369,7 +2371,7 @@ static int state_connected(struct file_i req->req.generation = get_hpsb_generation(fi->host); req->req.length = 0; queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; } switch (req->req.type) { @@ -2382,7 +2384,7 @@ static int state_connected(struct file_i if (req->req.length == 0) { req->req.error = RAW1394_ERROR_INVALID_ARG; queue_complete_req(req); - return sizeof(struct raw1394_request); + return 0; } return handle_async_request(fi, req, node); @@ -2393,7 +2395,7 @@ static ssize_t raw1394_write(struct file { struct file_info *fi = (struct file_info *)file->private_data; struct pending_request *req; - ssize_t retval = 0; + ssize_t retval = -EBADFD; #ifdef CONFIG_COMPAT if (count == sizeof(struct compat_raw1394_req) && @@ -2435,6 +2437,9 @@ #endif if (retval < 0) { free_pending_request(req); + } else { + BUG_ON(retval); + retval = count; } return retval; @@ -2800,6 +2805,99 @@ static int raw1394_ioctl(struct inode *i return -EINVAL; } +#ifdef CONFIG_COMPAT +struct raw1394_iso_packets32 { + __u32 n_packets; + compat_uptr_t infos; +} __attribute__((packed)); + +struct raw1394_cycle_timer32 { + __u32 cycle_timer; + __u64 local_time; +} __attribute__((packed)); + +#define RAW1394_IOC_ISO_RECV_PACKETS32 \ + _IOW ('#', 0x25, struct raw1394_iso_packets32) +#define RAW1394_IOC_ISO_XMIT_PACKETS32 \ + _IOW ('#', 0x27, struct raw1394_iso_packets32) +#define RAW1394_IOC_GET_CYCLE_TIMER32 \ + _IOR ('#', 0x30, struct raw1394_cycle_timer32) + +static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd, + struct raw1394_iso_packets32 __user *arg) +{ + compat_uptr_t infos32; + void *infos; + long err = -EFAULT; + struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets)); + + if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) && + !copy_from_user(&infos32, &arg->infos, sizeof infos32)) { + infos = compat_ptr(infos32); + if (!copy_to_user(&dst->infos, &infos, sizeof infos)) + err = raw1394_ioctl(NULL, file, cmd, (unsigned long)dst); + } + return err; +} + +static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr) +{ + struct raw1394_cycle_timer32 ct; + int err; + + err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time); + if (!err) + if (copy_to_user(uaddr, &ct, sizeof(ct))) + err = -EFAULT; + return err; +} + +static long raw1394_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct file_info *fi = file->private_data; + 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: + case RAW1394_IOC_ISO_RECV_START: + case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL: + case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL: + case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: + case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS: + case RAW1394_IOC_ISO_RECV_FLUSH: + case RAW1394_IOC_ISO_XMIT_RECV_STOP: + case RAW1394_IOC_ISO_XMIT_INIT: + case RAW1394_IOC_ISO_XMIT_START: + case RAW1394_IOC_ISO_XMIT_SYNC: + case RAW1394_IOC_ISO_GET_STATUS: + case RAW1394_IOC_ISO_SHUTDOWN: + case RAW1394_IOC_ISO_QUEUE_ACTIVITY: + err = raw1394_ioctl(NULL, file, cmd, arg); + break; + /* These request have different format. */ + case RAW1394_IOC_ISO_RECV_PACKETS32: + err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp); + break; + case RAW1394_IOC_ISO_XMIT_PACKETS32: + err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp); + break; + case RAW1394_IOC_GET_CYCLE_TIMER32: + err = raw1394_read_cycle_timer32(fi, argp); + break; + default: + err = -EINVAL; + break; + } + unlock_kernel(); + + return err; +} +#endif + static unsigned int raw1394_poll(struct file *file, poll_table * pt) { struct file_info *fi = file->private_data; @@ -3039,7 +3137,9 @@ static const struct file_operations raw1 .write = raw1394_write, .mmap = raw1394_mmap, .ioctl = raw1394_ioctl, - // .compat_ioctl = ... someone needs to do this +#ifdef CONFIG_COMPAT + .compat_ioctl = raw1394_compat_ioctl, +#endif .poll = raw1394_poll, .open = raw1394_open, .release = raw1394_release, diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 4cb6fa2..875eadd 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -70,6 +70,7 @@ #include #include #include #include +#include #include #include