diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 17:49:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-22 17:49:48 -0400 |
commit | 441c196e84b11aad3123baa9320eee7abc6b5c98 (patch) | |
tree | ea51d689c9ac09cce10a5758f19d6adbd8a7a9d7 /drivers/firewire | |
parent | 951cc93a7493a81a47e20231441bc6cf17c98a37 (diff) | |
parent | 9a00c24ae7cb08dcd46edf1327a47871e8466444 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
firewire: document the sysfs ABIs
firewire: cdev: ABI documentation enhancements
firewire: cdev: prevent race between first get_info ioctl and bus reset event queuing
firewire: cdev: return -ENOTTY for unimplemented ioctls, not -EINVAL
firewire: ohci: skip soft reset retries after card ejection
firewire: ohci: fix PHY reg access after card ejection
firewire: ohci: add a comment on PHY reg access serialization
firewire: ohci: reduce potential context_stop latency
firewire: ohci: remove superfluous posted write flushes
firewire: net: replacing deprecated __attribute__((packed)) with __packed
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 b1c11775839c..e6ad3bb6c1a6 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) | |||
253 | init_waitqueue_head(&client->wait); | 253 | init_waitqueue_head(&client->wait); |
254 | init_waitqueue_head(&client->tx_flush_wait); | 254 | init_waitqueue_head(&client->tx_flush_wait); |
255 | INIT_LIST_HEAD(&client->phy_receiver_link); | 255 | INIT_LIST_HEAD(&client->phy_receiver_link); |
256 | INIT_LIST_HEAD(&client->link); | ||
256 | kref_init(&client->kref); | 257 | kref_init(&client->kref); |
257 | 258 | ||
258 | file->private_data = client; | 259 | file->private_data = client; |
259 | 260 | ||
260 | mutex_lock(&device->client_list_mutex); | ||
261 | list_add_tail(&client->link, &device->client_list); | ||
262 | mutex_unlock(&device->client_list_mutex); | ||
263 | |||
264 | return nonseekable_open(inode, file); | 261 | return nonseekable_open(inode, file); |
265 | } | 262 | } |
266 | 263 | ||
@@ -451,15 +448,20 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg) | |||
451 | if (ret != 0) | 448 | if (ret != 0) |
452 | return -EFAULT; | 449 | return -EFAULT; |
453 | 450 | ||
451 | mutex_lock(&client->device->client_list_mutex); | ||
452 | |||
454 | client->bus_reset_closure = a->bus_reset_closure; | 453 | client->bus_reset_closure = a->bus_reset_closure; |
455 | if (a->bus_reset != 0) { | 454 | if (a->bus_reset != 0) { |
456 | fill_bus_reset_event(&bus_reset, client); | 455 | fill_bus_reset_event(&bus_reset, client); |
457 | if (copy_to_user(u64_to_uptr(a->bus_reset), | 456 | ret = copy_to_user(u64_to_uptr(a->bus_reset), |
458 | &bus_reset, sizeof(bus_reset))) | 457 | &bus_reset, sizeof(bus_reset)); |
459 | return -EFAULT; | ||
460 | } | 458 | } |
459 | if (ret == 0 && list_empty(&client->link)) | ||
460 | list_add_tail(&client->link, &client->device->client_list); | ||
461 | 461 | ||
462 | return 0; | 462 | mutex_unlock(&client->device->client_list_mutex); |
463 | |||
464 | return ret ? -EFAULT : 0; | ||
463 | } | 465 | } |
464 | 466 | ||
465 | static int add_client_resource(struct client *client, | 467 | static int add_client_resource(struct client *client, |
@@ -1583,7 +1585,7 @@ static int dispatch_ioctl(struct client *client, | |||
1583 | if (_IOC_TYPE(cmd) != '#' || | 1585 | if (_IOC_TYPE(cmd) != '#' || |
1584 | _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) || | 1586 | _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers) || |
1585 | _IOC_SIZE(cmd) > sizeof(buffer)) | 1587 | _IOC_SIZE(cmd) > sizeof(buffer)) |
1586 | return -EINVAL; | 1588 | return -ENOTTY; |
1587 | 1589 | ||
1588 | if (_IOC_DIR(cmd) == _IOC_READ) | 1590 | if (_IOC_DIR(cmd) == _IOC_READ) |
1589 | memset(&buffer, 0, _IOC_SIZE(cmd)); | 1591 | memset(&buffer, 0, _IOC_SIZE(cmd)); |
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index eced1c25bf58..03a7a85d0424 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c | |||
@@ -7,6 +7,7 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/bug.h> | 9 | #include <linux/bug.h> |
10 | #include <linux/compiler.h> | ||
10 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
11 | #include <linux/device.h> | 12 | #include <linux/device.h> |
12 | #include <linux/ethtool.h> | 13 | #include <linux/ethtool.h> |
@@ -73,7 +74,7 @@ struct rfc2734_arp { | |||
73 | __be32 fifo_lo; /* lo 32bits of sender's FIFO addr */ | 74 | __be32 fifo_lo; /* lo 32bits of sender's FIFO addr */ |
74 | __be32 sip; /* Sender's IP Address */ | 75 | __be32 sip; /* Sender's IP Address */ |
75 | __be32 tip; /* IP Address of requested hw addr */ | 76 | __be32 tip; /* IP Address of requested hw addr */ |
76 | } __attribute__((packed)); | 77 | } __packed; |
77 | 78 | ||
78 | /* This header format is specific to this driver implementation. */ | 79 | /* This header format is specific to this driver implementation. */ |
79 | #define FWNET_ALEN 8 | 80 | #define FWNET_ALEN 8 |
@@ -81,7 +82,7 @@ struct rfc2734_arp { | |||
81 | struct fwnet_header { | 82 | struct fwnet_header { |
82 | u8 h_dest[FWNET_ALEN]; /* destination address */ | 83 | u8 h_dest[FWNET_ALEN]; /* destination address */ |
83 | __be16 h_proto; /* packet type ID field */ | 84 | __be16 h_proto; /* packet type ID field */ |
84 | } __attribute__((packed)); | 85 | } __packed; |
85 | 86 | ||
86 | /* IPv4 and IPv6 encapsulation header */ | 87 | /* IPv4 and IPv6 encapsulation header */ |
87 | struct rfc2734_header { | 88 | struct rfc2734_header { |
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index ebb897329c1e..bcf792fac442 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) | |||
253 | #define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8 | 253 | #define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8 |
254 | 254 | ||
255 | #define OHCI1394_REGISTER_SIZE 0x800 | 255 | #define OHCI1394_REGISTER_SIZE 0x800 |
256 | #define OHCI_LOOP_COUNT 500 | ||
257 | #define OHCI1394_PCI_HCI_Control 0x40 | 256 | #define OHCI1394_PCI_HCI_Control 0x40 |
258 | #define SELF_ID_BUF_SIZE 0x800 | 257 | #define SELF_ID_BUF_SIZE 0x800 |
259 | #define OHCI_TCODE_PHY_PACKET 0x0e | 258 | #define OHCI_TCODE_PHY_PACKET 0x0e |
@@ -514,6 +513,12 @@ static inline void flush_writes(const struct fw_ohci *ohci) | |||
514 | reg_read(ohci, OHCI1394_Version); | 513 | reg_read(ohci, OHCI1394_Version); |
515 | } | 514 | } |
516 | 515 | ||
516 | /* | ||
517 | * Beware! read_phy_reg(), write_phy_reg(), update_phy_reg(), and | ||
518 | * read_paged_phy_reg() require the caller to hold ohci->phy_reg_mutex. | ||
519 | * In other words, only use ohci_read_phy_reg() and ohci_update_phy_reg() | ||
520 | * directly. Exceptions are intrinsically serialized contexts like pci_probe. | ||
521 | */ | ||
517 | static int read_phy_reg(struct fw_ohci *ohci, int addr) | 522 | static int read_phy_reg(struct fw_ohci *ohci, int addr) |
518 | { | 523 | { |
519 | u32 val; | 524 | u32 val; |
@@ -522,6 +527,9 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr) | |||
522 | reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); | 527 | reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); |
523 | for (i = 0; i < 3 + 100; i++) { | 528 | for (i = 0; i < 3 + 100; i++) { |
524 | val = reg_read(ohci, OHCI1394_PhyControl); | 529 | val = reg_read(ohci, OHCI1394_PhyControl); |
530 | if (!~val) | ||
531 | return -ENODEV; /* Card was ejected. */ | ||
532 | |||
525 | if (val & OHCI1394_PhyControl_ReadDone) | 533 | if (val & OHCI1394_PhyControl_ReadDone) |
526 | return OHCI1394_PhyControl_ReadData(val); | 534 | return OHCI1394_PhyControl_ReadData(val); |
527 | 535 | ||
@@ -545,6 +553,9 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val) | |||
545 | OHCI1394_PhyControl_Write(addr, val)); | 553 | OHCI1394_PhyControl_Write(addr, val)); |
546 | for (i = 0; i < 3 + 100; i++) { | 554 | for (i = 0; i < 3 + 100; i++) { |
547 | val = reg_read(ohci, OHCI1394_PhyControl); | 555 | val = reg_read(ohci, OHCI1394_PhyControl); |
556 | if (!~val) | ||
557 | return -ENODEV; /* Card was ejected. */ | ||
558 | |||
548 | if (!(val & OHCI1394_PhyControl_WritePending)) | 559 | if (!(val & OHCI1394_PhyControl_WritePending)) |
549 | return 0; | 560 | return 0; |
550 | 561 | ||
@@ -630,7 +641,6 @@ static void ar_context_link_page(struct ar_context *ctx, unsigned int index) | |||
630 | ctx->last_buffer_index = index; | 641 | ctx->last_buffer_index = index; |
631 | 642 | ||
632 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); | 643 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); |
633 | flush_writes(ctx->ohci); | ||
634 | } | 644 | } |
635 | 645 | ||
636 | static void ar_context_release(struct ar_context *ctx) | 646 | static void ar_context_release(struct ar_context *ctx) |
@@ -1002,7 +1012,6 @@ static void ar_context_run(struct ar_context *ctx) | |||
1002 | 1012 | ||
1003 | reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1); | 1013 | reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1); |
1004 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); | 1014 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); |
1005 | flush_writes(ctx->ohci); | ||
1006 | } | 1015 | } |
1007 | 1016 | ||
1008 | static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) | 1017 | static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) |
@@ -1202,14 +1211,14 @@ static void context_stop(struct context *ctx) | |||
1202 | 1211 | ||
1203 | reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); | 1212 | reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); |
1204 | ctx->running = false; | 1213 | ctx->running = false; |
1205 | flush_writes(ctx->ohci); | ||
1206 | 1214 | ||
1207 | for (i = 0; i < 10; i++) { | 1215 | for (i = 0; i < 1000; i++) { |
1208 | reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); | 1216 | reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); |
1209 | if ((reg & CONTEXT_ACTIVE) == 0) | 1217 | if ((reg & CONTEXT_ACTIVE) == 0) |
1210 | return; | 1218 | return; |
1211 | 1219 | ||
1212 | mdelay(1); | 1220 | if (i) |
1221 | udelay(10); | ||
1213 | } | 1222 | } |
1214 | fw_error("Error: DMA context still active (0x%08x)\n", reg); | 1223 | fw_error("Error: DMA context still active (0x%08x)\n", reg); |
1215 | } | 1224 | } |
@@ -1346,12 +1355,10 @@ static int at_context_queue_packet(struct context *ctx, | |||
1346 | 1355 | ||
1347 | context_append(ctx, d, z, 4 - z); | 1356 | context_append(ctx, d, z, 4 - z); |
1348 | 1357 | ||
1349 | if (ctx->running) { | 1358 | if (ctx->running) |
1350 | reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); | 1359 | reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); |
1351 | flush_writes(ohci); | 1360 | else |
1352 | } else { | ||
1353 | context_run(ctx, 0); | 1361 | context_run(ctx, 0); |
1354 | } | ||
1355 | 1362 | ||
1356 | return 0; | 1363 | return 0; |
1357 | } | 1364 | } |
@@ -1960,14 +1967,18 @@ static irqreturn_t irq_handler(int irq, void *data) | |||
1960 | 1967 | ||
1961 | static int software_reset(struct fw_ohci *ohci) | 1968 | static int software_reset(struct fw_ohci *ohci) |
1962 | { | 1969 | { |
1970 | u32 val; | ||
1963 | int i; | 1971 | int i; |
1964 | 1972 | ||
1965 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); | 1973 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); |
1974 | for (i = 0; i < 500; i++) { | ||
1975 | val = reg_read(ohci, OHCI1394_HCControlSet); | ||
1976 | if (!~val) | ||
1977 | return -ENODEV; /* Card was ejected. */ | ||
1966 | 1978 | ||
1967 | for (i = 0; i < OHCI_LOOP_COUNT; i++) { | 1979 | if (!(val & OHCI1394_HCControl_softReset)) |
1968 | if ((reg_read(ohci, OHCI1394_HCControlSet) & | ||
1969 | OHCI1394_HCControl_softReset) == 0) | ||
1970 | return 0; | 1980 | return 0; |
1981 | |||
1971 | msleep(1); | 1982 | msleep(1); |
1972 | } | 1983 | } |
1973 | 1984 | ||
@@ -2197,7 +2208,9 @@ static int ohci_enable(struct fw_card *card, | |||
2197 | OHCI1394_LinkControl_rcvPhyPkt); | 2208 | OHCI1394_LinkControl_rcvPhyPkt); |
2198 | 2209 | ||
2199 | ar_context_run(&ohci->ar_request_ctx); | 2210 | ar_context_run(&ohci->ar_request_ctx); |
2200 | ar_context_run(&ohci->ar_response_ctx); /* also flushes writes */ | 2211 | ar_context_run(&ohci->ar_response_ctx); |
2212 | |||
2213 | flush_writes(ohci); | ||
2201 | 2214 | ||
2202 | /* We are ready to go, reset bus to finish initialization. */ | 2215 | /* We are ready to go, reset bus to finish initialization. */ |
2203 | fw_schedule_bus_reset(&ohci->card, false, true); | 2216 | fw_schedule_bus_reset(&ohci->card, false, true); |
@@ -3129,7 +3142,6 @@ static void ohci_flush_queue_iso(struct fw_iso_context *base) | |||
3129 | &container_of(base, struct iso_context, base)->context; | 3142 | &container_of(base, struct iso_context, base)->context; |
3130 | 3143 | ||
3131 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); | 3144 | reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); |
3132 | flush_writes(ctx->ohci); | ||
3133 | } | 3145 | } |
3134 | 3146 | ||
3135 | static const struct fw_card_driver ohci_driver = { | 3147 | static const struct fw_card_driver ohci_driver = { |