diff options
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/core-cdev.c | 20 | ||||
-rw-r--r-- | drivers/firewire/net.c | 5 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 42 |
3 files changed, 41 insertions, 26 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index b1c1177..e6ad3bb 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -253,14 +253,11 @@ static int fw_device_op_open(struct inode *inode, struct file *file) init_waitqueue_head(&client->wait); init_waitqueue_head(&client->tx_flush_wait); INIT_LIST_HEAD(&client->phy_receiver_link); + INIT_LIST_HEAD(&client->link); kref_init(&client->kref); file->private_data = client; - mutex_lock(&device->client_list_mutex); - list_add_tail(&client->link, &device->client_list); - mutex_unlock(&device->client_list_mutex); - return nonseekable_open(inode, file); } @@ -451,15 +448,20 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg) if (ret != 0) return -EFAULT; + mutex_lock(&client->device->client_list_mutex); + client->bus_reset_closure = a->bus_reset_closure; if (a->bus_reset != 0) { fill_bus_reset_event(&bus_reset, client); - if (copy_to_user(u64_to_uptr(a->bus_reset), - &bus_reset, sizeof(bus_reset))) - return -EFAULT; + ret = copy_to_user(u64_to_uptr(a->bus_reset), + &bus_reset, sizeof(bus_reset)); } + if (ret == 0 && list_empty(&client->link)) + list_add_tail(&client->link, &client->device->client_list); - return 0; + mutex_unlock(&client->device->client_list_mutex); + + return ret ? -EFAULT : 0; } static int add_client_resource(struct client *client, @@ -1583,7 +1585,7 @@ static int dispatch_ioctl(struct client *client, if (_IOC_TYPE(cmd) != '#' || _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) || _IOC_SIZE(cmd) > sizeof(buffer)) - return -EINVAL; + return -ENOTTY; if (_IOC_DIR(cmd) == _IOC_READ) memset(&buffer, 0, _IOC_SIZE(cmd)); diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index eced1c2..03a7a85 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -7,6 +7,7 @@ */ #include <linux/bug.h> +#include <linux/compiler.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/ethtool.h> @@ -73,7 +74,7 @@ struct rfc2734_arp { __be32 fifo_lo; /* lo 32bits of sender's FIFO addr */ __be32 sip; /* Sender's IP Address */ __be32 tip; /* IP Address of requested hw addr */ -} __attribute__((packed)); +} __packed; /* This header format is specific to this driver implementation. */ #define FWNET_ALEN 8 @@ -81,7 +82,7 @@ struct rfc2734_arp { struct fwnet_header { u8 h_dest[FWNET_ALEN]; /* destination address */ __be16 h_proto; /* packet type ID field */ -} __attribute__((packed)); +} __packed; /* IPv4 and IPv6 encapsulation header */ struct rfc2734_header { diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index ebb8973..bcf792f 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -253,7 +253,6 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card) #define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8 #define OHCI1394_REGISTER_SIZE 0x800 -#define OHCI_LOOP_COUNT 500 #define OHCI1394_PCI_HCI_Control 0x40 #define SELF_ID_BUF_SIZE 0x800 #define OHCI_TCODE_PHY_PACKET 0x0e @@ -514,6 +513,12 @@ static inline void flush_writes(const struct fw_ohci *ohci) reg_read(ohci, OHCI1394_Version); } +/* + * Beware! read_phy_reg(), write_phy_reg(), update_phy_reg(), and + * read_paged_phy_reg() require the caller to hold ohci->phy_reg_mutex. + * In other words, only use ohci_read_phy_reg() and ohci_update_phy_reg() + * directly. Exceptions are intrinsically serialized contexts like pci_probe. + */ static int read_phy_reg(struct fw_ohci *ohci, int addr) { u32 val; @@ -522,6 +527,9 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr) reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); for (i = 0; i < 3 + 100; i++) { val = reg_read(ohci, OHCI1394_PhyControl); + if (!~val) + return -ENODEV; /* Card was ejected. */ + if (val & OHCI1394_PhyControl_ReadDone) return OHCI1394_PhyControl_ReadData(val); @@ -545,6 +553,9 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val) OHCI1394_PhyControl_Write(addr, val)); for (i = 0; i < 3 + 100; i++) { val = reg_read(ohci, OHCI1394_PhyControl); + if (!~val) + return -ENODEV; /* Card was ejected. */ + if (!(val & OHCI1394_PhyControl_WritePending)) return 0; @@ -630,7 +641,6 @@ static void ar_context_link_page(struct ar_context *ctx, unsigned int index) ctx->last_buffer_index = index; reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ctx->ohci); } static void ar_context_release(struct ar_context *ctx) @@ -1002,7 +1012,6 @@ static void ar_context_run(struct ar_context *ctx) reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1); reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); - flush_writes(ctx->ohci); } static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) @@ -1202,14 +1211,14 @@ static void context_stop(struct context *ctx) reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); ctx->running = false; - flush_writes(ctx->ohci); - for (i = 0; i < 10; i++) { + for (i = 0; i < 1000; i++) { reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); if ((reg & CONTEXT_ACTIVE) == 0) return; - mdelay(1); + if (i) + udelay(10); } fw_error("Error: DMA context still active (0x%08x)\n", reg); } @@ -1346,12 +1355,10 @@ static int at_context_queue_packet(struct context *ctx, context_append(ctx, d, z, 4 - z); - if (ctx->running) { + if (ctx->running) reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ohci); - } else { + else context_run(ctx, 0); - } return 0; } @@ -1960,14 +1967,18 @@ static irqreturn_t irq_handler(int irq, void *data) static int software_reset(struct fw_ohci *ohci) { + u32 val; int i; reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); + for (i = 0; i < 500; i++) { + val = reg_read(ohci, OHCI1394_HCControlSet); + if (!~val) + return -ENODEV; /* Card was ejected. */ - for (i = 0; i < OHCI_LOOP_COUNT; i++) { - if ((reg_read(ohci, OHCI1394_HCControlSet) & - OHCI1394_HCControl_softReset) == 0) + if (!(val & OHCI1394_HCControl_softReset)) return 0; + msleep(1); } @@ -2197,7 +2208,9 @@ static int ohci_enable(struct fw_card *card, OHCI1394_LinkControl_rcvPhyPkt); ar_context_run(&ohci->ar_request_ctx); - ar_context_run(&ohci->ar_response_ctx); /* also flushes writes */ + ar_context_run(&ohci->ar_response_ctx); + + flush_writes(ohci); /* We are ready to go, reset bus to finish initialization. */ fw_schedule_bus_reset(&ohci->card, false, true); @@ -3129,7 +3142,6 @@ static void ohci_flush_queue_iso(struct fw_iso_context *base) &container_of(base, struct iso_context, base)->context; reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); - flush_writes(ctx->ohci); } static const struct fw_card_driver ohci_driver = { |