diff options
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/core-card.c | 2 | ||||
-rw-r--r-- | drivers/firewire/core-cdev.c | 3 | ||||
-rw-r--r-- | drivers/firewire/core-device.c | 2 | ||||
-rw-r--r-- | drivers/firewire/core-iso.c | 1 | ||||
-rw-r--r-- | drivers/firewire/core-topology.c | 2 | ||||
-rw-r--r-- | drivers/firewire/core-transaction.c | 4 | ||||
-rw-r--r-- | drivers/firewire/core.h | 2 | ||||
-rw-r--r-- | drivers/firewire/net.c | 26 | ||||
-rw-r--r-- | drivers/firewire/nosy.c | 2 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 306 | ||||
-rw-r--r-- | drivers/firewire/sbp2.c | 260 |
11 files changed, 201 insertions, 409 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 85661b0..29d2423 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c @@ -32,7 +32,7 @@ #include <linux/spinlock.h> #include <linux/workqueue.h> -#include <linux/atomic.h> +#include <asm/atomic.h> #include <asm/byteorder.h> #include "core.h" diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index ee96b91..b97d4f0 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -1605,7 +1605,8 @@ static int dispatch_ioctl(struct client *client, _IOC_SIZE(cmd) > sizeof(buffer)) return -ENOTTY; - memset(&buffer, 0, sizeof(buffer)); + if (_IOC_DIR(cmd) == _IOC_READ) + memset(&buffer, 0, _IOC_SIZE(cmd)); if (_IOC_DIR(cmd) & _IOC_WRITE) if (copy_from_user(&buffer, arg, _IOC_SIZE(cmd))) diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 1f3dd51..812cea3 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -38,7 +38,7 @@ #include <linux/string.h> #include <linux/workqueue.h> -#include <linux/atomic.h> +#include <asm/atomic.h> #include <asm/byteorder.h> #include <asm/system.h> diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 0f90e00..57c3973 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -29,7 +29,6 @@ #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/vmalloc.h> -#include <linux/export.h> #include <asm/byteorder.h> diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index 94d3b49..193ed92 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -29,7 +29,7 @@ #include <linux/slab.h> #include <linux/spinlock.h> -#include <linux/atomic.h> +#include <asm/atomic.h> #include <asm/byteorder.h> #include <asm/system.h> diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 855ab3f..334b82a 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1046,8 +1046,8 @@ static void update_split_timeout(struct fw_card *card) cycles = card->split_timeout_hi * 8000 + (card->split_timeout_lo >> 19); - /* minimum per IEEE 1394, maximum which doesn't overflow OHCI */ - cycles = clamp(cycles, 800u, 3u * 8000u); + cycles = max(cycles, 800u); /* minimum as per the spec */ + cycles = min(cycles, 3u * 8000u); /* maximum OHCI timeout */ card->split_timeout_cycles = cycles; card->split_timeout_jiffies = DIV_ROUND_UP(cycles * HZ, 8000); diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index b45be57..0fe4e4e 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -9,7 +9,7 @@ #include <linux/slab.h> #include <linux/types.h> -#include <linux/atomic.h> +#include <asm/atomic.h> struct device; struct fw_card; diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 7c869b7..e74750b 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -7,7 +7,6 @@ */ #include <linux/bug.h> -#include <linux/compiler.h> #include <linux/delay.h> #include <linux/device.h> #include <linux/ethtool.h> @@ -74,7 +73,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 */ -} __packed; +} __attribute__((packed)); /* This header format is specific to this driver implementation. */ #define FWNET_ALEN 8 @@ -82,7 +81,7 @@ struct rfc2734_arp { struct fwnet_header { u8 h_dest[FWNET_ALEN]; /* destination address */ __be16 h_proto; /* packet type ID field */ -} __packed; +} __attribute__((packed)); /* IPv4 and IPv6 encapsulation header */ struct rfc2734_header { @@ -262,16 +261,16 @@ static int fwnet_header_rebuild(struct sk_buff *skb) } static int fwnet_header_cache(const struct neighbour *neigh, - struct hh_cache *hh, __be16 type) + struct hh_cache *hh) { struct net_device *net; struct fwnet_header *h; - if (type == cpu_to_be16(ETH_P_802_3)) + if (hh->hh_type == cpu_to_be16(ETH_P_802_3)) return -1; net = neigh->dev; h = (struct fwnet_header *)((u8 *)hh->hh_data + 16 - sizeof(*h)); - h->h_proto = type; + h->h_proto = hh->hh_type; memcpy(h->h_dest, neigh->ha, net->addr_len); hh->hh_len = FWNET_HLEN; @@ -502,7 +501,11 @@ static struct fwnet_peer *fwnet_peer_find_by_node_id(struct fwnet_device *dev, static unsigned fwnet_max_payload(unsigned max_rec, unsigned speed) { max_rec = min(max_rec, speed + 8); - max_rec = clamp(max_rec, 8U, 11U); /* 512...4096 */ + max_rec = min(max_rec, 0xbU); /* <= 4096 */ + if (max_rec < 8) { + fw_notify("max_rec %x out of range\n", max_rec); + max_rec = 8; + } return (1 << (max_rec + 1)) - RFC2374_FRAG_HDR_SIZE; } @@ -1126,12 +1129,17 @@ static int fwnet_broadcast_start(struct fwnet_device *dev) unsigned u; if (dev->local_fifo == FWNET_NO_FIFO_ADDR) { + /* outside OHCI posted write area? */ + static const struct fw_address_region region = { + .start = 0xffff00000000ULL, + .end = CSR_REGISTER_BASE, + }; + dev->handler.length = 4096; dev->handler.address_callback = fwnet_receive_packet; dev->handler.callback_data = dev; - retval = fw_core_add_address_handler(&dev->handler, - &fw_high_memory_region); + retval = fw_core_add_address_handler(&dev->handler, ®ion); if (retval < 0) goto failed_initial; diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c index 763626b..0618145 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c @@ -37,7 +37,7 @@ #include <linux/uaccess.h> #include <linux/wait.h> -#include <linux/atomic.h> +#include <asm/atomic.h> #include <asm/byteorder.h> #include "nosy.h" diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 0a0225a..271fc51 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -42,7 +42,6 @@ #include <linux/string.h> #include <linux/time.h> #include <linux/vmalloc.h> -#include <linux/workqueue.h> #include <asm/byteorder.h> #include <asm/page.h> @@ -126,7 +125,6 @@ struct context { struct fw_ohci *ohci; u32 regs; int total_allocation; - u32 current_bus; bool running; bool flushing; @@ -228,7 +226,7 @@ struct fw_ohci { __le32 *self_id_cpu; dma_addr_t self_id_bus; - struct work_struct bus_reset_work; + struct tasklet_struct bus_reset_tasklet; u32 self_id_buffer[512]; }; @@ -255,6 +253,7 @@ 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 @@ -266,8 +265,6 @@ static char ohci_driver_name[] = KBUILD_MODNAME; #define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001 #define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380 #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 -#define PCI_DEVICE_ID_TI_TSB12LV26 0x8020 -#define PCI_DEVICE_ID_TI_TSB82AA2 0x8025 #define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd #define QUIRK_CYCLE_TIMER 1 @@ -275,7 +272,6 @@ static char ohci_driver_name[] = KBUILD_MODNAME; #define QUIRK_BE_HEADERS 4 #define QUIRK_NO_1394A 8 #define QUIRK_NO_MSI 16 -#define QUIRK_TI_SLLZ059 32 /* In case of multiple matches in ohci_quirks[], only the first one is used. */ static const struct { @@ -308,12 +304,6 @@ static const struct { {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID, QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A}, - {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV26, PCI_ANY_ID, - QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059}, - - {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB82AA2, PCI_ANY_ID, - QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059}, - {PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID, QUIRK_RESET_PACKET}, @@ -330,7 +320,6 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) ", disable MSI = " __stringify(QUIRK_NO_MSI) - ", TI SLLZ059 erratum = " __stringify(QUIRK_TI_SLLZ059) ")"); #define OHCI_PARAM_DEBUG_AT_AR 1 @@ -532,12 +521,6 @@ 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; @@ -546,9 +529,6 @@ 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); @@ -572,9 +552,6 @@ 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; @@ -660,6 +637,7 @@ 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) @@ -875,7 +853,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) * * Alas some chips sometimes emit bus reset packets with a * wrong generation. We set the correct generation for these - * at a slightly incorrect time (in bus_reset_work). + * at a slightly incorrect time (in bus_reset_tasklet). */ if (evt == OHCI1394_evt_bus_reset) { if (!(ohci->quirks & QUIRK_RESET_PACKET)) @@ -1031,6 +1009,7 @@ 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) @@ -1062,7 +1041,6 @@ static void context_tasklet(unsigned long data) address = le32_to_cpu(last->branch_address); z = address & 0xf; address &= ~0xf; - ctx->current_bus = address; /* If the branch address points to a buffer outside of the * current buffer, advance to the next buffer. */ @@ -1231,14 +1209,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 < 1000; i++) { + for (i = 0; i < 10; i++) { reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); if ((reg & CONTEXT_ACTIVE) == 0) return; - if (i) - udelay(10); + mdelay(1); } fw_error("Error: DMA context still active (0x%08x)\n", reg); } @@ -1375,10 +1353,12 @@ 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); - else + flush_writes(ohci); + } else { context_run(ctx, 0); + } return 0; } @@ -1730,94 +1710,9 @@ static u32 update_bus_time(struct fw_ohci *ohci) return ohci->bus_time | cycle_time_seconds; } -static int get_status_for_port(struct fw_ohci *ohci, int port_index) -{ - int reg; - - mutex_lock(&ohci->phy_reg_mutex); - reg = write_phy_reg(ohci, 7, port_index); - if (reg >= 0) - reg = read_phy_reg(ohci, 8); - mutex_unlock(&ohci->phy_reg_mutex); - if (reg < 0) - return reg; - - switch (reg & 0x0f) { - case 0x06: - return 2; /* is child node (connected to parent node) */ - case 0x0e: - return 3; /* is parent node (connected to child node) */ - } - return 1; /* not connected */ -} - -static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id, - int self_id_count) -{ - int i; - u32 entry; - - for (i = 0; i < self_id_count; i++) { - entry = ohci->self_id_buffer[i]; - if ((self_id & 0xff000000) == (entry & 0xff000000)) - return -1; - if ((self_id & 0xff000000) < (entry & 0xff000000)) - return i; - } - return i; -} - -/* - * TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally - * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059. - * Construct the selfID from phy register contents. - * FIXME: How to determine the selfID.i flag? - */ -static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count) +static void bus_reset_tasklet(unsigned long data) { - int reg, i, pos, status; - /* link active 1, speed 3, bridge 0, contender 1, more packets 0 */ - u32 self_id = 0x8040c800; - - reg = reg_read(ohci, OHCI1394_NodeID); - if (!(reg & OHCI1394_NodeID_idValid)) { - fw_notify("node ID not valid, new bus reset in progress\n"); - return -EBUSY; - } - self_id |= ((reg & 0x3f) << 24); /* phy ID */ - - reg = ohci_read_phy_reg(&ohci->card, 4); - if (reg < 0) - return reg; - self_id |= ((reg & 0x07) << 8); /* power class */ - - reg = ohci_read_phy_reg(&ohci->card, 1); - if (reg < 0) - return reg; - self_id |= ((reg & 0x3f) << 16); /* gap count */ - - for (i = 0; i < 3; i++) { - status = get_status_for_port(ohci, i); - if (status < 0) - return status; - self_id |= ((status & 0x3) << (6 - (i * 2))); - } - - pos = get_self_id_pos(ohci, self_id, self_id_count); - if (pos >= 0) { - memmove(&(ohci->self_id_buffer[pos+1]), - &(ohci->self_id_buffer[pos]), - (self_id_count - pos) * sizeof(*ohci->self_id_buffer)); - ohci->self_id_buffer[pos] = self_id; - self_id_count++; - } - return self_id_count; -} - -static void bus_reset_work(struct work_struct *work) -{ - struct fw_ohci *ohci = - container_of(work, struct fw_ohci, bus_reset_work); + struct fw_ohci *ohci = (struct fw_ohci *)data; int self_id_count, i, j, reg; int generation, new_generation; unsigned long flags; @@ -1855,50 +1750,21 @@ static void bus_reset_work(struct work_struct *work) * bit extra to get the actual number of self IDs. */ self_id_count = (reg >> 3) & 0xff; - - if (self_id_count > 252) { + if (self_id_count == 0 || self_id_count > 252) { fw_notify("inconsistent self IDs\n"); return; } - generation = (cond_le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff; rmb(); for (i = 1, j = 0; j < self_id_count; i += 2, j++) { if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1]) { - /* - * If the invalid data looks like a cycle start packet, - * it's likely to be the result of the cycle master - * having a wrong gap count. In this case, the self IDs - * so far are valid and should be processed so that the - * bus manager can then correct the gap count. - */ - if (cond_le32_to_cpu(ohci->self_id_cpu[i]) - == 0xffff008f) { - fw_notify("ignoring spurious self IDs\n"); - self_id_count = j; - break; - } else { - fw_notify("inconsistent self IDs\n"); - return; - } + fw_notify("inconsistent self IDs\n"); + return; } ohci->self_id_buffer[j] = cond_le32_to_cpu(ohci->self_id_cpu[i]); } - - if (ohci->quirks & QUIRK_TI_SLLZ059) { - self_id_count = find_and_insert_self_id(ohci, self_id_count); - if (self_id_count < 0) { - fw_notify("could not construct local self ID\n"); - return; - } - } - - if (self_id_count == 0) { - fw_notify("inconsistent self IDs\n"); - return; - } rmb(); /* @@ -2018,7 +1884,7 @@ static irqreturn_t irq_handler(int irq, void *data) log_irqs(event); if (event & OHCI1394_selfIDComplete) - queue_work(fw_workqueue, &ohci->bus_reset_work); + tasklet_schedule(&ohci->bus_reset_tasklet); if (event & OHCI1394_RQPkt) tasklet_schedule(&ohci->ar_request_ctx.tasklet); @@ -2065,8 +1931,7 @@ static irqreturn_t irq_handler(int irq, void *data) reg_read(ohci, OHCI1394_PostedWriteAddressLo); reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_postedWriteErr); - if (printk_ratelimit()) - fw_error("PCI posted write error\n"); + fw_error("PCI posted write error\n"); } if (unlikely(event & OHCI1394_cycleTooLong)) { @@ -2102,18 +1967,14 @@ 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. */ - if (!(val & OHCI1394_HCControl_softReset)) + for (i = 0; i < OHCI_LOOP_COUNT; i++) { + if ((reg_read(ohci, OHCI1394_HCControlSet) & + OHCI1394_HCControl_softReset) == 0) return 0; - msleep(1); } @@ -2180,28 +2041,6 @@ static int configure_1394a_enhancements(struct fw_ohci *ohci) return 0; } -static int probe_tsb41ba3d(struct fw_ohci *ohci) -{ - /* TI vendor ID = 0x080028, TSB41BA3D product ID = 0x833005 (sic) */ - static const u8 id[] = { 0x08, 0x00, 0x28, 0x83, 0x30, 0x05, }; - int reg, i; - - reg = read_phy_reg(ohci, 2); - if (reg < 0) - return reg; - if ((reg & PHY_EXTENDED_REGISTERS) != PHY_EXTENDED_REGISTERS) - return 0; - - for (i = ARRAY_SIZE(id) - 1; i >= 0; i--) { - reg = read_paged_phy_reg(ohci, 1, i + 10); - if (reg < 0) - return reg; - if (reg != id[i]) - return 0; - } - return 1; -} - static int ohci_enable(struct fw_card *card, const __be32 *config_rom, size_t length) { @@ -2239,16 +2078,6 @@ static int ohci_enable(struct fw_card *card, return -EIO; } - if (ohci->quirks & QUIRK_TI_SLLZ059) { - ret = probe_tsb41ba3d(ohci); - if (ret < 0) - return ret; - if (ret) - fw_notify("local TSB41BA3D phy\n"); - else - ohci->quirks &= ~QUIRK_TI_SLLZ059; - } - reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwapData); @@ -2346,13 +2175,8 @@ static int ohci_enable(struct fw_card *card, ohci_driver_name, ohci)) { fw_error("Failed to allocate interrupt %d.\n", dev->irq); pci_disable_msi(dev); - - if (config_rom) { - dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, - ohci->next_config_rom, - ohci->next_config_rom_bus); - ohci->next_config_rom = NULL; - } + dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, + ohci->config_rom, ohci->config_rom_bus); return -EIO; } @@ -2380,9 +2204,7 @@ 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); - - flush_writes(ohci); + ar_context_run(&ohci->ar_response_ctx); /* also flushes writes */ /* We are ready to go, reset bus to finish initialization. */ fw_schedule_bus_reset(&ohci->card, false, true); @@ -2424,7 +2246,7 @@ static int ohci_set_config_rom(struct fw_card *card, * then set up the real values for the two registers. * * We use ohci->lock to avoid racing with the code that sets - * ohci->next_config_rom to NULL (see bus_reset_work). + * ohci->next_config_rom to NULL (see bus_reset_tasklet). */ next_config_rom = @@ -2703,7 +2525,6 @@ static int handle_ir_packet_per_buffer(struct context *context, struct iso_context *ctx = container_of(context, struct iso_context, context); struct descriptor *pd; - u32 buffer_dma; __le32 *ir_header; void *p; @@ -2714,16 +2535,6 @@ static int handle_ir_packet_per_buffer(struct context *context, /* Descriptor(s) not done yet, stop iteration */ return 0; - while (!(d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))) { - d++; - buffer_dma = le32_to_cpu(d->data_address); - dma_sync_single_range_for_cpu(context->ohci->card.device, - buffer_dma & PAGE_MASK, - buffer_dma & ~PAGE_MASK, - le16_to_cpu(d->req_count), - DMA_FROM_DEVICE); - } - p = last + 1; copy_iso_headers(ctx, p); @@ -2746,19 +2557,11 @@ static int handle_ir_buffer_fill(struct context *context, { struct iso_context *ctx = container_of(context, struct iso_context, context); - u32 buffer_dma; if (last->res_count != 0) /* Descriptor(s) not done yet, stop iteration */ return 0; - buffer_dma = le32_to_cpu(last->data_address); - dma_sync_single_range_for_cpu(context->ohci->card.device, - buffer_dma & PAGE_MASK, - buffer_dma & ~PAGE_MASK, - le16_to_cpu(last->req_count), - DMA_FROM_DEVICE); - if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) ctx->base.callback.mc(&ctx->base, le32_to_cpu(last->data_address) + @@ -2768,43 +2571,6 @@ static int handle_ir_buffer_fill(struct context *context, return 1; } -static inline void sync_it_packet_for_cpu(struct context *context, - struct descriptor *pd) -{ - __le16 control; - u32 buffer_dma; - - /* only packets beginning with OUTPUT_MORE* have data buffers */ - if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)) - return; - - /* skip over the OUTPUT_MORE_IMMEDIATE descriptor */ - pd += 2; - - /* - * If the packet has a header, the first OUTPUT_MORE/LAST descriptor's - * data buffer is in the context program's coherent page and must not - * be synced. - */ - if ((le32_to_cpu(pd->data_address) & PAGE_MASK) == - (context->current_bus & PAGE_MASK)) { - if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)) - return; - pd++; - } - - do { - buffer_dma = le32_to_cpu(pd->data_address); - dma_sync_single_range_for_cpu(context->ohci->card.device, - buffer_dma & PAGE_MASK, - buffer_dma & ~PAGE_MASK, - le16_to_cpu(pd->req_count), - DMA_TO_DEVICE); - control = pd->control; - pd++; - } while (!(control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))); -} - static int handle_it_packet(struct context *context, struct descriptor *d, struct descriptor *last) @@ -2821,8 +2587,6 @@ static int handle_it_packet(struct context *context, /* Descriptor(s) not done yet, stop iteration */ return 0; - sync_it_packet_for_cpu(context, d); - i = ctx->header_length; if (i + 4 < PAGE_SIZE) { /* Present this value as big-endian to match the receive code */ @@ -3192,10 +2956,6 @@ static int queue_iso_transmit(struct iso_context *ctx, page_bus = page_private(buffer->pages[page]); pd[i].data_address = cpu_to_le32(page_bus + offset); - dma_sync_single_range_for_device(ctx->context.ohci->card.device, - page_bus, offset, length, - DMA_TO_DEVICE); - payload_index += length; } @@ -3220,7 +2980,6 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx, struct fw_iso_buffer *buffer, unsigned long payload) { - struct device *device = ctx->context.ohci->card.device; struct descriptor *d, *pd; dma_addr_t d_bus, page_bus; u32 z, header_z, rest; @@ -3275,10 +3034,6 @@ static int queue_iso_packet_per_buffer(struct iso_context *ctx, page_bus = page_private(buffer->pages[page]); pd->data_address = cpu_to_le32(page_bus + offset); - dma_sync_single_range_for_device(device, page_bus, - offset, length, - DMA_FROM_DEVICE); - offset = (offset + length) & ~PAGE_MASK; rest -= length; if (offset == 0) @@ -3338,10 +3093,6 @@ static int queue_iso_buffer_fill(struct iso_context *ctx, page_bus = page_private(buffer->pages[page]); d->data_address = cpu_to_le32(page_bus + offset); - dma_sync_single_range_for_device(ctx->context.ohci->card.device, - page_bus, offset, length, - DMA_FROM_DEVICE); - rest -= length; offset = 0; page++; @@ -3384,6 +3135,7 @@ 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 = { @@ -3473,7 +3225,8 @@ static int __devinit pci_probe(struct pci_dev *dev, spin_lock_init(&ohci->lock); mutex_init(&ohci->phy_reg_mutex); - INIT_WORK(&ohci->bus_reset_work, bus_reset_work); + tasklet_init(&ohci->bus_reset_tasklet, + bus_reset_tasklet, (unsigned long)ohci); err = pci_request_region(dev, 0, ohci_driver_name); if (err) { @@ -3615,7 +3368,6 @@ static void pci_remove(struct pci_dev *dev) ohci = pci_get_drvdata(dev); reg_write(ohci, OHCI1394_IntMaskClear, ~0); flush_writes(ohci); - cancel_work_sync(&ohci->bus_reset_work); fw_core_remove_card(&ohci->card); /* diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 68375bc..17cef86 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -154,16 +154,12 @@ struct sbp2_logical_unit { bool blocked; }; -static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay) -{ - queue_delayed_work(fw_workqueue, &lu->work, delay); -} - /* * We create one struct sbp2_target per IEEE 1212 Unit Directory * and one struct Scsi_Host per sbp2_target. */ struct sbp2_target { + struct kref kref; struct fw_unit *unit; const char *bus_id; struct list_head lu_list; @@ -776,6 +772,71 @@ static int sbp2_lun2int(u16 lun) return scsilun_to_int(&eight_bytes_lun); } +static void sbp2_release_target(struct kref *kref) +{ + struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref); + struct sbp2_logical_unit *lu, *next; + struct Scsi_Host *shost = + container_of((void *)tgt, struct Scsi_Host, hostdata[0]); + struct scsi_device *sdev; + struct fw_device *device = target_device(tgt); + + /* prevent deadlocks */ + sbp2_unblock(tgt); + + list_for_each_entry_safe(lu, next, &tgt->lu_list, link) { + sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun)); + if (sdev) { + scsi_remove_device(sdev); + scsi_device_put(sdev); + } + if (lu->login_id != INVALID_LOGIN_ID) { + int generation, node_id; + /* + * tgt->node_id may be obsolete here if we failed + * during initial login or after a bus reset where + * the topology changed. + */ + generation = device->generation; + smp_rmb(); /* node_id vs. generation */ + node_id = device->node_id; + sbp2_send_management_orb(lu, node_id, generation, + SBP2_LOGOUT_REQUEST, + lu->login_id, NULL); + } + fw_core_remove_address_handler(&lu->address_handler); + list_del(&lu->link); + kfree(lu); + } + scsi_remove_host(shost); + fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no); + + fw_unit_put(tgt->unit); + scsi_host_put(shost); + fw_device_put(device); +} + +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); +} + +/* + * 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) +{ + sbp2_target_get(lu->tgt); + if (!queue_delayed_work(fw_workqueue, &lu->work, delay)) + sbp2_target_put(lu->tgt); +} + /* * Write retransmit retry values into the BUSY_TIMEOUT register. * - The single-phase retry protocol is supported by all SBP-2 devices, but the @@ -816,7 +877,7 @@ static void sbp2_login(struct work_struct *work) int generation, node_id, local_node_id; if (fw_device_is_shutdown(device)) - return; + goto out; generation = device->generation; smp_rmb(); /* node IDs must not be older than generation */ @@ -838,7 +899,7 @@ static void sbp2_login(struct work_struct *work) /* Let any waiting I/O fail from now on. */ sbp2_unblock(lu->tgt); } - return; + goto out; } tgt->node_id = node_id; @@ -864,8 +925,7 @@ static void sbp2_login(struct work_struct *work) if (lu->has_sdev) { sbp2_cancel_orbs(lu); sbp2_conditionally_unblock(lu); - - return; + goto out; } if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY) @@ -897,8 +957,7 @@ static void sbp2_login(struct work_struct *work) lu->has_sdev = true; scsi_device_put(sdev); sbp2_allow_block(lu); - - return; + goto out; out_logout_login: smp_rmb(); /* generation may have changed */ @@ -912,57 +971,8 @@ static void sbp2_login(struct work_struct *work) * lu->work already. Reset the work from reconnect to login. */ PREPARE_DELAYED_WORK(&lu->work, sbp2_login); -} - -static void sbp2_reconnect(struct work_struct *work) -{ - struct sbp2_logical_unit *lu = - container_of(work, struct sbp2_logical_unit, work.work); - struct sbp2_target *tgt = lu->tgt; - struct fw_device *device = target_device(tgt); - int generation, node_id, local_node_id; - - if (fw_device_is_shutdown(device)) - return; - - generation = device->generation; - smp_rmb(); /* node IDs must not be older than generation */ - node_id = device->node_id; - local_node_id = device->card->node_id; - - if (sbp2_send_management_orb(lu, node_id, generation, - SBP2_RECONNECT_REQUEST, - lu->login_id, NULL) < 0) { - /* - * If reconnect was impossible even though we are in the - * current generation, fall back and try to log in again. - * - * We could check for "Function rejected" status, but - * looking at the bus generation as simpler and more general. - */ - smp_rmb(); /* get current card generation */ - if (generation == device->card->generation || - lu->retries++ >= 5) { - fw_error("%s: failed to reconnect\n", tgt->bus_id); - lu->retries = 0; - PREPARE_DELAYED_WORK(&lu->work, sbp2_login); - } - sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); - - return; - } - - tgt->node_id = node_id; - tgt->address_high = local_node_id << 16; - smp_wmb(); /* node IDs must not be older than generation */ - lu->generation = generation; - - fw_notify("%s: reconnected to LUN %04x (%d retries)\n", - tgt->bus_id, lu->lun, lu->retries); - - sbp2_agent_reset(lu); - sbp2_cancel_orbs(lu); - sbp2_conditionally_unblock(lu); + out: + sbp2_target_put(tgt); } static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) @@ -1110,7 +1120,6 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model, } static struct scsi_host_template scsi_driver_template; -static int sbp2_remove(struct device *dev); static int sbp2_probe(struct device *dev) { @@ -1132,6 +1141,7 @@ static int sbp2_probe(struct device *dev) tgt = (struct sbp2_target *)shost->hostdata; dev_set_drvdata(&unit->device, tgt); tgt->unit = unit; + kref_init(&tgt->kref); INIT_LIST_HEAD(&tgt->lu_list); tgt->bus_id = dev_name(&unit->device); tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; @@ -1144,6 +1154,9 @@ static int sbp2_probe(struct device *dev) if (scsi_add_host(shost, &unit->device) < 0) goto fail_shost_put; + fw_device_get(device); + fw_unit_get(unit); + /* implicit directory ID */ tgt->directory_id = ((unit->directory - device->config_rom) * 4 + CSR_CONFIG_ROM) & 0xffffff; @@ -1153,7 +1166,7 @@ static int sbp2_probe(struct device *dev) if (sbp2_scan_unit_dir(tgt, unit->directory, &model, &firmware_revision) < 0) - goto fail_remove; + goto fail_tgt_put; sbp2_clamp_management_orb_timeout(tgt); sbp2_init_workarounds(tgt, model, firmware_revision); @@ -1164,17 +1177,16 @@ static int sbp2_probe(struct device *dev) * specifies the max payload size as 2 ^ (max_payload + 2), so * if we set this to max_speed + 7, we get the right value. */ - tgt->max_payload = min3(device->max_speed + 7, 10U, - device->card->max_receive - 1); + tgt->max_payload = min(device->max_speed + 7, 10U); + tgt->max_payload = min(tgt->max_payload, device->card->max_receive - 1); /* Do the login in a workqueue so we can easily reschedule retries. */ list_for_each_entry(lu, &tgt->lu_list, link) sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); - return 0; - fail_remove: - sbp2_remove(dev); + fail_tgt_put: + sbp2_target_put(tgt); return -ENOMEM; fail_shost_put: @@ -1182,6 +1194,71 @@ static int sbp2_probe(struct device *dev) return -ENOMEM; } +static int sbp2_remove(struct device *dev) +{ + struct fw_unit *unit = fw_unit(dev); + struct sbp2_target *tgt = dev_get_drvdata(&unit->device); + struct sbp2_logical_unit *lu; + + list_for_each_entry(lu, &tgt->lu_list, link) + cancel_delayed_work_sync(&lu->work); + + sbp2_target_put(tgt); + return 0; +} + +static void sbp2_reconnect(struct work_struct *work) +{ + struct sbp2_logical_unit *lu = + container_of(work, struct sbp2_logical_unit, work.work); + struct sbp2_target *tgt = lu->tgt; + struct fw_device *device = target_device(tgt); + int generation, node_id, local_node_id; + + if (fw_device_is_shutdown(device)) + goto out; + + generation = device->generation; + smp_rmb(); /* node IDs must not be older than generation */ + node_id = device->node_id; + local_node_id = device->card->node_id; + + if (sbp2_send_management_orb(lu, node_id, generation, + SBP2_RECONNECT_REQUEST, + lu->login_id, NULL) < 0) { + /* + * If reconnect was impossible even though we are in the + * current generation, fall back and try to log in again. + * + * We could check for "Function rejected" status, but + * looking at the bus generation as simpler and more general. + */ + smp_rmb(); /* get current card generation */ + if (generation == device->card->generation || + lu->retries++ >= 5) { + fw_error("%s: failed to reconnect\n", tgt->bus_id); + lu->retries = 0; + PREPARE_DELAYED_WORK(&lu->work, sbp2_login); + } + sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); + goto out; + } + + tgt->node_id = node_id; + tgt->address_high = local_node_id << 16; + smp_wmb(); /* node IDs must not be older than generation */ + lu->generation = generation; + + fw_notify("%s: reconnected to LUN %04x (%d retries)\n", + tgt->bus_id, lu->lun, lu->retries); + + sbp2_agent_reset(lu); + sbp2_cancel_orbs(lu); + sbp2_conditionally_unblock(lu); + out: + sbp2_target_put(tgt); +} + static void sbp2_update(struct fw_unit *unit) { struct sbp2_target *tgt = dev_get_drvdata(&unit->device); @@ -1200,51 +1277,6 @@ static void sbp2_update(struct fw_unit *unit) } } -static int sbp2_remove(struct device *dev) -{ - struct fw_unit *unit = fw_unit(dev); - struct fw_device *device = fw_parent_device(unit); - struct sbp2_target *tgt = dev_get_drvdata(&unit->device); - struct sbp2_logical_unit *lu, *next; - struct Scsi_Host *shost = - container_of((void *)tgt, struct Scsi_Host, hostdata[0]); - struct scsi_device *sdev; - - /* prevent deadlocks */ - sbp2_unblock(tgt); - - list_for_each_entry_safe(lu, next, &tgt->lu_list, link) { - cancel_delayed_work_sync(&lu->work); - sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun)); - if (sdev) { - scsi_remove_device(sdev); - scsi_device_put(sdev); - } - if (lu->login_id != INVALID_LOGIN_ID) { - int generation, node_id; - /* - * tgt->node_id may be obsolete here if we failed - * during initial login or after a bus reset where - * the topology changed. - */ - generation = device->generation; - smp_rmb(); /* node_id vs. generation */ - node_id = device->node_id; - sbp2_send_management_orb(lu, node_id, generation, - SBP2_LOGOUT_REQUEST, - lu->login_id, NULL); - } - fw_core_remove_address_handler(&lu->address_handler); - list_del(&lu->link); - kfree(lu); - } - scsi_remove_host(shost); - fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no); - - scsi_host_put(shost); - return 0; -} - #define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e #define SBP2_SW_VERSION_ENTRY 0x00010483 |