diff options
Diffstat (limited to 'drivers')
272 files changed, 26838 insertions, 2098 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index fceb71a741c3..e121b66ef082 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -57,6 +57,7 @@ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ | |||
57 | obj-$(CONFIG_PARIDE) += block/paride/ | 57 | obj-$(CONFIG_PARIDE) += block/paride/ |
58 | obj-$(CONFIG_TC) += tc/ | 58 | obj-$(CONFIG_TC) += tc/ |
59 | obj-$(CONFIG_UWB) += uwb/ | 59 | obj-$(CONFIG_UWB) += uwb/ |
60 | obj-$(CONFIG_USB_OTG_UTILS) += usb/otg/ | ||
60 | obj-$(CONFIG_USB) += usb/ | 61 | obj-$(CONFIG_USB) += usb/ |
61 | obj-$(CONFIG_USB_MUSB_HDRC) += usb/musb/ | 62 | obj-$(CONFIG_USB_MUSB_HDRC) += usb/musb/ |
62 | obj-$(CONFIG_PCI) += usb/ | 63 | obj-$(CONFIG_PCI) += usb/ |
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 63a17b55b39b..7a0f4aa4fa1e 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c | |||
@@ -20,7 +20,7 @@ | |||
20 | * | 20 | * |
21 | * | 21 | * |
22 | * ACPI based HotPlug driver that supports Memory Hotplug | 22 | * ACPI based HotPlug driver that supports Memory Hotplug |
23 | * This driver fields notifications from firmare for memory add | 23 | * This driver fields notifications from firmware for memory add |
24 | * and remove operations and alerts the VM of the affected memory | 24 | * and remove operations and alerts the VM of the affected memory |
25 | * ranges. | 25 | * ranges. |
26 | */ | 26 | */ |
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index 5d438c32989d..a7dc87ecee37 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c | |||
@@ -404,7 +404,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, | |||
404 | * | 404 | * |
405 | * RETURN: Status | 405 | * RETURN: Status |
406 | * | 406 | * |
407 | * DESCRIPTION: Construct an union acpi_operand_object of type def_field and | 407 | * DESCRIPTION: Construct a union acpi_operand_object of type def_field and |
408 | * connect it to the parent Node. | 408 | * connect it to the parent Node. |
409 | * | 409 | * |
410 | ******************************************************************************/ | 410 | ******************************************************************************/ |
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 89571b92a522..60e8c47128e9 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c | |||
@@ -146,7 +146,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, | |||
146 | 146 | ||
147 | stack_desc = *stack_ptr; | 147 | stack_desc = *stack_ptr; |
148 | 148 | ||
149 | /* This is an union acpi_operand_object */ | 149 | /* This is a union acpi_operand_object */ |
150 | 150 | ||
151 | switch (ACPI_GET_OBJECT_TYPE(stack_desc)) { | 151 | switch (ACPI_GET_OBJECT_TYPE(stack_desc)) { |
152 | case ACPI_TYPE_LOCAL_REFERENCE: | 152 | case ACPI_TYPE_LOCAL_REFERENCE: |
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index 3318df4cbd98..1c118ba78adb 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c | |||
@@ -274,7 +274,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, | |||
274 | * | 274 | * |
275 | * PARAMETERS: *source_desc - Value to be stored | 275 | * PARAMETERS: *source_desc - Value to be stored |
276 | * *dest_desc - Where to store it. Must be an NS node | 276 | * *dest_desc - Where to store it. Must be an NS node |
277 | * or an union acpi_operand_object of type | 277 | * or a union acpi_operand_object of type |
278 | * Reference; | 278 | * Reference; |
279 | * walk_state - Current walk state | 279 | * walk_state - Current walk state |
280 | * | 280 | * |
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index c0bbfa2c4193..08b8d73e6ee5 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c | |||
@@ -124,7 +124,7 @@ acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer, | |||
124 | * | 124 | * |
125 | * FUNCTION: acpi_rs_create_pci_routing_table | 125 | * FUNCTION: acpi_rs_create_pci_routing_table |
126 | * | 126 | * |
127 | * PARAMETERS: package_object - Pointer to an union acpi_operand_object | 127 | * PARAMETERS: package_object - Pointer to a union acpi_operand_object |
128 | * package | 128 | * package |
129 | * output_buffer - Pointer to the user's buffer | 129 | * output_buffer - Pointer to the user's buffer |
130 | * | 130 | * |
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index c354e7a42bcd..4bef3cfbaccb 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c | |||
@@ -297,7 +297,7 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size) | |||
297 | * | 297 | * |
298 | * RETURN: TRUE if object is valid, FALSE otherwise | 298 | * RETURN: TRUE if object is valid, FALSE otherwise |
299 | * | 299 | * |
300 | * DESCRIPTION: Validate a pointer to be an union acpi_operand_object | 300 | * DESCRIPTION: Validate a pointer to be a union acpi_operand_object |
301 | * | 301 | * |
302 | ******************************************************************************/ | 302 | ******************************************************************************/ |
303 | 303 | ||
@@ -389,7 +389,7 @@ void acpi_ut_delete_object_desc(union acpi_operand_object *object) | |||
389 | { | 389 | { |
390 | ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object); | 390 | ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object); |
391 | 391 | ||
392 | /* Object must be an union acpi_operand_object */ | 392 | /* Object must be a union acpi_operand_object */ |
393 | 393 | ||
394 | if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { | 394 | if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { |
395 | ACPI_ERROR((AE_INFO, | 395 | ACPI_ERROR((AE_INFO, |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index fecca4223f8e..f178a450ec08 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/workqueue.h> | 56 | #include <linux/workqueue.h> |
57 | #include <linux/scatterlist.h> | 57 | #include <linux/scatterlist.h> |
58 | #include <linux/io.h> | 58 | #include <linux/io.h> |
59 | #include <linux/async.h> | ||
59 | #include <scsi/scsi.h> | 60 | #include <scsi/scsi.h> |
60 | #include <scsi/scsi_cmnd.h> | 61 | #include <scsi/scsi_cmnd.h> |
61 | #include <scsi/scsi_host.h> | 62 | #include <scsi/scsi_host.h> |
@@ -5909,6 +5910,54 @@ void ata_host_init(struct ata_host *host, struct device *dev, | |||
5909 | host->ops = ops; | 5910 | host->ops = ops; |
5910 | } | 5911 | } |
5911 | 5912 | ||
5913 | |||
5914 | static void async_port_probe(void *data, async_cookie_t cookie) | ||
5915 | { | ||
5916 | int rc; | ||
5917 | struct ata_port *ap = data; | ||
5918 | /* probe */ | ||
5919 | if (ap->ops->error_handler) { | ||
5920 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
5921 | unsigned long flags; | ||
5922 | |||
5923 | ata_port_probe(ap); | ||
5924 | |||
5925 | /* kick EH for boot probing */ | ||
5926 | spin_lock_irqsave(ap->lock, flags); | ||
5927 | |||
5928 | ehi->probe_mask |= ATA_ALL_DEVICES; | ||
5929 | ehi->action |= ATA_EH_RESET | ATA_EH_LPM; | ||
5930 | ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; | ||
5931 | |||
5932 | ap->pflags &= ~ATA_PFLAG_INITIALIZING; | ||
5933 | ap->pflags |= ATA_PFLAG_LOADING; | ||
5934 | ata_port_schedule_eh(ap); | ||
5935 | |||
5936 | spin_unlock_irqrestore(ap->lock, flags); | ||
5937 | |||
5938 | /* wait for EH to finish */ | ||
5939 | ata_port_wait_eh(ap); | ||
5940 | } else { | ||
5941 | DPRINTK("ata%u: bus probe begin\n", ap->print_id); | ||
5942 | rc = ata_bus_probe(ap); | ||
5943 | DPRINTK("ata%u: bus probe end\n", ap->print_id); | ||
5944 | |||
5945 | if (rc) { | ||
5946 | /* FIXME: do something useful here? | ||
5947 | * Current libata behavior will | ||
5948 | * tear down everything when | ||
5949 | * the module is removed | ||
5950 | * or the h/w is unplugged. | ||
5951 | */ | ||
5952 | } | ||
5953 | } | ||
5954 | |||
5955 | /* in order to keep device order, we need to synchronize at this point */ | ||
5956 | async_synchronize_cookie(cookie); | ||
5957 | |||
5958 | ata_scsi_scan_host(ap, 1); | ||
5959 | |||
5960 | } | ||
5912 | /** | 5961 | /** |
5913 | * ata_host_register - register initialized ATA host | 5962 | * ata_host_register - register initialized ATA host |
5914 | * @host: ATA host to register | 5963 | * @host: ATA host to register |
@@ -5988,52 +6037,9 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) | |||
5988 | DPRINTK("probe begin\n"); | 6037 | DPRINTK("probe begin\n"); |
5989 | for (i = 0; i < host->n_ports; i++) { | 6038 | for (i = 0; i < host->n_ports; i++) { |
5990 | struct ata_port *ap = host->ports[i]; | 6039 | struct ata_port *ap = host->ports[i]; |
5991 | 6040 | async_schedule(async_port_probe, ap); | |
5992 | /* probe */ | ||
5993 | if (ap->ops->error_handler) { | ||
5994 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
5995 | unsigned long flags; | ||
5996 | |||
5997 | ata_port_probe(ap); | ||
5998 | |||
5999 | /* kick EH for boot probing */ | ||
6000 | spin_lock_irqsave(ap->lock, flags); | ||
6001 | |||
6002 | ehi->probe_mask |= ATA_ALL_DEVICES; | ||
6003 | ehi->action |= ATA_EH_RESET | ATA_EH_LPM; | ||
6004 | ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET; | ||
6005 | |||
6006 | ap->pflags &= ~ATA_PFLAG_INITIALIZING; | ||
6007 | ap->pflags |= ATA_PFLAG_LOADING; | ||
6008 | ata_port_schedule_eh(ap); | ||
6009 | |||
6010 | spin_unlock_irqrestore(ap->lock, flags); | ||
6011 | |||
6012 | /* wait for EH to finish */ | ||
6013 | ata_port_wait_eh(ap); | ||
6014 | } else { | ||
6015 | DPRINTK("ata%u: bus probe begin\n", ap->print_id); | ||
6016 | rc = ata_bus_probe(ap); | ||
6017 | DPRINTK("ata%u: bus probe end\n", ap->print_id); | ||
6018 | |||
6019 | if (rc) { | ||
6020 | /* FIXME: do something useful here? | ||
6021 | * Current libata behavior will | ||
6022 | * tear down everything when | ||
6023 | * the module is removed | ||
6024 | * or the h/w is unplugged. | ||
6025 | */ | ||
6026 | } | ||
6027 | } | ||
6028 | } | ||
6029 | |||
6030 | /* probes are done, now scan each port's disk(s) */ | ||
6031 | DPRINTK("host probe begin\n"); | ||
6032 | for (i = 0; i < host->n_ports; i++) { | ||
6033 | struct ata_port *ap = host->ports[i]; | ||
6034 | |||
6035 | ata_scsi_scan_host(ap, 1); | ||
6036 | } | 6041 | } |
6042 | DPRINTK("probe end\n"); | ||
6037 | 6043 | ||
6038 | return 0; | 6044 | return 0; |
6039 | } | 6045 | } |
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index d8e8c49c0cbd..8f006f96ff53 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
@@ -54,7 +54,7 @@ config FIRMWARE_IN_KERNEL | |||
54 | such firmware, and do not wish to use an initrd. | 54 | such firmware, and do not wish to use an initrd. |
55 | 55 | ||
56 | This single option controls the inclusion of firmware for | 56 | This single option controls the inclusion of firmware for |
57 | every driver which uses request_firmare() and ships its | 57 | every driver which uses request_firmware() and ships its |
58 | firmware in the kernel source tree, to avoid a proliferation | 58 | firmware in the kernel source tree, to avoid a proliferation |
59 | of 'Include firmware for xxx device' options. | 59 | of 'Include firmware for xxx device' options. |
60 | 60 | ||
diff --git a/drivers/base/topology.c b/drivers/base/topology.c index a8bc1cbcfa7c..a778fb52b11f 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/cpu.h> | 29 | #include <linux/cpu.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/hardirq.h> | ||
31 | #include <linux/topology.h> | 32 | #include <linux/topology.h> |
32 | 33 | ||
33 | #define define_one_ro(_name) \ | 34 | #define define_one_ro(_name) \ |
diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 048d71d244d7..12fb816db7b0 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c | |||
@@ -1579,7 +1579,7 @@ static void ub_reset_task(struct work_struct *work) | |||
1579 | struct ub_dev *sc = container_of(work, struct ub_dev, reset_work); | 1579 | struct ub_dev *sc = container_of(work, struct ub_dev, reset_work); |
1580 | unsigned long flags; | 1580 | unsigned long flags; |
1581 | struct ub_lun *lun; | 1581 | struct ub_lun *lun; |
1582 | int lkr, rc; | 1582 | int rc; |
1583 | 1583 | ||
1584 | if (!sc->reset) { | 1584 | if (!sc->reset) { |
1585 | printk(KERN_WARNING "%s: Running reset unrequested\n", | 1585 | printk(KERN_WARNING "%s: Running reset unrequested\n", |
@@ -1597,10 +1597,11 @@ static void ub_reset_task(struct work_struct *work) | |||
1597 | } else if (sc->dev->actconfig->desc.bNumInterfaces != 1) { | 1597 | } else if (sc->dev->actconfig->desc.bNumInterfaces != 1) { |
1598 | ; | 1598 | ; |
1599 | } else { | 1599 | } else { |
1600 | if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) { | 1600 | rc = usb_lock_device_for_reset(sc->dev, sc->intf); |
1601 | if (rc < 0) { | ||
1601 | printk(KERN_NOTICE | 1602 | printk(KERN_NOTICE |
1602 | "%s: usb_lock_device_for_reset failed (%d)\n", | 1603 | "%s: usb_lock_device_for_reset failed (%d)\n", |
1603 | sc->name, lkr); | 1604 | sc->name, rc); |
1604 | } else { | 1605 | } else { |
1605 | rc = usb_reset_device(sc->dev); | 1606 | rc = usb_reset_device(sc->dev); |
1606 | if (rc < 0) { | 1607 | if (rc < 0) { |
@@ -1608,9 +1609,7 @@ static void ub_reset_task(struct work_struct *work) | |||
1608 | "usb_lock_device_for_reset failed (%d)\n", | 1609 | "usb_lock_device_for_reset failed (%d)\n", |
1609 | sc->name, rc); | 1610 | sc->name, rc); |
1610 | } | 1611 | } |
1611 | 1612 | usb_unlock_device(sc->dev); | |
1612 | if (lkr) | ||
1613 | usb_unlock_device(sc->dev); | ||
1614 | } | 1613 | } |
1615 | } | 1614 | } |
1616 | 1615 | ||
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 39ad820b2350..af7c13ca9493 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -769,7 +769,7 @@ static int pc_open(struct tty_struct *tty, struct file *filp) | |||
769 | /* Check status of board configured in system. */ | 769 | /* Check status of board configured in system. */ |
770 | 770 | ||
771 | /* | 771 | /* |
772 | * I check to see if the epca_setup routine detected an user error. It | 772 | * I check to see if the epca_setup routine detected a user error. It |
773 | * might be better to put this in pc_init, but for the moment it goes | 773 | * might be better to put this in pc_init, but for the moment it goes |
774 | * here. | 774 | * here. |
775 | */ | 775 | */ |
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 5f076aef74fa..a8c8d9c19d74 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig | |||
@@ -83,7 +83,7 @@ config CPU_FREQ_DEFAULT_GOV_USERSPACE | |||
83 | select CPU_FREQ_GOV_USERSPACE | 83 | select CPU_FREQ_GOV_USERSPACE |
84 | help | 84 | help |
85 | Use the CPUFreq governor 'userspace' as default. This allows | 85 | Use the CPUFreq governor 'userspace' as default. This allows |
86 | you to set the CPU frequency manually or when an userspace | 86 | you to set the CPU frequency manually or when a userspace |
87 | program shall be able to set the CPU dynamically without having | 87 | program shall be able to set the CPU dynamically without having |
88 | to enable the userspace governor manually. | 88 | to enable the userspace governor manually. |
89 | 89 | ||
@@ -138,7 +138,7 @@ config CPU_FREQ_GOV_USERSPACE | |||
138 | tristate "'userspace' governor for userspace frequency scaling" | 138 | tristate "'userspace' governor for userspace frequency scaling" |
139 | help | 139 | help |
140 | Enable this cpufreq governor when you either want to set the | 140 | Enable this cpufreq governor when you either want to set the |
141 | CPU frequency manually or when an userspace program shall | 141 | CPU frequency manually or when a userspace program shall |
142 | be able to set the CPU dynamically, like on LART | 142 | be able to set the CPU dynamically, like on LART |
143 | <http://www.lartmaker.nl/>. | 143 | <http://www.lartmaker.nl/>. |
144 | 144 | ||
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 418c18f07e9d..799f94424c8a 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c | |||
@@ -75,7 +75,7 @@ generate_config_rom(struct fw_card *card, size_t *config_rom_length) | |||
75 | * controller, block reads to the config rom accesses the host | 75 | * controller, block reads to the config rom accesses the host |
76 | * memory, but quadlet read access the hardware bus info block | 76 | * memory, but quadlet read access the hardware bus info block |
77 | * registers. That's just crack, but it means we should make | 77 | * registers. That's just crack, but it means we should make |
78 | * sure the contents of bus info block in host memory mathces | 78 | * sure the contents of bus info block in host memory matches |
79 | * the version stored in the OHCI registers. | 79 | * the version stored in the OHCI registers. |
80 | */ | 80 | */ |
81 | 81 | ||
@@ -189,6 +189,17 @@ static const char gap_count_table[] = { | |||
189 | 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 | 189 | 63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40 |
190 | }; | 190 | }; |
191 | 191 | ||
192 | void | ||
193 | fw_schedule_bm_work(struct fw_card *card, unsigned long delay) | ||
194 | { | ||
195 | int scheduled; | ||
196 | |||
197 | fw_card_get(card); | ||
198 | scheduled = schedule_delayed_work(&card->work, delay); | ||
199 | if (!scheduled) | ||
200 | fw_card_put(card); | ||
201 | } | ||
202 | |||
192 | static void | 203 | static void |
193 | fw_card_bm_work(struct work_struct *work) | 204 | fw_card_bm_work(struct work_struct *work) |
194 | { | 205 | { |
@@ -206,7 +217,7 @@ fw_card_bm_work(struct work_struct *work) | |||
206 | 217 | ||
207 | if (local_node == NULL) { | 218 | if (local_node == NULL) { |
208 | spin_unlock_irqrestore(&card->lock, flags); | 219 | spin_unlock_irqrestore(&card->lock, flags); |
209 | return; | 220 | goto out_put_card; |
210 | } | 221 | } |
211 | fw_node_get(local_node); | 222 | fw_node_get(local_node); |
212 | fw_node_get(root_node); | 223 | fw_node_get(root_node); |
@@ -280,7 +291,7 @@ fw_card_bm_work(struct work_struct *work) | |||
280 | * this task 100ms from now. | 291 | * this task 100ms from now. |
281 | */ | 292 | */ |
282 | spin_unlock_irqrestore(&card->lock, flags); | 293 | spin_unlock_irqrestore(&card->lock, flags); |
283 | schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10)); | 294 | fw_schedule_bm_work(card, DIV_ROUND_UP(HZ, 10)); |
284 | goto out; | 295 | goto out; |
285 | } | 296 | } |
286 | 297 | ||
@@ -355,6 +366,8 @@ fw_card_bm_work(struct work_struct *work) | |||
355 | fw_device_put(root_device); | 366 | fw_device_put(root_device); |
356 | fw_node_put(root_node); | 367 | fw_node_put(root_node); |
357 | fw_node_put(local_node); | 368 | fw_node_put(local_node); |
369 | out_put_card: | ||
370 | fw_card_put(card); | ||
358 | } | 371 | } |
359 | 372 | ||
360 | static void | 373 | static void |
@@ -510,7 +523,6 @@ fw_core_remove_card(struct fw_card *card) | |||
510 | fw_card_put(card); | 523 | fw_card_put(card); |
511 | wait_for_completion(&card->done); | 524 | wait_for_completion(&card->done); |
512 | 525 | ||
513 | cancel_delayed_work_sync(&card->work); | ||
514 | WARN_ON(!list_empty(&card->transaction_list)); | 526 | WARN_ON(!list_empty(&card->transaction_list)); |
515 | del_timer_sync(&card->flush_timer); | 527 | del_timer_sync(&card->flush_timer); |
516 | } | 528 | } |
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 6b9be42c7b98..c173be383725 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c | |||
@@ -617,7 +617,7 @@ static int shutdown_unit(struct device *device, void *data) | |||
617 | */ | 617 | */ |
618 | DECLARE_RWSEM(fw_device_rwsem); | 618 | DECLARE_RWSEM(fw_device_rwsem); |
619 | 619 | ||
620 | static DEFINE_IDR(fw_device_idr); | 620 | DEFINE_IDR(fw_device_idr); |
621 | int fw_cdev_major; | 621 | int fw_cdev_major; |
622 | 622 | ||
623 | struct fw_device *fw_device_get_by_devt(dev_t devt) | 623 | struct fw_device *fw_device_get_by_devt(dev_t devt) |
@@ -689,7 +689,7 @@ static void fw_device_init(struct work_struct *work) | |||
689 | fw_notify("giving up on config rom for node id %x\n", | 689 | fw_notify("giving up on config rom for node id %x\n", |
690 | device->node_id); | 690 | device->node_id); |
691 | if (device->node == device->card->root_node) | 691 | if (device->node == device->card->root_node) |
692 | schedule_delayed_work(&device->card->work, 0); | 692 | fw_schedule_bm_work(device->card, 0); |
693 | fw_device_release(&device->device); | 693 | fw_device_release(&device->device); |
694 | } | 694 | } |
695 | return; | 695 | return; |
@@ -758,7 +758,7 @@ static void fw_device_init(struct work_struct *work) | |||
758 | * pretty harmless. | 758 | * pretty harmless. |
759 | */ | 759 | */ |
760 | if (device->node == device->card->root_node) | 760 | if (device->node == device->card->root_node) |
761 | schedule_delayed_work(&device->card->work, 0); | 761 | fw_schedule_bm_work(device->card, 0); |
762 | 762 | ||
763 | return; | 763 | return; |
764 | 764 | ||
@@ -892,7 +892,7 @@ static void fw_device_refresh(struct work_struct *work) | |||
892 | fw_device_shutdown(work); | 892 | fw_device_shutdown(work); |
893 | out: | 893 | out: |
894 | if (node_id == card->root_node->node_id) | 894 | if (node_id == card->root_node->node_id) |
895 | schedule_delayed_work(&card->work, 0); | 895 | fw_schedule_bm_work(card, 0); |
896 | } | 896 | } |
897 | 897 | ||
898 | void fw_node_event(struct fw_card *card, struct fw_node *node, int event) | 898 | void fw_node_event(struct fw_card *card, struct fw_node *node, int event) |
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 42305bbac72f..df51732608d9 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
23 | #include <linux/cdev.h> | 23 | #include <linux/cdev.h> |
24 | #include <linux/idr.h> | ||
24 | #include <linux/rwsem.h> | 25 | #include <linux/rwsem.h> |
25 | #include <asm/atomic.h> | 26 | #include <asm/atomic.h> |
26 | 27 | ||
@@ -99,6 +100,7 @@ void fw_device_cdev_update(struct fw_device *device); | |||
99 | void fw_device_cdev_remove(struct fw_device *device); | 100 | void fw_device_cdev_remove(struct fw_device *device); |
100 | 101 | ||
101 | extern struct rw_semaphore fw_device_rwsem; | 102 | extern struct rw_semaphore fw_device_rwsem; |
103 | extern struct idr fw_device_idr; | ||
102 | extern int fw_cdev_major; | 104 | extern int fw_cdev_major; |
103 | 105 | ||
104 | /* | 106 | /* |
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index e54403ee59e7..e88d5067448c 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c | |||
@@ -670,17 +670,6 @@ static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) | |||
670 | &d, sizeof(d), complete_agent_reset_write_no_wait, t); | 670 | &d, sizeof(d), complete_agent_reset_write_no_wait, t); |
671 | } | 671 | } |
672 | 672 | ||
673 | static void sbp2_set_generation(struct sbp2_logical_unit *lu, int generation) | ||
674 | { | ||
675 | struct fw_card *card = fw_device(lu->tgt->unit->device.parent)->card; | ||
676 | unsigned long flags; | ||
677 | |||
678 | /* serialize with comparisons of lu->generation and card->generation */ | ||
679 | spin_lock_irqsave(&card->lock, flags); | ||
680 | lu->generation = generation; | ||
681 | spin_unlock_irqrestore(&card->lock, flags); | ||
682 | } | ||
683 | |||
684 | static inline void sbp2_allow_block(struct sbp2_logical_unit *lu) | 673 | static inline void sbp2_allow_block(struct sbp2_logical_unit *lu) |
685 | { | 674 | { |
686 | /* | 675 | /* |
@@ -884,7 +873,7 @@ static void sbp2_login(struct work_struct *work) | |||
884 | goto out; | 873 | goto out; |
885 | 874 | ||
886 | generation = device->generation; | 875 | generation = device->generation; |
887 | smp_rmb(); /* node_id must not be older than generation */ | 876 | smp_rmb(); /* node IDs must not be older than generation */ |
888 | node_id = device->node_id; | 877 | node_id = device->node_id; |
889 | local_node_id = device->card->node_id; | 878 | local_node_id = device->card->node_id; |
890 | 879 | ||
@@ -908,7 +897,8 @@ static void sbp2_login(struct work_struct *work) | |||
908 | 897 | ||
909 | tgt->node_id = node_id; | 898 | tgt->node_id = node_id; |
910 | tgt->address_high = local_node_id << 16; | 899 | tgt->address_high = local_node_id << 16; |
911 | sbp2_set_generation(lu, generation); | 900 | smp_wmb(); /* node IDs must not be older than generation */ |
901 | lu->generation = generation; | ||
912 | 902 | ||
913 | lu->command_block_agent_address = | 903 | lu->command_block_agent_address = |
914 | ((u64)(be32_to_cpu(response.command_block_agent.high) & 0xffff) | 904 | ((u64)(be32_to_cpu(response.command_block_agent.high) & 0xffff) |
@@ -1201,7 +1191,7 @@ static void sbp2_reconnect(struct work_struct *work) | |||
1201 | goto out; | 1191 | goto out; |
1202 | 1192 | ||
1203 | generation = device->generation; | 1193 | generation = device->generation; |
1204 | smp_rmb(); /* node_id must not be older than generation */ | 1194 | smp_rmb(); /* node IDs must not be older than generation */ |
1205 | node_id = device->node_id; | 1195 | node_id = device->node_id; |
1206 | local_node_id = device->card->node_id; | 1196 | local_node_id = device->card->node_id; |
1207 | 1197 | ||
@@ -1228,7 +1218,8 @@ static void sbp2_reconnect(struct work_struct *work) | |||
1228 | 1218 | ||
1229 | tgt->node_id = node_id; | 1219 | tgt->node_id = node_id; |
1230 | tgt->address_high = local_node_id << 16; | 1220 | tgt->address_high = local_node_id << 16; |
1231 | sbp2_set_generation(lu, generation); | 1221 | smp_wmb(); /* node IDs must not be older than generation */ |
1222 | lu->generation = generation; | ||
1232 | 1223 | ||
1233 | fw_notify("%s: reconnected to LUN %04x (%d retries)\n", | 1224 | fw_notify("%s: reconnected to LUN %04x (%d retries)\n", |
1234 | tgt->bus_id, lu->lun, lu->retries); | 1225 | tgt->bus_id, lu->lun, lu->retries); |
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index 5e204713002d..c9be6e6948c4 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c | |||
@@ -355,6 +355,9 @@ report_lost_node(struct fw_card *card, | |||
355 | { | 355 | { |
356 | fw_node_event(card, node, FW_NODE_DESTROYED); | 356 | fw_node_event(card, node, FW_NODE_DESTROYED); |
357 | fw_node_put(node); | 357 | fw_node_put(node); |
358 | |||
359 | /* Topology has changed - reset bus manager retry counter */ | ||
360 | card->bm_retries = 0; | ||
358 | } | 361 | } |
359 | 362 | ||
360 | static void | 363 | static void |
@@ -374,6 +377,9 @@ report_found_node(struct fw_card *card, | |||
374 | } | 377 | } |
375 | 378 | ||
376 | fw_node_event(card, node, FW_NODE_CREATED); | 379 | fw_node_event(card, node, FW_NODE_CREATED); |
380 | |||
381 | /* Topology has changed - reset bus manager retry counter */ | ||
382 | card->bm_retries = 0; | ||
377 | } | 383 | } |
378 | 384 | ||
379 | void fw_destroy_nodes(struct fw_card *card) | 385 | void fw_destroy_nodes(struct fw_card *card) |
@@ -514,14 +520,6 @@ fw_core_handle_bus_reset(struct fw_card *card, | |||
514 | 520 | ||
515 | spin_lock_irqsave(&card->lock, flags); | 521 | spin_lock_irqsave(&card->lock, flags); |
516 | 522 | ||
517 | /* | ||
518 | * If the new topology has a different self_id_count the topology | ||
519 | * changed, either nodes were added or removed. In that case we | ||
520 | * reset the IRM reset counter. | ||
521 | */ | ||
522 | if (card->self_id_count != self_id_count) | ||
523 | card->bm_retries = 0; | ||
524 | |||
525 | card->node_id = node_id; | 523 | card->node_id = node_id; |
526 | /* | 524 | /* |
527 | * Update node_id before generation to prevent anybody from using | 525 | * Update node_id before generation to prevent anybody from using |
@@ -530,7 +528,7 @@ fw_core_handle_bus_reset(struct fw_card *card, | |||
530 | smp_wmb(); | 528 | smp_wmb(); |
531 | card->generation = generation; | 529 | card->generation = generation; |
532 | card->reset_jiffies = jiffies; | 530 | card->reset_jiffies = jiffies; |
533 | schedule_delayed_work(&card->work, 0); | 531 | fw_schedule_bm_work(card, 0); |
534 | 532 | ||
535 | local_node = build_tree(card, self_ids, self_id_count); | 533 | local_node = build_tree(card, self_ids, self_id_count); |
536 | 534 | ||
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c index 2884f876397b..699ac041f39a 100644 --- a/drivers/firewire/fw-transaction.c +++ b/drivers/firewire/fw-transaction.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/completion.h> | 21 | #include <linux/completion.h> |
22 | #include <linux/idr.h> | ||
22 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
23 | #include <linux/kref.h> | 24 | #include <linux/kref.h> |
24 | #include <linux/module.h> | 25 | #include <linux/module.h> |
@@ -971,6 +972,7 @@ static void __exit fw_core_cleanup(void) | |||
971 | { | 972 | { |
972 | unregister_chrdev(fw_cdev_major, "firewire"); | 973 | unregister_chrdev(fw_cdev_major, "firewire"); |
973 | bus_unregister(&fw_bus_type); | 974 | bus_unregister(&fw_bus_type); |
975 | idr_destroy(&fw_device_idr); | ||
974 | } | 976 | } |
975 | 977 | ||
976 | module_init(fw_core_init); | 978 | module_init(fw_core_init); |
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 839466f0a795..c9ab12a15f6e 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h | |||
@@ -237,14 +237,6 @@ struct fw_card { | |||
237 | int link_speed; | 237 | int link_speed; |
238 | int config_rom_generation; | 238 | int config_rom_generation; |
239 | 239 | ||
240 | /* | ||
241 | * We need to store up to 4 self ID for a maximum of 63 | ||
242 | * devices plus 3 words for the topology map header. | ||
243 | */ | ||
244 | int self_id_count; | ||
245 | u32 topology_map[252 + 3]; | ||
246 | u32 broadcast_channel; | ||
247 | |||
248 | spinlock_t lock; /* Take this lock when handling the lists in | 240 | spinlock_t lock; /* Take this lock when handling the lists in |
249 | * this struct. */ | 241 | * this struct. */ |
250 | struct fw_node *local_node; | 242 | struct fw_node *local_node; |
@@ -262,6 +254,9 @@ struct fw_card { | |||
262 | struct delayed_work work; | 254 | struct delayed_work work; |
263 | int bm_retries; | 255 | int bm_retries; |
264 | int bm_generation; | 256 | int bm_generation; |
257 | |||
258 | u32 broadcast_channel; | ||
259 | u32 topology_map[(CSR_TOPOLOGY_MAP_END - CSR_TOPOLOGY_MAP) / 4]; | ||
265 | }; | 260 | }; |
266 | 261 | ||
267 | static inline struct fw_card *fw_card_get(struct fw_card *card) | 262 | static inline struct fw_card *fw_card_get(struct fw_card *card) |
@@ -278,6 +273,8 @@ static inline void fw_card_put(struct fw_card *card) | |||
278 | kref_put(&card->kref, fw_card_release); | 273 | kref_put(&card->kref, fw_card_release); |
279 | } | 274 | } |
280 | 275 | ||
276 | extern void fw_schedule_bm_work(struct fw_card *card, unsigned long delay); | ||
277 | |||
281 | /* | 278 | /* |
282 | * The iso packet format allows for an immediate header/payload part | 279 | * The iso packet format allows for an immediate header/payload part |
283 | * stored in 'header' immediately after the packet info plus an | 280 | * stored in 'header' immediately after the packet info plus an |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 03cb494af1c5..f0a0f72238ab 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -102,7 +102,7 @@ static void hid_reset(struct work_struct *work) | |||
102 | struct usbhid_device *usbhid = | 102 | struct usbhid_device *usbhid = |
103 | container_of(work, struct usbhid_device, reset_work); | 103 | container_of(work, struct usbhid_device, reset_work); |
104 | struct hid_device *hid = usbhid->hid; | 104 | struct hid_device *hid = usbhid->hid; |
105 | int rc_lock, rc = 0; | 105 | int rc = 0; |
106 | 106 | ||
107 | if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) { | 107 | if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) { |
108 | dev_dbg(&usbhid->intf->dev, "clear halt\n"); | 108 | dev_dbg(&usbhid->intf->dev, "clear halt\n"); |
@@ -113,11 +113,10 @@ static void hid_reset(struct work_struct *work) | |||
113 | 113 | ||
114 | else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) { | 114 | else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) { |
115 | dev_dbg(&usbhid->intf->dev, "resetting device\n"); | 115 | dev_dbg(&usbhid->intf->dev, "resetting device\n"); |
116 | rc = rc_lock = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf); | 116 | rc = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf); |
117 | if (rc_lock >= 0) { | 117 | if (rc == 0) { |
118 | rc = usb_reset_device(hid_to_usb_dev(hid)); | 118 | rc = usb_reset_device(hid_to_usb_dev(hid)); |
119 | if (rc_lock) | 119 | usb_unlock_device(hid_to_usb_dev(hid)); |
120 | usb_unlock_device(hid_to_usb_dev(hid)); | ||
121 | } | 120 | } |
122 | clear_bit(HID_RESET_PENDING, &usbhid->iofl); | 121 | clear_bit(HID_RESET_PENDING, &usbhid->iofl); |
123 | } | 122 | } |
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 6a98f9f572b0..d73eea382ab3 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
@@ -874,12 +874,14 @@ int hiddev_connect(struct hid_device *hid, unsigned int force) | |||
874 | INIT_LIST_HEAD(&hiddev->list); | 874 | INIT_LIST_HEAD(&hiddev->list); |
875 | spin_lock_init(&hiddev->list_lock); | 875 | spin_lock_init(&hiddev->list_lock); |
876 | mutex_init(&hiddev->existancelock); | 876 | mutex_init(&hiddev->existancelock); |
877 | hid->hiddev = hiddev; | ||
877 | hiddev->hid = hid; | 878 | hiddev->hid = hid; |
878 | hiddev->exist = 1; | 879 | hiddev->exist = 1; |
879 | 880 | ||
880 | retval = usb_register_dev(usbhid->intf, &hiddev_class); | 881 | retval = usb_register_dev(usbhid->intf, &hiddev_class); |
881 | if (retval) { | 882 | if (retval) { |
882 | err_hid("Not able to get a minor for this device."); | 883 | err_hid("Not able to get a minor for this device."); |
884 | hid->hiddev = NULL; | ||
883 | kfree(hiddev); | 885 | kfree(hiddev); |
884 | return -1; | 886 | return -1; |
885 | } else { | 887 | } else { |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c709e821f04b..4b33bc82cc24 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -284,11 +284,12 @@ config SENSORS_F71805F | |||
284 | will be called f71805f. | 284 | will be called f71805f. |
285 | 285 | ||
286 | config SENSORS_F71882FG | 286 | config SENSORS_F71882FG |
287 | tristate "Fintek F71882FG and F71883FG" | 287 | tristate "Fintek F71862FG, F71882FG and F8000" |
288 | depends on EXPERIMENTAL | 288 | depends on EXPERIMENTAL |
289 | help | 289 | help |
290 | If you say yes here you get support for hardware monitoring | 290 | If you say yes here you get support for hardware monitoring |
291 | features of the Fintek F71882FG and F71883FG Super-I/O chips. | 291 | features of the Fintek F71882FG/F71883FG, F71862FG/71863FG |
292 | and F8000 Super-I/O chips. | ||
292 | 293 | ||
293 | This driver can also be built as a module. If so, the module | 294 | This driver can also be built as a module. If so, the module |
294 | will be called f71882fg. | 295 | will be called f71882fg. |
@@ -304,9 +305,13 @@ config SENSORS_F75375S | |||
304 | will be called f75375s. | 305 | will be called f75375s. |
305 | 306 | ||
306 | config SENSORS_FSCHER | 307 | config SENSORS_FSCHER |
307 | tristate "FSC Hermes" | 308 | tristate "FSC Hermes (DEPRECATED)" |
308 | depends on X86 && I2C | 309 | depends on X86 && I2C |
309 | help | 310 | help |
311 | This driver is DEPRECATED please use the new merged fschmd | ||
312 | ("FSC Poseidon, Scylla, Hermes, Heimdall and Heracles") driver | ||
313 | instead. | ||
314 | |||
310 | If you say yes here you get support for Fujitsu Siemens | 315 | If you say yes here you get support for Fujitsu Siemens |
311 | Computers Hermes sensor chips. | 316 | Computers Hermes sensor chips. |
312 | 317 | ||
@@ -314,9 +319,13 @@ config SENSORS_FSCHER | |||
314 | will be called fscher. | 319 | will be called fscher. |
315 | 320 | ||
316 | config SENSORS_FSCPOS | 321 | config SENSORS_FSCPOS |
317 | tristate "FSC Poseidon" | 322 | tristate "FSC Poseidon (DEPRECATED)" |
318 | depends on X86 && I2C | 323 | depends on X86 && I2C |
319 | help | 324 | help |
325 | This driver is DEPRECATED please use the new merged fschmd | ||
326 | ("FSC Poseidon, Scylla, Hermes, Heimdall and Heracles") driver | ||
327 | instead. | ||
328 | |||
320 | If you say yes here you get support for Fujitsu Siemens | 329 | If you say yes here you get support for Fujitsu Siemens |
321 | Computers Poseidon sensor chips. | 330 | Computers Poseidon sensor chips. |
322 | 331 | ||
@@ -325,14 +334,15 @@ config SENSORS_FSCPOS | |||
325 | 334 | ||
326 | config SENSORS_FSCHMD | 335 | config SENSORS_FSCHMD |
327 | tristate "FSC Poseidon, Scylla, Hermes, Heimdall and Heracles" | 336 | tristate "FSC Poseidon, Scylla, Hermes, Heimdall and Heracles" |
328 | depends on X86 && I2C && EXPERIMENTAL | 337 | depends on X86 && I2C |
329 | help | 338 | help |
330 | If you say yes here you get support for various Fujitsu Siemens | 339 | If you say yes here you get support for various Fujitsu Siemens |
331 | Computers sensor chips. | 340 | Computers sensor chips, including support for the integrated |
341 | watchdog. | ||
332 | 342 | ||
333 | This is a new merged driver for FSC sensor chips which is intended | 343 | This is a merged driver for FSC sensor chips replacing the fscpos, |
334 | as a replacment for the fscpos, fscscy and fscher drivers and adds | 344 | fscscy and fscher drivers and adding support for several other FSC |
335 | support for several other FCS sensor chips. | 345 | sensor chips. |
336 | 346 | ||
337 | This driver can also be built as a module. If so, the module | 347 | This driver can also be built as a module. If so, the module |
338 | will be called fschmd. | 348 | will be called fschmd. |
@@ -399,7 +409,8 @@ config SENSORS_IT87 | |||
399 | select HWMON_VID | 409 | select HWMON_VID |
400 | help | 410 | help |
401 | If you say yes here you get support for ITE IT8705F, IT8712F, | 411 | If you say yes here you get support for ITE IT8705F, IT8712F, |
402 | IT8716F, IT8718F and IT8726F sensor chips, and the SiS960 clone. | 412 | IT8716F, IT8718F, IT8720F and IT8726F sensor chips, and the |
413 | SiS960 clone. | ||
403 | 414 | ||
404 | This driver can also be built as a module. If so, the module | 415 | This driver can also be built as a module. If so, the module |
405 | will be called it87. | 416 | will be called it87. |
@@ -417,11 +428,12 @@ config SENSORS_LM63 | |||
417 | will be called lm63. | 428 | will be called lm63. |
418 | 429 | ||
419 | config SENSORS_LM70 | 430 | config SENSORS_LM70 |
420 | tristate "National Semiconductor LM70" | 431 | tristate "National Semiconductor LM70 / Texas Instruments TMP121" |
421 | depends on SPI_MASTER && EXPERIMENTAL | 432 | depends on SPI_MASTER && EXPERIMENTAL |
422 | help | 433 | help |
423 | If you say yes here you get support for the National Semiconductor | 434 | If you say yes here you get support for the National Semiconductor |
424 | LM70 digital temperature sensor chip. | 435 | LM70 and Texas Instruments TMP121/TMP123 digital temperature |
436 | sensor chips. | ||
425 | 437 | ||
426 | This driver can also be built as a module. If so, the module | 438 | This driver can also be built as a module. If so, the module |
427 | will be called lm70. | 439 | will be called lm70. |
@@ -548,6 +560,17 @@ config SENSORS_LM93 | |||
548 | This driver can also be built as a module. If so, the module | 560 | This driver can also be built as a module. If so, the module |
549 | will be called lm93. | 561 | will be called lm93. |
550 | 562 | ||
563 | config SENSORS_LTC4245 | ||
564 | tristate "Linear Technology LTC4245" | ||
565 | depends on I2C && EXPERIMENTAL | ||
566 | default n | ||
567 | help | ||
568 | If you say yes here you get support for Linear Technology LTC4245 | ||
569 | Multiple Supply Hot Swap Controller I2C interface. | ||
570 | |||
571 | This driver can also be built as a module. If so, the module will | ||
572 | be called ltc4245. | ||
573 | |||
551 | config SENSORS_MAX1111 | 574 | config SENSORS_MAX1111 |
552 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" | 575 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" |
553 | depends on SPI_MASTER | 576 | depends on SPI_MASTER |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 58fc5be5355d..8fd124eff646 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o | |||
62 | obj-$(CONFIG_SENSORS_LM90) += lm90.o | 62 | obj-$(CONFIG_SENSORS_LM90) += lm90.o |
63 | obj-$(CONFIG_SENSORS_LM92) += lm92.o | 63 | obj-$(CONFIG_SENSORS_LM92) += lm92.o |
64 | obj-$(CONFIG_SENSORS_LM93) += lm93.o | 64 | obj-$(CONFIG_SENSORS_LM93) += lm93.o |
65 | obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o | ||
65 | obj-$(CONFIG_SENSORS_MAX1111) += max1111.o | 66 | obj-$(CONFIG_SENSORS_MAX1111) += max1111.o |
66 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o | 67 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o |
67 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o | 68 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o |
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 8a45a2e6ba8a..8acf82977e7b 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c | |||
@@ -53,7 +53,10 @@ static const unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; | |||
53 | 53 | ||
54 | /* Insmod parameters */ | 54 | /* Insmod parameters */ |
55 | I2C_CLIENT_INSMOD_1(asb100); | 55 | I2C_CLIENT_INSMOD_1(asb100); |
56 | I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " | 56 | |
57 | static unsigned short force_subclients[4]; | ||
58 | module_param_array(force_subclients, short, NULL, 0); | ||
59 | MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " | ||
57 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); | 60 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); |
58 | 61 | ||
59 | /* Voltage IN registers 0-6 */ | 62 | /* Voltage IN registers 0-6 */ |
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 27a5d397f9a1..3df202a9ad72 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/hwmon-vid.h> | 34 | #include <linux/hwmon-vid.h> |
35 | #include <linux/err.h> | 35 | #include <linux/err.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/acpi.h> | ||
37 | #include <asm/io.h> | 38 | #include <asm/io.h> |
38 | 39 | ||
39 | /* ISA device, if found */ | 40 | /* ISA device, if found */ |
@@ -2361,6 +2362,10 @@ static int __init dme1737_isa_device_add(unsigned short addr) | |||
2361 | }; | 2362 | }; |
2362 | int err; | 2363 | int err; |
2363 | 2364 | ||
2365 | err = acpi_check_resource_conflict(&res); | ||
2366 | if (err) | ||
2367 | goto exit; | ||
2368 | |||
2364 | if (!(pdev = platform_device_alloc("dme1737", addr))) { | 2369 | if (!(pdev = platform_device_alloc("dme1737", addr))) { |
2365 | printk(KERN_ERR "dme1737: Failed to allocate device.\n"); | 2370 | printk(KERN_ERR "dme1737: Failed to allocate device.\n"); |
2366 | err = -ENOMEM; | 2371 | err = -ENOMEM; |
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index 7a14a2dbb752..899876579253 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/mutex.h> | 39 | #include <linux/mutex.h> |
40 | #include <linux/sysfs.h> | 40 | #include <linux/sysfs.h> |
41 | #include <linux/ioport.h> | 41 | #include <linux/ioport.h> |
42 | #include <linux/acpi.h> | ||
42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
43 | 44 | ||
44 | static unsigned short force_id; | 45 | static unsigned short force_id; |
@@ -1455,6 +1456,10 @@ static int __init f71805f_device_add(unsigned short address, | |||
1455 | } | 1456 | } |
1456 | 1457 | ||
1457 | res.name = pdev->name; | 1458 | res.name = pdev->name; |
1459 | err = acpi_check_resource_conflict(&res); | ||
1460 | if (err) | ||
1461 | goto exit_device_put; | ||
1462 | |||
1458 | err = platform_device_add_resources(pdev, &res, 1); | 1463 | err = platform_device_add_resources(pdev, &res, 1); |
1459 | if (err) { | 1464 | if (err) { |
1460 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | 1465 | printk(KERN_ERR DRVNAME ": Device resource addition failed " |
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 67067e9a323e..609cafff86bc 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> * | 2 | * Copyright (C) 2006 by Hans Edgington <hans@edgington.nl> * |
3 | * Copyright (C) 2007 by Hans de Goede <j.w.r.degoede@hhs.nl> * | 3 | * Copyright (C) 2007,2008 by Hans de Goede <hdegoede@redhat.com> * |
4 | * * | 4 | * * |
5 | * This program is free software; you can redistribute it and/or modify * | 5 | * This program is free software; you can redistribute it and/or modify * |
6 | * it under the terms of the GNU General Public License as published by * | 6 | * it under the terms of the GNU General Public License as published by * |
@@ -27,11 +27,12 @@ | |||
27 | #include <linux/hwmon-sysfs.h> | 27 | #include <linux/hwmon-sysfs.h> |
28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
30 | #include <asm/io.h> | 30 | #include <linux/io.h> |
31 | #include <linux/acpi.h> | ||
31 | 32 | ||
32 | #define DRVNAME "f71882fg" | 33 | #define DRVNAME "f71882fg" |
33 | 34 | ||
34 | #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device*/ | 35 | #define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ |
35 | #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ | 36 | #define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ |
36 | #define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ | 37 | #define SIO_LOCK_KEY 0xAA /* Key to diasble Super-I/O */ |
37 | 38 | ||
@@ -43,7 +44,9 @@ | |||
43 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ | 44 | #define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ |
44 | 45 | ||
45 | #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ | 46 | #define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ |
47 | #define SIO_F71862_ID 0x0601 /* Chipset ID */ | ||
46 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ | 48 | #define SIO_F71882_ID 0x0541 /* Chipset ID */ |
49 | #define SIO_F8000_ID 0x0581 /* Chipset ID */ | ||
47 | 50 | ||
48 | #define REGION_LENGTH 8 | 51 | #define REGION_LENGTH 8 |
49 | #define ADDR_REG_OFFSET 5 | 52 | #define ADDR_REG_OFFSET 5 |
@@ -51,25 +54,36 @@ | |||
51 | 54 | ||
52 | #define F71882FG_REG_PECI 0x0A | 55 | #define F71882FG_REG_PECI 0x0A |
53 | 56 | ||
54 | #define F71882FG_REG_IN_STATUS 0x12 | 57 | #define F71882FG_REG_IN_STATUS 0x12 /* f71882fg only */ |
55 | #define F71882FG_REG_IN_BEEP 0x13 | 58 | #define F71882FG_REG_IN_BEEP 0x13 /* f71882fg only */ |
56 | #define F71882FG_REG_IN(nr) (0x20 + (nr)) | 59 | #define F71882FG_REG_IN(nr) (0x20 + (nr)) |
57 | #define F71882FG_REG_IN1_HIGH 0x32 | 60 | #define F71882FG_REG_IN1_HIGH 0x32 /* f71882fg only */ |
58 | 61 | ||
59 | #define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr))) | 62 | #define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr))) |
63 | #define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr))) | ||
64 | #define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr))) | ||
60 | #define F71882FG_REG_FAN_STATUS 0x92 | 65 | #define F71882FG_REG_FAN_STATUS 0x92 |
61 | #define F71882FG_REG_FAN_BEEP 0x93 | 66 | #define F71882FG_REG_FAN_BEEP 0x93 |
62 | 67 | ||
63 | #define F71882FG_REG_TEMP(nr) (0x72 + 2 * (nr)) | 68 | #define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr)) |
64 | #define F71882FG_REG_TEMP_OVT(nr) (0x82 + 2 * (nr)) | 69 | #define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr)) |
65 | #define F71882FG_REG_TEMP_HIGH(nr) (0x83 + 2 * (nr)) | 70 | #define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr)) |
66 | #define F71882FG_REG_TEMP_STATUS 0x62 | 71 | #define F71882FG_REG_TEMP_STATUS 0x62 |
67 | #define F71882FG_REG_TEMP_BEEP 0x63 | 72 | #define F71882FG_REG_TEMP_BEEP 0x63 |
68 | #define F71882FG_REG_TEMP_HYST1 0x6C | 73 | #define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr)) |
69 | #define F71882FG_REG_TEMP_HYST23 0x6D | ||
70 | #define F71882FG_REG_TEMP_TYPE 0x6B | 74 | #define F71882FG_REG_TEMP_TYPE 0x6B |
71 | #define F71882FG_REG_TEMP_DIODE_OPEN 0x6F | 75 | #define F71882FG_REG_TEMP_DIODE_OPEN 0x6F |
72 | 76 | ||
77 | #define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr))) | ||
78 | #define F71882FG_REG_PWM_TYPE 0x94 | ||
79 | #define F71882FG_REG_PWM_ENABLE 0x96 | ||
80 | |||
81 | #define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr)) | ||
82 | |||
83 | #define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm))) | ||
84 | #define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm))) | ||
85 | #define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr)) | ||
86 | |||
73 | #define F71882FG_REG_START 0x01 | 87 | #define F71882FG_REG_START 0x01 |
74 | 88 | ||
75 | #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ | 89 | #define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ |
@@ -78,7 +92,15 @@ static unsigned short force_id; | |||
78 | module_param(force_id, ushort, 0); | 92 | module_param(force_id, ushort, 0); |
79 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); | 93 | MODULE_PARM_DESC(force_id, "Override the detected device ID"); |
80 | 94 | ||
81 | static struct platform_device *f71882fg_pdev = NULL; | 95 | enum chips { f71862fg, f71882fg, f8000 }; |
96 | |||
97 | static const char *f71882fg_names[] = { | ||
98 | "f71862fg", | ||
99 | "f71882fg", | ||
100 | "f8000", | ||
101 | }; | ||
102 | |||
103 | static struct platform_device *f71882fg_pdev; | ||
82 | 104 | ||
83 | /* Super-I/O Function prototypes */ | 105 | /* Super-I/O Function prototypes */ |
84 | static inline int superio_inb(int base, int reg); | 106 | static inline int superio_inb(int base, int reg); |
@@ -87,8 +109,13 @@ static inline void superio_enter(int base); | |||
87 | static inline void superio_select(int base, int ld); | 109 | static inline void superio_select(int base, int ld); |
88 | static inline void superio_exit(int base); | 110 | static inline void superio_exit(int base); |
89 | 111 | ||
112 | struct f71882fg_sio_data { | ||
113 | enum chips type; | ||
114 | }; | ||
115 | |||
90 | struct f71882fg_data { | 116 | struct f71882fg_data { |
91 | unsigned short addr; | 117 | unsigned short addr; |
118 | enum chips type; | ||
92 | struct device *hwmon_dev; | 119 | struct device *hwmon_dev; |
93 | 120 | ||
94 | struct mutex update_lock; | 121 | struct mutex update_lock; |
@@ -102,19 +129,30 @@ struct f71882fg_data { | |||
102 | u8 in_status; | 129 | u8 in_status; |
103 | u8 in_beep; | 130 | u8 in_beep; |
104 | u16 fan[4]; | 131 | u16 fan[4]; |
132 | u16 fan_target[4]; | ||
133 | u16 fan_full_speed[4]; | ||
105 | u8 fan_status; | 134 | u8 fan_status; |
106 | u8 fan_beep; | 135 | u8 fan_beep; |
107 | u8 temp[3]; | 136 | /* Note: all models have only 3 temperature channels, but on some |
108 | u8 temp_ovt[3]; | 137 | they are addressed as 0-2 and on others as 1-3, so for coding |
109 | u8 temp_high[3]; | 138 | convenience we reserve space for 4 channels */ |
110 | u8 temp_hyst[3]; | 139 | u8 temp[4]; |
111 | u8 temp_type[3]; | 140 | u8 temp_ovt[4]; |
141 | u8 temp_high[4]; | ||
142 | u8 temp_hyst[2]; /* 2 hysts stored per reg */ | ||
143 | u8 temp_type[4]; | ||
112 | u8 temp_status; | 144 | u8 temp_status; |
113 | u8 temp_beep; | 145 | u8 temp_beep; |
114 | u8 temp_diode_open; | 146 | u8 temp_diode_open; |
147 | u8 pwm[4]; | ||
148 | u8 pwm_enable; | ||
149 | u8 pwm_auto_point_hyst[2]; | ||
150 | u8 pwm_auto_point_mapping[4]; | ||
151 | u8 pwm_auto_point_pwm[4][5]; | ||
152 | u8 pwm_auto_point_temp[4][4]; | ||
115 | }; | 153 | }; |
116 | 154 | ||
117 | /* Sysfs in*/ | 155 | /* Sysfs in */ |
118 | static ssize_t show_in(struct device *dev, struct device_attribute *devattr, | 156 | static ssize_t show_in(struct device *dev, struct device_attribute *devattr, |
119 | char *buf); | 157 | char *buf); |
120 | static ssize_t show_in_max(struct device *dev, struct device_attribute | 158 | static ssize_t show_in_max(struct device *dev, struct device_attribute |
@@ -130,6 +168,10 @@ static ssize_t show_in_alarm(struct device *dev, struct device_attribute | |||
130 | /* Sysfs Fan */ | 168 | /* Sysfs Fan */ |
131 | static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, | 169 | static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, |
132 | char *buf); | 170 | char *buf); |
171 | static ssize_t show_fan_full_speed(struct device *dev, | ||
172 | struct device_attribute *devattr, char *buf); | ||
173 | static ssize_t store_fan_full_speed(struct device *dev, | ||
174 | struct device_attribute *devattr, const char *buf, size_t count); | ||
133 | static ssize_t show_fan_beep(struct device *dev, struct device_attribute | 175 | static ssize_t show_fan_beep(struct device *dev, struct device_attribute |
134 | *devattr, char *buf); | 176 | *devattr, char *buf); |
135 | static ssize_t store_fan_beep(struct device *dev, struct device_attribute | 177 | static ssize_t store_fan_beep(struct device *dev, struct device_attribute |
@@ -163,16 +205,41 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute | |||
163 | *devattr, char *buf); | 205 | *devattr, char *buf); |
164 | static ssize_t show_temp_fault(struct device *dev, struct device_attribute | 206 | static ssize_t show_temp_fault(struct device *dev, struct device_attribute |
165 | *devattr, char *buf); | 207 | *devattr, char *buf); |
208 | /* PWM and Auto point control */ | ||
209 | static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, | ||
210 | char *buf); | ||
211 | static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr, | ||
212 | const char *buf, size_t count); | ||
213 | static ssize_t show_pwm_enable(struct device *dev, | ||
214 | struct device_attribute *devattr, char *buf); | ||
215 | static ssize_t store_pwm_enable(struct device *dev, | ||
216 | struct device_attribute *devattr, const char *buf, size_t count); | ||
217 | static ssize_t show_pwm_interpolate(struct device *dev, | ||
218 | struct device_attribute *devattr, char *buf); | ||
219 | static ssize_t store_pwm_interpolate(struct device *dev, | ||
220 | struct device_attribute *devattr, const char *buf, size_t count); | ||
221 | static ssize_t show_pwm_auto_point_channel(struct device *dev, | ||
222 | struct device_attribute *devattr, char *buf); | ||
223 | static ssize_t store_pwm_auto_point_channel(struct device *dev, | ||
224 | struct device_attribute *devattr, const char *buf, size_t count); | ||
225 | static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev, | ||
226 | struct device_attribute *devattr, char *buf); | ||
227 | static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, | ||
228 | struct device_attribute *devattr, const char *buf, size_t count); | ||
229 | static ssize_t show_pwm_auto_point_pwm(struct device *dev, | ||
230 | struct device_attribute *devattr, char *buf); | ||
231 | static ssize_t store_pwm_auto_point_pwm(struct device *dev, | ||
232 | struct device_attribute *devattr, const char *buf, size_t count); | ||
233 | static ssize_t show_pwm_auto_point_temp(struct device *dev, | ||
234 | struct device_attribute *devattr, char *buf); | ||
235 | static ssize_t store_pwm_auto_point_temp(struct device *dev, | ||
236 | struct device_attribute *devattr, const char *buf, size_t count); | ||
166 | /* Sysfs misc */ | 237 | /* Sysfs misc */ |
167 | static ssize_t show_name(struct device *dev, struct device_attribute *devattr, | 238 | static ssize_t show_name(struct device *dev, struct device_attribute *devattr, |
168 | char *buf); | 239 | char *buf); |
169 | 240 | ||
170 | static int __devinit f71882fg_probe(struct platform_device * pdev); | 241 | static int __devinit f71882fg_probe(struct platform_device * pdev); |
171 | static int __devexit f71882fg_remove(struct platform_device *pdev); | 242 | static int f71882fg_remove(struct platform_device *pdev); |
172 | static int __init f71882fg_init(void); | ||
173 | static int __init f71882fg_find(int sioaddr, unsigned short *address); | ||
174 | static int __init f71882fg_device_add(unsigned short address); | ||
175 | static void __exit f71882fg_exit(void); | ||
176 | 243 | ||
177 | static struct platform_driver f71882fg_driver = { | 244 | static struct platform_driver f71882fg_driver = { |
178 | .driver = { | 245 | .driver = { |
@@ -183,86 +250,531 @@ static struct platform_driver f71882fg_driver = { | |||
183 | .remove = __devexit_p(f71882fg_remove), | 250 | .remove = __devexit_p(f71882fg_remove), |
184 | }; | 251 | }; |
185 | 252 | ||
186 | static struct device_attribute f71882fg_dev_attr[] = | 253 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
187 | { | 254 | |
188 | __ATTR( name, S_IRUGO, show_name, NULL ), | 255 | /* Temp and in attr common to both the f71862fg and f71882fg */ |
256 | static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = { | ||
257 | SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), | ||
258 | SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), | ||
259 | SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), | ||
260 | SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), | ||
261 | SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), | ||
262 | SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), | ||
263 | SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), | ||
264 | SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), | ||
265 | SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), | ||
266 | SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), | ||
267 | SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, | ||
268 | store_temp_max, 0, 1), | ||
269 | SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, | ||
270 | store_temp_max_hyst, 0, 1), | ||
271 | /* Should really be temp1_max_alarm, but older versions did not handle | ||
272 | the max and crit alarms separately and lm_sensors v2 depends on the | ||
273 | presence of temp#_alarm files. The same goes for temp2/3 _alarm. */ | ||
274 | SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1), | ||
275 | SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep, | ||
276 | store_temp_beep, 0, 1), | ||
277 | SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit, | ||
278 | store_temp_crit, 0, 1), | ||
279 | SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, | ||
280 | 0, 1), | ||
281 | SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5), | ||
282 | SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep, | ||
283 | store_temp_beep, 0, 5), | ||
284 | SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1), | ||
285 | SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1), | ||
286 | SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2), | ||
287 | SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max, | ||
288 | store_temp_max, 0, 2), | ||
289 | SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, | ||
290 | store_temp_max_hyst, 0, 2), | ||
291 | /* Should be temp2_max_alarm, see temp1_alarm note */ | ||
292 | SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2), | ||
293 | SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep, | ||
294 | store_temp_beep, 0, 2), | ||
295 | SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit, | ||
296 | store_temp_crit, 0, 2), | ||
297 | SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, | ||
298 | 0, 2), | ||
299 | SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6), | ||
300 | SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep, | ||
301 | store_temp_beep, 0, 6), | ||
302 | SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), | ||
303 | SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), | ||
304 | SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), | ||
305 | SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, | ||
306 | store_temp_max, 0, 3), | ||
307 | SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, | ||
308 | store_temp_max_hyst, 0, 3), | ||
309 | /* Should be temp3_max_alarm, see temp1_alarm note */ | ||
310 | SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3), | ||
311 | SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep, | ||
312 | store_temp_beep, 0, 3), | ||
313 | SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit, | ||
314 | store_temp_crit, 0, 3), | ||
315 | SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, | ||
316 | 0, 3), | ||
317 | SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7), | ||
318 | SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep, | ||
319 | store_temp_beep, 0, 7), | ||
320 | SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3), | ||
321 | SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3), | ||
322 | }; | ||
323 | |||
324 | /* Temp and in attr found only on the f71882fg */ | ||
325 | static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = { | ||
326 | SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, | ||
327 | 0, 1), | ||
328 | SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep, | ||
329 | 0, 1), | ||
330 | SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1), | ||
331 | }; | ||
332 | |||
333 | /* Temp and in attr for the f8000 | ||
334 | Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max) | ||
335 | is used as hysteresis value to clear alarms | ||
336 | */ | ||
337 | static struct sensor_device_attribute_2 f8000_in_temp_attr[] = { | ||
338 | SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), | ||
339 | SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), | ||
340 | SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), | ||
341 | SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0), | ||
342 | SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit, | ||
343 | store_temp_crit, 0, 0), | ||
344 | SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, | ||
345 | store_temp_max, 0, 0), | ||
346 | SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4), | ||
347 | SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1), | ||
348 | SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit, | ||
349 | store_temp_crit, 0, 1), | ||
350 | SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, | ||
351 | store_temp_max, 0, 1), | ||
352 | SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5), | ||
353 | SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1), | ||
354 | SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2), | ||
355 | SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit, | ||
356 | store_temp_crit, 0, 2), | ||
357 | SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, | ||
358 | store_temp_max, 0, 2), | ||
359 | SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6), | ||
360 | }; | ||
361 | |||
362 | /* Fan / PWM attr common to all models */ | ||
363 | static struct sensor_device_attribute_2 fxxxx_fan_attr[] = { | ||
364 | SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), | ||
365 | SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR, | ||
366 | show_fan_full_speed, | ||
367 | store_fan_full_speed, 0, 0), | ||
368 | SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0), | ||
369 | SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1), | ||
370 | SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR, | ||
371 | show_fan_full_speed, | ||
372 | store_fan_full_speed, 0, 1), | ||
373 | SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1), | ||
374 | SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), | ||
375 | SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR, | ||
376 | show_fan_full_speed, | ||
377 | store_fan_full_speed, 0, 2), | ||
378 | SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), | ||
379 | |||
380 | SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0), | ||
381 | SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
382 | store_pwm_enable, 0, 0), | ||
383 | SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR, | ||
384 | show_pwm_interpolate, store_pwm_interpolate, 0, 0), | ||
385 | SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, | ||
386 | show_pwm_auto_point_channel, | ||
387 | store_pwm_auto_point_channel, 0, 0), | ||
388 | |||
389 | SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1), | ||
390 | SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
391 | store_pwm_enable, 0, 1), | ||
392 | SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR, | ||
393 | show_pwm_interpolate, store_pwm_interpolate, 0, 1), | ||
394 | SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, | ||
395 | show_pwm_auto_point_channel, | ||
396 | store_pwm_auto_point_channel, 0, 1), | ||
397 | |||
398 | SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR, | ||
399 | show_pwm_interpolate, store_pwm_interpolate, 0, 2), | ||
400 | SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, | ||
401 | show_pwm_auto_point_channel, | ||
402 | store_pwm_auto_point_channel, 0, 2), | ||
189 | }; | 403 | }; |
190 | 404 | ||
191 | static struct sensor_device_attribute f71882fg_in_temp_attr[] = | 405 | /* Fan / PWM attr for the f71862fg, less pwms and less zones per pwm than the |
192 | { | 406 | f71882fg */ |
193 | SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), | 407 | static struct sensor_device_attribute_2 f71862fg_fan_attr[] = { |
194 | SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), | 408 | SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
195 | SENSOR_ATTR(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, 1), | 409 | store_fan_beep, 0, 0), |
196 | SENSOR_ATTR(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep, 1), | 410 | SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
197 | SENSOR_ATTR(in1_alarm, S_IRUGO, show_in_alarm, NULL, 1), | 411 | store_fan_beep, 0, 1), |
198 | SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), | 412 | SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
199 | SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), | 413 | store_fan_beep, 0, 2), |
200 | SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), | 414 | |
201 | SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), | 415 | SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, |
202 | SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), | 416 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, |
203 | SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), | 417 | 1, 0), |
204 | SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), | 418 | SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR, |
205 | SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0), | 419 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, |
206 | SENSOR_ATTR(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, | 420 | 4, 0), |
207 | store_temp_max, 0), | 421 | SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR, |
208 | SENSOR_ATTR(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, | 422 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, |
209 | store_temp_max_hyst, 0), | 423 | 0, 0), |
210 | SENSOR_ATTR(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit, | 424 | SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR, |
211 | store_temp_crit, 0), | 425 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, |
212 | SENSOR_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 0), | 426 | 3, 0), |
213 | SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), | 427 | SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, |
214 | SENSOR_ATTR(temp1_beep, S_IRUGO|S_IWUSR, show_temp_beep, | 428 | show_pwm_auto_point_temp_hyst, |
215 | store_temp_beep, 0), | 429 | store_pwm_auto_point_temp_hyst, |
216 | SENSOR_ATTR(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0), | 430 | 0, 0), |
217 | SENSOR_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0), | 431 | SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO, |
218 | SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1), | 432 | show_pwm_auto_point_temp_hyst, NULL, 3, 0), |
219 | SENSOR_ATTR(temp2_max, S_IRUGO|S_IWUSR, show_temp_max, | 433 | |
220 | store_temp_max, 1), | 434 | SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR, |
221 | SENSOR_ATTR(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, | 435 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, |
222 | store_temp_max_hyst, 1), | 436 | 1, 1), |
223 | SENSOR_ATTR(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit, | 437 | SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR, |
224 | store_temp_crit, 1), | 438 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, |
225 | SENSOR_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 1), | 439 | 4, 1), |
226 | SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), | 440 | SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR, |
227 | SENSOR_ATTR(temp2_beep, S_IRUGO|S_IWUSR, show_temp_beep, | 441 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, |
228 | store_temp_beep, 1), | 442 | 0, 1), |
229 | SENSOR_ATTR(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 1), | 443 | SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR, |
230 | SENSOR_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1), | 444 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, |
231 | SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2), | 445 | 3, 1), |
232 | SENSOR_ATTR(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, | 446 | SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, |
233 | store_temp_max, 2), | 447 | show_pwm_auto_point_temp_hyst, |
234 | SENSOR_ATTR(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, | 448 | store_pwm_auto_point_temp_hyst, |
235 | store_temp_max_hyst, 2), | 449 | 0, 1), |
236 | SENSOR_ATTR(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit, | 450 | SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, |
237 | store_temp_crit, 2), | 451 | show_pwm_auto_point_temp_hyst, NULL, 3, 1), |
238 | SENSOR_ATTR(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 2), | 452 | |
239 | SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), | 453 | SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), |
240 | SENSOR_ATTR(temp3_beep, S_IRUGO|S_IWUSR, show_temp_beep, | 454 | SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, |
241 | store_temp_beep, 2), | 455 | store_pwm_enable, 0, 2), |
242 | SENSOR_ATTR(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 2), | 456 | SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, |
243 | SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2) | 457 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, |
458 | 1, 2), | ||
459 | SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
460 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
461 | 4, 2), | ||
462 | SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
463 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
464 | 0, 2), | ||
465 | SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
466 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
467 | 3, 2), | ||
468 | SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
469 | show_pwm_auto_point_temp_hyst, | ||
470 | store_pwm_auto_point_temp_hyst, | ||
471 | 0, 2), | ||
472 | SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO, | ||
473 | show_pwm_auto_point_temp_hyst, NULL, 3, 2), | ||
244 | }; | 474 | }; |
245 | 475 | ||
246 | static struct sensor_device_attribute f71882fg_fan_attr[] = | 476 | /* Fan / PWM attr for the f71882fg */ |
247 | { | 477 | static struct sensor_device_attribute_2 f71882fg_fan_attr[] = { |
248 | SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), | 478 | SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
249 | SENSOR_ATTR(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, | 479 | store_fan_beep, 0, 0), |
250 | store_fan_beep, 0), | 480 | SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
251 | SENSOR_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0), | 481 | store_fan_beep, 0, 1), |
252 | SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), | 482 | SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
253 | SENSOR_ATTR(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, | 483 | store_fan_beep, 0, 2), |
254 | store_fan_beep, 1), | 484 | SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), |
255 | SENSOR_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1), | 485 | SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR, |
256 | SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), | 486 | show_fan_full_speed, |
257 | SENSOR_ATTR(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, | 487 | store_fan_full_speed, 0, 3), |
258 | store_fan_beep, 2), | 488 | SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, |
259 | SENSOR_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2), | 489 | store_fan_beep, 0, 3), |
260 | SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), | 490 | SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3), |
261 | SENSOR_ATTR(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, | 491 | |
262 | store_fan_beep, 3), | 492 | SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, |
263 | SENSOR_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3) | 493 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, |
494 | 0, 0), | ||
495 | SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
496 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
497 | 1, 0), | ||
498 | SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
499 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
500 | 2, 0), | ||
501 | SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
502 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
503 | 3, 0), | ||
504 | SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
505 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
506 | 4, 0), | ||
507 | SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
508 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
509 | 0, 0), | ||
510 | SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
511 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
512 | 1, 0), | ||
513 | SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
514 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
515 | 2, 0), | ||
516 | SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
517 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
518 | 3, 0), | ||
519 | SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
520 | show_pwm_auto_point_temp_hyst, | ||
521 | store_pwm_auto_point_temp_hyst, | ||
522 | 0, 0), | ||
523 | SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO, | ||
524 | show_pwm_auto_point_temp_hyst, NULL, 1, 0), | ||
525 | SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO, | ||
526 | show_pwm_auto_point_temp_hyst, NULL, 2, 0), | ||
527 | SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO, | ||
528 | show_pwm_auto_point_temp_hyst, NULL, 3, 0), | ||
529 | |||
530 | SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
531 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
532 | 0, 1), | ||
533 | SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
534 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
535 | 1, 1), | ||
536 | SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
537 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
538 | 2, 1), | ||
539 | SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
540 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
541 | 3, 1), | ||
542 | SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
543 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
544 | 4, 1), | ||
545 | SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
546 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
547 | 0, 1), | ||
548 | SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
549 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
550 | 1, 1), | ||
551 | SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
552 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
553 | 2, 1), | ||
554 | SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
555 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
556 | 3, 1), | ||
557 | SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
558 | show_pwm_auto_point_temp_hyst, | ||
559 | store_pwm_auto_point_temp_hyst, | ||
560 | 0, 1), | ||
561 | SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, | ||
562 | show_pwm_auto_point_temp_hyst, NULL, 1, 1), | ||
563 | SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO, | ||
564 | show_pwm_auto_point_temp_hyst, NULL, 2, 1), | ||
565 | SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO, | ||
566 | show_pwm_auto_point_temp_hyst, NULL, 3, 1), | ||
567 | |||
568 | SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), | ||
569 | SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
570 | store_pwm_enable, 0, 2), | ||
571 | SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
572 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
573 | 0, 2), | ||
574 | SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
575 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
576 | 1, 2), | ||
577 | SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
578 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
579 | 2, 2), | ||
580 | SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
581 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
582 | 3, 2), | ||
583 | SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
584 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
585 | 4, 2), | ||
586 | SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
587 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
588 | 0, 2), | ||
589 | SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
590 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
591 | 1, 2), | ||
592 | SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
593 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
594 | 2, 2), | ||
595 | SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
596 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
597 | 3, 2), | ||
598 | SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
599 | show_pwm_auto_point_temp_hyst, | ||
600 | store_pwm_auto_point_temp_hyst, | ||
601 | 0, 2), | ||
602 | SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO, | ||
603 | show_pwm_auto_point_temp_hyst, NULL, 1, 2), | ||
604 | SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO, | ||
605 | show_pwm_auto_point_temp_hyst, NULL, 2, 2), | ||
606 | SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO, | ||
607 | show_pwm_auto_point_temp_hyst, NULL, 3, 2), | ||
608 | |||
609 | SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3), | ||
610 | SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable, | ||
611 | store_pwm_enable, 0, 3), | ||
612 | SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR, | ||
613 | show_pwm_interpolate, store_pwm_interpolate, 0, 3), | ||
614 | SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR, | ||
615 | show_pwm_auto_point_channel, | ||
616 | store_pwm_auto_point_channel, 0, 3), | ||
617 | SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
618 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
619 | 0, 3), | ||
620 | SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
621 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
622 | 1, 3), | ||
623 | SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
624 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
625 | 2, 3), | ||
626 | SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
627 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
628 | 3, 3), | ||
629 | SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
630 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
631 | 4, 3), | ||
632 | SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
633 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
634 | 0, 3), | ||
635 | SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
636 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
637 | 1, 3), | ||
638 | SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
639 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
640 | 2, 3), | ||
641 | SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
642 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
643 | 3, 3), | ||
644 | SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
645 | show_pwm_auto_point_temp_hyst, | ||
646 | store_pwm_auto_point_temp_hyst, | ||
647 | 0, 3), | ||
648 | SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO, | ||
649 | show_pwm_auto_point_temp_hyst, NULL, 1, 3), | ||
650 | SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO, | ||
651 | show_pwm_auto_point_temp_hyst, NULL, 2, 3), | ||
652 | SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO, | ||
653 | show_pwm_auto_point_temp_hyst, NULL, 3, 3), | ||
264 | }; | 654 | }; |
265 | 655 | ||
656 | /* Fan / PWM attr for the f8000, zones mapped to temp instead of to pwm! | ||
657 | Also the register block at offset A0 maps to TEMP1 (so our temp2, as the | ||
658 | F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */ | ||
659 | static struct sensor_device_attribute_2 f8000_fan_attr[] = { | ||
660 | SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), | ||
661 | |||
662 | SENSOR_ATTR_2(pwm3, S_IRUGO, show_pwm, NULL, 0, 2), | ||
663 | |||
664 | SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
665 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
666 | 0, 2), | ||
667 | SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
668 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
669 | 1, 2), | ||
670 | SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
671 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
672 | 2, 2), | ||
673 | SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
674 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
675 | 3, 2), | ||
676 | SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
677 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
678 | 4, 2), | ||
679 | SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
680 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
681 | 0, 2), | ||
682 | SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
683 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
684 | 1, 2), | ||
685 | SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
686 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
687 | 2, 2), | ||
688 | SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
689 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
690 | 3, 2), | ||
691 | SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
692 | show_pwm_auto_point_temp_hyst, | ||
693 | store_pwm_auto_point_temp_hyst, | ||
694 | 0, 2), | ||
695 | SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO, | ||
696 | show_pwm_auto_point_temp_hyst, NULL, 1, 2), | ||
697 | SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO, | ||
698 | show_pwm_auto_point_temp_hyst, NULL, 2, 2), | ||
699 | SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO, | ||
700 | show_pwm_auto_point_temp_hyst, NULL, 3, 2), | ||
701 | |||
702 | SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
703 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
704 | 0, 0), | ||
705 | SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
706 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
707 | 1, 0), | ||
708 | SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
709 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
710 | 2, 0), | ||
711 | SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
712 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
713 | 3, 0), | ||
714 | SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
715 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
716 | 4, 0), | ||
717 | SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
718 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
719 | 0, 0), | ||
720 | SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
721 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
722 | 1, 0), | ||
723 | SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
724 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
725 | 2, 0), | ||
726 | SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
727 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
728 | 3, 0), | ||
729 | SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
730 | show_pwm_auto_point_temp_hyst, | ||
731 | store_pwm_auto_point_temp_hyst, | ||
732 | 0, 0), | ||
733 | SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO, | ||
734 | show_pwm_auto_point_temp_hyst, NULL, 1, 0), | ||
735 | SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO, | ||
736 | show_pwm_auto_point_temp_hyst, NULL, 2, 0), | ||
737 | SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO, | ||
738 | show_pwm_auto_point_temp_hyst, NULL, 3, 0), | ||
739 | |||
740 | SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR, | ||
741 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
742 | 0, 1), | ||
743 | SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR, | ||
744 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
745 | 1, 1), | ||
746 | SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR, | ||
747 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
748 | 2, 1), | ||
749 | SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR, | ||
750 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
751 | 3, 1), | ||
752 | SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR, | ||
753 | show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, | ||
754 | 4, 1), | ||
755 | SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR, | ||
756 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
757 | 0, 1), | ||
758 | SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR, | ||
759 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
760 | 1, 1), | ||
761 | SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR, | ||
762 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
763 | 2, 1), | ||
764 | SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR, | ||
765 | show_pwm_auto_point_temp, store_pwm_auto_point_temp, | ||
766 | 3, 1), | ||
767 | SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, | ||
768 | show_pwm_auto_point_temp_hyst, | ||
769 | store_pwm_auto_point_temp_hyst, | ||
770 | 0, 1), | ||
771 | SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO, | ||
772 | show_pwm_auto_point_temp_hyst, NULL, 1, 1), | ||
773 | SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO, | ||
774 | show_pwm_auto_point_temp_hyst, NULL, 2, 1), | ||
775 | SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO, | ||
776 | show_pwm_auto_point_temp_hyst, NULL, 3, 1), | ||
777 | }; | ||
266 | 778 | ||
267 | /* Super I/O functions */ | 779 | /* Super I/O functions */ |
268 | static inline int superio_inb(int base, int reg) | 780 | static inline int superio_inb(int base, int reg) |
@@ -299,11 +811,16 @@ static inline void superio_exit(int base) | |||
299 | outb(SIO_LOCK_KEY, base); | 811 | outb(SIO_LOCK_KEY, base); |
300 | } | 812 | } |
301 | 813 | ||
302 | static inline u16 fan_from_reg(u16 reg) | 814 | static inline int fan_from_reg(u16 reg) |
303 | { | 815 | { |
304 | return reg ? (1500000 / reg) : 0; | 816 | return reg ? (1500000 / reg) : 0; |
305 | } | 817 | } |
306 | 818 | ||
819 | static inline u16 fan_to_reg(int fan) | ||
820 | { | ||
821 | return fan ? (1500000 / fan) : 0; | ||
822 | } | ||
823 | |||
307 | static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg) | 824 | static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg) |
308 | { | 825 | { |
309 | u8 val; | 826 | u8 val; |
@@ -332,52 +849,111 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) | |||
332 | outb(val, data->addr + DATA_REG_OFFSET); | 849 | outb(val, data->addr + DATA_REG_OFFSET); |
333 | } | 850 | } |
334 | 851 | ||
335 | static struct f71882fg_data *f71882fg_update_device(struct device * dev) | 852 | static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) |
853 | { | ||
854 | outb(reg++, data->addr + ADDR_REG_OFFSET); | ||
855 | outb(val >> 8, data->addr + DATA_REG_OFFSET); | ||
856 | outb(reg, data->addr + ADDR_REG_OFFSET); | ||
857 | outb(val & 255, data->addr + DATA_REG_OFFSET); | ||
858 | } | ||
859 | |||
860 | static struct f71882fg_data *f71882fg_update_device(struct device *dev) | ||
336 | { | 861 | { |
337 | struct f71882fg_data *data = dev_get_drvdata(dev); | 862 | struct f71882fg_data *data = dev_get_drvdata(dev); |
338 | int nr, reg, reg2; | 863 | int nr, reg = 0, reg2; |
864 | int nr_fans = (data->type == f71882fg) ? 4 : 3; | ||
865 | int nr_ins = (data->type == f8000) ? 3 : 9; | ||
866 | int temp_start = (data->type == f8000) ? 0 : 1; | ||
339 | 867 | ||
340 | mutex_lock(&data->update_lock); | 868 | mutex_lock(&data->update_lock); |
341 | 869 | ||
342 | /* Update once every 60 seconds */ | 870 | /* Update once every 60 seconds */ |
343 | if ( time_after(jiffies, data->last_limits + 60 * HZ ) || | 871 | if ( time_after(jiffies, data->last_limits + 60 * HZ ) || |
344 | !data->valid) { | 872 | !data->valid) { |
345 | data->in1_max = f71882fg_read8(data, F71882FG_REG_IN1_HIGH); | 873 | if (data->type == f71882fg) { |
346 | data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP); | 874 | data->in1_max = |
875 | f71882fg_read8(data, F71882FG_REG_IN1_HIGH); | ||
876 | data->in_beep = | ||
877 | f71882fg_read8(data, F71882FG_REG_IN_BEEP); | ||
878 | } | ||
347 | 879 | ||
348 | /* Get High & boundary temps*/ | 880 | /* Get High & boundary temps*/ |
349 | for (nr = 0; nr < 3; nr++) { | 881 | for (nr = temp_start; nr < 3 + temp_start; nr++) { |
350 | data->temp_ovt[nr] = f71882fg_read8(data, | 882 | data->temp_ovt[nr] = f71882fg_read8(data, |
351 | F71882FG_REG_TEMP_OVT(nr)); | 883 | F71882FG_REG_TEMP_OVT(nr)); |
352 | data->temp_high[nr] = f71882fg_read8(data, | 884 | data->temp_high[nr] = f71882fg_read8(data, |
353 | F71882FG_REG_TEMP_HIGH(nr)); | 885 | F71882FG_REG_TEMP_HIGH(nr)); |
354 | } | 886 | } |
355 | 887 | ||
356 | /* Have to hardcode hyst*/ | 888 | if (data->type != f8000) { |
357 | data->temp_hyst[0] = f71882fg_read8(data, | 889 | data->fan_beep = f71882fg_read8(data, |
358 | F71882FG_REG_TEMP_HYST1) >> 4; | 890 | F71882FG_REG_FAN_BEEP); |
359 | /* Hyst temps 2 & 3 stored in same register */ | 891 | data->temp_beep = f71882fg_read8(data, |
360 | reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST23); | 892 | F71882FG_REG_TEMP_BEEP); |
361 | data->temp_hyst[1] = reg & 0x0F; | 893 | data->temp_hyst[0] = f71882fg_read8(data, |
362 | data->temp_hyst[2] = reg >> 4; | 894 | F71882FG_REG_TEMP_HYST(0)); |
363 | 895 | data->temp_hyst[1] = f71882fg_read8(data, | |
364 | /* Have to hardcode type, because temp1 is special */ | 896 | F71882FG_REG_TEMP_HYST(1)); |
365 | reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); | 897 | /* Have to hardcode type, because temp1 is special */ |
898 | reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); | ||
899 | data->temp_type[2] = (reg & 0x04) ? 2 : 4; | ||
900 | data->temp_type[3] = (reg & 0x08) ? 2 : 4; | ||
901 | } | ||
366 | reg2 = f71882fg_read8(data, F71882FG_REG_PECI); | 902 | reg2 = f71882fg_read8(data, F71882FG_REG_PECI); |
367 | if ((reg2 & 0x03) == 0x01) | 903 | if ((reg2 & 0x03) == 0x01) |
368 | data->temp_type[0] = 6 /* PECI */; | 904 | data->temp_type[1] = 6 /* PECI */; |
369 | else if ((reg2 & 0x03) == 0x02) | 905 | else if ((reg2 & 0x03) == 0x02) |
370 | data->temp_type[0] = 5 /* AMDSI */; | 906 | data->temp_type[1] = 5 /* AMDSI */; |
907 | else if (data->type != f8000) | ||
908 | data->temp_type[1] = (reg & 0x02) ? 2 : 4; | ||
371 | else | 909 | else |
372 | data->temp_type[0] = (reg & 0x02) ? 2 : 4; | 910 | data->temp_type[1] = 2; /* F8000 only supports BJT */ |
373 | 911 | ||
374 | data->temp_type[1] = (reg & 0x04) ? 2 : 4; | 912 | data->pwm_enable = f71882fg_read8(data, |
375 | data->temp_type[2] = (reg & 0x08) ? 2 : 4; | 913 | F71882FG_REG_PWM_ENABLE); |
376 | 914 | data->pwm_auto_point_hyst[0] = | |
377 | data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); | 915 | f71882fg_read8(data, F71882FG_REG_FAN_HYST(0)); |
378 | 916 | data->pwm_auto_point_hyst[1] = | |
379 | data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); | 917 | f71882fg_read8(data, F71882FG_REG_FAN_HYST(1)); |
380 | 918 | ||
919 | for (nr = 0; nr < nr_fans; nr++) { | ||
920 | data->pwm_auto_point_mapping[nr] = | ||
921 | f71882fg_read8(data, | ||
922 | F71882FG_REG_POINT_MAPPING(nr)); | ||
923 | |||
924 | if (data->type != f71862fg) { | ||
925 | int point; | ||
926 | for (point = 0; point < 5; point++) { | ||
927 | data->pwm_auto_point_pwm[nr][point] = | ||
928 | f71882fg_read8(data, | ||
929 | F71882FG_REG_POINT_PWM | ||
930 | (nr, point)); | ||
931 | } | ||
932 | for (point = 0; point < 4; point++) { | ||
933 | data->pwm_auto_point_temp[nr][point] = | ||
934 | f71882fg_read8(data, | ||
935 | F71882FG_REG_POINT_TEMP | ||
936 | (nr, point)); | ||
937 | } | ||
938 | } else { | ||
939 | data->pwm_auto_point_pwm[nr][1] = | ||
940 | f71882fg_read8(data, | ||
941 | F71882FG_REG_POINT_PWM | ||
942 | (nr, 1)); | ||
943 | data->pwm_auto_point_pwm[nr][4] = | ||
944 | f71882fg_read8(data, | ||
945 | F71882FG_REG_POINT_PWM | ||
946 | (nr, 4)); | ||
947 | data->pwm_auto_point_temp[nr][0] = | ||
948 | f71882fg_read8(data, | ||
949 | F71882FG_REG_POINT_TEMP | ||
950 | (nr, 0)); | ||
951 | data->pwm_auto_point_temp[nr][3] = | ||
952 | f71882fg_read8(data, | ||
953 | F71882FG_REG_POINT_TEMP | ||
954 | (nr, 3)); | ||
955 | } | ||
956 | } | ||
381 | data->last_limits = jiffies; | 957 | data->last_limits = jiffies; |
382 | } | 958 | } |
383 | 959 | ||
@@ -387,19 +963,32 @@ static struct f71882fg_data *f71882fg_update_device(struct device * dev) | |||
387 | F71882FG_REG_TEMP_STATUS); | 963 | F71882FG_REG_TEMP_STATUS); |
388 | data->temp_diode_open = f71882fg_read8(data, | 964 | data->temp_diode_open = f71882fg_read8(data, |
389 | F71882FG_REG_TEMP_DIODE_OPEN); | 965 | F71882FG_REG_TEMP_DIODE_OPEN); |
390 | for (nr = 0; nr < 3; nr++) | 966 | for (nr = temp_start; nr < 3 + temp_start; nr++) |
391 | data->temp[nr] = f71882fg_read8(data, | 967 | data->temp[nr] = f71882fg_read8(data, |
392 | F71882FG_REG_TEMP(nr)); | 968 | F71882FG_REG_TEMP(nr)); |
393 | 969 | ||
394 | data->fan_status = f71882fg_read8(data, | 970 | data->fan_status = f71882fg_read8(data, |
395 | F71882FG_REG_FAN_STATUS); | 971 | F71882FG_REG_FAN_STATUS); |
396 | for (nr = 0; nr < 4; nr++) | 972 | for (nr = 0; nr < nr_fans; nr++) { |
397 | data->fan[nr] = f71882fg_read16(data, | 973 | data->fan[nr] = f71882fg_read16(data, |
398 | F71882FG_REG_FAN(nr)); | 974 | F71882FG_REG_FAN(nr)); |
975 | data->fan_target[nr] = | ||
976 | f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr)); | ||
977 | data->fan_full_speed[nr] = | ||
978 | f71882fg_read16(data, | ||
979 | F71882FG_REG_FAN_FULL_SPEED(nr)); | ||
980 | data->pwm[nr] = | ||
981 | f71882fg_read8(data, F71882FG_REG_PWM(nr)); | ||
982 | } | ||
399 | 983 | ||
400 | data->in_status = f71882fg_read8(data, | 984 | /* The f8000 can monitor 1 more fan, but has no pwm for it */ |
985 | if (data->type == f8000) | ||
986 | data->fan[3] = f71882fg_read16(data, | ||
987 | F71882FG_REG_FAN(3)); | ||
988 | if (data->type == f71882fg) | ||
989 | data->in_status = f71882fg_read8(data, | ||
401 | F71882FG_REG_IN_STATUS); | 990 | F71882FG_REG_IN_STATUS); |
402 | for (nr = 0; nr < 9; nr++) | 991 | for (nr = 0; nr < nr_ins; nr++) |
403 | data->in[nr] = f71882fg_read8(data, | 992 | data->in[nr] = f71882fg_read8(data, |
404 | F71882FG_REG_IN(nr)); | 993 | F71882FG_REG_IN(nr)); |
405 | 994 | ||
@@ -417,7 +1006,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, | |||
417 | char *buf) | 1006 | char *buf) |
418 | { | 1007 | { |
419 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1008 | struct f71882fg_data *data = f71882fg_update_device(dev); |
420 | int nr = to_sensor_dev_attr(devattr)->index; | 1009 | int nr = to_sensor_dev_attr_2(devattr)->index; |
421 | int speed = fan_from_reg(data->fan[nr]); | 1010 | int speed = fan_from_reg(data->fan[nr]); |
422 | 1011 | ||
423 | if (speed == FAN_MIN_DETECT) | 1012 | if (speed == FAN_MIN_DETECT) |
@@ -426,11 +1015,39 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, | |||
426 | return sprintf(buf, "%d\n", speed); | 1015 | return sprintf(buf, "%d\n", speed); |
427 | } | 1016 | } |
428 | 1017 | ||
1018 | static ssize_t show_fan_full_speed(struct device *dev, | ||
1019 | struct device_attribute *devattr, char *buf) | ||
1020 | { | ||
1021 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1022 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1023 | int speed = fan_from_reg(data->fan_full_speed[nr]); | ||
1024 | return sprintf(buf, "%d\n", speed); | ||
1025 | } | ||
1026 | |||
1027 | static ssize_t store_fan_full_speed(struct device *dev, | ||
1028 | struct device_attribute *devattr, | ||
1029 | const char *buf, size_t count) | ||
1030 | { | ||
1031 | struct f71882fg_data *data = dev_get_drvdata(dev); | ||
1032 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1033 | long val = simple_strtol(buf, NULL, 10); | ||
1034 | |||
1035 | val = SENSORS_LIMIT(val, 23, 1500000); | ||
1036 | val = fan_to_reg(val); | ||
1037 | |||
1038 | mutex_lock(&data->update_lock); | ||
1039 | f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val); | ||
1040 | data->fan_full_speed[nr] = val; | ||
1041 | mutex_unlock(&data->update_lock); | ||
1042 | |||
1043 | return count; | ||
1044 | } | ||
1045 | |||
429 | static ssize_t show_fan_beep(struct device *dev, struct device_attribute | 1046 | static ssize_t show_fan_beep(struct device *dev, struct device_attribute |
430 | *devattr, char *buf) | 1047 | *devattr, char *buf) |
431 | { | 1048 | { |
432 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1049 | struct f71882fg_data *data = f71882fg_update_device(dev); |
433 | int nr = to_sensor_dev_attr(devattr)->index; | 1050 | int nr = to_sensor_dev_attr_2(devattr)->index; |
434 | 1051 | ||
435 | if (data->fan_beep & (1 << nr)) | 1052 | if (data->fan_beep & (1 << nr)) |
436 | return sprintf(buf, "1\n"); | 1053 | return sprintf(buf, "1\n"); |
@@ -442,10 +1059,11 @@ static ssize_t store_fan_beep(struct device *dev, struct device_attribute | |||
442 | *devattr, const char *buf, size_t count) | 1059 | *devattr, const char *buf, size_t count) |
443 | { | 1060 | { |
444 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1061 | struct f71882fg_data *data = dev_get_drvdata(dev); |
445 | int nr = to_sensor_dev_attr(devattr)->index; | 1062 | int nr = to_sensor_dev_attr_2(devattr)->index; |
446 | int val = simple_strtoul(buf, NULL, 10); | 1063 | unsigned long val = simple_strtoul(buf, NULL, 10); |
447 | 1064 | ||
448 | mutex_lock(&data->update_lock); | 1065 | mutex_lock(&data->update_lock); |
1066 | data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); | ||
449 | if (val) | 1067 | if (val) |
450 | data->fan_beep |= 1 << nr; | 1068 | data->fan_beep |= 1 << nr; |
451 | else | 1069 | else |
@@ -461,7 +1079,7 @@ static ssize_t show_fan_alarm(struct device *dev, struct device_attribute | |||
461 | *devattr, char *buf) | 1079 | *devattr, char *buf) |
462 | { | 1080 | { |
463 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1081 | struct f71882fg_data *data = f71882fg_update_device(dev); |
464 | int nr = to_sensor_dev_attr(devattr)->index; | 1082 | int nr = to_sensor_dev_attr_2(devattr)->index; |
465 | 1083 | ||
466 | if (data->fan_status & (1 << nr)) | 1084 | if (data->fan_status & (1 << nr)) |
467 | return sprintf(buf, "1\n"); | 1085 | return sprintf(buf, "1\n"); |
@@ -473,7 +1091,7 @@ static ssize_t show_in(struct device *dev, struct device_attribute *devattr, | |||
473 | char *buf) | 1091 | char *buf) |
474 | { | 1092 | { |
475 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1093 | struct f71882fg_data *data = f71882fg_update_device(dev); |
476 | int nr = to_sensor_dev_attr(devattr)->index; | 1094 | int nr = to_sensor_dev_attr_2(devattr)->index; |
477 | 1095 | ||
478 | return sprintf(buf, "%d\n", data->in[nr] * 8); | 1096 | return sprintf(buf, "%d\n", data->in[nr] * 8); |
479 | } | 1097 | } |
@@ -490,10 +1108,8 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute | |||
490 | *devattr, const char *buf, size_t count) | 1108 | *devattr, const char *buf, size_t count) |
491 | { | 1109 | { |
492 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1110 | struct f71882fg_data *data = dev_get_drvdata(dev); |
493 | int val = simple_strtoul(buf, NULL, 10) / 8; | 1111 | long val = simple_strtol(buf, NULL, 10) / 8; |
494 | 1112 | val = SENSORS_LIMIT(val, 0, 255); | |
495 | if (val > 255) | ||
496 | val = 255; | ||
497 | 1113 | ||
498 | mutex_lock(&data->update_lock); | 1114 | mutex_lock(&data->update_lock); |
499 | f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val); | 1115 | f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val); |
@@ -507,7 +1123,7 @@ static ssize_t show_in_beep(struct device *dev, struct device_attribute | |||
507 | *devattr, char *buf) | 1123 | *devattr, char *buf) |
508 | { | 1124 | { |
509 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1125 | struct f71882fg_data *data = f71882fg_update_device(dev); |
510 | int nr = to_sensor_dev_attr(devattr)->index; | 1126 | int nr = to_sensor_dev_attr_2(devattr)->index; |
511 | 1127 | ||
512 | if (data->in_beep & (1 << nr)) | 1128 | if (data->in_beep & (1 << nr)) |
513 | return sprintf(buf, "1\n"); | 1129 | return sprintf(buf, "1\n"); |
@@ -519,10 +1135,11 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute | |||
519 | *devattr, const char *buf, size_t count) | 1135 | *devattr, const char *buf, size_t count) |
520 | { | 1136 | { |
521 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1137 | struct f71882fg_data *data = dev_get_drvdata(dev); |
522 | int nr = to_sensor_dev_attr(devattr)->index; | 1138 | int nr = to_sensor_dev_attr_2(devattr)->index; |
523 | int val = simple_strtoul(buf, NULL, 10); | 1139 | unsigned long val = simple_strtoul(buf, NULL, 10); |
524 | 1140 | ||
525 | mutex_lock(&data->update_lock); | 1141 | mutex_lock(&data->update_lock); |
1142 | data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP); | ||
526 | if (val) | 1143 | if (val) |
527 | data->in_beep |= 1 << nr; | 1144 | data->in_beep |= 1 << nr; |
528 | else | 1145 | else |
@@ -538,7 +1155,7 @@ static ssize_t show_in_alarm(struct device *dev, struct device_attribute | |||
538 | *devattr, char *buf) | 1155 | *devattr, char *buf) |
539 | { | 1156 | { |
540 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1157 | struct f71882fg_data *data = f71882fg_update_device(dev); |
541 | int nr = to_sensor_dev_attr(devattr)->index; | 1158 | int nr = to_sensor_dev_attr_2(devattr)->index; |
542 | 1159 | ||
543 | if (data->in_status & (1 << nr)) | 1160 | if (data->in_status & (1 << nr)) |
544 | return sprintf(buf, "1\n"); | 1161 | return sprintf(buf, "1\n"); |
@@ -550,7 +1167,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, | |||
550 | char *buf) | 1167 | char *buf) |
551 | { | 1168 | { |
552 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1169 | struct f71882fg_data *data = f71882fg_update_device(dev); |
553 | int nr = to_sensor_dev_attr(devattr)->index; | 1170 | int nr = to_sensor_dev_attr_2(devattr)->index; |
554 | 1171 | ||
555 | return sprintf(buf, "%d\n", data->temp[nr] * 1000); | 1172 | return sprintf(buf, "%d\n", data->temp[nr] * 1000); |
556 | } | 1173 | } |
@@ -559,7 +1176,7 @@ static ssize_t show_temp_max(struct device *dev, struct device_attribute | |||
559 | *devattr, char *buf) | 1176 | *devattr, char *buf) |
560 | { | 1177 | { |
561 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1178 | struct f71882fg_data *data = f71882fg_update_device(dev); |
562 | int nr = to_sensor_dev_attr(devattr)->index; | 1179 | int nr = to_sensor_dev_attr_2(devattr)->index; |
563 | 1180 | ||
564 | return sprintf(buf, "%d\n", data->temp_high[nr] * 1000); | 1181 | return sprintf(buf, "%d\n", data->temp_high[nr] * 1000); |
565 | } | 1182 | } |
@@ -568,11 +1185,9 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute | |||
568 | *devattr, const char *buf, size_t count) | 1185 | *devattr, const char *buf, size_t count) |
569 | { | 1186 | { |
570 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1187 | struct f71882fg_data *data = dev_get_drvdata(dev); |
571 | int nr = to_sensor_dev_attr(devattr)->index; | 1188 | int nr = to_sensor_dev_attr_2(devattr)->index; |
572 | int val = simple_strtoul(buf, NULL, 10) / 1000; | 1189 | long val = simple_strtol(buf, NULL, 10) / 1000; |
573 | 1190 | val = SENSORS_LIMIT(val, 0, 255); | |
574 | if (val > 255) | ||
575 | val = 255; | ||
576 | 1191 | ||
577 | mutex_lock(&data->update_lock); | 1192 | mutex_lock(&data->update_lock); |
578 | f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val); | 1193 | f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val); |
@@ -586,48 +1201,46 @@ static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute | |||
586 | *devattr, char *buf) | 1201 | *devattr, char *buf) |
587 | { | 1202 | { |
588 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1203 | struct f71882fg_data *data = f71882fg_update_device(dev); |
589 | int nr = to_sensor_dev_attr(devattr)->index; | 1204 | int nr = to_sensor_dev_attr_2(devattr)->index; |
1205 | int temp_max_hyst; | ||
1206 | |||
1207 | mutex_lock(&data->update_lock); | ||
1208 | if (nr & 1) | ||
1209 | temp_max_hyst = data->temp_hyst[nr / 2] >> 4; | ||
1210 | else | ||
1211 | temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f; | ||
1212 | temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000; | ||
1213 | mutex_unlock(&data->update_lock); | ||
590 | 1214 | ||
591 | return sprintf(buf, "%d\n", | 1215 | return sprintf(buf, "%d\n", temp_max_hyst); |
592 | (data->temp_high[nr] - data->temp_hyst[nr]) * 1000); | ||
593 | } | 1216 | } |
594 | 1217 | ||
595 | static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute | 1218 | static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute |
596 | *devattr, const char *buf, size_t count) | 1219 | *devattr, const char *buf, size_t count) |
597 | { | 1220 | { |
598 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1221 | struct f71882fg_data *data = dev_get_drvdata(dev); |
599 | int nr = to_sensor_dev_attr(devattr)->index; | 1222 | int nr = to_sensor_dev_attr_2(devattr)->index; |
600 | int val = simple_strtoul(buf, NULL, 10) / 1000; | 1223 | long val = simple_strtol(buf, NULL, 10) / 1000; |
601 | ssize_t ret = count; | 1224 | ssize_t ret = count; |
1225 | u8 reg; | ||
602 | 1226 | ||
603 | mutex_lock(&data->update_lock); | 1227 | mutex_lock(&data->update_lock); |
604 | 1228 | ||
605 | /* convert abs to relative and check */ | 1229 | /* convert abs to relative and check */ |
1230 | data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr)); | ||
1231 | val = SENSORS_LIMIT(val, data->temp_high[nr] - 15, | ||
1232 | data->temp_high[nr]); | ||
606 | val = data->temp_high[nr] - val; | 1233 | val = data->temp_high[nr] - val; |
607 | if (val < 0 || val > 15) { | ||
608 | ret = -EINVAL; | ||
609 | goto store_temp_max_hyst_exit; | ||
610 | } | ||
611 | |||
612 | data->temp_hyst[nr] = val; | ||
613 | 1234 | ||
614 | /* convert value to register contents */ | 1235 | /* convert value to register contents */ |
615 | switch (nr) { | 1236 | reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2)); |
616 | case 0: | 1237 | if (nr & 1) |
617 | val = val << 4; | 1238 | reg = (reg & 0x0f) | (val << 4); |
618 | break; | 1239 | else |
619 | case 1: | 1240 | reg = (reg & 0xf0) | val; |
620 | val = val | (data->temp_hyst[2] << 4); | 1241 | f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg); |
621 | break; | 1242 | data->temp_hyst[nr / 2] = reg; |
622 | case 2: | ||
623 | val = data->temp_hyst[1] | (val << 4); | ||
624 | break; | ||
625 | } | ||
626 | |||
627 | f71882fg_write8(data, nr ? F71882FG_REG_TEMP_HYST23 : | ||
628 | F71882FG_REG_TEMP_HYST1, val); | ||
629 | 1243 | ||
630 | store_temp_max_hyst_exit: | ||
631 | mutex_unlock(&data->update_lock); | 1244 | mutex_unlock(&data->update_lock); |
632 | return ret; | 1245 | return ret; |
633 | } | 1246 | } |
@@ -636,7 +1249,7 @@ static ssize_t show_temp_crit(struct device *dev, struct device_attribute | |||
636 | *devattr, char *buf) | 1249 | *devattr, char *buf) |
637 | { | 1250 | { |
638 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1251 | struct f71882fg_data *data = f71882fg_update_device(dev); |
639 | int nr = to_sensor_dev_attr(devattr)->index; | 1252 | int nr = to_sensor_dev_attr_2(devattr)->index; |
640 | 1253 | ||
641 | return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000); | 1254 | return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000); |
642 | } | 1255 | } |
@@ -645,11 +1258,9 @@ static ssize_t store_temp_crit(struct device *dev, struct device_attribute | |||
645 | *devattr, const char *buf, size_t count) | 1258 | *devattr, const char *buf, size_t count) |
646 | { | 1259 | { |
647 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1260 | struct f71882fg_data *data = dev_get_drvdata(dev); |
648 | int nr = to_sensor_dev_attr(devattr)->index; | 1261 | int nr = to_sensor_dev_attr_2(devattr)->index; |
649 | int val = simple_strtoul(buf, NULL, 10) / 1000; | 1262 | long val = simple_strtol(buf, NULL, 10) / 1000; |
650 | 1263 | val = SENSORS_LIMIT(val, 0, 255); | |
651 | if (val > 255) | ||
652 | val = 255; | ||
653 | 1264 | ||
654 | mutex_lock(&data->update_lock); | 1265 | mutex_lock(&data->update_lock); |
655 | f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val); | 1266 | f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val); |
@@ -663,17 +1274,25 @@ static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute | |||
663 | *devattr, char *buf) | 1274 | *devattr, char *buf) |
664 | { | 1275 | { |
665 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1276 | struct f71882fg_data *data = f71882fg_update_device(dev); |
666 | int nr = to_sensor_dev_attr(devattr)->index; | 1277 | int nr = to_sensor_dev_attr_2(devattr)->index; |
1278 | int temp_crit_hyst; | ||
1279 | |||
1280 | mutex_lock(&data->update_lock); | ||
1281 | if (nr & 1) | ||
1282 | temp_crit_hyst = data->temp_hyst[nr / 2] >> 4; | ||
1283 | else | ||
1284 | temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f; | ||
1285 | temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000; | ||
1286 | mutex_unlock(&data->update_lock); | ||
667 | 1287 | ||
668 | return sprintf(buf, "%d\n", | 1288 | return sprintf(buf, "%d\n", temp_crit_hyst); |
669 | (data->temp_ovt[nr] - data->temp_hyst[nr]) * 1000); | ||
670 | } | 1289 | } |
671 | 1290 | ||
672 | static ssize_t show_temp_type(struct device *dev, struct device_attribute | 1291 | static ssize_t show_temp_type(struct device *dev, struct device_attribute |
673 | *devattr, char *buf) | 1292 | *devattr, char *buf) |
674 | { | 1293 | { |
675 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1294 | struct f71882fg_data *data = f71882fg_update_device(dev); |
676 | int nr = to_sensor_dev_attr(devattr)->index; | 1295 | int nr = to_sensor_dev_attr_2(devattr)->index; |
677 | 1296 | ||
678 | return sprintf(buf, "%d\n", data->temp_type[nr]); | 1297 | return sprintf(buf, "%d\n", data->temp_type[nr]); |
679 | } | 1298 | } |
@@ -682,9 +1301,9 @@ static ssize_t show_temp_beep(struct device *dev, struct device_attribute | |||
682 | *devattr, char *buf) | 1301 | *devattr, char *buf) |
683 | { | 1302 | { |
684 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1303 | struct f71882fg_data *data = f71882fg_update_device(dev); |
685 | int nr = to_sensor_dev_attr(devattr)->index; | 1304 | int nr = to_sensor_dev_attr_2(devattr)->index; |
686 | 1305 | ||
687 | if (data->temp_beep & (1 << (nr + 1))) | 1306 | if (data->temp_beep & (1 << nr)) |
688 | return sprintf(buf, "1\n"); | 1307 | return sprintf(buf, "1\n"); |
689 | else | 1308 | else |
690 | return sprintf(buf, "0\n"); | 1309 | return sprintf(buf, "0\n"); |
@@ -694,14 +1313,15 @@ static ssize_t store_temp_beep(struct device *dev, struct device_attribute | |||
694 | *devattr, const char *buf, size_t count) | 1313 | *devattr, const char *buf, size_t count) |
695 | { | 1314 | { |
696 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1315 | struct f71882fg_data *data = dev_get_drvdata(dev); |
697 | int nr = to_sensor_dev_attr(devattr)->index; | 1316 | int nr = to_sensor_dev_attr_2(devattr)->index; |
698 | int val = simple_strtoul(buf, NULL, 10); | 1317 | unsigned long val = simple_strtoul(buf, NULL, 10); |
699 | 1318 | ||
700 | mutex_lock(&data->update_lock); | 1319 | mutex_lock(&data->update_lock); |
1320 | data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); | ||
701 | if (val) | 1321 | if (val) |
702 | data->temp_beep |= 1 << (nr + 1); | 1322 | data->temp_beep |= 1 << nr; |
703 | else | 1323 | else |
704 | data->temp_beep &= ~(1 << (nr + 1)); | 1324 | data->temp_beep &= ~(1 << nr); |
705 | 1325 | ||
706 | f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep); | 1326 | f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep); |
707 | mutex_unlock(&data->update_lock); | 1327 | mutex_unlock(&data->update_lock); |
@@ -713,9 +1333,9 @@ static ssize_t show_temp_alarm(struct device *dev, struct device_attribute | |||
713 | *devattr, char *buf) | 1333 | *devattr, char *buf) |
714 | { | 1334 | { |
715 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1335 | struct f71882fg_data *data = f71882fg_update_device(dev); |
716 | int nr = to_sensor_dev_attr(devattr)->index; | 1336 | int nr = to_sensor_dev_attr_2(devattr)->index; |
717 | 1337 | ||
718 | if (data->temp_status & (1 << (nr + 1))) | 1338 | if (data->temp_status & (1 << nr)) |
719 | return sprintf(buf, "1\n"); | 1339 | return sprintf(buf, "1\n"); |
720 | else | 1340 | else |
721 | return sprintf(buf, "0\n"); | 1341 | return sprintf(buf, "0\n"); |
@@ -725,113 +1345,528 @@ static ssize_t show_temp_fault(struct device *dev, struct device_attribute | |||
725 | *devattr, char *buf) | 1345 | *devattr, char *buf) |
726 | { | 1346 | { |
727 | struct f71882fg_data *data = f71882fg_update_device(dev); | 1347 | struct f71882fg_data *data = f71882fg_update_device(dev); |
728 | int nr = to_sensor_dev_attr(devattr)->index; | 1348 | int nr = to_sensor_dev_attr_2(devattr)->index; |
729 | 1349 | ||
730 | if (data->temp_diode_open & (1 << (nr + 1))) | 1350 | if (data->temp_diode_open & (1 << nr)) |
731 | return sprintf(buf, "1\n"); | 1351 | return sprintf(buf, "1\n"); |
732 | else | 1352 | else |
733 | return sprintf(buf, "0\n"); | 1353 | return sprintf(buf, "0\n"); |
734 | } | 1354 | } |
735 | 1355 | ||
1356 | static ssize_t show_pwm(struct device *dev, | ||
1357 | struct device_attribute *devattr, char *buf) | ||
1358 | { | ||
1359 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1360 | int val, nr = to_sensor_dev_attr_2(devattr)->index; | ||
1361 | mutex_lock(&data->update_lock); | ||
1362 | if (data->pwm_enable & (1 << (2 * nr))) | ||
1363 | /* PWM mode */ | ||
1364 | val = data->pwm[nr]; | ||
1365 | else { | ||
1366 | /* RPM mode */ | ||
1367 | val = 255 * fan_from_reg(data->fan_target[nr]) | ||
1368 | / fan_from_reg(data->fan_full_speed[nr]); | ||
1369 | } | ||
1370 | mutex_unlock(&data->update_lock); | ||
1371 | return sprintf(buf, "%d\n", val); | ||
1372 | } | ||
1373 | |||
1374 | static ssize_t store_pwm(struct device *dev, | ||
1375 | struct device_attribute *devattr, const char *buf, | ||
1376 | size_t count) | ||
1377 | { | ||
1378 | struct f71882fg_data *data = dev_get_drvdata(dev); | ||
1379 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1380 | long val = simple_strtol(buf, NULL, 10); | ||
1381 | val = SENSORS_LIMIT(val, 0, 255); | ||
1382 | |||
1383 | mutex_lock(&data->update_lock); | ||
1384 | data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); | ||
1385 | if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) || | ||
1386 | (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) { | ||
1387 | count = -EROFS; | ||
1388 | goto leave; | ||
1389 | } | ||
1390 | if (data->pwm_enable & (1 << (2 * nr))) { | ||
1391 | /* PWM mode */ | ||
1392 | f71882fg_write8(data, F71882FG_REG_PWM(nr), val); | ||
1393 | data->pwm[nr] = val; | ||
1394 | } else { | ||
1395 | /* RPM mode */ | ||
1396 | int target, full_speed; | ||
1397 | full_speed = f71882fg_read16(data, | ||
1398 | F71882FG_REG_FAN_FULL_SPEED(nr)); | ||
1399 | target = fan_to_reg(val * fan_from_reg(full_speed) / 255); | ||
1400 | f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target); | ||
1401 | data->fan_target[nr] = target; | ||
1402 | data->fan_full_speed[nr] = full_speed; | ||
1403 | } | ||
1404 | leave: | ||
1405 | mutex_unlock(&data->update_lock); | ||
1406 | |||
1407 | return count; | ||
1408 | } | ||
1409 | |||
1410 | static ssize_t show_pwm_enable(struct device *dev, | ||
1411 | struct device_attribute *devattr, char *buf) | ||
1412 | { | ||
1413 | int result = 0; | ||
1414 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1415 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1416 | |||
1417 | switch ((data->pwm_enable >> 2 * nr) & 3) { | ||
1418 | case 0: | ||
1419 | case 1: | ||
1420 | result = 2; /* Normal auto mode */ | ||
1421 | break; | ||
1422 | case 2: | ||
1423 | result = 1; /* Manual mode */ | ||
1424 | break; | ||
1425 | case 3: | ||
1426 | if (data->type == f8000) | ||
1427 | result = 3; /* Thermostat mode */ | ||
1428 | else | ||
1429 | result = 1; /* Manual mode */ | ||
1430 | break; | ||
1431 | } | ||
1432 | |||
1433 | return sprintf(buf, "%d\n", result); | ||
1434 | } | ||
1435 | |||
1436 | static ssize_t store_pwm_enable(struct device *dev, struct device_attribute | ||
1437 | *devattr, const char *buf, size_t count) | ||
1438 | { | ||
1439 | struct f71882fg_data *data = dev_get_drvdata(dev); | ||
1440 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1441 | long val = simple_strtol(buf, NULL, 10); | ||
1442 | |||
1443 | mutex_lock(&data->update_lock); | ||
1444 | data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); | ||
1445 | /* Special case for F8000 auto PWM mode / Thermostat mode */ | ||
1446 | if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) { | ||
1447 | switch (val) { | ||
1448 | case 2: | ||
1449 | data->pwm_enable &= ~(2 << (2 * nr)); | ||
1450 | break; /* Normal auto mode */ | ||
1451 | case 3: | ||
1452 | data->pwm_enable |= 2 << (2 * nr); | ||
1453 | break; /* Thermostat mode */ | ||
1454 | default: | ||
1455 | count = -EINVAL; | ||
1456 | goto leave; | ||
1457 | } | ||
1458 | } else { | ||
1459 | switch (val) { | ||
1460 | case 1: | ||
1461 | data->pwm_enable |= 2 << (2 * nr); | ||
1462 | break; /* Manual */ | ||
1463 | case 2: | ||
1464 | data->pwm_enable &= ~(2 << (2 * nr)); | ||
1465 | break; /* Normal auto mode */ | ||
1466 | default: | ||
1467 | count = -EINVAL; | ||
1468 | goto leave; | ||
1469 | } | ||
1470 | } | ||
1471 | f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable); | ||
1472 | leave: | ||
1473 | mutex_unlock(&data->update_lock); | ||
1474 | |||
1475 | return count; | ||
1476 | } | ||
1477 | |||
1478 | static ssize_t show_pwm_auto_point_pwm(struct device *dev, | ||
1479 | struct device_attribute *devattr, | ||
1480 | char *buf) | ||
1481 | { | ||
1482 | int result; | ||
1483 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1484 | int pwm = to_sensor_dev_attr_2(devattr)->index; | ||
1485 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1486 | |||
1487 | mutex_lock(&data->update_lock); | ||
1488 | if (data->pwm_enable & (1 << (2 * pwm))) { | ||
1489 | /* PWM mode */ | ||
1490 | result = data->pwm_auto_point_pwm[pwm][point]; | ||
1491 | } else { | ||
1492 | /* RPM mode */ | ||
1493 | result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]); | ||
1494 | } | ||
1495 | mutex_unlock(&data->update_lock); | ||
1496 | |||
1497 | return sprintf(buf, "%d\n", result); | ||
1498 | } | ||
1499 | |||
1500 | static ssize_t store_pwm_auto_point_pwm(struct device *dev, | ||
1501 | struct device_attribute *devattr, | ||
1502 | const char *buf, size_t count) | ||
1503 | { | ||
1504 | struct f71882fg_data *data = dev_get_drvdata(dev); | ||
1505 | int pwm = to_sensor_dev_attr_2(devattr)->index; | ||
1506 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1507 | long val = simple_strtol(buf, NULL, 10); | ||
1508 | val = SENSORS_LIMIT(val, 0, 255); | ||
1509 | |||
1510 | mutex_lock(&data->update_lock); | ||
1511 | data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); | ||
1512 | if (data->pwm_enable & (1 << (2 * pwm))) { | ||
1513 | /* PWM mode */ | ||
1514 | } else { | ||
1515 | /* RPM mode */ | ||
1516 | if (val < 29) /* Prevent negative numbers */ | ||
1517 | val = 255; | ||
1518 | else | ||
1519 | val = (255 - val) * 32 / val; | ||
1520 | } | ||
1521 | f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val); | ||
1522 | data->pwm_auto_point_pwm[pwm][point] = val; | ||
1523 | mutex_unlock(&data->update_lock); | ||
1524 | |||
1525 | return count; | ||
1526 | } | ||
1527 | |||
1528 | static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev, | ||
1529 | struct device_attribute *devattr, | ||
1530 | char *buf) | ||
1531 | { | ||
1532 | int result = 0; | ||
1533 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1534 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1535 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1536 | |||
1537 | mutex_lock(&data->update_lock); | ||
1538 | if (nr & 1) | ||
1539 | result = data->pwm_auto_point_hyst[nr / 2] >> 4; | ||
1540 | else | ||
1541 | result = data->pwm_auto_point_hyst[nr / 2] & 0x0f; | ||
1542 | result = 1000 * (data->pwm_auto_point_temp[nr][point] - result); | ||
1543 | mutex_unlock(&data->update_lock); | ||
1544 | |||
1545 | return sprintf(buf, "%d\n", result); | ||
1546 | } | ||
1547 | |||
1548 | static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, | ||
1549 | struct device_attribute *devattr, | ||
1550 | const char *buf, size_t count) | ||
1551 | { | ||
1552 | struct f71882fg_data *data = dev_get_drvdata(dev); | ||
1553 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1554 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1555 | long val = simple_strtol(buf, NULL, 10) / 1000; | ||
1556 | u8 reg; | ||
1557 | |||
1558 | mutex_lock(&data->update_lock); | ||
1559 | data->pwm_auto_point_temp[nr][point] = | ||
1560 | f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point)); | ||
1561 | val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15, | ||
1562 | data->pwm_auto_point_temp[nr][point]); | ||
1563 | val = data->pwm_auto_point_temp[nr][point] - val; | ||
1564 | |||
1565 | reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2)); | ||
1566 | if (nr & 1) | ||
1567 | reg = (reg & 0x0f) | (val << 4); | ||
1568 | else | ||
1569 | reg = (reg & 0xf0) | val; | ||
1570 | |||
1571 | f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg); | ||
1572 | data->pwm_auto_point_hyst[nr / 2] = reg; | ||
1573 | mutex_unlock(&data->update_lock); | ||
1574 | |||
1575 | return count; | ||
1576 | } | ||
1577 | |||
1578 | static ssize_t show_pwm_interpolate(struct device *dev, | ||
1579 | struct device_attribute *devattr, char *buf) | ||
1580 | { | ||
1581 | int result; | ||
1582 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1583 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1584 | |||
1585 | result = (data->pwm_auto_point_mapping[nr] >> 4) & 1; | ||
1586 | |||
1587 | return sprintf(buf, "%d\n", result); | ||
1588 | } | ||
1589 | |||
1590 | static ssize_t store_pwm_interpolate(struct device *dev, | ||
1591 | struct device_attribute *devattr, | ||
1592 | const char *buf, size_t count) | ||
1593 | { | ||
1594 | struct f71882fg_data *data = dev_get_drvdata(dev); | ||
1595 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1596 | unsigned long val = simple_strtoul(buf, NULL, 10); | ||
1597 | |||
1598 | mutex_lock(&data->update_lock); | ||
1599 | data->pwm_auto_point_mapping[nr] = | ||
1600 | f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr)); | ||
1601 | if (val) | ||
1602 | val = data->pwm_auto_point_mapping[nr] | (1 << 4); | ||
1603 | else | ||
1604 | val = data->pwm_auto_point_mapping[nr] & (~(1 << 4)); | ||
1605 | f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val); | ||
1606 | data->pwm_auto_point_mapping[nr] = val; | ||
1607 | mutex_unlock(&data->update_lock); | ||
1608 | |||
1609 | return count; | ||
1610 | } | ||
1611 | |||
1612 | static ssize_t show_pwm_auto_point_channel(struct device *dev, | ||
1613 | struct device_attribute *devattr, | ||
1614 | char *buf) | ||
1615 | { | ||
1616 | int result; | ||
1617 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1618 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1619 | int temp_start = (data->type == f8000) ? 0 : 1; | ||
1620 | |||
1621 | result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - temp_start); | ||
1622 | |||
1623 | return sprintf(buf, "%d\n", result); | ||
1624 | } | ||
1625 | |||
1626 | static ssize_t store_pwm_auto_point_channel(struct device *dev, | ||
1627 | struct device_attribute *devattr, | ||
1628 | const char *buf, size_t count) | ||
1629 | { | ||
1630 | struct f71882fg_data *data = dev_get_drvdata(dev); | ||
1631 | int nr = to_sensor_dev_attr_2(devattr)->index; | ||
1632 | int temp_start = (data->type == f8000) ? 0 : 1; | ||
1633 | long val = simple_strtol(buf, NULL, 10); | ||
1634 | |||
1635 | switch (val) { | ||
1636 | case 1: | ||
1637 | val = 0; | ||
1638 | break; | ||
1639 | case 2: | ||
1640 | val = 1; | ||
1641 | break; | ||
1642 | case 4: | ||
1643 | val = 2; | ||
1644 | break; | ||
1645 | default: | ||
1646 | return -EINVAL; | ||
1647 | } | ||
1648 | val += temp_start; | ||
1649 | mutex_lock(&data->update_lock); | ||
1650 | data->pwm_auto_point_mapping[nr] = | ||
1651 | f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr)); | ||
1652 | val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val; | ||
1653 | f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val); | ||
1654 | data->pwm_auto_point_mapping[nr] = val; | ||
1655 | mutex_unlock(&data->update_lock); | ||
1656 | |||
1657 | return count; | ||
1658 | } | ||
1659 | |||
1660 | static ssize_t show_pwm_auto_point_temp(struct device *dev, | ||
1661 | struct device_attribute *devattr, | ||
1662 | char *buf) | ||
1663 | { | ||
1664 | int result; | ||
1665 | struct f71882fg_data *data = f71882fg_update_device(dev); | ||
1666 | int pwm = to_sensor_dev_attr_2(devattr)->index; | ||
1667 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1668 | |||
1669 | result = data->pwm_auto_point_temp[pwm][point]; | ||
1670 | return sprintf(buf, "%d\n", 1000 * result); | ||
1671 | } | ||
1672 | |||
1673 | static ssize_t store_pwm_auto_point_temp(struct device *dev, | ||
1674 | struct device_attribute *devattr, | ||
1675 | const char *buf, size_t count) | ||
1676 | { | ||
1677 | struct f71882fg_data *data = dev_get_drvdata(dev); | ||
1678 | int pwm = to_sensor_dev_attr_2(devattr)->index; | ||
1679 | int point = to_sensor_dev_attr_2(devattr)->nr; | ||
1680 | long val = simple_strtol(buf, NULL, 10) / 1000; | ||
1681 | val = SENSORS_LIMIT(val, 0, 255); | ||
1682 | |||
1683 | mutex_lock(&data->update_lock); | ||
1684 | f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val); | ||
1685 | data->pwm_auto_point_temp[pwm][point] = val; | ||
1686 | mutex_unlock(&data->update_lock); | ||
1687 | |||
1688 | return count; | ||
1689 | } | ||
1690 | |||
736 | static ssize_t show_name(struct device *dev, struct device_attribute *devattr, | 1691 | static ssize_t show_name(struct device *dev, struct device_attribute *devattr, |
737 | char *buf) | 1692 | char *buf) |
738 | { | 1693 | { |
739 | return sprintf(buf, DRVNAME "\n"); | 1694 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1695 | return sprintf(buf, "%s\n", f71882fg_names[data->type]); | ||
740 | } | 1696 | } |
741 | 1697 | ||
1698 | static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev, | ||
1699 | struct sensor_device_attribute_2 *attr, int count) | ||
1700 | { | ||
1701 | int err, i; | ||
1702 | |||
1703 | for (i = 0; i < count; i++) { | ||
1704 | err = device_create_file(&pdev->dev, &attr[i].dev_attr); | ||
1705 | if (err) | ||
1706 | return err; | ||
1707 | } | ||
1708 | return 0; | ||
1709 | } | ||
742 | 1710 | ||
743 | static int __devinit f71882fg_probe(struct platform_device * pdev) | 1711 | static int __devinit f71882fg_probe(struct platform_device *pdev) |
744 | { | 1712 | { |
745 | struct f71882fg_data *data; | 1713 | struct f71882fg_data *data; |
746 | int err, i; | 1714 | struct f71882fg_sio_data *sio_data = pdev->dev.platform_data; |
1715 | int err, i, nr_fans = (sio_data->type == f71882fg) ? 4 : 3; | ||
747 | u8 start_reg; | 1716 | u8 start_reg; |
748 | 1717 | ||
749 | if (!(data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL))) | 1718 | data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL); |
1719 | if (!data) | ||
750 | return -ENOMEM; | 1720 | return -ENOMEM; |
751 | 1721 | ||
752 | data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; | 1722 | data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; |
1723 | data->type = sio_data->type; | ||
753 | mutex_init(&data->update_lock); | 1724 | mutex_init(&data->update_lock); |
754 | platform_set_drvdata(pdev, data); | 1725 | platform_set_drvdata(pdev, data); |
755 | 1726 | ||
756 | /* Register sysfs interface files */ | 1727 | start_reg = f71882fg_read8(data, F71882FG_REG_START); |
757 | for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) { | 1728 | if (start_reg & 0x04) { |
758 | err = device_create_file(&pdev->dev, &f71882fg_dev_attr[i]); | 1729 | dev_warn(&pdev->dev, "Hardware monitor is powered down\n"); |
759 | if (err) | 1730 | err = -ENODEV; |
760 | goto exit_unregister_sysfs; | 1731 | goto exit_free; |
1732 | } | ||
1733 | if (!(start_reg & 0x03)) { | ||
1734 | dev_warn(&pdev->dev, "Hardware monitoring not activated\n"); | ||
1735 | err = -ENODEV; | ||
1736 | goto exit_free; | ||
761 | } | 1737 | } |
762 | 1738 | ||
763 | start_reg = f71882fg_read8(data, F71882FG_REG_START); | 1739 | data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); |
1740 | /* If it is a 71862 and the fan / pwm part is enabled sanity check | ||
1741 | the pwm settings */ | ||
1742 | if (data->type == f71862fg && (start_reg & 0x02)) { | ||
1743 | if ((data->pwm_enable & 0x15) != 0x15) { | ||
1744 | dev_err(&pdev->dev, | ||
1745 | "Invalid (reserved) pwm settings: 0x%02x\n", | ||
1746 | (unsigned int)data->pwm_enable); | ||
1747 | err = -ENODEV; | ||
1748 | goto exit_free; | ||
1749 | } | ||
1750 | } | ||
1751 | |||
1752 | /* Register sysfs interface files */ | ||
1753 | err = device_create_file(&pdev->dev, &dev_attr_name); | ||
1754 | if (err) | ||
1755 | goto exit_unregister_sysfs; | ||
1756 | |||
764 | if (start_reg & 0x01) { | 1757 | if (start_reg & 0x01) { |
765 | for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) { | 1758 | switch (data->type) { |
766 | err = device_create_file(&pdev->dev, | 1759 | case f71882fg: |
767 | &f71882fg_in_temp_attr[i].dev_attr); | 1760 | err = f71882fg_create_sysfs_files(pdev, |
1761 | f71882fg_in_temp_attr, | ||
1762 | ARRAY_SIZE(f71882fg_in_temp_attr)); | ||
768 | if (err) | 1763 | if (err) |
769 | goto exit_unregister_sysfs; | 1764 | goto exit_unregister_sysfs; |
1765 | /* fall through! */ | ||
1766 | case f71862fg: | ||
1767 | err = f71882fg_create_sysfs_files(pdev, | ||
1768 | f718x2fg_in_temp_attr, | ||
1769 | ARRAY_SIZE(f718x2fg_in_temp_attr)); | ||
1770 | break; | ||
1771 | case f8000: | ||
1772 | err = f71882fg_create_sysfs_files(pdev, | ||
1773 | f8000_in_temp_attr, | ||
1774 | ARRAY_SIZE(f8000_in_temp_attr)); | ||
1775 | break; | ||
770 | } | 1776 | } |
1777 | if (err) | ||
1778 | goto exit_unregister_sysfs; | ||
771 | } | 1779 | } |
772 | 1780 | ||
773 | if (start_reg & 0x02) { | 1781 | if (start_reg & 0x02) { |
774 | for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) { | 1782 | err = f71882fg_create_sysfs_files(pdev, fxxxx_fan_attr, |
775 | err = device_create_file(&pdev->dev, | 1783 | ARRAY_SIZE(fxxxx_fan_attr)); |
776 | &f71882fg_fan_attr[i].dev_attr); | 1784 | if (err) |
777 | if (err) | 1785 | goto exit_unregister_sysfs; |
778 | goto exit_unregister_sysfs; | 1786 | |
1787 | switch (data->type) { | ||
1788 | case f71862fg: | ||
1789 | err = f71882fg_create_sysfs_files(pdev, | ||
1790 | f71862fg_fan_attr, | ||
1791 | ARRAY_SIZE(f71862fg_fan_attr)); | ||
1792 | break; | ||
1793 | case f71882fg: | ||
1794 | err = f71882fg_create_sysfs_files(pdev, | ||
1795 | f71882fg_fan_attr, | ||
1796 | ARRAY_SIZE(f71882fg_fan_attr)); | ||
1797 | break; | ||
1798 | case f8000: | ||
1799 | err = f71882fg_create_sysfs_files(pdev, | ||
1800 | f8000_fan_attr, | ||
1801 | ARRAY_SIZE(f8000_fan_attr)); | ||
1802 | break; | ||
779 | } | 1803 | } |
1804 | if (err) | ||
1805 | goto exit_unregister_sysfs; | ||
1806 | |||
1807 | for (i = 0; i < nr_fans; i++) | ||
1808 | dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1, | ||
1809 | (data->pwm_enable & (1 << 2 * i)) ? | ||
1810 | "duty-cycle" : "RPM"); | ||
780 | } | 1811 | } |
781 | 1812 | ||
782 | data->hwmon_dev = hwmon_device_register(&pdev->dev); | 1813 | data->hwmon_dev = hwmon_device_register(&pdev->dev); |
783 | if (IS_ERR(data->hwmon_dev)) { | 1814 | if (IS_ERR(data->hwmon_dev)) { |
784 | err = PTR_ERR(data->hwmon_dev); | 1815 | err = PTR_ERR(data->hwmon_dev); |
1816 | data->hwmon_dev = NULL; | ||
785 | goto exit_unregister_sysfs; | 1817 | goto exit_unregister_sysfs; |
786 | } | 1818 | } |
787 | 1819 | ||
788 | return 0; | 1820 | return 0; |
789 | 1821 | ||
790 | exit_unregister_sysfs: | 1822 | exit_unregister_sysfs: |
791 | for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) | 1823 | f71882fg_remove(pdev); /* Will unregister the sysfs files for us */ |
792 | device_remove_file(&pdev->dev, &f71882fg_dev_attr[i]); | 1824 | return err; /* f71882fg_remove() also frees our data */ |
793 | 1825 | exit_free: | |
794 | for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) | ||
795 | device_remove_file(&pdev->dev, | ||
796 | &f71882fg_in_temp_attr[i].dev_attr); | ||
797 | |||
798 | for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) | ||
799 | device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); | ||
800 | |||
801 | kfree(data); | 1826 | kfree(data); |
802 | |||
803 | return err; | 1827 | return err; |
804 | } | 1828 | } |
805 | 1829 | ||
806 | static int __devexit f71882fg_remove(struct platform_device *pdev) | 1830 | static int f71882fg_remove(struct platform_device *pdev) |
807 | { | 1831 | { |
808 | int i; | 1832 | int i; |
809 | struct f71882fg_data *data = platform_get_drvdata(pdev); | 1833 | struct f71882fg_data *data = platform_get_drvdata(pdev); |
810 | 1834 | ||
811 | platform_set_drvdata(pdev, NULL); | 1835 | platform_set_drvdata(pdev, NULL); |
812 | hwmon_device_unregister(data->hwmon_dev); | 1836 | if (data->hwmon_dev) |
1837 | hwmon_device_unregister(data->hwmon_dev); | ||
1838 | |||
1839 | /* Note we are not looping over all attr arrays we have as the ones | ||
1840 | below are supersets of the ones skipped. */ | ||
1841 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
813 | 1842 | ||
814 | for (i = 0; i < ARRAY_SIZE(f71882fg_dev_attr); i++) | 1843 | for (i = 0; i < ARRAY_SIZE(f718x2fg_in_temp_attr); i++) |
815 | device_remove_file(&pdev->dev, &f71882fg_dev_attr[i]); | 1844 | device_remove_file(&pdev->dev, |
1845 | &f718x2fg_in_temp_attr[i].dev_attr); | ||
816 | 1846 | ||
817 | for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) | 1847 | for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++) |
818 | device_remove_file(&pdev->dev, | 1848 | device_remove_file(&pdev->dev, |
819 | &f71882fg_in_temp_attr[i].dev_attr); | 1849 | &f71882fg_in_temp_attr[i].dev_attr); |
820 | 1850 | ||
1851 | for (i = 0; i < ARRAY_SIZE(fxxxx_fan_attr); i++) | ||
1852 | device_remove_file(&pdev->dev, &fxxxx_fan_attr[i].dev_attr); | ||
1853 | |||
821 | for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) | 1854 | for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++) |
822 | device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); | 1855 | device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr); |
823 | 1856 | ||
1857 | for (i = 0; i < ARRAY_SIZE(f8000_fan_attr); i++) | ||
1858 | device_remove_file(&pdev->dev, &f8000_fan_attr[i].dev_attr); | ||
1859 | |||
824 | kfree(data); | 1860 | kfree(data); |
825 | 1861 | ||
826 | return 0; | 1862 | return 0; |
827 | } | 1863 | } |
828 | 1864 | ||
829 | static int __init f71882fg_find(int sioaddr, unsigned short *address) | 1865 | static int __init f71882fg_find(int sioaddr, unsigned short *address, |
1866 | struct f71882fg_sio_data *sio_data) | ||
830 | { | 1867 | { |
831 | int err = -ENODEV; | 1868 | int err = -ENODEV; |
832 | u16 devid; | 1869 | u16 devid; |
833 | u8 start_reg; | ||
834 | struct f71882fg_data data; | ||
835 | 1870 | ||
836 | superio_enter(sioaddr); | 1871 | superio_enter(sioaddr); |
837 | 1872 | ||
@@ -842,7 +1877,17 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address) | |||
842 | } | 1877 | } |
843 | 1878 | ||
844 | devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); | 1879 | devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); |
845 | if (devid != SIO_F71882_ID) { | 1880 | switch (devid) { |
1881 | case SIO_F71862_ID: | ||
1882 | sio_data->type = f71862fg; | ||
1883 | break; | ||
1884 | case SIO_F71882_ID: | ||
1885 | sio_data->type = f71882fg; | ||
1886 | break; | ||
1887 | case SIO_F8000_ID: | ||
1888 | sio_data->type = f8000; | ||
1889 | break; | ||
1890 | default: | ||
846 | printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); | 1891 | printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n"); |
847 | goto exit; | 1892 | goto exit; |
848 | } | 1893 | } |
@@ -861,24 +1906,17 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address) | |||
861 | } | 1906 | } |
862 | *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ | 1907 | *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ |
863 | 1908 | ||
864 | data.addr = *address; | ||
865 | start_reg = f71882fg_read8(&data, F71882FG_REG_START); | ||
866 | if (!(start_reg & 0x03)) { | ||
867 | printk(KERN_WARNING DRVNAME | ||
868 | ": Hardware monitoring not activated\n"); | ||
869 | goto exit; | ||
870 | } | ||
871 | |||
872 | err = 0; | 1909 | err = 0; |
873 | printk(KERN_INFO DRVNAME ": Found F71882FG chip at %#x, revision %d\n", | 1910 | printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %d\n", |
874 | (unsigned int)*address, | 1911 | f71882fg_names[sio_data->type], (unsigned int)*address, |
875 | (int)superio_inb(sioaddr, SIO_REG_DEVREV)); | 1912 | (int)superio_inb(sioaddr, SIO_REG_DEVREV)); |
876 | exit: | 1913 | exit: |
877 | superio_exit(sioaddr); | 1914 | superio_exit(sioaddr); |
878 | return err; | 1915 | return err; |
879 | } | 1916 | } |
880 | 1917 | ||
881 | static int __init f71882fg_device_add(unsigned short address) | 1918 | static int __init f71882fg_device_add(unsigned short address, |
1919 | const struct f71882fg_sio_data *sio_data) | ||
882 | { | 1920 | { |
883 | struct resource res = { | 1921 | struct resource res = { |
884 | .start = address, | 1922 | .start = address, |
@@ -892,12 +1930,23 @@ static int __init f71882fg_device_add(unsigned short address) | |||
892 | return -ENOMEM; | 1930 | return -ENOMEM; |
893 | 1931 | ||
894 | res.name = f71882fg_pdev->name; | 1932 | res.name = f71882fg_pdev->name; |
1933 | err = acpi_check_resource_conflict(&res); | ||
1934 | if (err) | ||
1935 | return err; | ||
1936 | |||
895 | err = platform_device_add_resources(f71882fg_pdev, &res, 1); | 1937 | err = platform_device_add_resources(f71882fg_pdev, &res, 1); |
896 | if (err) { | 1938 | if (err) { |
897 | printk(KERN_ERR DRVNAME ": Device resource addition failed\n"); | 1939 | printk(KERN_ERR DRVNAME ": Device resource addition failed\n"); |
898 | goto exit_device_put; | 1940 | goto exit_device_put; |
899 | } | 1941 | } |
900 | 1942 | ||
1943 | err = platform_device_add_data(f71882fg_pdev, sio_data, | ||
1944 | sizeof(struct f71882fg_sio_data)); | ||
1945 | if (err) { | ||
1946 | printk(KERN_ERR DRVNAME ": Platform data allocation failed\n"); | ||
1947 | goto exit_device_put; | ||
1948 | } | ||
1949 | |||
901 | err = platform_device_add(f71882fg_pdev); | 1950 | err = platform_device_add(f71882fg_pdev); |
902 | if (err) { | 1951 | if (err) { |
903 | printk(KERN_ERR DRVNAME ": Device addition failed\n"); | 1952 | printk(KERN_ERR DRVNAME ": Device addition failed\n"); |
@@ -916,14 +1965,20 @@ static int __init f71882fg_init(void) | |||
916 | { | 1965 | { |
917 | int err = -ENODEV; | 1966 | int err = -ENODEV; |
918 | unsigned short address; | 1967 | unsigned short address; |
1968 | struct f71882fg_sio_data sio_data; | ||
1969 | |||
1970 | memset(&sio_data, 0, sizeof(sio_data)); | ||
919 | 1971 | ||
920 | if (f71882fg_find(0x2e, &address) && f71882fg_find(0x4e, &address)) | 1972 | if (f71882fg_find(0x2e, &address, &sio_data) && |
1973 | f71882fg_find(0x4e, &address, &sio_data)) | ||
921 | goto exit; | 1974 | goto exit; |
922 | 1975 | ||
923 | if ((err = platform_driver_register(&f71882fg_driver))) | 1976 | err = platform_driver_register(&f71882fg_driver); |
1977 | if (err) | ||
924 | goto exit; | 1978 | goto exit; |
925 | 1979 | ||
926 | if ((err = f71882fg_device_add(address))) | 1980 | err = f71882fg_device_add(address, &sio_data); |
1981 | if (err) | ||
927 | goto exit_driver; | 1982 | goto exit_driver; |
928 | 1983 | ||
929 | return 0; | 1984 | return 0; |
@@ -941,7 +1996,7 @@ static void __exit f71882fg_exit(void) | |||
941 | } | 1996 | } |
942 | 1997 | ||
943 | MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver"); | 1998 | MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver"); |
944 | MODULE_AUTHOR("Hans Edgington (hans@edgington.nl)"); | 1999 | MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)"); |
945 | MODULE_LICENSE("GPL"); | 2000 | MODULE_LICENSE("GPL"); |
946 | 2001 | ||
947 | module_init(f71882fg_init); | 2002 | module_init(f71882fg_init); |
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index 967170368933..d07f4ef75092 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* fschmd.c | 1 | /* fschmd.c |
2 | * | 2 | * |
3 | * Copyright (C) 2007 Hans de Goede <j.w.r.degoede@hhs.nl> | 3 | * Copyright (C) 2007,2008 Hans de Goede <hdegoede@redhat.com> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -42,11 +42,20 @@ | |||
42 | #include <linux/mutex.h> | 42 | #include <linux/mutex.h> |
43 | #include <linux/sysfs.h> | 43 | #include <linux/sysfs.h> |
44 | #include <linux/dmi.h> | 44 | #include <linux/dmi.h> |
45 | #include <linux/fs.h> | ||
46 | #include <linux/watchdog.h> | ||
47 | #include <linux/miscdevice.h> | ||
48 | #include <linux/uaccess.h> | ||
49 | #include <linux/kref.h> | ||
45 | 50 | ||
46 | /* Addresses to scan */ | 51 | /* Addresses to scan */ |
47 | static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; | 52 | static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; |
48 | 53 | ||
49 | /* Insmod parameters */ | 54 | /* Insmod parameters */ |
55 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
56 | module_param(nowayout, int, 0); | ||
57 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | ||
58 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
50 | I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd); | 59 | I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd); |
51 | 60 | ||
52 | /* | 61 | /* |
@@ -63,19 +72,26 @@ I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd); | |||
63 | #define FSCHMD_REG_EVENT_STATE 0x04 | 72 | #define FSCHMD_REG_EVENT_STATE 0x04 |
64 | #define FSCHMD_REG_CONTROL 0x05 | 73 | #define FSCHMD_REG_CONTROL 0x05 |
65 | 74 | ||
66 | #define FSCHMD_CONTROL_ALERT_LED_MASK 0x01 | 75 | #define FSCHMD_CONTROL_ALERT_LED 0x01 |
67 | 76 | ||
68 | /* watchdog (support to be implemented) */ | 77 | /* watchdog */ |
69 | #define FSCHMD_REG_WDOG_PRESET 0x28 | 78 | #define FSCHMD_REG_WDOG_PRESET 0x28 |
70 | #define FSCHMD_REG_WDOG_STATE 0x23 | 79 | #define FSCHMD_REG_WDOG_STATE 0x23 |
71 | #define FSCHMD_REG_WDOG_CONTROL 0x21 | 80 | #define FSCHMD_REG_WDOG_CONTROL 0x21 |
72 | 81 | ||
82 | #define FSCHMD_WDOG_CONTROL_TRIGGER 0x10 | ||
83 | #define FSCHMD_WDOG_CONTROL_STARTED 0x10 /* the same as trigger */ | ||
84 | #define FSCHMD_WDOG_CONTROL_STOP 0x20 | ||
85 | #define FSCHMD_WDOG_CONTROL_RESOLUTION 0x40 | ||
86 | |||
87 | #define FSCHMD_WDOG_STATE_CARDRESET 0x02 | ||
88 | |||
73 | /* voltages, weird order is to keep the same order as the old drivers */ | 89 | /* voltages, weird order is to keep the same order as the old drivers */ |
74 | static const u8 FSCHMD_REG_VOLT[3] = { 0x45, 0x42, 0x48 }; | 90 | static const u8 FSCHMD_REG_VOLT[3] = { 0x45, 0x42, 0x48 }; |
75 | 91 | ||
76 | /* minimum pwm at which the fan is driven (pwm can by increased depending on | 92 | /* minimum pwm at which the fan is driven (pwm can by increased depending on |
77 | the temp. Notice that for the scy some fans share there minimum speed. | 93 | the temp. Notice that for the scy some fans share there minimum speed. |
78 | Also notice that with the scy the sensor order is different then with the | 94 | Also notice that with the scy the sensor order is different than with the |
79 | other chips, this order was in the 2.4 driver and kept for consistency. */ | 95 | other chips, this order was in the 2.4 driver and kept for consistency. */ |
80 | static const u8 FSCHMD_REG_FAN_MIN[5][6] = { | 96 | static const u8 FSCHMD_REG_FAN_MIN[5][6] = { |
81 | { 0x55, 0x65 }, /* pos */ | 97 | { 0x55, 0x65 }, /* pos */ |
@@ -115,8 +131,8 @@ static const u8 FSCHMD_REG_FAN_RIPPLE[5][6] = { | |||
115 | static const int FSCHMD_NO_FAN_SENSORS[5] = { 3, 3, 6, 4, 5 }; | 131 | static const int FSCHMD_NO_FAN_SENSORS[5] = { 3, 3, 6, 4, 5 }; |
116 | 132 | ||
117 | /* Fan status register bitmasks */ | 133 | /* Fan status register bitmasks */ |
118 | #define FSCHMD_FAN_ALARM_MASK 0x04 /* called fault by FSC! */ | 134 | #define FSCHMD_FAN_ALARM 0x04 /* called fault by FSC! */ |
119 | #define FSCHMD_FAN_NOT_PRESENT_MASK 0x08 /* not documented */ | 135 | #define FSCHMD_FAN_NOT_PRESENT 0x08 /* not documented */ |
120 | 136 | ||
121 | 137 | ||
122 | /* actual temperature registers */ | 138 | /* actual temperature registers */ |
@@ -158,14 +174,11 @@ static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; */ | |||
158 | static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; | 174 | static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; |
159 | 175 | ||
160 | /* temp status register bitmasks */ | 176 | /* temp status register bitmasks */ |
161 | #define FSCHMD_TEMP_WORKING_MASK 0x01 | 177 | #define FSCHMD_TEMP_WORKING 0x01 |
162 | #define FSCHMD_TEMP_ALERT_MASK 0x02 | 178 | #define FSCHMD_TEMP_ALERT 0x02 |
163 | /* there only really is an alarm if the sensor is working and alert == 1 */ | 179 | /* there only really is an alarm if the sensor is working and alert == 1 */ |
164 | #define FSCHMD_TEMP_ALARM_MASK \ | 180 | #define FSCHMD_TEMP_ALARM_MASK \ |
165 | (FSCHMD_TEMP_WORKING_MASK | FSCHMD_TEMP_ALERT_MASK) | 181 | (FSCHMD_TEMP_WORKING | FSCHMD_TEMP_ALERT) |
166 | |||
167 | /* our driver name */ | ||
168 | #define FSCHMD_NAME "fschmd" | ||
169 | 182 | ||
170 | /* | 183 | /* |
171 | * Functions declarations | 184 | * Functions declarations |
@@ -195,7 +208,7 @@ MODULE_DEVICE_TABLE(i2c, fschmd_id); | |||
195 | static struct i2c_driver fschmd_driver = { | 208 | static struct i2c_driver fschmd_driver = { |
196 | .class = I2C_CLASS_HWMON, | 209 | .class = I2C_CLASS_HWMON, |
197 | .driver = { | 210 | .driver = { |
198 | .name = FSCHMD_NAME, | 211 | .name = "fschmd", |
199 | }, | 212 | }, |
200 | .probe = fschmd_probe, | 213 | .probe = fschmd_probe, |
201 | .remove = fschmd_remove, | 214 | .remove = fschmd_remove, |
@@ -209,14 +222,26 @@ static struct i2c_driver fschmd_driver = { | |||
209 | */ | 222 | */ |
210 | 223 | ||
211 | struct fschmd_data { | 224 | struct fschmd_data { |
225 | struct i2c_client *client; | ||
212 | struct device *hwmon_dev; | 226 | struct device *hwmon_dev; |
213 | struct mutex update_lock; | 227 | struct mutex update_lock; |
228 | struct mutex watchdog_lock; | ||
229 | struct list_head list; /* member of the watchdog_data_list */ | ||
230 | struct kref kref; | ||
231 | struct miscdevice watchdog_miscdev; | ||
214 | int kind; | 232 | int kind; |
233 | unsigned long watchdog_is_open; | ||
234 | char watchdog_expect_close; | ||
235 | char watchdog_name[10]; /* must be unique to avoid sysfs conflict */ | ||
215 | char valid; /* zero until following fields are valid */ | 236 | char valid; /* zero until following fields are valid */ |
216 | unsigned long last_updated; /* in jiffies */ | 237 | unsigned long last_updated; /* in jiffies */ |
217 | 238 | ||
218 | /* register values */ | 239 | /* register values */ |
240 | u8 revision; /* chip revision */ | ||
219 | u8 global_control; /* global control register */ | 241 | u8 global_control; /* global control register */ |
242 | u8 watchdog_control; /* watchdog control register */ | ||
243 | u8 watchdog_state; /* watchdog status register */ | ||
244 | u8 watchdog_preset; /* watchdog counter preset on trigger val */ | ||
220 | u8 volt[3]; /* 12, 5, battery voltage */ | 245 | u8 volt[3]; /* 12, 5, battery voltage */ |
221 | u8 temp_act[5]; /* temperature */ | 246 | u8 temp_act[5]; /* temperature */ |
222 | u8 temp_status[5]; /* status of sensor */ | 247 | u8 temp_status[5]; /* status of sensor */ |
@@ -228,11 +253,28 @@ struct fschmd_data { | |||
228 | }; | 253 | }; |
229 | 254 | ||
230 | /* Global variables to hold information read from special DMI tables, which are | 255 | /* Global variables to hold information read from special DMI tables, which are |
231 | available on FSC machines with an fscher or later chip. */ | 256 | available on FSC machines with an fscher or later chip. There is no need to |
257 | protect these with a lock as they are only modified from our attach function | ||
258 | which always gets called with the i2c-core lock held and never accessed | ||
259 | before the attach function is done with them. */ | ||
232 | static int dmi_mult[3] = { 490, 200, 100 }; | 260 | static int dmi_mult[3] = { 490, 200, 100 }; |
233 | static int dmi_offset[3] = { 0, 0, 0 }; | 261 | static int dmi_offset[3] = { 0, 0, 0 }; |
234 | static int dmi_vref = -1; | 262 | static int dmi_vref = -1; |
235 | 263 | ||
264 | /* Somewhat ugly :( global data pointer list with all fschmd devices, so that | ||
265 | we can find our device data as when using misc_register there is no other | ||
266 | method to get to ones device data from the open fop. */ | ||
267 | static LIST_HEAD(watchdog_data_list); | ||
268 | /* Note this lock not only protect list access, but also data.kref access */ | ||
269 | static DEFINE_MUTEX(watchdog_data_mutex); | ||
270 | |||
271 | /* Release our data struct when we're detached from the i2c client *and* all | ||
272 | references to our watchdog device are released */ | ||
273 | static void fschmd_release_resources(struct kref *ref) | ||
274 | { | ||
275 | struct fschmd_data *data = container_of(ref, struct fschmd_data, kref); | ||
276 | kfree(data); | ||
277 | } | ||
236 | 278 | ||
237 | /* | 279 | /* |
238 | * Sysfs attr show / store functions | 280 | * Sysfs attr show / store functions |
@@ -300,7 +342,7 @@ static ssize_t show_temp_fault(struct device *dev, | |||
300 | struct fschmd_data *data = fschmd_update_device(dev); | 342 | struct fschmd_data *data = fschmd_update_device(dev); |
301 | 343 | ||
302 | /* bit 0 set means sensor working ok, so no fault! */ | 344 | /* bit 0 set means sensor working ok, so no fault! */ |
303 | if (data->temp_status[index] & FSCHMD_TEMP_WORKING_MASK) | 345 | if (data->temp_status[index] & FSCHMD_TEMP_WORKING) |
304 | return sprintf(buf, "0\n"); | 346 | return sprintf(buf, "0\n"); |
305 | else | 347 | else |
306 | return sprintf(buf, "1\n"); | 348 | return sprintf(buf, "1\n"); |
@@ -385,7 +427,7 @@ static ssize_t show_fan_alarm(struct device *dev, | |||
385 | int index = to_sensor_dev_attr(devattr)->index; | 427 | int index = to_sensor_dev_attr(devattr)->index; |
386 | struct fschmd_data *data = fschmd_update_device(dev); | 428 | struct fschmd_data *data = fschmd_update_device(dev); |
387 | 429 | ||
388 | if (data->fan_status[index] & FSCHMD_FAN_ALARM_MASK) | 430 | if (data->fan_status[index] & FSCHMD_FAN_ALARM) |
389 | return sprintf(buf, "1\n"); | 431 | return sprintf(buf, "1\n"); |
390 | else | 432 | else |
391 | return sprintf(buf, "0\n"); | 433 | return sprintf(buf, "0\n"); |
@@ -397,7 +439,7 @@ static ssize_t show_fan_fault(struct device *dev, | |||
397 | int index = to_sensor_dev_attr(devattr)->index; | 439 | int index = to_sensor_dev_attr(devattr)->index; |
398 | struct fschmd_data *data = fschmd_update_device(dev); | 440 | struct fschmd_data *data = fschmd_update_device(dev); |
399 | 441 | ||
400 | if (data->fan_status[index] & FSCHMD_FAN_NOT_PRESENT_MASK) | 442 | if (data->fan_status[index] & FSCHMD_FAN_NOT_PRESENT) |
401 | return sprintf(buf, "1\n"); | 443 | return sprintf(buf, "1\n"); |
402 | else | 444 | else |
403 | return sprintf(buf, "0\n"); | 445 | return sprintf(buf, "0\n"); |
@@ -449,7 +491,7 @@ static ssize_t show_alert_led(struct device *dev, | |||
449 | { | 491 | { |
450 | struct fschmd_data *data = fschmd_update_device(dev); | 492 | struct fschmd_data *data = fschmd_update_device(dev); |
451 | 493 | ||
452 | if (data->global_control & FSCHMD_CONTROL_ALERT_LED_MASK) | 494 | if (data->global_control & FSCHMD_CONTROL_ALERT_LED) |
453 | return sprintf(buf, "1\n"); | 495 | return sprintf(buf, "1\n"); |
454 | else | 496 | else |
455 | return sprintf(buf, "0\n"); | 497 | return sprintf(buf, "0\n"); |
@@ -467,9 +509,9 @@ static ssize_t store_alert_led(struct device *dev, | |||
467 | reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL); | 509 | reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL); |
468 | 510 | ||
469 | if (v) | 511 | if (v) |
470 | reg |= FSCHMD_CONTROL_ALERT_LED_MASK; | 512 | reg |= FSCHMD_CONTROL_ALERT_LED; |
471 | else | 513 | else |
472 | reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK; | 514 | reg &= ~FSCHMD_CONTROL_ALERT_LED; |
473 | 515 | ||
474 | i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg); | 516 | i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg); |
475 | 517 | ||
@@ -551,7 +593,265 @@ static struct sensor_device_attribute fschmd_fan_attr[] = { | |||
551 | 593 | ||
552 | 594 | ||
553 | /* | 595 | /* |
554 | * Real code | 596 | * Watchdog routines |
597 | */ | ||
598 | |||
599 | static int watchdog_set_timeout(struct fschmd_data *data, int timeout) | ||
600 | { | ||
601 | int ret, resolution; | ||
602 | int kind = data->kind + 1; /* 0-x array index -> 1-x module param */ | ||
603 | |||
604 | /* 2 second or 60 second resolution? */ | ||
605 | if (timeout <= 510 || kind == fscpos || kind == fscscy) | ||
606 | resolution = 2; | ||
607 | else | ||
608 | resolution = 60; | ||
609 | |||
610 | if (timeout < resolution || timeout > (resolution * 255)) | ||
611 | return -EINVAL; | ||
612 | |||
613 | mutex_lock(&data->watchdog_lock); | ||
614 | if (!data->client) { | ||
615 | ret = -ENODEV; | ||
616 | goto leave; | ||
617 | } | ||
618 | |||
619 | if (resolution == 2) | ||
620 | data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_RESOLUTION; | ||
621 | else | ||
622 | data->watchdog_control |= FSCHMD_WDOG_CONTROL_RESOLUTION; | ||
623 | |||
624 | data->watchdog_preset = DIV_ROUND_UP(timeout, resolution); | ||
625 | |||
626 | /* Write new timeout value */ | ||
627 | i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_PRESET, | ||
628 | data->watchdog_preset); | ||
629 | /* Write new control register, do not trigger! */ | ||
630 | i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL, | ||
631 | data->watchdog_control & ~FSCHMD_WDOG_CONTROL_TRIGGER); | ||
632 | |||
633 | ret = data->watchdog_preset * resolution; | ||
634 | |||
635 | leave: | ||
636 | mutex_unlock(&data->watchdog_lock); | ||
637 | return ret; | ||
638 | } | ||
639 | |||
640 | static int watchdog_get_timeout(struct fschmd_data *data) | ||
641 | { | ||
642 | int timeout; | ||
643 | |||
644 | mutex_lock(&data->watchdog_lock); | ||
645 | if (data->watchdog_control & FSCHMD_WDOG_CONTROL_RESOLUTION) | ||
646 | timeout = data->watchdog_preset * 60; | ||
647 | else | ||
648 | timeout = data->watchdog_preset * 2; | ||
649 | mutex_unlock(&data->watchdog_lock); | ||
650 | |||
651 | return timeout; | ||
652 | } | ||
653 | |||
654 | static int watchdog_trigger(struct fschmd_data *data) | ||
655 | { | ||
656 | int ret = 0; | ||
657 | |||
658 | mutex_lock(&data->watchdog_lock); | ||
659 | if (!data->client) { | ||
660 | ret = -ENODEV; | ||
661 | goto leave; | ||
662 | } | ||
663 | |||
664 | data->watchdog_control |= FSCHMD_WDOG_CONTROL_TRIGGER; | ||
665 | i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL, | ||
666 | data->watchdog_control); | ||
667 | leave: | ||
668 | mutex_unlock(&data->watchdog_lock); | ||
669 | return ret; | ||
670 | } | ||
671 | |||
672 | static int watchdog_stop(struct fschmd_data *data) | ||
673 | { | ||
674 | int ret = 0; | ||
675 | |||
676 | mutex_lock(&data->watchdog_lock); | ||
677 | if (!data->client) { | ||
678 | ret = -ENODEV; | ||
679 | goto leave; | ||
680 | } | ||
681 | |||
682 | data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_STARTED; | ||
683 | /* Don't store the stop flag in our watchdog control register copy, as | ||
684 | its a write only bit (read always returns 0) */ | ||
685 | i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL, | ||
686 | data->watchdog_control | FSCHMD_WDOG_CONTROL_STOP); | ||
687 | leave: | ||
688 | mutex_unlock(&data->watchdog_lock); | ||
689 | return ret; | ||
690 | } | ||
691 | |||
692 | static int watchdog_open(struct inode *inode, struct file *filp) | ||
693 | { | ||
694 | struct fschmd_data *pos, *data = NULL; | ||
695 | |||
696 | /* We get called from drivers/char/misc.c with misc_mtx hold, and we | ||
697 | call misc_register() from fschmd_probe() with watchdog_data_mutex | ||
698 | hold, as misc_register() takes the misc_mtx lock, this is a possible | ||
699 | deadlock, so we use mutex_trylock here. */ | ||
700 | if (!mutex_trylock(&watchdog_data_mutex)) | ||
701 | return -ERESTARTSYS; | ||
702 | list_for_each_entry(pos, &watchdog_data_list, list) { | ||
703 | if (pos->watchdog_miscdev.minor == iminor(inode)) { | ||
704 | data = pos; | ||
705 | break; | ||
706 | } | ||
707 | } | ||
708 | /* Note we can never not have found data, so we don't check for this */ | ||
709 | kref_get(&data->kref); | ||
710 | mutex_unlock(&watchdog_data_mutex); | ||
711 | |||
712 | if (test_and_set_bit(0, &data->watchdog_is_open)) | ||
713 | return -EBUSY; | ||
714 | |||
715 | /* Start the watchdog */ | ||
716 | watchdog_trigger(data); | ||
717 | filp->private_data = data; | ||
718 | |||
719 | return nonseekable_open(inode, filp); | ||
720 | } | ||
721 | |||
722 | static int watchdog_release(struct inode *inode, struct file *filp) | ||
723 | { | ||
724 | struct fschmd_data *data = filp->private_data; | ||
725 | |||
726 | if (data->watchdog_expect_close) { | ||
727 | watchdog_stop(data); | ||
728 | data->watchdog_expect_close = 0; | ||
729 | } else { | ||
730 | watchdog_trigger(data); | ||
731 | dev_crit(&data->client->dev, | ||
732 | "unexpected close, not stopping watchdog!\n"); | ||
733 | } | ||
734 | |||
735 | clear_bit(0, &data->watchdog_is_open); | ||
736 | |||
737 | mutex_lock(&watchdog_data_mutex); | ||
738 | kref_put(&data->kref, fschmd_release_resources); | ||
739 | mutex_unlock(&watchdog_data_mutex); | ||
740 | |||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static ssize_t watchdog_write(struct file *filp, const char __user *buf, | ||
745 | size_t count, loff_t *offset) | ||
746 | { | ||
747 | size_t ret; | ||
748 | struct fschmd_data *data = filp->private_data; | ||
749 | |||
750 | if (count) { | ||
751 | if (!nowayout) { | ||
752 | size_t i; | ||
753 | |||
754 | /* Clear it in case it was set with a previous write */ | ||
755 | data->watchdog_expect_close = 0; | ||
756 | |||
757 | for (i = 0; i != count; i++) { | ||
758 | char c; | ||
759 | if (get_user(c, buf + i)) | ||
760 | return -EFAULT; | ||
761 | if (c == 'V') | ||
762 | data->watchdog_expect_close = 1; | ||
763 | } | ||
764 | } | ||
765 | ret = watchdog_trigger(data); | ||
766 | if (ret < 0) | ||
767 | return ret; | ||
768 | } | ||
769 | return count; | ||
770 | } | ||
771 | |||
772 | static int watchdog_ioctl(struct inode *inode, struct file *filp, | ||
773 | unsigned int cmd, unsigned long arg) | ||
774 | { | ||
775 | static struct watchdog_info ident = { | ||
776 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | | ||
777 | WDIOF_CARDRESET, | ||
778 | .identity = "FSC watchdog" | ||
779 | }; | ||
780 | int i, ret = 0; | ||
781 | struct fschmd_data *data = filp->private_data; | ||
782 | |||
783 | switch (cmd) { | ||
784 | case WDIOC_GETSUPPORT: | ||
785 | ident.firmware_version = data->revision; | ||
786 | if (!nowayout) | ||
787 | ident.options |= WDIOF_MAGICCLOSE; | ||
788 | if (copy_to_user((void __user *)arg, &ident, sizeof(ident))) | ||
789 | ret = -EFAULT; | ||
790 | break; | ||
791 | |||
792 | case WDIOC_GETSTATUS: | ||
793 | ret = put_user(0, (int __user *)arg); | ||
794 | break; | ||
795 | |||
796 | case WDIOC_GETBOOTSTATUS: | ||
797 | if (data->watchdog_state & FSCHMD_WDOG_STATE_CARDRESET) | ||
798 | ret = put_user(WDIOF_CARDRESET, (int __user *)arg); | ||
799 | else | ||
800 | ret = put_user(0, (int __user *)arg); | ||
801 | break; | ||
802 | |||
803 | case WDIOC_KEEPALIVE: | ||
804 | ret = watchdog_trigger(data); | ||
805 | break; | ||
806 | |||
807 | case WDIOC_GETTIMEOUT: | ||
808 | i = watchdog_get_timeout(data); | ||
809 | ret = put_user(i, (int __user *)arg); | ||
810 | break; | ||
811 | |||
812 | case WDIOC_SETTIMEOUT: | ||
813 | if (get_user(i, (int __user *)arg)) { | ||
814 | ret = -EFAULT; | ||
815 | break; | ||
816 | } | ||
817 | ret = watchdog_set_timeout(data, i); | ||
818 | if (ret > 0) | ||
819 | ret = put_user(ret, (int __user *)arg); | ||
820 | break; | ||
821 | |||
822 | case WDIOC_SETOPTIONS: | ||
823 | if (get_user(i, (int __user *)arg)) { | ||
824 | ret = -EFAULT; | ||
825 | break; | ||
826 | } | ||
827 | |||
828 | if (i & WDIOS_DISABLECARD) | ||
829 | ret = watchdog_stop(data); | ||
830 | else if (i & WDIOS_ENABLECARD) | ||
831 | ret = watchdog_trigger(data); | ||
832 | else | ||
833 | ret = -EINVAL; | ||
834 | |||
835 | break; | ||
836 | default: | ||
837 | ret = -ENOTTY; | ||
838 | } | ||
839 | |||
840 | return ret; | ||
841 | } | ||
842 | |||
843 | static struct file_operations watchdog_fops = { | ||
844 | .owner = THIS_MODULE, | ||
845 | .llseek = no_llseek, | ||
846 | .open = watchdog_open, | ||
847 | .release = watchdog_release, | ||
848 | .write = watchdog_write, | ||
849 | .ioctl = watchdog_ioctl, | ||
850 | }; | ||
851 | |||
852 | |||
853 | /* | ||
854 | * Detect, register, unregister and update device functions | ||
555 | */ | 855 | */ |
556 | 856 | ||
557 | /* DMI decode routine to read voltage scaling factors from special DMI tables, | 857 | /* DMI decode routine to read voltage scaling factors from special DMI tables, |
@@ -661,9 +961,9 @@ static int fschmd_probe(struct i2c_client *client, | |||
661 | const struct i2c_device_id *id) | 961 | const struct i2c_device_id *id) |
662 | { | 962 | { |
663 | struct fschmd_data *data; | 963 | struct fschmd_data *data; |
664 | u8 revision; | ||
665 | const char * const names[5] = { "Poseidon", "Hermes", "Scylla", | 964 | const char * const names[5] = { "Poseidon", "Hermes", "Scylla", |
666 | "Heracles", "Heimdall" }; | 965 | "Heracles", "Heimdall" }; |
966 | const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 }; | ||
667 | int i, err; | 967 | int i, err; |
668 | enum chips kind = id->driver_data; | 968 | enum chips kind = id->driver_data; |
669 | 969 | ||
@@ -673,6 +973,13 @@ static int fschmd_probe(struct i2c_client *client, | |||
673 | 973 | ||
674 | i2c_set_clientdata(client, data); | 974 | i2c_set_clientdata(client, data); |
675 | mutex_init(&data->update_lock); | 975 | mutex_init(&data->update_lock); |
976 | mutex_init(&data->watchdog_lock); | ||
977 | INIT_LIST_HEAD(&data->list); | ||
978 | kref_init(&data->kref); | ||
979 | /* Store client pointer in our data struct for watchdog usage | ||
980 | (where the client is found through a data ptr instead of the | ||
981 | otherway around) */ | ||
982 | data->client = client; | ||
676 | 983 | ||
677 | if (kind == fscpos) { | 984 | if (kind == fscpos) { |
678 | /* The Poseidon has hardwired temp limits, fill these | 985 | /* The Poseidon has hardwired temp limits, fill these |
@@ -683,16 +990,27 @@ static int fschmd_probe(struct i2c_client *client, | |||
683 | } | 990 | } |
684 | 991 | ||
685 | /* Read the special DMI table for fscher and newer chips */ | 992 | /* Read the special DMI table for fscher and newer chips */ |
686 | if (kind == fscher || kind >= fschrc) { | 993 | if ((kind == fscher || kind >= fschrc) && dmi_vref == -1) { |
687 | dmi_walk(fschmd_dmi_decode); | 994 | dmi_walk(fschmd_dmi_decode); |
688 | if (dmi_vref == -1) { | 995 | if (dmi_vref == -1) { |
689 | printk(KERN_WARNING FSCHMD_NAME | 996 | dev_warn(&client->dev, |
690 | ": Couldn't get voltage scaling factors from " | 997 | "Couldn't get voltage scaling factors from " |
691 | "BIOS DMI table, using builtin defaults\n"); | 998 | "BIOS DMI table, using builtin defaults\n"); |
692 | dmi_vref = 33; | 999 | dmi_vref = 33; |
693 | } | 1000 | } |
694 | } | 1001 | } |
695 | 1002 | ||
1003 | /* Read in some never changing registers */ | ||
1004 | data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION); | ||
1005 | data->global_control = i2c_smbus_read_byte_data(client, | ||
1006 | FSCHMD_REG_CONTROL); | ||
1007 | data->watchdog_control = i2c_smbus_read_byte_data(client, | ||
1008 | FSCHMD_REG_WDOG_CONTROL); | ||
1009 | data->watchdog_state = i2c_smbus_read_byte_data(client, | ||
1010 | FSCHMD_REG_WDOG_STATE); | ||
1011 | data->watchdog_preset = i2c_smbus_read_byte_data(client, | ||
1012 | FSCHMD_REG_WDOG_PRESET); | ||
1013 | |||
696 | /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ | 1014 | /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ |
697 | data->kind = kind - 1; | 1015 | data->kind = kind - 1; |
698 | 1016 | ||
@@ -735,9 +1053,43 @@ static int fschmd_probe(struct i2c_client *client, | |||
735 | goto exit_detach; | 1053 | goto exit_detach; |
736 | } | 1054 | } |
737 | 1055 | ||
738 | revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION); | 1056 | /* We take the data_mutex lock early so that watchdog_open() cannot |
739 | printk(KERN_INFO FSCHMD_NAME ": Detected FSC %s chip, revision: %d\n", | 1057 | run when misc_register() has completed, but we've not yet added |
740 | names[data->kind], (int) revision); | 1058 | our data to the watchdog_data_list (and set the default timeout) */ |
1059 | mutex_lock(&watchdog_data_mutex); | ||
1060 | for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) { | ||
1061 | /* Register our watchdog part */ | ||
1062 | snprintf(data->watchdog_name, sizeof(data->watchdog_name), | ||
1063 | "watchdog%c", (i == 0) ? '\0' : ('0' + i)); | ||
1064 | data->watchdog_miscdev.name = data->watchdog_name; | ||
1065 | data->watchdog_miscdev.fops = &watchdog_fops; | ||
1066 | data->watchdog_miscdev.minor = watchdog_minors[i]; | ||
1067 | err = misc_register(&data->watchdog_miscdev); | ||
1068 | if (err == -EBUSY) | ||
1069 | continue; | ||
1070 | if (err) { | ||
1071 | data->watchdog_miscdev.minor = 0; | ||
1072 | dev_err(&client->dev, | ||
1073 | "Registering watchdog chardev: %d\n", err); | ||
1074 | break; | ||
1075 | } | ||
1076 | |||
1077 | list_add(&data->list, &watchdog_data_list); | ||
1078 | watchdog_set_timeout(data, 60); | ||
1079 | dev_info(&client->dev, | ||
1080 | "Registered watchdog chardev major 10, minor: %d\n", | ||
1081 | watchdog_minors[i]); | ||
1082 | break; | ||
1083 | } | ||
1084 | if (i == ARRAY_SIZE(watchdog_minors)) { | ||
1085 | data->watchdog_miscdev.minor = 0; | ||
1086 | dev_warn(&client->dev, "Couldn't register watchdog chardev " | ||
1087 | "(due to no free minor)\n"); | ||
1088 | } | ||
1089 | mutex_unlock(&watchdog_data_mutex); | ||
1090 | |||
1091 | dev_info(&client->dev, "Detected FSC %s chip, revision: %d\n", | ||
1092 | names[data->kind], (int) data->revision); | ||
741 | 1093 | ||
742 | return 0; | 1094 | return 0; |
743 | 1095 | ||
@@ -751,6 +1103,24 @@ static int fschmd_remove(struct i2c_client *client) | |||
751 | struct fschmd_data *data = i2c_get_clientdata(client); | 1103 | struct fschmd_data *data = i2c_get_clientdata(client); |
752 | int i; | 1104 | int i; |
753 | 1105 | ||
1106 | /* Unregister the watchdog (if registered) */ | ||
1107 | if (data->watchdog_miscdev.minor) { | ||
1108 | misc_deregister(&data->watchdog_miscdev); | ||
1109 | if (data->watchdog_is_open) { | ||
1110 | dev_warn(&client->dev, | ||
1111 | "i2c client detached with watchdog open! " | ||
1112 | "Stopping watchdog.\n"); | ||
1113 | watchdog_stop(data); | ||
1114 | } | ||
1115 | mutex_lock(&watchdog_data_mutex); | ||
1116 | list_del(&data->list); | ||
1117 | mutex_unlock(&watchdog_data_mutex); | ||
1118 | /* Tell the watchdog code the client is gone */ | ||
1119 | mutex_lock(&data->watchdog_lock); | ||
1120 | data->client = NULL; | ||
1121 | mutex_unlock(&data->watchdog_lock); | ||
1122 | } | ||
1123 | |||
754 | /* Check if registered in case we're called from fschmd_detect | 1124 | /* Check if registered in case we're called from fschmd_detect |
755 | to cleanup after an error */ | 1125 | to cleanup after an error */ |
756 | if (data->hwmon_dev) | 1126 | if (data->hwmon_dev) |
@@ -765,7 +1135,10 @@ static int fschmd_remove(struct i2c_client *client) | |||
765 | device_remove_file(&client->dev, | 1135 | device_remove_file(&client->dev, |
766 | &fschmd_fan_attr[i].dev_attr); | 1136 | &fschmd_fan_attr[i].dev_attr); |
767 | 1137 | ||
768 | kfree(data); | 1138 | mutex_lock(&watchdog_data_mutex); |
1139 | kref_put(&data->kref, fschmd_release_resources); | ||
1140 | mutex_unlock(&watchdog_data_mutex); | ||
1141 | |||
769 | return 0; | 1142 | return 0; |
770 | } | 1143 | } |
771 | 1144 | ||
@@ -798,7 +1171,7 @@ static struct fschmd_data *fschmd_update_device(struct device *dev) | |||
798 | data->temp_act[i] < data->temp_max[i]) | 1171 | data->temp_act[i] < data->temp_max[i]) |
799 | i2c_smbus_write_byte_data(client, | 1172 | i2c_smbus_write_byte_data(client, |
800 | FSCHMD_REG_TEMP_STATE[data->kind][i], | 1173 | FSCHMD_REG_TEMP_STATE[data->kind][i], |
801 | FSCHMD_TEMP_ALERT_MASK); | 1174 | FSCHMD_TEMP_ALERT); |
802 | } | 1175 | } |
803 | 1176 | ||
804 | for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) { | 1177 | for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) { |
@@ -816,28 +1189,17 @@ static struct fschmd_data *fschmd_update_device(struct device *dev) | |||
816 | FSCHMD_REG_FAN_MIN[data->kind][i]); | 1189 | FSCHMD_REG_FAN_MIN[data->kind][i]); |
817 | 1190 | ||
818 | /* reset fan status if speed is back to > 0 */ | 1191 | /* reset fan status if speed is back to > 0 */ |
819 | if ((data->fan_status[i] & FSCHMD_FAN_ALARM_MASK) && | 1192 | if ((data->fan_status[i] & FSCHMD_FAN_ALARM) && |
820 | data->fan_act[i]) | 1193 | data->fan_act[i]) |
821 | i2c_smbus_write_byte_data(client, | 1194 | i2c_smbus_write_byte_data(client, |
822 | FSCHMD_REG_FAN_STATE[data->kind][i], | 1195 | FSCHMD_REG_FAN_STATE[data->kind][i], |
823 | FSCHMD_FAN_ALARM_MASK); | 1196 | FSCHMD_FAN_ALARM); |
824 | } | 1197 | } |
825 | 1198 | ||
826 | for (i = 0; i < 3; i++) | 1199 | for (i = 0; i < 3; i++) |
827 | data->volt[i] = i2c_smbus_read_byte_data(client, | 1200 | data->volt[i] = i2c_smbus_read_byte_data(client, |
828 | FSCHMD_REG_VOLT[i]); | 1201 | FSCHMD_REG_VOLT[i]); |
829 | 1202 | ||
830 | data->global_control = i2c_smbus_read_byte_data(client, | ||
831 | FSCHMD_REG_CONTROL); | ||
832 | |||
833 | /* To be implemented in the future | ||
834 | data->watchdog[0] = i2c_smbus_read_byte_data(client, | ||
835 | FSCHMD_REG_WDOG_PRESET); | ||
836 | data->watchdog[1] = i2c_smbus_read_byte_data(client, | ||
837 | FSCHMD_REG_WDOG_STATE); | ||
838 | data->watchdog[2] = i2c_smbus_read_byte_data(client, | ||
839 | FSCHMD_REG_WDOG_CONTROL); */ | ||
840 | |||
841 | data->last_updated = jiffies; | 1203 | data->last_updated = jiffies; |
842 | data->valid = 1; | 1204 | data->valid = 1; |
843 | } | 1205 | } |
@@ -857,7 +1219,7 @@ static void __exit fschmd_exit(void) | |||
857 | i2c_del_driver(&fschmd_driver); | 1219 | i2c_del_driver(&fschmd_driver); |
858 | } | 1220 | } |
859 | 1221 | ||
860 | MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>"); | 1222 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); |
861 | MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles and " | 1223 | MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles and " |
862 | "Heimdall driver"); | 1224 | "Heimdall driver"); |
863 | MODULE_LICENSE("GPL"); | 1225 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index 2ede9388096b..27d7f72a5f11 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c | |||
@@ -490,6 +490,13 @@ static unsigned long chipset_ids[] = { | |||
490 | 0 | 490 | 0 |
491 | }; | 491 | }; |
492 | 492 | ||
493 | static struct pci_device_id i5k_amb_ids[] __devinitdata = { | ||
494 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) }, | ||
495 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) }, | ||
496 | { 0, } | ||
497 | }; | ||
498 | MODULE_DEVICE_TABLE(pci, i5k_amb_ids); | ||
499 | |||
493 | static int __devinit i5k_amb_probe(struct platform_device *pdev) | 500 | static int __devinit i5k_amb_probe(struct platform_device *pdev) |
494 | { | 501 | { |
495 | struct i5k_amb_data *data; | 502 | struct i5k_amb_data *data; |
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index b74c95735f95..95a99c590da2 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c | |||
@@ -14,6 +14,7 @@ | |||
14 | IT8712F Super I/O chip w/LPC interface | 14 | IT8712F Super I/O chip w/LPC interface |
15 | IT8716F Super I/O chip w/LPC interface | 15 | IT8716F Super I/O chip w/LPC interface |
16 | IT8718F Super I/O chip w/LPC interface | 16 | IT8718F Super I/O chip w/LPC interface |
17 | IT8720F Super I/O chip w/LPC interface | ||
17 | IT8726F Super I/O chip w/LPC interface | 18 | IT8726F Super I/O chip w/LPC interface |
18 | Sis950 A clone of the IT8705F | 19 | Sis950 A clone of the IT8705F |
19 | 20 | ||
@@ -48,11 +49,12 @@ | |||
48 | #include <linux/sysfs.h> | 49 | #include <linux/sysfs.h> |
49 | #include <linux/string.h> | 50 | #include <linux/string.h> |
50 | #include <linux/dmi.h> | 51 | #include <linux/dmi.h> |
52 | #include <linux/acpi.h> | ||
51 | #include <asm/io.h> | 53 | #include <asm/io.h> |
52 | 54 | ||
53 | #define DRVNAME "it87" | 55 | #define DRVNAME "it87" |
54 | 56 | ||
55 | enum chips { it87, it8712, it8716, it8718 }; | 57 | enum chips { it87, it8712, it8716, it8718, it8720 }; |
56 | 58 | ||
57 | static unsigned short force_id; | 59 | static unsigned short force_id; |
58 | module_param(force_id, ushort, 0); | 60 | module_param(force_id, ushort, 0); |
@@ -64,7 +66,10 @@ static struct platform_device *pdev; | |||
64 | #define DEV 0x07 /* Register: Logical device select */ | 66 | #define DEV 0x07 /* Register: Logical device select */ |
65 | #define VAL 0x2f /* The value to read/write */ | 67 | #define VAL 0x2f /* The value to read/write */ |
66 | #define PME 0x04 /* The device with the fan registers in it */ | 68 | #define PME 0x04 /* The device with the fan registers in it */ |
67 | #define GPIO 0x07 /* The device with the IT8718F VID value in it */ | 69 | |
70 | /* The device with the IT8718F/IT8720F VID value in it */ | ||
71 | #define GPIO 0x07 | ||
72 | |||
68 | #define DEVID 0x20 /* Register: Device ID */ | 73 | #define DEVID 0x20 /* Register: Device ID */ |
69 | #define DEVREV 0x22 /* Register: Device Revision */ | 74 | #define DEVREV 0x22 /* Register: Device Revision */ |
70 | 75 | ||
@@ -113,6 +118,7 @@ superio_exit(void) | |||
113 | #define IT8705F_DEVID 0x8705 | 118 | #define IT8705F_DEVID 0x8705 |
114 | #define IT8716F_DEVID 0x8716 | 119 | #define IT8716F_DEVID 0x8716 |
115 | #define IT8718F_DEVID 0x8718 | 120 | #define IT8718F_DEVID 0x8718 |
121 | #define IT8720F_DEVID 0x8720 | ||
116 | #define IT8726F_DEVID 0x8726 | 122 | #define IT8726F_DEVID 0x8726 |
117 | #define IT87_ACT_REG 0x30 | 123 | #define IT87_ACT_REG 0x30 |
118 | #define IT87_BASE_REG 0x60 | 124 | #define IT87_BASE_REG 0x60 |
@@ -150,8 +156,8 @@ static int fix_pwm_polarity; | |||
150 | #define IT87_REG_ALARM2 0x02 | 156 | #define IT87_REG_ALARM2 0x02 |
151 | #define IT87_REG_ALARM3 0x03 | 157 | #define IT87_REG_ALARM3 0x03 |
152 | 158 | ||
153 | /* The IT8718F has the VID value in a different register, in Super-I/O | 159 | /* The IT8718F and IT8720F have the VID value in a different register, in |
154 | configuration space. */ | 160 | Super-I/O configuration space. */ |
155 | #define IT87_REG_VID 0x0a | 161 | #define IT87_REG_VID 0x0a |
156 | /* The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b | 162 | /* The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b |
157 | for fan divisors. Later IT8712F revisions must use 16-bit tachometer | 163 | for fan divisors. Later IT8712F revisions must use 16-bit tachometer |
@@ -282,7 +288,8 @@ static inline int has_16bit_fans(const struct it87_data *data) | |||
282 | return (data->type == it87 && data->revision >= 0x03) | 288 | return (data->type == it87 && data->revision >= 0x03) |
283 | || (data->type == it8712 && data->revision >= 0x08) | 289 | || (data->type == it8712 && data->revision >= 0x08) |
284 | || data->type == it8716 | 290 | || data->type == it8716 |
285 | || data->type == it8718; | 291 | || data->type == it8718 |
292 | || data->type == it8720; | ||
286 | } | 293 | } |
287 | 294 | ||
288 | static int it87_probe(struct platform_device *pdev); | 295 | static int it87_probe(struct platform_device *pdev); |
@@ -992,6 +999,9 @@ static int __init it87_find(unsigned short *address, | |||
992 | case IT8718F_DEVID: | 999 | case IT8718F_DEVID: |
993 | sio_data->type = it8718; | 1000 | sio_data->type = it8718; |
994 | break; | 1001 | break; |
1002 | case IT8720F_DEVID: | ||
1003 | sio_data->type = it8720; | ||
1004 | break; | ||
995 | case 0xffff: /* No device at all */ | 1005 | case 0xffff: /* No device at all */ |
996 | goto exit; | 1006 | goto exit; |
997 | default: | 1007 | default: |
@@ -1022,7 +1032,8 @@ static int __init it87_find(unsigned short *address, | |||
1022 | int reg; | 1032 | int reg; |
1023 | 1033 | ||
1024 | superio_select(GPIO); | 1034 | superio_select(GPIO); |
1025 | if (chip_type == it8718) | 1035 | if ((chip_type == it8718) || |
1036 | (chip_type == it8720)) | ||
1026 | sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); | 1037 | sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); |
1027 | 1038 | ||
1028 | reg = superio_inb(IT87_SIO_PINX2_REG); | 1039 | reg = superio_inb(IT87_SIO_PINX2_REG); |
@@ -1068,6 +1079,7 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1068 | "it8712", | 1079 | "it8712", |
1069 | "it8716", | 1080 | "it8716", |
1070 | "it8718", | 1081 | "it8718", |
1082 | "it8720", | ||
1071 | }; | 1083 | }; |
1072 | 1084 | ||
1073 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | 1085 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
@@ -1226,7 +1238,7 @@ static int __devinit it87_probe(struct platform_device *pdev) | |||
1226 | } | 1238 | } |
1227 | 1239 | ||
1228 | if (data->type == it8712 || data->type == it8716 | 1240 | if (data->type == it8712 || data->type == it8716 |
1229 | || data->type == it8718) { | 1241 | || data->type == it8718 || data->type == it8720) { |
1230 | data->vrm = vid_which_vrm(); | 1242 | data->vrm = vid_which_vrm(); |
1231 | /* VID reading from Super-I/O config space if available */ | 1243 | /* VID reading from Super-I/O config space if available */ |
1232 | data->vid = sio_data->vid_value; | 1244 | data->vid = sio_data->vid_value; |
@@ -1374,7 +1386,7 @@ static void __devinit it87_init_device(struct platform_device *pdev) | |||
1374 | it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); | 1386 | it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); |
1375 | } | 1387 | } |
1376 | 1388 | ||
1377 | /* Check if temperature channnels are reset manually or by some reason */ | 1389 | /* Check if temperature channels are reset manually or by some reason */ |
1378 | tmp = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 1390 | tmp = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
1379 | if ((tmp & 0x3f) == 0) { | 1391 | if ((tmp & 0x3f) == 0) { |
1380 | /* Temp1,Temp3=thermistor; Temp2=thermal diode */ | 1392 | /* Temp1,Temp3=thermistor; Temp2=thermal diode */ |
@@ -1513,7 +1525,8 @@ static struct it87_data *it87_update_device(struct device *dev) | |||
1513 | 1525 | ||
1514 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); | 1526 | data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); |
1515 | /* The 8705 does not have VID capability. | 1527 | /* The 8705 does not have VID capability. |
1516 | The 8718 does not use IT87_REG_VID for the same purpose. */ | 1528 | The 8718 and the 8720 don't use IT87_REG_VID for the |
1529 | same purpose. */ | ||
1517 | if (data->type == it8712 || data->type == it8716) { | 1530 | if (data->type == it8712 || data->type == it8716) { |
1518 | data->vid = it87_read_value(data, IT87_REG_VID); | 1531 | data->vid = it87_read_value(data, IT87_REG_VID); |
1519 | /* The older IT8712F revisions had only 5 VID pins, | 1532 | /* The older IT8712F revisions had only 5 VID pins, |
@@ -1540,6 +1553,10 @@ static int __init it87_device_add(unsigned short address, | |||
1540 | }; | 1553 | }; |
1541 | int err; | 1554 | int err; |
1542 | 1555 | ||
1556 | err = acpi_check_resource_conflict(&res); | ||
1557 | if (err) | ||
1558 | goto exit; | ||
1559 | |||
1543 | pdev = platform_device_alloc(DRVNAME, address); | 1560 | pdev = platform_device_alloc(DRVNAME, address); |
1544 | if (!pdev) { | 1561 | if (!pdev) { |
1545 | err = -ENOMEM; | 1562 | err = -ENOMEM; |
@@ -1608,7 +1625,7 @@ static void __exit sm_it87_exit(void) | |||
1608 | 1625 | ||
1609 | MODULE_AUTHOR("Chris Gauthron, " | 1626 | MODULE_AUTHOR("Chris Gauthron, " |
1610 | "Jean Delvare <khali@linux-fr.org>"); | 1627 | "Jean Delvare <khali@linux-fr.org>"); |
1611 | MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8726F, SiS950 driver"); | 1628 | MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8720F/8726F, SiS950 driver"); |
1612 | module_param(update_vbat, bool, 0); | 1629 | module_param(update_vbat, bool, 0); |
1613 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); | 1630 | MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); |
1614 | module_param(fix_pwm_polarity, bool, 0); | 1631 | module_param(fix_pwm_polarity, bool, 0); |
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index d435f003292d..ae6204f33214 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c | |||
@@ -37,9 +37,13 @@ | |||
37 | 37 | ||
38 | #define DRVNAME "lm70" | 38 | #define DRVNAME "lm70" |
39 | 39 | ||
40 | #define LM70_CHIP_LM70 0 /* original NS LM70 */ | ||
41 | #define LM70_CHIP_TMP121 1 /* TI TMP121/TMP123 */ | ||
42 | |||
40 | struct lm70 { | 43 | struct lm70 { |
41 | struct device *hwmon_dev; | 44 | struct device *hwmon_dev; |
42 | struct mutex lock; | 45 | struct mutex lock; |
46 | unsigned int chip; | ||
43 | }; | 47 | }; |
44 | 48 | ||
45 | /* sysfs hook function */ | 49 | /* sysfs hook function */ |
@@ -47,7 +51,7 @@ static ssize_t lm70_sense_temp(struct device *dev, | |||
47 | struct device_attribute *attr, char *buf) | 51 | struct device_attribute *attr, char *buf) |
48 | { | 52 | { |
49 | struct spi_device *spi = to_spi_device(dev); | 53 | struct spi_device *spi = to_spi_device(dev); |
50 | int status, val; | 54 | int status, val = 0; |
51 | u8 rxbuf[2]; | 55 | u8 rxbuf[2]; |
52 | s16 raw=0; | 56 | s16 raw=0; |
53 | struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); | 57 | struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); |
@@ -65,12 +69,12 @@ static ssize_t lm70_sense_temp(struct device *dev, | |||
65 | "spi_write_then_read failed with status %d\n", status); | 69 | "spi_write_then_read failed with status %d\n", status); |
66 | goto out; | 70 | goto out; |
67 | } | 71 | } |
68 | dev_dbg(dev, "rxbuf[1] : 0x%x rxbuf[0] : 0x%x\n", rxbuf[1], rxbuf[0]); | 72 | raw = (rxbuf[0] << 8) + rxbuf[1]; |
69 | 73 | dev_dbg(dev, "rxbuf[0] : 0x%02x rxbuf[1] : 0x%02x raw=0x%04x\n", | |
70 | raw = (rxbuf[1] << 8) + rxbuf[0]; | 74 | rxbuf[0], rxbuf[1], raw); |
71 | dev_dbg(dev, "raw=0x%x\n", raw); | ||
72 | 75 | ||
73 | /* | 76 | /* |
77 | * LM70: | ||
74 | * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's | 78 | * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's |
75 | * complement value. Only the MSB 11 bits (1 sign + 10 temperature | 79 | * complement value. Only the MSB 11 bits (1 sign + 10 temperature |
76 | * bits) are meaningful; the LSB 5 bits are to be discarded. | 80 | * bits) are meaningful; the LSB 5 bits are to be discarded. |
@@ -80,8 +84,21 @@ static ssize_t lm70_sense_temp(struct device *dev, | |||
80 | * by 0.25. Also multiply by 1000 to represent in millidegrees | 84 | * by 0.25. Also multiply by 1000 to represent in millidegrees |
81 | * Celsius. | 85 | * Celsius. |
82 | * So it's equivalent to multiplying by 0.25 * 1000 = 250. | 86 | * So it's equivalent to multiplying by 0.25 * 1000 = 250. |
87 | * | ||
88 | * TMP121/TMP123: | ||
89 | * 13 bits of 2's complement data, discard LSB 3 bits, | ||
90 | * resolution 0.0625 degrees celsius. | ||
83 | */ | 91 | */ |
84 | val = ((int)raw/32) * 250; | 92 | switch (p_lm70->chip) { |
93 | case LM70_CHIP_LM70: | ||
94 | val = ((int)raw / 32) * 250; | ||
95 | break; | ||
96 | |||
97 | case LM70_CHIP_TMP121: | ||
98 | val = ((int)raw / 8) * 625 / 10; | ||
99 | break; | ||
100 | } | ||
101 | |||
85 | status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ | 102 | status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ |
86 | out: | 103 | out: |
87 | mutex_unlock(&p_lm70->lock); | 104 | mutex_unlock(&p_lm70->lock); |
@@ -93,27 +110,39 @@ static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL); | |||
93 | static ssize_t lm70_show_name(struct device *dev, struct device_attribute | 110 | static ssize_t lm70_show_name(struct device *dev, struct device_attribute |
94 | *devattr, char *buf) | 111 | *devattr, char *buf) |
95 | { | 112 | { |
96 | return sprintf(buf, "lm70\n"); | 113 | struct lm70 *p_lm70 = dev_get_drvdata(dev); |
114 | int ret; | ||
115 | |||
116 | switch (p_lm70->chip) { | ||
117 | case LM70_CHIP_LM70: | ||
118 | ret = sprintf(buf, "lm70\n"); | ||
119 | break; | ||
120 | case LM70_CHIP_TMP121: | ||
121 | ret = sprintf(buf, "tmp121\n"); | ||
122 | break; | ||
123 | default: | ||
124 | ret = -EINVAL; | ||
125 | } | ||
126 | return ret; | ||
97 | } | 127 | } |
98 | 128 | ||
99 | static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL); | 129 | static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL); |
100 | 130 | ||
101 | /*----------------------------------------------------------------------*/ | 131 | /*----------------------------------------------------------------------*/ |
102 | 132 | ||
103 | static int __devinit lm70_probe(struct spi_device *spi) | 133 | static int __devinit common_probe(struct spi_device *spi, int chip) |
104 | { | 134 | { |
105 | struct lm70 *p_lm70; | 135 | struct lm70 *p_lm70; |
106 | int status; | 136 | int status; |
107 | 137 | ||
108 | /* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */ | 138 | /* NOTE: we assume 8-bit words, and convert to 16 bits manually */ |
109 | if ((spi->mode & (SPI_CPOL|SPI_CPHA)) || !(spi->mode & SPI_3WIRE)) | ||
110 | return -EINVAL; | ||
111 | 139 | ||
112 | p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); | 140 | p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); |
113 | if (!p_lm70) | 141 | if (!p_lm70) |
114 | return -ENOMEM; | 142 | return -ENOMEM; |
115 | 143 | ||
116 | mutex_init(&p_lm70->lock); | 144 | mutex_init(&p_lm70->lock); |
145 | p_lm70->chip = chip; | ||
117 | 146 | ||
118 | /* sysfs hook */ | 147 | /* sysfs hook */ |
119 | p_lm70->hwmon_dev = hwmon_device_register(&spi->dev); | 148 | p_lm70->hwmon_dev = hwmon_device_register(&spi->dev); |
@@ -141,6 +170,24 @@ out_dev_reg_failed: | |||
141 | return status; | 170 | return status; |
142 | } | 171 | } |
143 | 172 | ||
173 | static int __devinit lm70_probe(struct spi_device *spi) | ||
174 | { | ||
175 | /* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */ | ||
176 | if ((spi->mode & (SPI_CPOL | SPI_CPHA)) || !(spi->mode & SPI_3WIRE)) | ||
177 | return -EINVAL; | ||
178 | |||
179 | return common_probe(spi, LM70_CHIP_LM70); | ||
180 | } | ||
181 | |||
182 | static int __devinit tmp121_probe(struct spi_device *spi) | ||
183 | { | ||
184 | /* signaling is SPI_MODE_0 with only MISO connected */ | ||
185 | if (spi->mode & (SPI_CPOL | SPI_CPHA)) | ||
186 | return -EINVAL; | ||
187 | |||
188 | return common_probe(spi, LM70_CHIP_TMP121); | ||
189 | } | ||
190 | |||
144 | static int __devexit lm70_remove(struct spi_device *spi) | 191 | static int __devexit lm70_remove(struct spi_device *spi) |
145 | { | 192 | { |
146 | struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); | 193 | struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); |
@@ -154,6 +201,15 @@ static int __devexit lm70_remove(struct spi_device *spi) | |||
154 | return 0; | 201 | return 0; |
155 | } | 202 | } |
156 | 203 | ||
204 | static struct spi_driver tmp121_driver = { | ||
205 | .driver = { | ||
206 | .name = "tmp121", | ||
207 | .owner = THIS_MODULE, | ||
208 | }, | ||
209 | .probe = tmp121_probe, | ||
210 | .remove = __devexit_p(lm70_remove), | ||
211 | }; | ||
212 | |||
157 | static struct spi_driver lm70_driver = { | 213 | static struct spi_driver lm70_driver = { |
158 | .driver = { | 214 | .driver = { |
159 | .name = "lm70", | 215 | .name = "lm70", |
@@ -165,17 +221,26 @@ static struct spi_driver lm70_driver = { | |||
165 | 221 | ||
166 | static int __init init_lm70(void) | 222 | static int __init init_lm70(void) |
167 | { | 223 | { |
168 | return spi_register_driver(&lm70_driver); | 224 | int ret = spi_register_driver(&lm70_driver); |
225 | if (ret) | ||
226 | return ret; | ||
227 | |||
228 | ret = spi_register_driver(&tmp121_driver); | ||
229 | if (ret) | ||
230 | spi_unregister_driver(&lm70_driver); | ||
231 | |||
232 | return ret; | ||
169 | } | 233 | } |
170 | 234 | ||
171 | static void __exit cleanup_lm70(void) | 235 | static void __exit cleanup_lm70(void) |
172 | { | 236 | { |
173 | spi_unregister_driver(&lm70_driver); | 237 | spi_unregister_driver(&lm70_driver); |
238 | spi_unregister_driver(&tmp121_driver); | ||
174 | } | 239 | } |
175 | 240 | ||
176 | module_init(init_lm70); | 241 | module_init(init_lm70); |
177 | module_exit(cleanup_lm70); | 242 | module_exit(cleanup_lm70); |
178 | 243 | ||
179 | MODULE_AUTHOR("Kaiwan N Billimoria"); | 244 | MODULE_AUTHOR("Kaiwan N Billimoria"); |
180 | MODULE_DESCRIPTION("National Semiconductor LM70 Linux driver"); | 245 | MODULE_DESCRIPTION("NS LM70 / TI TMP121/TMP123 Linux driver"); |
181 | MODULE_LICENSE("GPL"); | 246 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c new file mode 100644 index 000000000000..034b2c515848 --- /dev/null +++ b/drivers/hwmon/ltc4245.c | |||
@@ -0,0 +1,567 @@ | |||
1 | /* | ||
2 | * Driver for Linear Technology LTC4245 I2C Multiple Supply Hot Swap Controller | ||
3 | * | ||
4 | * Copyright (C) 2008 Ira W. Snyder <iws@ovro.caltech.edu> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This driver is based on the ds1621 and ina209 drivers. | ||
11 | * | ||
12 | * Datasheet: | ||
13 | * http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1140,P19392,D13517 | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/hwmon.h> | ||
23 | #include <linux/hwmon-sysfs.h> | ||
24 | |||
25 | /* Valid addresses are 0x20 - 0x3f | ||
26 | * | ||
27 | * For now, we do not probe, since some of these addresses | ||
28 | * are known to be unfriendly to probing */ | ||
29 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
30 | |||
31 | /* Insmod parameters */ | ||
32 | I2C_CLIENT_INSMOD_1(ltc4245); | ||
33 | |||
34 | /* Here are names of the chip's registers (a.k.a. commands) */ | ||
35 | enum ltc4245_cmd { | ||
36 | LTC4245_STATUS = 0x00, /* readonly */ | ||
37 | LTC4245_ALERT = 0x01, | ||
38 | LTC4245_CONTROL = 0x02, | ||
39 | LTC4245_ON = 0x03, | ||
40 | LTC4245_FAULT1 = 0x04, | ||
41 | LTC4245_FAULT2 = 0x05, | ||
42 | LTC4245_GPIO = 0x06, | ||
43 | LTC4245_ADCADR = 0x07, | ||
44 | |||
45 | LTC4245_12VIN = 0x10, | ||
46 | LTC4245_12VSENSE = 0x11, | ||
47 | LTC4245_12VOUT = 0x12, | ||
48 | LTC4245_5VIN = 0x13, | ||
49 | LTC4245_5VSENSE = 0x14, | ||
50 | LTC4245_5VOUT = 0x15, | ||
51 | LTC4245_3VIN = 0x16, | ||
52 | LTC4245_3VSENSE = 0x17, | ||
53 | LTC4245_3VOUT = 0x18, | ||
54 | LTC4245_VEEIN = 0x19, | ||
55 | LTC4245_VEESENSE = 0x1a, | ||
56 | LTC4245_VEEOUT = 0x1b, | ||
57 | LTC4245_GPIOADC1 = 0x1c, | ||
58 | LTC4245_GPIOADC2 = 0x1d, | ||
59 | LTC4245_GPIOADC3 = 0x1e, | ||
60 | }; | ||
61 | |||
62 | struct ltc4245_data { | ||
63 | struct device *hwmon_dev; | ||
64 | |||
65 | struct mutex update_lock; | ||
66 | bool valid; | ||
67 | unsigned long last_updated; /* in jiffies */ | ||
68 | |||
69 | /* Control registers */ | ||
70 | u8 cregs[0x08]; | ||
71 | |||
72 | /* Voltage registers */ | ||
73 | u8 vregs[0x0f]; | ||
74 | }; | ||
75 | |||
76 | static struct ltc4245_data *ltc4245_update_device(struct device *dev) | ||
77 | { | ||
78 | struct i2c_client *client = to_i2c_client(dev); | ||
79 | struct ltc4245_data *data = i2c_get_clientdata(client); | ||
80 | s32 val; | ||
81 | int i; | ||
82 | |||
83 | mutex_lock(&data->update_lock); | ||
84 | |||
85 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | ||
86 | |||
87 | dev_dbg(&client->dev, "Starting ltc4245 update\n"); | ||
88 | |||
89 | /* Read control registers -- 0x00 to 0x07 */ | ||
90 | for (i = 0; i < ARRAY_SIZE(data->cregs); i++) { | ||
91 | val = i2c_smbus_read_byte_data(client, i); | ||
92 | if (unlikely(val < 0)) | ||
93 | data->cregs[i] = 0; | ||
94 | else | ||
95 | data->cregs[i] = val; | ||
96 | } | ||
97 | |||
98 | /* Read voltage registers -- 0x10 to 0x1f */ | ||
99 | for (i = 0; i < ARRAY_SIZE(data->vregs); i++) { | ||
100 | val = i2c_smbus_read_byte_data(client, i+0x10); | ||
101 | if (unlikely(val < 0)) | ||
102 | data->vregs[i] = 0; | ||
103 | else | ||
104 | data->vregs[i] = val; | ||
105 | } | ||
106 | |||
107 | data->last_updated = jiffies; | ||
108 | data->valid = 1; | ||
109 | } | ||
110 | |||
111 | mutex_unlock(&data->update_lock); | ||
112 | |||
113 | return data; | ||
114 | } | ||
115 | |||
116 | /* Return the voltage from the given register in millivolts */ | ||
117 | static int ltc4245_get_voltage(struct device *dev, u8 reg) | ||
118 | { | ||
119 | struct ltc4245_data *data = ltc4245_update_device(dev); | ||
120 | const u8 regval = data->vregs[reg - 0x10]; | ||
121 | u32 voltage = 0; | ||
122 | |||
123 | switch (reg) { | ||
124 | case LTC4245_12VIN: | ||
125 | case LTC4245_12VOUT: | ||
126 | voltage = regval * 55; | ||
127 | break; | ||
128 | case LTC4245_5VIN: | ||
129 | case LTC4245_5VOUT: | ||
130 | voltage = regval * 22; | ||
131 | break; | ||
132 | case LTC4245_3VIN: | ||
133 | case LTC4245_3VOUT: | ||
134 | voltage = regval * 15; | ||
135 | break; | ||
136 | case LTC4245_VEEIN: | ||
137 | case LTC4245_VEEOUT: | ||
138 | voltage = regval * -55; | ||
139 | break; | ||
140 | case LTC4245_GPIOADC1: | ||
141 | case LTC4245_GPIOADC2: | ||
142 | case LTC4245_GPIOADC3: | ||
143 | voltage = regval * 10; | ||
144 | break; | ||
145 | default: | ||
146 | /* If we get here, the developer messed up */ | ||
147 | WARN_ON_ONCE(1); | ||
148 | break; | ||
149 | } | ||
150 | |||
151 | return voltage; | ||
152 | } | ||
153 | |||
154 | /* Return the current in the given sense register in milliAmperes */ | ||
155 | static unsigned int ltc4245_get_current(struct device *dev, u8 reg) | ||
156 | { | ||
157 | struct ltc4245_data *data = ltc4245_update_device(dev); | ||
158 | const u8 regval = data->vregs[reg - 0x10]; | ||
159 | unsigned int voltage; | ||
160 | unsigned int curr; | ||
161 | |||
162 | /* The strange looking conversions that follow are fixed-point | ||
163 | * math, since we cannot do floating point in the kernel. | ||
164 | * | ||
165 | * Step 1: convert sense register to microVolts | ||
166 | * Step 2: convert voltage to milliAmperes | ||
167 | * | ||
168 | * If you play around with the V=IR equation, you come up with | ||
169 | * the following: X uV / Y mOhm == Z mA | ||
170 | * | ||
171 | * With the resistors that are fractions of a milliOhm, we multiply | ||
172 | * the voltage and resistance by 10, to shift the decimal point. | ||
173 | * Now we can use the normal division operator again. | ||
174 | */ | ||
175 | |||
176 | switch (reg) { | ||
177 | case LTC4245_12VSENSE: | ||
178 | voltage = regval * 250; /* voltage in uV */ | ||
179 | curr = voltage / 50; /* sense resistor 50 mOhm */ | ||
180 | break; | ||
181 | case LTC4245_5VSENSE: | ||
182 | voltage = regval * 125; /* voltage in uV */ | ||
183 | curr = (voltage * 10) / 35; /* sense resistor 3.5 mOhm */ | ||
184 | break; | ||
185 | case LTC4245_3VSENSE: | ||
186 | voltage = regval * 125; /* voltage in uV */ | ||
187 | curr = (voltage * 10) / 25; /* sense resistor 2.5 mOhm */ | ||
188 | break; | ||
189 | case LTC4245_VEESENSE: | ||
190 | voltage = regval * 250; /* voltage in uV */ | ||
191 | curr = voltage / 100; /* sense resistor 100 mOhm */ | ||
192 | break; | ||
193 | default: | ||
194 | /* If we get here, the developer messed up */ | ||
195 | WARN_ON_ONCE(1); | ||
196 | curr = 0; | ||
197 | break; | ||
198 | } | ||
199 | |||
200 | return curr; | ||
201 | } | ||
202 | |||
203 | static ssize_t ltc4245_show_voltage(struct device *dev, | ||
204 | struct device_attribute *da, | ||
205 | char *buf) | ||
206 | { | ||
207 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
208 | const int voltage = ltc4245_get_voltage(dev, attr->index); | ||
209 | |||
210 | return snprintf(buf, PAGE_SIZE, "%d\n", voltage); | ||
211 | } | ||
212 | |||
213 | static ssize_t ltc4245_show_current(struct device *dev, | ||
214 | struct device_attribute *da, | ||
215 | char *buf) | ||
216 | { | ||
217 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
218 | const unsigned int curr = ltc4245_get_current(dev, attr->index); | ||
219 | |||
220 | return snprintf(buf, PAGE_SIZE, "%u\n", curr); | ||
221 | } | ||
222 | |||
223 | static ssize_t ltc4245_show_power(struct device *dev, | ||
224 | struct device_attribute *da, | ||
225 | char *buf) | ||
226 | { | ||
227 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
228 | const unsigned int curr = ltc4245_get_current(dev, attr->index); | ||
229 | const int output_voltage = ltc4245_get_voltage(dev, attr->index+1); | ||
230 | |||
231 | /* current in mA * voltage in mV == power in uW */ | ||
232 | const unsigned int power = abs(output_voltage * curr); | ||
233 | |||
234 | return snprintf(buf, PAGE_SIZE, "%u\n", power); | ||
235 | } | ||
236 | |||
237 | static ssize_t ltc4245_show_alarm(struct device *dev, | ||
238 | struct device_attribute *da, | ||
239 | char *buf) | ||
240 | { | ||
241 | struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da); | ||
242 | struct ltc4245_data *data = ltc4245_update_device(dev); | ||
243 | const u8 reg = data->cregs[attr->index]; | ||
244 | const u32 mask = attr->nr; | ||
245 | |||
246 | return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0); | ||
247 | } | ||
248 | |||
249 | /* These macros are used below in constructing device attribute objects | ||
250 | * for use with sysfs_create_group() to make a sysfs device file | ||
251 | * for each register. | ||
252 | */ | ||
253 | |||
254 | #define LTC4245_VOLTAGE(name, ltc4245_cmd_idx) \ | ||
255 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
256 | ltc4245_show_voltage, NULL, ltc4245_cmd_idx) | ||
257 | |||
258 | #define LTC4245_CURRENT(name, ltc4245_cmd_idx) \ | ||
259 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
260 | ltc4245_show_current, NULL, ltc4245_cmd_idx) | ||
261 | |||
262 | #define LTC4245_POWER(name, ltc4245_cmd_idx) \ | ||
263 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
264 | ltc4245_show_power, NULL, ltc4245_cmd_idx) | ||
265 | |||
266 | #define LTC4245_ALARM(name, mask, reg) \ | ||
267 | static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \ | ||
268 | ltc4245_show_alarm, NULL, (mask), reg) | ||
269 | |||
270 | /* Construct a sensor_device_attribute structure for each register */ | ||
271 | |||
272 | /* Input voltages */ | ||
273 | LTC4245_VOLTAGE(in1_input, LTC4245_12VIN); | ||
274 | LTC4245_VOLTAGE(in2_input, LTC4245_5VIN); | ||
275 | LTC4245_VOLTAGE(in3_input, LTC4245_3VIN); | ||
276 | LTC4245_VOLTAGE(in4_input, LTC4245_VEEIN); | ||
277 | |||
278 | /* Input undervoltage alarms */ | ||
279 | LTC4245_ALARM(in1_min_alarm, (1 << 0), LTC4245_FAULT1); | ||
280 | LTC4245_ALARM(in2_min_alarm, (1 << 1), LTC4245_FAULT1); | ||
281 | LTC4245_ALARM(in3_min_alarm, (1 << 2), LTC4245_FAULT1); | ||
282 | LTC4245_ALARM(in4_min_alarm, (1 << 3), LTC4245_FAULT1); | ||
283 | |||
284 | /* Currents (via sense resistor) */ | ||
285 | LTC4245_CURRENT(curr1_input, LTC4245_12VSENSE); | ||
286 | LTC4245_CURRENT(curr2_input, LTC4245_5VSENSE); | ||
287 | LTC4245_CURRENT(curr3_input, LTC4245_3VSENSE); | ||
288 | LTC4245_CURRENT(curr4_input, LTC4245_VEESENSE); | ||
289 | |||
290 | /* Overcurrent alarms */ | ||
291 | LTC4245_ALARM(curr1_max_alarm, (1 << 4), LTC4245_FAULT1); | ||
292 | LTC4245_ALARM(curr2_max_alarm, (1 << 5), LTC4245_FAULT1); | ||
293 | LTC4245_ALARM(curr3_max_alarm, (1 << 6), LTC4245_FAULT1); | ||
294 | LTC4245_ALARM(curr4_max_alarm, (1 << 7), LTC4245_FAULT1); | ||
295 | |||
296 | /* Output voltages */ | ||
297 | LTC4245_VOLTAGE(in5_input, LTC4245_12VOUT); | ||
298 | LTC4245_VOLTAGE(in6_input, LTC4245_5VOUT); | ||
299 | LTC4245_VOLTAGE(in7_input, LTC4245_3VOUT); | ||
300 | LTC4245_VOLTAGE(in8_input, LTC4245_VEEOUT); | ||
301 | |||
302 | /* Power Bad alarms */ | ||
303 | LTC4245_ALARM(in5_min_alarm, (1 << 0), LTC4245_FAULT2); | ||
304 | LTC4245_ALARM(in6_min_alarm, (1 << 1), LTC4245_FAULT2); | ||
305 | LTC4245_ALARM(in7_min_alarm, (1 << 2), LTC4245_FAULT2); | ||
306 | LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2); | ||
307 | |||
308 | /* GPIO voltages */ | ||
309 | LTC4245_VOLTAGE(in9_input, LTC4245_GPIOADC1); | ||
310 | LTC4245_VOLTAGE(in10_input, LTC4245_GPIOADC2); | ||
311 | LTC4245_VOLTAGE(in11_input, LTC4245_GPIOADC3); | ||
312 | |||
313 | /* Power Consumption (virtual) */ | ||
314 | LTC4245_POWER(power1_input, LTC4245_12VSENSE); | ||
315 | LTC4245_POWER(power2_input, LTC4245_5VSENSE); | ||
316 | LTC4245_POWER(power3_input, LTC4245_3VSENSE); | ||
317 | LTC4245_POWER(power4_input, LTC4245_VEESENSE); | ||
318 | |||
319 | /* Finally, construct an array of pointers to members of the above objects, | ||
320 | * as required for sysfs_create_group() | ||
321 | */ | ||
322 | static struct attribute *ltc4245_attributes[] = { | ||
323 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
324 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
325 | &sensor_dev_attr_in3_input.dev_attr.attr, | ||
326 | &sensor_dev_attr_in4_input.dev_attr.attr, | ||
327 | |||
328 | &sensor_dev_attr_in1_min_alarm.dev_attr.attr, | ||
329 | &sensor_dev_attr_in2_min_alarm.dev_attr.attr, | ||
330 | &sensor_dev_attr_in3_min_alarm.dev_attr.attr, | ||
331 | &sensor_dev_attr_in4_min_alarm.dev_attr.attr, | ||
332 | |||
333 | &sensor_dev_attr_curr1_input.dev_attr.attr, | ||
334 | &sensor_dev_attr_curr2_input.dev_attr.attr, | ||
335 | &sensor_dev_attr_curr3_input.dev_attr.attr, | ||
336 | &sensor_dev_attr_curr4_input.dev_attr.attr, | ||
337 | |||
338 | &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, | ||
339 | &sensor_dev_attr_curr2_max_alarm.dev_attr.attr, | ||
340 | &sensor_dev_attr_curr3_max_alarm.dev_attr.attr, | ||
341 | &sensor_dev_attr_curr4_max_alarm.dev_attr.attr, | ||
342 | |||
343 | &sensor_dev_attr_in5_input.dev_attr.attr, | ||
344 | &sensor_dev_attr_in6_input.dev_attr.attr, | ||
345 | &sensor_dev_attr_in7_input.dev_attr.attr, | ||
346 | &sensor_dev_attr_in8_input.dev_attr.attr, | ||
347 | |||
348 | &sensor_dev_attr_in5_min_alarm.dev_attr.attr, | ||
349 | &sensor_dev_attr_in6_min_alarm.dev_attr.attr, | ||
350 | &sensor_dev_attr_in7_min_alarm.dev_attr.attr, | ||
351 | &sensor_dev_attr_in8_min_alarm.dev_attr.attr, | ||
352 | |||
353 | &sensor_dev_attr_in9_input.dev_attr.attr, | ||
354 | &sensor_dev_attr_in10_input.dev_attr.attr, | ||
355 | &sensor_dev_attr_in11_input.dev_attr.attr, | ||
356 | |||
357 | &sensor_dev_attr_power1_input.dev_attr.attr, | ||
358 | &sensor_dev_attr_power2_input.dev_attr.attr, | ||
359 | &sensor_dev_attr_power3_input.dev_attr.attr, | ||
360 | &sensor_dev_attr_power4_input.dev_attr.attr, | ||
361 | |||
362 | NULL, | ||
363 | }; | ||
364 | |||
365 | static const struct attribute_group ltc4245_group = { | ||
366 | .attrs = ltc4245_attributes, | ||
367 | }; | ||
368 | |||
369 | static int ltc4245_probe(struct i2c_client *client, | ||
370 | const struct i2c_device_id *id) | ||
371 | { | ||
372 | struct ltc4245_data *data; | ||
373 | int ret; | ||
374 | |||
375 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
376 | if (!data) { | ||
377 | ret = -ENOMEM; | ||
378 | goto out_kzalloc; | ||
379 | } | ||
380 | |||
381 | i2c_set_clientdata(client, data); | ||
382 | mutex_init(&data->update_lock); | ||
383 | |||
384 | /* Initialize the LTC4245 chip */ | ||
385 | /* TODO */ | ||
386 | |||
387 | /* Register sysfs hooks */ | ||
388 | ret = sysfs_create_group(&client->dev.kobj, <c4245_group); | ||
389 | if (ret) | ||
390 | goto out_sysfs_create_group; | ||
391 | |||
392 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
393 | if (IS_ERR(data->hwmon_dev)) { | ||
394 | ret = PTR_ERR(data->hwmon_dev); | ||
395 | goto out_hwmon_device_register; | ||
396 | } | ||
397 | |||
398 | return 0; | ||
399 | |||
400 | out_hwmon_device_register: | ||
401 | sysfs_remove_group(&client->dev.kobj, <c4245_group); | ||
402 | out_sysfs_create_group: | ||
403 | kfree(data); | ||
404 | out_kzalloc: | ||
405 | return ret; | ||
406 | } | ||
407 | |||
408 | static int ltc4245_remove(struct i2c_client *client) | ||
409 | { | ||
410 | struct ltc4245_data *data = i2c_get_clientdata(client); | ||
411 | |||
412 | hwmon_device_unregister(data->hwmon_dev); | ||
413 | sysfs_remove_group(&client->dev.kobj, <c4245_group); | ||
414 | |||
415 | kfree(data); | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | /* Check that some bits in a control register appear at all possible | ||
421 | * locations without changing value | ||
422 | * | ||
423 | * @client: the i2c client to use | ||
424 | * @reg: the register to read | ||
425 | * @bits: the bits to check (0xff checks all bits, | ||
426 | * 0x03 checks only the last two bits) | ||
427 | * | ||
428 | * return -ERRNO if the register read failed | ||
429 | * return -ENODEV if the register value doesn't stay constant at all | ||
430 | * possible addresses | ||
431 | * | ||
432 | * return 0 for success | ||
433 | */ | ||
434 | static int ltc4245_check_control_reg(struct i2c_client *client, u8 reg, u8 bits) | ||
435 | { | ||
436 | int i; | ||
437 | s32 v, voff1, voff2; | ||
438 | |||
439 | /* Read register and check for error */ | ||
440 | v = i2c_smbus_read_byte_data(client, reg); | ||
441 | if (v < 0) | ||
442 | return v; | ||
443 | |||
444 | v &= bits; | ||
445 | |||
446 | for (i = 0x00; i < 0xff; i += 0x20) { | ||
447 | |||
448 | voff1 = i2c_smbus_read_byte_data(client, reg + i); | ||
449 | if (voff1 < 0) | ||
450 | return voff1; | ||
451 | |||
452 | voff2 = i2c_smbus_read_byte_data(client, reg + i + 0x08); | ||
453 | if (voff2 < 0) | ||
454 | return voff2; | ||
455 | |||
456 | voff1 &= bits; | ||
457 | voff2 &= bits; | ||
458 | |||
459 | if (v != voff1 || v != voff2) | ||
460 | return -ENODEV; | ||
461 | } | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static int ltc4245_detect(struct i2c_client *client, | ||
467 | int kind, | ||
468 | struct i2c_board_info *info) | ||
469 | { | ||
470 | struct i2c_adapter *adapter = client->adapter; | ||
471 | |||
472 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
473 | return -ENODEV; | ||
474 | |||
475 | if (kind < 0) { /* probed detection - check the chip type */ | ||
476 | s32 v; /* 8 bits from the chip, or -ERRNO */ | ||
477 | |||
478 | /* Chip registers 0x00-0x07 are control registers | ||
479 | * Chip registers 0x10-0x1f are data registers | ||
480 | * | ||
481 | * Address bits b7-b5 are ignored. This makes the chip "repeat" | ||
482 | * in steps of 0x20. Any control registers should appear with | ||
483 | * the same values across all duplicated addresses. | ||
484 | * | ||
485 | * Register 0x02 bit b2 is reserved, expect 0 | ||
486 | * Register 0x07 bits b7 to b4 are reserved, expect 0 | ||
487 | * | ||
488 | * Registers 0x01, 0x02 are control registers and should not | ||
489 | * change on their own. | ||
490 | * | ||
491 | * Register 0x06 bits b6 and b7 are control bits, and should | ||
492 | * not change on their own. | ||
493 | * | ||
494 | * Register 0x07 bits b3 to b0 are control bits, and should | ||
495 | * not change on their own. | ||
496 | */ | ||
497 | |||
498 | /* read register 0x02 reserved bit, expect 0 */ | ||
499 | v = i2c_smbus_read_byte_data(client, LTC4245_CONTROL); | ||
500 | if (v < 0 || (v & 0x04) != 0) | ||
501 | return -ENODEV; | ||
502 | |||
503 | /* read register 0x07 reserved bits, expect 0 */ | ||
504 | v = i2c_smbus_read_byte_data(client, LTC4245_ADCADR); | ||
505 | if (v < 0 || (v & 0xf0) != 0) | ||
506 | return -ENODEV; | ||
507 | |||
508 | /* check that the alert register appears at all locations */ | ||
509 | if (ltc4245_check_control_reg(client, LTC4245_ALERT, 0xff)) | ||
510 | return -ENODEV; | ||
511 | |||
512 | /* check that the control register appears at all locations */ | ||
513 | if (ltc4245_check_control_reg(client, LTC4245_CONTROL, 0xff)) | ||
514 | return -ENODEV; | ||
515 | |||
516 | /* check that register 0x06 bits b6 and b7 stay constant */ | ||
517 | if (ltc4245_check_control_reg(client, LTC4245_GPIO, 0xc0)) | ||
518 | return -ENODEV; | ||
519 | |||
520 | /* check that register 0x07 bits b3-b0 stay constant */ | ||
521 | if (ltc4245_check_control_reg(client, LTC4245_ADCADR, 0x0f)) | ||
522 | return -ENODEV; | ||
523 | } | ||
524 | |||
525 | strlcpy(info->type, "ltc4245", I2C_NAME_SIZE); | ||
526 | dev_info(&adapter->dev, "ltc4245 %s at address 0x%02x\n", | ||
527 | kind < 0 ? "probed" : "forced", | ||
528 | client->addr); | ||
529 | |||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | static const struct i2c_device_id ltc4245_id[] = { | ||
534 | { "ltc4245", ltc4245 }, | ||
535 | { } | ||
536 | }; | ||
537 | MODULE_DEVICE_TABLE(i2c, ltc4245_id); | ||
538 | |||
539 | /* This is the driver that will be inserted */ | ||
540 | static struct i2c_driver ltc4245_driver = { | ||
541 | .class = I2C_CLASS_HWMON, | ||
542 | .driver = { | ||
543 | .name = "ltc4245", | ||
544 | }, | ||
545 | .probe = ltc4245_probe, | ||
546 | .remove = ltc4245_remove, | ||
547 | .id_table = ltc4245_id, | ||
548 | .detect = ltc4245_detect, | ||
549 | .address_data = &addr_data, | ||
550 | }; | ||
551 | |||
552 | static int __init ltc4245_init(void) | ||
553 | { | ||
554 | return i2c_add_driver(<c4245_driver); | ||
555 | } | ||
556 | |||
557 | static void __exit ltc4245_exit(void) | ||
558 | { | ||
559 | i2c_del_driver(<c4245_driver); | ||
560 | } | ||
561 | |||
562 | MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); | ||
563 | MODULE_DESCRIPTION("LTC4245 driver"); | ||
564 | MODULE_LICENSE("GPL"); | ||
565 | |||
566 | module_init(ltc4245_init); | ||
567 | module_exit(ltc4245_exit); | ||
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index 5fbfa34c110e..fb052fea3744 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/hwmon-vid.h> | 43 | #include <linux/hwmon-vid.h> |
44 | #include <linux/err.h> | 44 | #include <linux/err.h> |
45 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> |
46 | #include <linux/acpi.h> | ||
46 | #include <asm/io.h> | 47 | #include <asm/io.h> |
47 | 48 | ||
48 | static u8 devid; | 49 | static u8 devid; |
@@ -1627,6 +1628,11 @@ static int __init pc87360_device_add(unsigned short address) | |||
1627 | continue; | 1628 | continue; |
1628 | res.start = extra_isa[i]; | 1629 | res.start = extra_isa[i]; |
1629 | res.end = extra_isa[i] + PC87360_EXTENT - 1; | 1630 | res.end = extra_isa[i] + PC87360_EXTENT - 1; |
1631 | |||
1632 | err = acpi_check_resource_conflict(&res); | ||
1633 | if (err) | ||
1634 | goto exit_device_put; | ||
1635 | |||
1630 | err = platform_device_add_resources(pdev, &res, 1); | 1636 | err = platform_device_add_resources(pdev, &res, 1); |
1631 | if (err) { | 1637 | if (err) { |
1632 | printk(KERN_ERR "pc87360: Device resource[%d] " | 1638 | printk(KERN_ERR "pc87360: Device resource[%d] " |
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index 7265f22ae5cd..3a8a0f7a7736 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/sysfs.h> | 33 | #include <linux/sysfs.h> |
34 | #include <linux/ioport.h> | 34 | #include <linux/ioport.h> |
35 | #include <linux/acpi.h> | ||
35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
36 | 37 | ||
37 | static unsigned short force_id; | 38 | static unsigned short force_id; |
@@ -524,6 +525,10 @@ static int __init pc87427_device_add(unsigned short address) | |||
524 | }; | 525 | }; |
525 | int err; | 526 | int err; |
526 | 527 | ||
528 | err = acpi_check_resource_conflict(&res); | ||
529 | if (err) | ||
530 | goto exit; | ||
531 | |||
527 | pdev = platform_device_alloc(DRVNAME, address); | 532 | pdev = platform_device_alloc(DRVNAME, address); |
528 | if (!pdev) { | 533 | if (!pdev) { |
529 | err = -ENOMEM; | 534 | err = -ENOMEM; |
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index a276806f3d53..aa2e8318f167 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <linux/jiffies.h> | 62 | #include <linux/jiffies.h> |
63 | #include <linux/mutex.h> | 63 | #include <linux/mutex.h> |
64 | #include <linux/sysfs.h> | 64 | #include <linux/sysfs.h> |
65 | #include <linux/acpi.h> | ||
65 | #include <asm/io.h> | 66 | #include <asm/io.h> |
66 | 67 | ||
67 | 68 | ||
@@ -727,6 +728,10 @@ static int __devinit sis5595_device_add(unsigned short address) | |||
727 | }; | 728 | }; |
728 | int err; | 729 | int err; |
729 | 730 | ||
731 | err = acpi_check_resource_conflict(&res); | ||
732 | if (err) | ||
733 | goto exit; | ||
734 | |||
730 | pdev = platform_device_alloc("sis5595", address); | 735 | pdev = platform_device_alloc("sis5595", address); |
731 | if (!pdev) { | 736 | if (!pdev) { |
732 | err = -ENOMEM; | 737 | err = -ENOMEM; |
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index eb03544c731c..6f6d52b4fb64 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/err.h> | 36 | #include <linux/err.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
39 | #include <linux/acpi.h> | ||
39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
40 | 41 | ||
41 | static unsigned short force_id; | 42 | static unsigned short force_id; |
@@ -303,6 +304,10 @@ static int __init smsc47b397_device_add(unsigned short address) | |||
303 | }; | 304 | }; |
304 | int err; | 305 | int err; |
305 | 306 | ||
307 | err = acpi_check_resource_conflict(&res); | ||
308 | if (err) | ||
309 | goto exit; | ||
310 | |||
306 | pdev = platform_device_alloc(DRVNAME, address); | 311 | pdev = platform_device_alloc(DRVNAME, address); |
307 | if (!pdev) { | 312 | if (!pdev) { |
308 | err = -ENOMEM; | 313 | err = -ENOMEM; |
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index d1b498548736..a92dbb97ee99 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
39 | #include <linux/sysfs.h> | 39 | #include <linux/sysfs.h> |
40 | #include <linux/acpi.h> | ||
40 | #include <asm/io.h> | 41 | #include <asm/io.h> |
41 | 42 | ||
42 | static unsigned short force_id; | 43 | static unsigned short force_id; |
@@ -705,6 +706,10 @@ static int __init smsc47m1_device_add(unsigned short address, | |||
705 | }; | 706 | }; |
706 | int err; | 707 | int err; |
707 | 708 | ||
709 | err = acpi_check_resource_conflict(&res); | ||
710 | if (err) | ||
711 | goto exit; | ||
712 | |||
708 | pdev = platform_device_alloc(DRVNAME, address); | 713 | pdev = platform_device_alloc(DRVNAME, address); |
709 | if (!pdev) { | 714 | if (!pdev) { |
710 | err = -ENOMEM; | 715 | err = -ENOMEM; |
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index f1ee5e731968..a022aedcaacb 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/init.h> | 41 | #include <linux/init.h> |
42 | #include <linux/mutex.h> | 42 | #include <linux/mutex.h> |
43 | #include <linux/sysfs.h> | 43 | #include <linux/sysfs.h> |
44 | #include <linux/acpi.h> | ||
44 | #include <asm/io.h> | 45 | #include <asm/io.h> |
45 | 46 | ||
46 | 47 | ||
@@ -783,6 +784,10 @@ static int __devinit via686a_device_add(unsigned short address) | |||
783 | }; | 784 | }; |
784 | int err; | 785 | int err; |
785 | 786 | ||
787 | err = acpi_check_resource_conflict(&res); | ||
788 | if (err) | ||
789 | goto exit; | ||
790 | |||
786 | pdev = platform_device_alloc("via686a", address); | 791 | pdev = platform_device_alloc("via686a", address); |
787 | if (!pdev) { | 792 | if (!pdev) { |
788 | err = -ENOMEM; | 793 | err = -ENOMEM; |
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 12b43590fa53..b0ce37852281 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/err.h> | 32 | #include <linux/err.h> |
33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
34 | #include <linux/ioport.h> | 34 | #include <linux/ioport.h> |
35 | #include <linux/acpi.h> | ||
35 | #include <asm/io.h> | 36 | #include <asm/io.h> |
36 | 37 | ||
37 | static int uch_config = -1; | 38 | static int uch_config = -1; |
@@ -1259,6 +1260,10 @@ static int __init vt1211_device_add(unsigned short address) | |||
1259 | } | 1260 | } |
1260 | 1261 | ||
1261 | res.name = pdev->name; | 1262 | res.name = pdev->name; |
1263 | err = acpi_check_resource_conflict(&res); | ||
1264 | if (err) | ||
1265 | goto EXIT; | ||
1266 | |||
1262 | err = platform_device_add_resources(pdev, &res, 1); | 1267 | err = platform_device_add_resources(pdev, &res, 1); |
1263 | if (err) { | 1268 | if (err) { |
1264 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | 1269 | printk(KERN_ERR DRVNAME ": Device resource addition failed " |
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 5bc57275cae8..9982b45fbb14 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/hwmon-vid.h> | 35 | #include <linux/hwmon-vid.h> |
36 | #include <linux/err.h> | 36 | #include <linux/err.h> |
37 | #include <linux/mutex.h> | 37 | #include <linux/mutex.h> |
38 | #include <linux/acpi.h> | ||
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
39 | 40 | ||
40 | static int force_addr; | 41 | static int force_addr; |
@@ -894,6 +895,10 @@ static int __devinit vt8231_device_add(unsigned short address) | |||
894 | }; | 895 | }; |
895 | int err; | 896 | int err; |
896 | 897 | ||
898 | err = acpi_check_resource_conflict(&res); | ||
899 | if (err) | ||
900 | goto exit; | ||
901 | |||
897 | pdev = platform_device_alloc("vt8231", address); | 902 | pdev = platform_device_alloc("vt8231", address); |
898 | if (!pdev) { | 903 | if (!pdev) { |
899 | err = -ENOMEM; | 904 | err = -ENOMEM; |
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 075164dd65a7..cb808d015361 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/hwmon-vid.h> | 48 | #include <linux/hwmon-vid.h> |
49 | #include <linux/err.h> | 49 | #include <linux/err.h> |
50 | #include <linux/mutex.h> | 50 | #include <linux/mutex.h> |
51 | #include <linux/acpi.h> | ||
51 | #include <asm/io.h> | 52 | #include <asm/io.h> |
52 | #include "lm75.h" | 53 | #include "lm75.h" |
53 | 54 | ||
@@ -502,7 +503,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
502 | } | 503 | } |
503 | 504 | ||
504 | for (i = 0; i < 4; i++) { | 505 | for (i = 0; i < 4; i++) { |
505 | /* pwmcfg, tolarance mapped for i=0, i=1 to same reg */ | 506 | /* pwmcfg, tolerance mapped for i=0, i=1 to same reg */ |
506 | if (i != 1) { | 507 | if (i != 1) { |
507 | pwmcfg = w83627ehf_read_value(data, | 508 | pwmcfg = w83627ehf_read_value(data, |
508 | W83627EHF_REG_PWM_ENABLE[i]); | 509 | W83627EHF_REG_PWM_ENABLE[i]); |
@@ -1544,6 +1545,11 @@ static int __init sensors_w83627ehf_init(void) | |||
1544 | res.start = address + IOREGION_OFFSET; | 1545 | res.start = address + IOREGION_OFFSET; |
1545 | res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; | 1546 | res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1; |
1546 | res.flags = IORESOURCE_IO; | 1547 | res.flags = IORESOURCE_IO; |
1548 | |||
1549 | err = acpi_check_resource_conflict(&res); | ||
1550 | if (err) | ||
1551 | goto exit; | ||
1552 | |||
1547 | err = platform_device_add_resources(pdev, &res, 1); | 1553 | err = platform_device_add_resources(pdev, &res, 1); |
1548 | if (err) { | 1554 | if (err) { |
1549 | printk(KERN_ERR DRVNAME ": Device resource addition failed " | 1555 | printk(KERN_ERR DRVNAME ": Device resource addition failed " |
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index b30e5796cb26..389150ba30d3 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/err.h> | 50 | #include <linux/err.h> |
51 | #include <linux/mutex.h> | 51 | #include <linux/mutex.h> |
52 | #include <linux/ioport.h> | 52 | #include <linux/ioport.h> |
53 | #include <linux/acpi.h> | ||
53 | #include <asm/io.h> | 54 | #include <asm/io.h> |
54 | #include "lm75.h" | 55 | #include "lm75.h" |
55 | 56 | ||
@@ -1793,6 +1794,10 @@ static int __init w83627hf_device_add(unsigned short address, | |||
1793 | }; | 1794 | }; |
1794 | int err; | 1795 | int err; |
1795 | 1796 | ||
1797 | err = acpi_check_resource_conflict(&res); | ||
1798 | if (err) | ||
1799 | goto exit; | ||
1800 | |||
1796 | pdev = platform_device_alloc(DRVNAME, address); | 1801 | pdev = platform_device_alloc(DRVNAME, address); |
1797 | if (!pdev) { | 1802 | if (!pdev) { |
1798 | err = -ENOMEM; | 1803 | err = -ENOMEM; |
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index fc12bd412e3a..dbfb30c588d8 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
@@ -58,7 +58,10 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, | |||
58 | 0x2e, 0x2f, I2C_CLIENT_END }; | 58 | 0x2e, 0x2f, I2C_CLIENT_END }; |
59 | /* Insmod parameters */ | 59 | /* Insmod parameters */ |
60 | I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f); | 60 | I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f); |
61 | I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " | 61 | |
62 | static unsigned short force_subclients[4]; | ||
63 | module_param_array(force_subclients, short, NULL, 0); | ||
64 | MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " | ||
62 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); | 65 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); |
63 | 66 | ||
64 | static int reset; | 67 | static int reset; |
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 5768def8a4f2..97851c5ba3a3 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c | |||
@@ -53,7 +53,10 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, | |||
53 | 53 | ||
54 | /* Insmod parameters */ | 54 | /* Insmod parameters */ |
55 | I2C_CLIENT_INSMOD_1(w83791d); | 55 | I2C_CLIENT_INSMOD_1(w83791d); |
56 | I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " | 56 | |
57 | static unsigned short force_subclients[4]; | ||
58 | module_param_array(force_subclients, short, NULL, 0); | ||
59 | MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " | ||
57 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); | 60 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); |
58 | 61 | ||
59 | static int reset; | 62 | static int reset; |
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index cf94c5b0c879..2be16194ddf3 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c | |||
@@ -51,7 +51,10 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, | |||
51 | 51 | ||
52 | /* Insmod parameters */ | 52 | /* Insmod parameters */ |
53 | I2C_CLIENT_INSMOD_1(w83792d); | 53 | I2C_CLIENT_INSMOD_1(w83792d); |
54 | I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " | 54 | |
55 | static unsigned short force_subclients[4]; | ||
56 | module_param_array(force_subclients, short, NULL, 0); | ||
57 | MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " | ||
55 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); | 58 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); |
56 | 59 | ||
57 | static int init; | 60 | static int init; |
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index 0a739f1c69be..47dd398f7258 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c | |||
@@ -42,7 +42,10 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, | |||
42 | 42 | ||
43 | /* Insmod parameters */ | 43 | /* Insmod parameters */ |
44 | I2C_CLIENT_INSMOD_1(w83793); | 44 | I2C_CLIENT_INSMOD_1(w83793); |
45 | I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " | 45 | |
46 | static unsigned short force_subclients[4]; | ||
47 | module_param_array(force_subclients, short, NULL, 0); | ||
48 | MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " | ||
46 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); | 49 | "{bus, clientaddr, subclientaddr1, subclientaddr2}"); |
47 | 50 | ||
48 | static int reset; | 51 | static int reset; |
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index fc3e5b026423..dd9e796fad69 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c | |||
@@ -399,8 +399,8 @@ static int __devinit ali1563_probe(struct pci_dev * dev, | |||
399 | if ((error = ali1563_setup(dev))) | 399 | if ((error = ali1563_setup(dev))) |
400 | goto exit; | 400 | goto exit; |
401 | ali1563_adapter.dev.parent = &dev->dev; | 401 | ali1563_adapter.dev.parent = &dev->dev; |
402 | sprintf(ali1563_adapter.name,"SMBus ALi 1563 Adapter @ %04x", | 402 | snprintf(ali1563_adapter.name, sizeof(ali1563_adapter.name), |
403 | ali1563_smba); | 403 | "SMBus ALi 1563 Adapter @ %04x", ali1563_smba); |
404 | if ((error = i2c_add_adapter(&ali1563_adapter))) | 404 | if ((error = i2c_add_adapter(&ali1563_adapter))) |
405 | goto exit_shutdown; | 405 | goto exit_shutdown; |
406 | return 0; | 406 | return 0; |
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index 8ba2bcf727d3..378fcb5d5783 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c | |||
@@ -197,8 +197,8 @@ static int __init amd756_s4882_init(void) | |||
197 | for (i = 1; i < 5; i++) { | 197 | for (i = 1; i < 5; i++) { |
198 | s4882_algo[i] = *(amd756_smbus.algo); | 198 | s4882_algo[i] = *(amd756_smbus.algo); |
199 | s4882_adapter[i] = amd756_smbus; | 199 | s4882_adapter[i] = amd756_smbus; |
200 | sprintf(s4882_adapter[i].name, | 200 | snprintf(s4882_adapter[i].name, sizeof(s4882_adapter[i].name), |
201 | "SMBus 8111 adapter (CPU%d)", i-1); | 201 | "SMBus 8111 adapter (CPU%d)", i-1); |
202 | s4882_adapter[i].algo = s4882_algo+i; | 202 | s4882_adapter[i].algo = s4882_algo+i; |
203 | s4882_adapter[i].dev.parent = amd756_smbus.dev.parent; | 203 | s4882_adapter[i].dev.parent = amd756_smbus.dev.parent; |
204 | } | 204 | } |
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index 424dad6f18d8..36bee5b9c952 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c | |||
@@ -380,8 +380,9 @@ static int __devinit amd756_probe(struct pci_dev *pdev, | |||
380 | /* set up the sysfs linkage to our parent device */ | 380 | /* set up the sysfs linkage to our parent device */ |
381 | amd756_smbus.dev.parent = &pdev->dev; | 381 | amd756_smbus.dev.parent = &pdev->dev; |
382 | 382 | ||
383 | sprintf(amd756_smbus.name, "SMBus %s adapter at %04x", | 383 | snprintf(amd756_smbus.name, sizeof(amd756_smbus.name), |
384 | chipname[id->driver_data], amd756_ioport); | 384 | "SMBus %s adapter at %04x", chipname[id->driver_data], |
385 | amd756_ioport); | ||
385 | 386 | ||
386 | error = i2c_add_adapter(&amd756_smbus); | 387 | error = i2c_add_adapter(&amd756_smbus); |
387 | if (error) { | 388 | if (error) { |
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 9efb02137254..67d9dc5b351b 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c | |||
@@ -222,7 +222,7 @@ static int __devinit at91_i2c_probe(struct platform_device *pdev) | |||
222 | rc = -ENOMEM; | 222 | rc = -ENOMEM; |
223 | goto fail2; | 223 | goto fail2; |
224 | } | 224 | } |
225 | sprintf(adapter->name, "AT91"); | 225 | snprintf(adapter->name, sizeof(adapter->name), "AT91"); |
226 | adapter->algo = &at91_algorithm; | 226 | adapter->algo = &at91_algorithm; |
227 | adapter->class = I2C_CLASS_HWMON; | 227 | adapter->class = I2C_CLASS_HWMON; |
228 | adapter->dev.parent = &pdev->dev; | 228 | adapter->dev.parent = &pdev->dev; |
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 3c855ff2992f..3fd2c417c1e0 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c | |||
@@ -656,7 +656,7 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) | |||
656 | strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); | 656 | strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); |
657 | p_adap->algo = &bfin_twi_algorithm; | 657 | p_adap->algo = &bfin_twi_algorithm; |
658 | p_adap->algo_data = iface; | 658 | p_adap->algo_data = iface; |
659 | p_adap->class = I2C_CLASS_ALL; | 659 | p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; |
660 | p_adap->dev.parent = &pdev->dev; | 660 | p_adap->dev.parent = &pdev->dev; |
661 | 661 | ||
662 | rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi"); | 662 | rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi"); |
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 5123eb69a971..526625eaa84b 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -64,7 +64,7 @@ | |||
64 | #include <linux/init.h> | 64 | #include <linux/init.h> |
65 | #include <linux/i2c.h> | 65 | #include <linux/i2c.h> |
66 | #include <linux/acpi.h> | 66 | #include <linux/acpi.h> |
67 | #include <asm/io.h> | 67 | #include <linux/io.h> |
68 | 68 | ||
69 | /* I801 SMBus address offsets */ | 69 | /* I801 SMBus address offsets */ |
70 | #define SMBHSTSTS (0 + i801_smba) | 70 | #define SMBHSTSTS (0 + i801_smba) |
@@ -583,6 +583,40 @@ static struct pci_device_id i801_ids[] = { | |||
583 | 583 | ||
584 | MODULE_DEVICE_TABLE (pci, i801_ids); | 584 | MODULE_DEVICE_TABLE (pci, i801_ids); |
585 | 585 | ||
586 | #if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE | ||
587 | static unsigned char apanel_addr; | ||
588 | |||
589 | /* Scan the system ROM for the signature "FJKEYINF" */ | ||
590 | static __init const void __iomem *bios_signature(const void __iomem *bios) | ||
591 | { | ||
592 | ssize_t offset; | ||
593 | const unsigned char signature[] = "FJKEYINF"; | ||
594 | |||
595 | for (offset = 0; offset < 0x10000; offset += 0x10) { | ||
596 | if (check_signature(bios + offset, signature, | ||
597 | sizeof(signature)-1)) | ||
598 | return bios + offset; | ||
599 | } | ||
600 | return NULL; | ||
601 | } | ||
602 | |||
603 | static void __init input_apanel_init(void) | ||
604 | { | ||
605 | void __iomem *bios; | ||
606 | const void __iomem *p; | ||
607 | |||
608 | bios = ioremap(0xF0000, 0x10000); /* Can't fail */ | ||
609 | p = bios_signature(bios); | ||
610 | if (p) { | ||
611 | /* just use the first address */ | ||
612 | apanel_addr = readb(p + 8 + 3) >> 1; | ||
613 | } | ||
614 | iounmap(bios); | ||
615 | } | ||
616 | #else | ||
617 | static void __init input_apanel_init(void) {} | ||
618 | #endif | ||
619 | |||
586 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) | 620 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) |
587 | { | 621 | { |
588 | unsigned char temp; | 622 | unsigned char temp; |
@@ -667,6 +701,19 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id | |||
667 | dev_err(&dev->dev, "Failed to add SMBus adapter\n"); | 701 | dev_err(&dev->dev, "Failed to add SMBus adapter\n"); |
668 | goto exit_release; | 702 | goto exit_release; |
669 | } | 703 | } |
704 | |||
705 | /* Register optional slaves */ | ||
706 | #if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE | ||
707 | if (apanel_addr) { | ||
708 | struct i2c_board_info info; | ||
709 | |||
710 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
711 | info.addr = apanel_addr; | ||
712 | strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE); | ||
713 | i2c_new_device(&i801_adapter, &info); | ||
714 | } | ||
715 | #endif | ||
716 | |||
670 | return 0; | 717 | return 0; |
671 | 718 | ||
672 | exit_release: | 719 | exit_release: |
@@ -717,6 +764,7 @@ static struct pci_driver i801_driver = { | |||
717 | 764 | ||
718 | static int __init i2c_i801_init(void) | 765 | static int __init i2c_i801_init(void) |
719 | { | 766 | { |
767 | input_apanel_init(); | ||
720 | return pci_register_driver(&i801_driver); | 768 | return pci_register_driver(&i801_driver); |
721 | } | 769 | } |
722 | 770 | ||
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 587f5b2380d4..6af68146c342 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -1076,10 +1076,10 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
1076 | 1076 | ||
1077 | #ifdef CONFIG_I2C_PXA_SLAVE | 1077 | #ifdef CONFIG_I2C_PXA_SLAVE |
1078 | printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n", | 1078 | printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n", |
1079 | i2c->adap.dev.bus_id, i2c->slave_addr); | 1079 | dev_name(&i2c->adap.dev), i2c->slave_addr); |
1080 | #else | 1080 | #else |
1081 | printk(KERN_INFO "I2C: %s: PXA I2C adapter\n", | 1081 | printk(KERN_INFO "I2C: %s: PXA I2C adapter\n", |
1082 | i2c->adap.dev.bus_id); | 1082 | dev_name(&i2c->adap.dev)); |
1083 | #endif | 1083 | #endif |
1084 | return 0; | 1084 | return 0; |
1085 | 1085 | ||
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index f69f91ffb469..5b7f95641ba4 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
@@ -906,7 +906,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) | |||
906 | 906 | ||
907 | platform_set_drvdata(pdev, i2c); | 907 | platform_set_drvdata(pdev, i2c); |
908 | 908 | ||
909 | dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id); | 909 | dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev)); |
910 | return 0; | 910 | return 0; |
911 | 911 | ||
912 | err_cpufreq: | 912 | err_cpufreq: |
diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index 5e0e254976de..baa28b73ae42 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c | |||
@@ -475,7 +475,7 @@ static int __devinit sh7760_i2c_probe(struct platform_device *pdev) | |||
475 | 475 | ||
476 | id->adap.nr = pdev->id; | 476 | id->adap.nr = pdev->id; |
477 | id->adap.algo = &sh7760_i2c_algo; | 477 | id->adap.algo = &sh7760_i2c_algo; |
478 | id->adap.class = I2C_CLASS_ALL; | 478 | id->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; |
479 | id->adap.retries = 3; | 479 | id->adap.retries = 3; |
480 | id->adap.algo_data = id; | 480 | id->adap.algo_data = id; |
481 | id->adap.dev.parent = &pdev->dev; | 481 | id->adap.dev.parent = &pdev->dev; |
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 6c3d60b939bf..1c01083b01b5 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c | |||
@@ -500,7 +500,7 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) | |||
500 | while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) { | 500 | while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) { |
501 | for (n = res->start; hook && n <= res->end; n++) { | 501 | for (n = res->start; hook && n <= res->end; n++) { |
502 | if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED, | 502 | if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED, |
503 | dev->dev.bus_id, dev)) | 503 | dev_name(&dev->dev), dev)) |
504 | goto rollback; | 504 | goto rollback; |
505 | } | 505 | } |
506 | k++; | 506 | k++; |
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index dfc2d5eb6a68..8ce2daff985c 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c | |||
@@ -389,8 +389,8 @@ static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_ | |||
389 | /* set up the sysfs linkage to our parent device */ | 389 | /* set up the sysfs linkage to our parent device */ |
390 | sis5595_adapter.dev.parent = &dev->dev; | 390 | sis5595_adapter.dev.parent = &dev->dev; |
391 | 391 | ||
392 | sprintf(sis5595_adapter.name, "SMBus SIS5595 adapter at %04x", | 392 | snprintf(sis5595_adapter.name, sizeof(sis5595_adapter.name), |
393 | sis5595_base + SMB_INDEX); | 393 | "SMBus SIS5595 adapter at %04x", sis5595_base + SMB_INDEX); |
394 | err = i2c_add_adapter(&sis5595_adapter); | 394 | err = i2c_add_adapter(&sis5595_adapter); |
395 | if (err) { | 395 | if (err) { |
396 | release_region(sis5595_base + SMB_INDEX, 2); | 396 | release_region(sis5595_base + SMB_INDEX, 2); |
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index e7c4b790da54..9c9c016ff2b5 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c | |||
@@ -487,8 +487,8 @@ static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_i | |||
487 | /* set up the sysfs linkage to our parent device */ | 487 | /* set up the sysfs linkage to our parent device */ |
488 | sis630_adapter.dev.parent = &dev->dev; | 488 | sis630_adapter.dev.parent = &dev->dev; |
489 | 489 | ||
490 | sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x", | 490 | snprintf(sis630_adapter.name, sizeof(sis630_adapter.name), |
491 | acpi_base + SMB_STS); | 491 | "SMBus SIS630 adapter at %04x", acpi_base + SMB_STS); |
492 | 492 | ||
493 | return i2c_add_adapter(&sis630_adapter); | 493 | return i2c_add_adapter(&sis630_adapter); |
494 | } | 494 | } |
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index 864ac561fdbb..59c3d23f5bdc 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig | |||
@@ -114,18 +114,6 @@ config SENSORS_PCF8591 | |||
114 | These devices are hard to detect and rarely found on mainstream | 114 | These devices are hard to detect and rarely found on mainstream |
115 | hardware. If unsure, say N. | 115 | hardware. If unsure, say N. |
116 | 116 | ||
117 | config ISP1301_OMAP | ||
118 | tristate "Philips ISP1301 with OMAP OTG" | ||
119 | depends on ARCH_OMAP_OTG | ||
120 | help | ||
121 | If you say yes here you get support for the Philips ISP1301 | ||
122 | USB-On-The-Go transceiver working with the OMAP OTG controller. | ||
123 | The ISP1301 is used in products including H2 and H3 development | ||
124 | boards for Texas Instruments OMAP processors. | ||
125 | |||
126 | This driver can also be built as a module. If so, the module | ||
127 | will be called isp1301_omap. | ||
128 | |||
129 | config SENSORS_MAX6875 | 117 | config SENSORS_MAX6875 |
130 | tristate "Maxim MAX6875 Power supply supervisor" | 118 | tristate "Maxim MAX6875 Power supply supervisor" |
131 | depends on EXPERIMENTAL | 119 | depends on EXPERIMENTAL |
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 8b95f41a5001..83accaaf8164 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile | |||
@@ -18,7 +18,6 @@ obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o | |||
18 | obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o | 18 | obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o |
19 | obj-$(CONFIG_PCF8575) += pcf8575.o | 19 | obj-$(CONFIG_PCF8575) += pcf8575.o |
20 | obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o | 20 | obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o |
21 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o | ||
22 | obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o | 21 | obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o |
23 | obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o | 22 | obj-$(CONFIG_MCU_MPC8349EMITX) += mcu_mpc8349emitx.o |
24 | 23 | ||
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index c6a63f46bc15..b1c9abe24c7b 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -459,7 +459,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) | |||
459 | pr_debug("I2C adapter driver [%s] forgot to specify " | 459 | pr_debug("I2C adapter driver [%s] forgot to specify " |
460 | "physical device\n", adap->name); | 460 | "physical device\n", adap->name); |
461 | } | 461 | } |
462 | sprintf(adap->dev.bus_id, "i2c-%d", adap->nr); | 462 | dev_set_name(&adap->dev, "i2c-%d", adap->nr); |
463 | adap->dev.release = &i2c_adapter_dev_release; | 463 | adap->dev.release = &i2c_adapter_dev_release; |
464 | adap->dev.class = &i2c_adapter_class; | 464 | adap->dev.class = &i2c_adapter_class; |
465 | res = device_register(&adap->dev); | 465 | res = device_register(&adap->dev); |
@@ -845,8 +845,8 @@ int i2c_attach_client(struct i2c_client *client) | |||
845 | } else | 845 | } else |
846 | client->dev.release = i2c_client_dev_release; | 846 | client->dev.release = i2c_client_dev_release; |
847 | 847 | ||
848 | snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id), | 848 | dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adapter), |
849 | "%d-%04x", i2c_adapter_id(adapter), client->addr); | 849 | client->addr); |
850 | res = device_register(&client->dev); | 850 | res = device_register(&client->dev); |
851 | if (res) | 851 | if (res) |
852 | goto out_err; | 852 | goto out_err; |
@@ -856,7 +856,7 @@ int i2c_attach_client(struct i2c_client *client) | |||
856 | mutex_unlock(&adapter->clist_lock); | 856 | mutex_unlock(&adapter->clist_lock); |
857 | 857 | ||
858 | dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", | 858 | dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n", |
859 | client->name, client->dev.bus_id); | 859 | client->name, dev_name(&client->dev)); |
860 | 860 | ||
861 | if (adapter->client_register) { | 861 | if (adapter->client_register) { |
862 | if (adapter->client_register(client)) { | 862 | if (adapter->client_register(client)) { |
diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c index c90be4070e40..31400c8ae051 100644 --- a/drivers/ieee1394/csr.c +++ b/drivers/ieee1394/csr.c | |||
@@ -68,22 +68,22 @@ static struct hpsb_highlevel csr_highlevel = { | |||
68 | .host_reset = host_reset, | 68 | .host_reset = host_reset, |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static struct hpsb_address_ops map_ops = { | 71 | const static struct hpsb_address_ops map_ops = { |
72 | .read = read_maps, | 72 | .read = read_maps, |
73 | }; | 73 | }; |
74 | 74 | ||
75 | static struct hpsb_address_ops fcp_ops = { | 75 | const static struct hpsb_address_ops fcp_ops = { |
76 | .write = write_fcp, | 76 | .write = write_fcp, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static struct hpsb_address_ops reg_ops = { | 79 | const static struct hpsb_address_ops reg_ops = { |
80 | .read = read_regs, | 80 | .read = read_regs, |
81 | .write = write_regs, | 81 | .write = write_regs, |
82 | .lock = lock_regs, | 82 | .lock = lock_regs, |
83 | .lock64 = lock64_regs, | 83 | .lock64 = lock64_regs, |
84 | }; | 84 | }; |
85 | 85 | ||
86 | static struct hpsb_address_ops config_rom_ops = { | 86 | const static struct hpsb_address_ops config_rom_ops = { |
87 | .read = read_config_rom, | 87 | .read = read_config_rom, |
88 | }; | 88 | }; |
89 | 89 | ||
@@ -217,7 +217,7 @@ static void add_host(struct hpsb_host *host) | |||
217 | 217 | ||
218 | host->csr.generation = 2; | 218 | host->csr.generation = 2; |
219 | 219 | ||
220 | bus_info[1] = __constant_cpu_to_be32(0x31333934); | 220 | bus_info[1] = IEEE1394_BUSID_MAGIC; |
221 | bus_info[2] = cpu_to_be32((hpsb_disable_irm ? 0 : 1 << CSR_IRMC_SHIFT) | | 221 | bus_info[2] = cpu_to_be32((hpsb_disable_irm ? 0 : 1 << CSR_IRMC_SHIFT) | |
222 | (1 << CSR_CMC_SHIFT) | | 222 | (1 << CSR_CMC_SHIFT) | |
223 | (1 << CSR_ISC_SHIFT) | | 223 | (1 << CSR_ISC_SHIFT) | |
@@ -250,7 +250,7 @@ static void remove_host(struct hpsb_host *host) | |||
250 | { | 250 | { |
251 | quadlet_t bus_info[CSR_BUS_INFO_SIZE]; | 251 | quadlet_t bus_info[CSR_BUS_INFO_SIZE]; |
252 | 252 | ||
253 | bus_info[1] = __constant_cpu_to_be32(0x31333934); | 253 | bus_info[1] = IEEE1394_BUSID_MAGIC; |
254 | bus_info[2] = cpu_to_be32((0 << CSR_IRMC_SHIFT) | | 254 | bus_info[2] = cpu_to_be32((0 << CSR_IRMC_SHIFT) | |
255 | (0 << CSR_CMC_SHIFT) | | 255 | (0 << CSR_CMC_SHIFT) | |
256 | (0 << CSR_ISC_SHIFT) | | 256 | (0 << CSR_ISC_SHIFT) | |
diff --git a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h index f11546550d84..90fb3f2192c3 100644 --- a/drivers/ieee1394/csr.h +++ b/drivers/ieee1394/csr.h | |||
@@ -50,11 +50,11 @@ | |||
50 | #define CSR_MAX_ROM_SHIFT 8 | 50 | #define CSR_MAX_ROM_SHIFT 8 |
51 | #define CSR_GENERATION_SHIFT 4 | 51 | #define CSR_GENERATION_SHIFT 4 |
52 | 52 | ||
53 | #define CSR_SET_BUS_INFO_GENERATION(csr, gen) \ | 53 | static inline void csr_set_bus_info_generation(struct csr1212_csr *csr, u8 gen) |
54 | ((csr)->bus_info_data[2] = \ | 54 | { |
55 | cpu_to_be32((be32_to_cpu((csr)->bus_info_data[2]) & \ | 55 | csr->bus_info_data[2] &= ~cpu_to_be32(0xf << CSR_GENERATION_SHIFT); |
56 | ~(0xf << CSR_GENERATION_SHIFT)) | \ | 56 | csr->bus_info_data[2] |= cpu_to_be32((u32)gen << CSR_GENERATION_SHIFT); |
57 | (gen) << CSR_GENERATION_SHIFT)) | 57 | } |
58 | 58 | ||
59 | struct csr_control { | 59 | struct csr_control { |
60 | spinlock_t lock; | 60 | spinlock_t lock; |
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c index 5e38a68b8af2..a6dfeb0b3372 100644 --- a/drivers/ieee1394/csr1212.c +++ b/drivers/ieee1394/csr1212.c | |||
@@ -1077,15 +1077,10 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) | |||
1077 | int i; | 1077 | int i; |
1078 | int ret; | 1078 | int ret; |
1079 | 1079 | ||
1080 | /* IEEE 1212 says that the entire bus info block should be readable in | ||
1081 | * a single transaction regardless of the max_rom value. | ||
1082 | * Unfortunately, many IEEE 1394 devices do not abide by that, so the | ||
1083 | * bus info block will be read 1 quadlet at a time. The rest of the | ||
1084 | * ConfigROM will be read according to the max_rom field. */ | ||
1085 | for (i = 0; i < csr->bus_info_len; i += sizeof(u32)) { | 1080 | for (i = 0; i < csr->bus_info_len; i += sizeof(u32)) { |
1086 | ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, | 1081 | ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, |
1087 | sizeof(u32), &csr->cache_head->data[bytes_to_quads(i)], | 1082 | &csr->cache_head->data[bytes_to_quads(i)], |
1088 | csr->private); | 1083 | csr->private); |
1089 | if (ret != CSR1212_SUCCESS) | 1084 | if (ret != CSR1212_SUCCESS) |
1090 | return ret; | 1085 | return ret; |
1091 | 1086 | ||
@@ -1104,8 +1099,8 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) | |||
1104 | * a time. */ | 1099 | * a time. */ |
1105 | for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(u32)) { | 1100 | for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(u32)) { |
1106 | ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, | 1101 | ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, |
1107 | sizeof(u32), &csr->cache_head->data[bytes_to_quads(i)], | 1102 | &csr->cache_head->data[bytes_to_quads(i)], |
1108 | csr->private); | 1103 | csr->private); |
1109 | if (ret != CSR1212_SUCCESS) | 1104 | if (ret != CSR1212_SUCCESS) |
1110 | return ret; | 1105 | return ret; |
1111 | } | 1106 | } |
@@ -1289,7 +1284,7 @@ csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) | |||
1289 | 1284 | ||
1290 | if (csr->ops->bus_read(csr, | 1285 | if (csr->ops->bus_read(csr, |
1291 | CSR1212_REGISTER_SPACE_BASE + kv->offset, | 1286 | CSR1212_REGISTER_SPACE_BASE + kv->offset, |
1292 | sizeof(u32), &q, csr->private)) | 1287 | &q, csr->private)) |
1293 | return -EIO; | 1288 | return -EIO; |
1294 | 1289 | ||
1295 | kv->value.leaf.len = be32_to_cpu(q) >> 16; | 1290 | kv->value.leaf.len = be32_to_cpu(q) >> 16; |
@@ -1372,17 +1367,8 @@ csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) | |||
1372 | addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset + | 1367 | addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset + |
1373 | cr->offset_end) & ~(csr->max_rom - 1); | 1368 | cr->offset_end) & ~(csr->max_rom - 1); |
1374 | 1369 | ||
1375 | if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr, | 1370 | if (csr->ops->bus_read(csr, addr, cache_ptr, csr->private)) |
1376 | csr->private)) { | 1371 | return -EIO; |
1377 | if (csr->max_rom == 4) | ||
1378 | /* We've got problems! */ | ||
1379 | return -EIO; | ||
1380 | |||
1381 | /* Apperently the max_rom value was a lie, set it to | ||
1382 | * do quadlet reads and try again. */ | ||
1383 | csr->max_rom = 4; | ||
1384 | continue; | ||
1385 | } | ||
1386 | 1372 | ||
1387 | cr->offset_end += csr->max_rom - (cr->offset_end & | 1373 | cr->offset_end += csr->max_rom - (cr->offset_end & |
1388 | (csr->max_rom - 1)); | 1374 | (csr->max_rom - 1)); |
@@ -1433,7 +1419,6 @@ csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) | |||
1433 | 1419 | ||
1434 | int csr1212_parse_csr(struct csr1212_csr *csr) | 1420 | int csr1212_parse_csr(struct csr1212_csr *csr) |
1435 | { | 1421 | { |
1436 | static const int mr_map[] = { 4, 64, 1024, 0 }; | ||
1437 | struct csr1212_dentry *dentry; | 1422 | struct csr1212_dentry *dentry; |
1438 | int ret; | 1423 | int ret; |
1439 | 1424 | ||
@@ -1443,15 +1428,13 @@ int csr1212_parse_csr(struct csr1212_csr *csr) | |||
1443 | if (ret != CSR1212_SUCCESS) | 1428 | if (ret != CSR1212_SUCCESS) |
1444 | return ret; | 1429 | return ret; |
1445 | 1430 | ||
1446 | if (!csr->ops->get_max_rom) { | 1431 | /* |
1447 | csr->max_rom = mr_map[0]; /* default value */ | 1432 | * There has been a buggy firmware with bus_info_block.max_rom > 0 |
1448 | } else { | 1433 | * spotted which actually only supported quadlet read requests to the |
1449 | int i = csr->ops->get_max_rom(csr->bus_info_data, | 1434 | * config ROM. Therefore read everything quadlet by quadlet regardless |
1450 | csr->private); | 1435 | * of what the bus info block says. |
1451 | if (i & ~0x3) | 1436 | */ |
1452 | return -EINVAL; | 1437 | csr->max_rom = 4; |
1453 | csr->max_rom = mr_map[i]; | ||
1454 | } | ||
1455 | 1438 | ||
1456 | csr->cache_head->layout_head = csr->root_kv; | 1439 | csr->cache_head->layout_head = csr->root_kv; |
1457 | csr->cache_head->layout_tail = csr->root_kv; | 1440 | csr->cache_head->layout_tail = csr->root_kv; |
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h index 043039fc63ec..a892d922dbc9 100644 --- a/drivers/ieee1394/csr1212.h +++ b/drivers/ieee1394/csr1212.h | |||
@@ -181,7 +181,7 @@ struct csr1212_csr_rom_cache { | |||
181 | struct csr1212_csr { | 181 | struct csr1212_csr { |
182 | size_t bus_info_len; /* bus info block length in bytes */ | 182 | size_t bus_info_len; /* bus info block length in bytes */ |
183 | size_t crc_len; /* crc length in bytes */ | 183 | size_t crc_len; /* crc length in bytes */ |
184 | u32 *bus_info_data; /* bus info data incl bus name and EUI */ | 184 | __be32 *bus_info_data; /* bus info data incl bus name and EUI */ |
185 | 185 | ||
186 | void *private; /* private, bus specific data */ | 186 | void *private; /* private, bus specific data */ |
187 | struct csr1212_bus_ops *ops; | 187 | struct csr1212_bus_ops *ops; |
@@ -200,7 +200,7 @@ struct csr1212_bus_ops { | |||
200 | * entries located in the Units Space. Must return 0 on success | 200 | * entries located in the Units Space. Must return 0 on success |
201 | * anything else indicates an error. */ | 201 | * anything else indicates an error. */ |
202 | int (*bus_read) (struct csr1212_csr *csr, u64 addr, | 202 | int (*bus_read) (struct csr1212_csr *csr, u64 addr, |
203 | u16 length, void *buffer, void *private); | 203 | void *buffer, void *private); |
204 | 204 | ||
205 | /* This function is used by csr1212 to allocate a region in units space | 205 | /* This function is used by csr1212 to allocate a region in units space |
206 | * in the event that Config ROM entries don't all fit in the predefined | 206 | * in the event that Config ROM entries don't all fit in the predefined |
@@ -211,11 +211,6 @@ struct csr1212_bus_ops { | |||
211 | /* This function is used by csr1212 to release a region in units space | 211 | /* This function is used by csr1212 to release a region in units space |
212 | * that is no longer needed. */ | 212 | * that is no longer needed. */ |
213 | void (*release_addr) (u64 addr, void *private); | 213 | void (*release_addr) (u64 addr, void *private); |
214 | |||
215 | /* This function is used by csr1212 to determine the max read request | ||
216 | * supported by a remote node when reading the ConfigROM space. Must | ||
217 | * return 0, 1, or 2 per IEEE 1212. */ | ||
218 | int (*get_max_rom) (u32 *bus_info, void *private); | ||
219 | }; | 214 | }; |
220 | 215 | ||
221 | 216 | ||
diff --git a/drivers/ieee1394/dv1394-private.h b/drivers/ieee1394/dv1394-private.h index 7d1d2845b420..18b92cbf4a9f 100644 --- a/drivers/ieee1394/dv1394-private.h +++ b/drivers/ieee1394/dv1394-private.h | |||
@@ -77,11 +77,11 @@ static inline void fill_cip_header(struct CIP_header *cip, | |||
77 | See the Texas Instruments OHCI 1394 chipset documentation. | 77 | See the Texas Instruments OHCI 1394 chipset documentation. |
78 | */ | 78 | */ |
79 | 79 | ||
80 | struct output_more_immediate { u32 q[8]; }; | 80 | struct output_more_immediate { __le32 q[8]; }; |
81 | struct output_more { u32 q[4]; }; | 81 | struct output_more { __le32 q[4]; }; |
82 | struct output_last { u32 q[4]; }; | 82 | struct output_last { __le32 q[4]; }; |
83 | struct input_more { u32 q[4]; }; | 83 | struct input_more { __le32 q[4]; }; |
84 | struct input_last { u32 q[4]; }; | 84 | struct input_last { __le32 q[4]; }; |
85 | 85 | ||
86 | /* outputs */ | 86 | /* outputs */ |
87 | 87 | ||
@@ -92,9 +92,9 @@ static inline void fill_output_more_immediate(struct output_more_immediate *omi, | |||
92 | unsigned int payload_size) | 92 | unsigned int payload_size) |
93 | { | 93 | { |
94 | omi->q[0] = cpu_to_le32(0x02000000 | 8); /* OUTPUT_MORE_IMMEDIATE; 8 is the size of the IT header */ | 94 | omi->q[0] = cpu_to_le32(0x02000000 | 8); /* OUTPUT_MORE_IMMEDIATE; 8 is the size of the IT header */ |
95 | omi->q[1] = 0; | 95 | omi->q[1] = cpu_to_le32(0); |
96 | omi->q[2] = 0; | 96 | omi->q[2] = cpu_to_le32(0); |
97 | omi->q[3] = 0; | 97 | omi->q[3] = cpu_to_le32(0); |
98 | 98 | ||
99 | /* IT packet header */ | 99 | /* IT packet header */ |
100 | omi->q[4] = cpu_to_le32( (0x0 << 16) /* IEEE1394_SPEED_100 */ | 100 | omi->q[4] = cpu_to_le32( (0x0 << 16) /* IEEE1394_SPEED_100 */ |
@@ -106,8 +106,8 @@ static inline void fill_output_more_immediate(struct output_more_immediate *omi, | |||
106 | /* reserved field; mimic behavior of my Sony DSR-40 */ | 106 | /* reserved field; mimic behavior of my Sony DSR-40 */ |
107 | omi->q[5] = cpu_to_le32((payload_size << 16) | (0x7F << 8) | 0xA0); | 107 | omi->q[5] = cpu_to_le32((payload_size << 16) | (0x7F << 8) | 0xA0); |
108 | 108 | ||
109 | omi->q[6] = 0; | 109 | omi->q[6] = cpu_to_le32(0); |
110 | omi->q[7] = 0; | 110 | omi->q[7] = cpu_to_le32(0); |
111 | } | 111 | } |
112 | 112 | ||
113 | static inline void fill_output_more(struct output_more *om, | 113 | static inline void fill_output_more(struct output_more *om, |
@@ -116,8 +116,8 @@ static inline void fill_output_more(struct output_more *om, | |||
116 | { | 116 | { |
117 | om->q[0] = cpu_to_le32(data_size); | 117 | om->q[0] = cpu_to_le32(data_size); |
118 | om->q[1] = cpu_to_le32(data_phys_addr); | 118 | om->q[1] = cpu_to_le32(data_phys_addr); |
119 | om->q[2] = 0; | 119 | om->q[2] = cpu_to_le32(0); |
120 | om->q[3] = 0; | 120 | om->q[3] = cpu_to_le32(0); |
121 | } | 121 | } |
122 | 122 | ||
123 | static inline void fill_output_last(struct output_last *ol, | 123 | static inline void fill_output_last(struct output_last *ol, |
@@ -140,8 +140,8 @@ static inline void fill_output_last(struct output_last *ol, | |||
140 | 140 | ||
141 | ol->q[0] = cpu_to_le32(temp); | 141 | ol->q[0] = cpu_to_le32(temp); |
142 | ol->q[1] = cpu_to_le32(data_phys_addr); | 142 | ol->q[1] = cpu_to_le32(data_phys_addr); |
143 | ol->q[2] = 0; | 143 | ol->q[2] = cpu_to_le32(0); |
144 | ol->q[3] = 0; | 144 | ol->q[3] = cpu_to_le32(0); |
145 | } | 145 | } |
146 | 146 | ||
147 | /* inputs */ | 147 | /* inputs */ |
@@ -161,8 +161,8 @@ static inline void fill_input_more(struct input_more *im, | |||
161 | 161 | ||
162 | im->q[0] = cpu_to_le32(temp); | 162 | im->q[0] = cpu_to_le32(temp); |
163 | im->q[1] = cpu_to_le32(data_phys_addr); | 163 | im->q[1] = cpu_to_le32(data_phys_addr); |
164 | im->q[2] = 0; /* branchAddress and Z not use in packet-per-buffer mode */ | 164 | im->q[2] = cpu_to_le32(0); /* branchAddress and Z not use in packet-per-buffer mode */ |
165 | im->q[3] = 0; /* xferStatus & resCount, resCount must be initialize to data_size */ | 165 | im->q[3] = cpu_to_le32(0); /* xferStatus & resCount, resCount must be initialize to data_size */ |
166 | } | 166 | } |
167 | 167 | ||
168 | static inline void fill_input_last(struct input_last *il, | 168 | static inline void fill_input_last(struct input_last *il, |
@@ -331,7 +331,7 @@ struct frame { | |||
331 | 331 | ||
332 | /* points to status/timestamp field of first DMA packet */ | 332 | /* points to status/timestamp field of first DMA packet */ |
333 | /* (we'll check it later to monitor timestamp accuracy) */ | 333 | /* (we'll check it later to monitor timestamp accuracy) */ |
334 | u32 *frame_begin_timestamp; | 334 | __le32 *frame_begin_timestamp; |
335 | 335 | ||
336 | /* the timestamp we assigned to the first packet in the frame */ | 336 | /* the timestamp we assigned to the first packet in the frame */ |
337 | u32 assigned_timestamp; | 337 | u32 assigned_timestamp; |
@@ -348,15 +348,15 @@ struct frame { | |||
348 | that can cause interrupts. We'll check these from the | 348 | that can cause interrupts. We'll check these from the |
349 | interrupt handler. | 349 | interrupt handler. |
350 | */ | 350 | */ |
351 | u32 *mid_frame_timestamp; | 351 | __le32 *mid_frame_timestamp; |
352 | u32 *frame_end_timestamp; | 352 | __le32 *frame_end_timestamp; |
353 | 353 | ||
354 | /* branch address field of final packet. This is effectively | 354 | /* branch address field of final packet. This is effectively |
355 | the "tail" in the chain of DMA descriptor blocks. | 355 | the "tail" in the chain of DMA descriptor blocks. |
356 | We will fill it with the address of the first DMA descriptor | 356 | We will fill it with the address of the first DMA descriptor |
357 | block in the subsequent frame, once it is ready. | 357 | block in the subsequent frame, once it is ready. |
358 | */ | 358 | */ |
359 | u32 *frame_end_branch; | 359 | __le32 *frame_end_branch; |
360 | 360 | ||
361 | /* the number of descriptors in the first descriptor block | 361 | /* the number of descriptors in the first descriptor block |
362 | of the frame. Needed to start DMA */ | 362 | of the frame. Needed to start DMA */ |
@@ -365,10 +365,10 @@ struct frame { | |||
365 | 365 | ||
366 | 366 | ||
367 | struct packet { | 367 | struct packet { |
368 | u16 timestamp; | 368 | __le16 timestamp; |
369 | u16 invalid; | 369 | u16 invalid; |
370 | u16 iso_header; | 370 | u16 iso_header; |
371 | u16 data_length; | 371 | __le16 data_length; |
372 | u32 cip_h1; | 372 | u32 cip_h1; |
373 | u32 cip_h2; | 373 | u32 cip_h2; |
374 | unsigned char data[480]; | 374 | unsigned char data[480]; |
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index c19f23267157..a329e6bd5d2d 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c | |||
@@ -265,7 +265,7 @@ static void frame_prepare(struct video_card *video, unsigned int this_frame) | |||
265 | /* these flags denote packets that need special attention */ | 265 | /* these flags denote packets that need special attention */ |
266 | int empty_packet, first_packet, last_packet, mid_packet; | 266 | int empty_packet, first_packet, last_packet, mid_packet; |
267 | 267 | ||
268 | u32 *branch_address, *last_branch_address = NULL; | 268 | __le32 *branch_address, *last_branch_address = NULL; |
269 | unsigned long data_p; | 269 | unsigned long data_p; |
270 | int first_packet_empty = 0; | 270 | int first_packet_empty = 0; |
271 | u32 cycleTimer, ct_sec, ct_cyc, ct_off; | 271 | u32 cycleTimer, ct_sec, ct_cyc, ct_off; |
@@ -848,7 +848,7 @@ static void receive_packets(struct video_card *video) | |||
848 | dma_addr_t block_dma = 0; | 848 | dma_addr_t block_dma = 0; |
849 | struct packet *data = NULL; | 849 | struct packet *data = NULL; |
850 | dma_addr_t data_dma = 0; | 850 | dma_addr_t data_dma = 0; |
851 | u32 *last_branch_address = NULL; | 851 | __le32 *last_branch_address = NULL; |
852 | unsigned long irq_flags; | 852 | unsigned long irq_flags; |
853 | int want_interrupt = 0; | 853 | int want_interrupt = 0; |
854 | struct frame *f = NULL; | 854 | struct frame *f = NULL; |
@@ -2110,17 +2110,17 @@ static void ir_tasklet_func(unsigned long data) | |||
2110 | f = video->frames[next_i / MAX_PACKETS]; | 2110 | f = video->frames[next_i / MAX_PACKETS]; |
2111 | next = &(f->descriptor_pool[next_i % MAX_PACKETS]); | 2111 | next = &(f->descriptor_pool[next_i % MAX_PACKETS]); |
2112 | next_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; | 2112 | next_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; |
2113 | next->u.in.il.q[0] |= 3 << 20; /* enable interrupt */ | 2113 | next->u.in.il.q[0] |= cpu_to_le32(3 << 20); /* enable interrupt */ |
2114 | next->u.in.il.q[2] = 0; /* disable branch */ | 2114 | next->u.in.il.q[2] = cpu_to_le32(0); /* disable branch */ |
2115 | 2115 | ||
2116 | /* link previous to next */ | 2116 | /* link previous to next */ |
2117 | prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1); | 2117 | prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1); |
2118 | f = video->frames[prev_i / MAX_PACKETS]; | 2118 | f = video->frames[prev_i / MAX_PACKETS]; |
2119 | prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]); | 2119 | prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]); |
2120 | if (prev_i % (MAX_PACKETS/2)) { | 2120 | if (prev_i % (MAX_PACKETS/2)) { |
2121 | prev->u.in.il.q[0] &= ~(3 << 20); /* no interrupt */ | 2121 | prev->u.in.il.q[0] &= ~cpu_to_le32(3 << 20); /* no interrupt */ |
2122 | } else { | 2122 | } else { |
2123 | prev->u.in.il.q[0] |= 3 << 20; /* enable interrupt */ | 2123 | prev->u.in.il.q[0] |= cpu_to_le32(3 << 20); /* enable interrupt */ |
2124 | } | 2124 | } |
2125 | prev->u.in.il.q[2] = cpu_to_le32(next_dma | 1); /* set Z=1 */ | 2125 | prev->u.in.il.q[2] = cpu_to_le32(next_dma | 1); /* set Z=1 */ |
2126 | wmb(); | 2126 | wmb(); |
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 20128692b339..a074bfd5f825 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c | |||
@@ -92,7 +92,7 @@ struct partial_datagram { | |||
92 | struct list_head list; | 92 | struct list_head list; |
93 | u16 dgl; | 93 | u16 dgl; |
94 | u16 dg_size; | 94 | u16 dg_size; |
95 | u16 ether_type; | 95 | __be16 ether_type; |
96 | struct sk_buff *skb; | 96 | struct sk_buff *skb; |
97 | char *pbuf; | 97 | char *pbuf; |
98 | struct list_head frag_info; | 98 | struct list_head frag_info; |
@@ -181,7 +181,7 @@ static void ether1394_remove_host(struct hpsb_host *host); | |||
181 | static void ether1394_host_reset(struct hpsb_host *host); | 181 | static void ether1394_host_reset(struct hpsb_host *host); |
182 | 182 | ||
183 | /* Function for incoming 1394 packets */ | 183 | /* Function for incoming 1394 packets */ |
184 | static struct hpsb_address_ops addr_ops = { | 184 | const static struct hpsb_address_ops addr_ops = { |
185 | .write = ether1394_write, | 185 | .write = ether1394_write, |
186 | }; | 186 | }; |
187 | 187 | ||
@@ -767,7 +767,7 @@ static int ether1394_header_parse(const struct sk_buff *skb, | |||
767 | static int ether1394_header_cache(const struct neighbour *neigh, | 767 | static int ether1394_header_cache(const struct neighbour *neigh, |
768 | struct hh_cache *hh) | 768 | struct hh_cache *hh) |
769 | { | 769 | { |
770 | unsigned short type = hh->hh_type; | 770 | __be16 type = hh->hh_type; |
771 | struct net_device *dev = neigh->dev; | 771 | struct net_device *dev = neigh->dev; |
772 | struct eth1394hdr *eth = | 772 | struct eth1394hdr *eth = |
773 | (struct eth1394hdr *)((u8 *)hh->hh_data + 16 - ETH1394_HLEN); | 773 | (struct eth1394hdr *)((u8 *)hh->hh_data + 16 - ETH1394_HLEN); |
@@ -795,7 +795,7 @@ static void ether1394_header_cache_update(struct hh_cache *hh, | |||
795 | ******************************************/ | 795 | ******************************************/ |
796 | 796 | ||
797 | /* Copied from net/ethernet/eth.c */ | 797 | /* Copied from net/ethernet/eth.c */ |
798 | static u16 ether1394_type_trans(struct sk_buff *skb, struct net_device *dev) | 798 | static __be16 ether1394_type_trans(struct sk_buff *skb, struct net_device *dev) |
799 | { | 799 | { |
800 | struct eth1394hdr *eth; | 800 | struct eth1394hdr *eth; |
801 | unsigned char *rawp; | 801 | unsigned char *rawp; |
@@ -829,17 +829,17 @@ static u16 ether1394_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
829 | 829 | ||
830 | /* Parse an encapsulated IP1394 header into an ethernet frame packet. | 830 | /* Parse an encapsulated IP1394 header into an ethernet frame packet. |
831 | * We also perform ARP translation here, if need be. */ | 831 | * We also perform ARP translation here, if need be. */ |
832 | static u16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev, | 832 | static __be16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev, |
833 | nodeid_t srcid, nodeid_t destid, | 833 | nodeid_t srcid, nodeid_t destid, |
834 | u16 ether_type) | 834 | __be16 ether_type) |
835 | { | 835 | { |
836 | struct eth1394_priv *priv = netdev_priv(dev); | 836 | struct eth1394_priv *priv = netdev_priv(dev); |
837 | u64 dest_hw; | 837 | __be64 dest_hw; |
838 | unsigned short ret = 0; | 838 | __be16 ret = 0; |
839 | 839 | ||
840 | /* Setup our hw addresses. We use these to build the ethernet header. */ | 840 | /* Setup our hw addresses. We use these to build the ethernet header. */ |
841 | if (destid == (LOCAL_BUS | ALL_NODES)) | 841 | if (destid == (LOCAL_BUS | ALL_NODES)) |
842 | dest_hw = ~0ULL; /* broadcast */ | 842 | dest_hw = ~cpu_to_be64(0); /* broadcast */ |
843 | else | 843 | else |
844 | dest_hw = cpu_to_be64((u64)priv->host->csr.guid_hi << 32 | | 844 | dest_hw = cpu_to_be64((u64)priv->host->csr.guid_hi << 32 | |
845 | priv->host->csr.guid_lo); | 845 | priv->host->csr.guid_lo); |
@@ -873,7 +873,7 @@ static u16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev, | |||
873 | node = eth1394_find_node_guid(&priv->ip_node_list, | 873 | node = eth1394_find_node_guid(&priv->ip_node_list, |
874 | be64_to_cpu(guid)); | 874 | be64_to_cpu(guid)); |
875 | if (!node) | 875 | if (!node) |
876 | return 0; | 876 | return cpu_to_be16(0); |
877 | 877 | ||
878 | node_info = | 878 | node_info = |
879 | (struct eth1394_node_info *)node->ud->device.driver_data; | 879 | (struct eth1394_node_info *)node->ud->device.driver_data; |
@@ -1063,7 +1063,7 @@ static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, | |||
1063 | unsigned long flags; | 1063 | unsigned long flags; |
1064 | struct eth1394_priv *priv = netdev_priv(dev); | 1064 | struct eth1394_priv *priv = netdev_priv(dev); |
1065 | union eth1394_hdr *hdr = (union eth1394_hdr *)buf; | 1065 | union eth1394_hdr *hdr = (union eth1394_hdr *)buf; |
1066 | u16 ether_type = 0; /* initialized to clear warning */ | 1066 | __be16 ether_type = cpu_to_be16(0); /* initialized to clear warning */ |
1067 | int hdr_len; | 1067 | int hdr_len; |
1068 | struct unit_directory *ud = priv->ud_list[NODEID_TO_NODE(srcid)]; | 1068 | struct unit_directory *ud = priv->ud_list[NODEID_TO_NODE(srcid)]; |
1069 | struct eth1394_node_info *node_info; | 1069 | struct eth1394_node_info *node_info; |
@@ -1259,7 +1259,7 @@ static int ether1394_write(struct hpsb_host *host, int srcid, int destid, | |||
1259 | 1259 | ||
1260 | static void ether1394_iso(struct hpsb_iso *iso) | 1260 | static void ether1394_iso(struct hpsb_iso *iso) |
1261 | { | 1261 | { |
1262 | quadlet_t *data; | 1262 | __be32 *data; |
1263 | char *buf; | 1263 | char *buf; |
1264 | struct eth1394_host_info *hi; | 1264 | struct eth1394_host_info *hi; |
1265 | struct net_device *dev; | 1265 | struct net_device *dev; |
@@ -1283,7 +1283,7 @@ static void ether1394_iso(struct hpsb_iso *iso) | |||
1283 | for (i = 0; i < nready; i++) { | 1283 | for (i = 0; i < nready; i++) { |
1284 | struct hpsb_iso_packet_info *info = | 1284 | struct hpsb_iso_packet_info *info = |
1285 | &iso->infos[(iso->first_packet + i) % iso->buf_packets]; | 1285 | &iso->infos[(iso->first_packet + i) % iso->buf_packets]; |
1286 | data = (quadlet_t *)(iso->data_buf.kvirt + info->offset); | 1286 | data = (__be32 *)(iso->data_buf.kvirt + info->offset); |
1287 | 1287 | ||
1288 | /* skip over GASP header */ | 1288 | /* skip over GASP header */ |
1289 | buf = (char *)data + 8; | 1289 | buf = (char *)data + 8; |
@@ -1614,7 +1614,7 @@ static int ether1394_tx(struct sk_buff *skb, struct net_device *dev) | |||
1614 | if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) | 1614 | if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) |
1615 | priv->bc_dgl++; | 1615 | priv->bc_dgl++; |
1616 | } else { | 1616 | } else { |
1617 | __be64 guid = get_unaligned((u64 *)hdr_buf.h_dest); | 1617 | __be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest); |
1618 | 1618 | ||
1619 | node = eth1394_find_node_guid(&priv->ip_node_list, | 1619 | node = eth1394_find_node_guid(&priv->ip_node_list, |
1620 | be64_to_cpu(guid)); | 1620 | be64_to_cpu(guid)); |
diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h index 4f3e2dd46f00..e1b5ea80f623 100644 --- a/drivers/ieee1394/eth1394.h +++ b/drivers/ieee1394/eth1394.h | |||
@@ -82,7 +82,7 @@ struct eth1394_priv { | |||
82 | 82 | ||
83 | struct eth1394hdr { | 83 | struct eth1394hdr { |
84 | unsigned char h_dest[ETH1394_ALEN]; /* destination eth1394 addr */ | 84 | unsigned char h_dest[ETH1394_ALEN]; /* destination eth1394 addr */ |
85 | unsigned short h_proto; /* packet type ID field */ | 85 | __be16 h_proto; /* packet type ID field */ |
86 | } __attribute__((packed)); | 86 | } __attribute__((packed)); |
87 | 87 | ||
88 | static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb) | 88 | static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb) |
@@ -99,13 +99,13 @@ typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type; | |||
99 | struct eth1394_uf_hdr { | 99 | struct eth1394_uf_hdr { |
100 | u16 lf:2; | 100 | u16 lf:2; |
101 | u16 res:14; | 101 | u16 res:14; |
102 | u16 ether_type; /* Ethernet packet type */ | 102 | __be16 ether_type; /* Ethernet packet type */ |
103 | } __attribute__((packed)); | 103 | } __attribute__((packed)); |
104 | #elif defined __LITTLE_ENDIAN_BITFIELD | 104 | #elif defined __LITTLE_ENDIAN_BITFIELD |
105 | struct eth1394_uf_hdr { | 105 | struct eth1394_uf_hdr { |
106 | u16 res:14; | 106 | u16 res:14; |
107 | u16 lf:2; | 107 | u16 lf:2; |
108 | u16 ether_type; | 108 | __be16 ether_type; |
109 | } __attribute__((packed)); | 109 | } __attribute__((packed)); |
110 | #else | 110 | #else |
111 | #error Unknown bit field type | 111 | #error Unknown bit field type |
@@ -117,7 +117,7 @@ struct eth1394_ff_hdr { | |||
117 | u16 lf:2; | 117 | u16 lf:2; |
118 | u16 res1:2; | 118 | u16 res1:2; |
119 | u16 dg_size:12; /* Datagram size */ | 119 | u16 dg_size:12; /* Datagram size */ |
120 | u16 ether_type; /* Ethernet packet type */ | 120 | __be16 ether_type; /* Ethernet packet type */ |
121 | u16 dgl; /* Datagram label */ | 121 | u16 dgl; /* Datagram label */ |
122 | u16 res2; | 122 | u16 res2; |
123 | } __attribute__((packed)); | 123 | } __attribute__((packed)); |
@@ -126,7 +126,7 @@ struct eth1394_ff_hdr { | |||
126 | u16 dg_size:12; | 126 | u16 dg_size:12; |
127 | u16 res1:2; | 127 | u16 res1:2; |
128 | u16 lf:2; | 128 | u16 lf:2; |
129 | u16 ether_type; | 129 | __be16 ether_type; |
130 | u16 dgl; | 130 | u16 dgl; |
131 | u16 res2; | 131 | u16 res2; |
132 | } __attribute__((packed)); | 132 | } __attribute__((packed)); |
@@ -207,11 +207,11 @@ struct eth1394_arp { | |||
207 | u16 opcode; /* ARP Opcode */ | 207 | u16 opcode; /* ARP Opcode */ |
208 | /* Above is exactly the same format as struct arphdr */ | 208 | /* Above is exactly the same format as struct arphdr */ |
209 | 209 | ||
210 | u64 s_uniq_id; /* Sender's 64bit EUI */ | 210 | __be64 s_uniq_id; /* Sender's 64bit EUI */ |
211 | u8 max_rec; /* Sender's max packet size */ | 211 | u8 max_rec; /* Sender's max packet size */ |
212 | u8 sspd; /* Sender's max speed */ | 212 | u8 sspd; /* Sender's max speed */ |
213 | u16 fifo_hi; /* hi 16bits of sender's FIFO addr */ | 213 | __be16 fifo_hi; /* hi 16bits of sender's FIFO addr */ |
214 | u32 fifo_lo; /* lo 32bits of sender's FIFO addr */ | 214 | __be32 fifo_lo; /* lo 32bits of sender's FIFO addr */ |
215 | u32 sip; /* Sender's IP Address */ | 215 | u32 sip; /* Sender's IP Address */ |
216 | u32 tip; /* IP Address of requested hw addr */ | 216 | u32 tip; /* IP Address of requested hw addr */ |
217 | }; | 217 | }; |
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c index 272543a42a43..600e391c8fe7 100644 --- a/drivers/ieee1394/highlevel.c +++ b/drivers/ieee1394/highlevel.c | |||
@@ -320,7 +320,7 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) | |||
320 | */ | 320 | */ |
321 | u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, | 321 | u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, |
322 | struct hpsb_host *host, | 322 | struct hpsb_host *host, |
323 | struct hpsb_address_ops *ops, | 323 | const struct hpsb_address_ops *ops, |
324 | u64 size, u64 alignment, | 324 | u64 size, u64 alignment, |
325 | u64 start, u64 end) | 325 | u64 start, u64 end) |
326 | { | 326 | { |
@@ -407,7 +407,8 @@ u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, | |||
407 | * are automatically deallocated together with the hpsb_highlevel @hl. | 407 | * are automatically deallocated together with the hpsb_highlevel @hl. |
408 | */ | 408 | */ |
409 | int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, | 409 | int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, |
410 | struct hpsb_address_ops *ops, u64 start, u64 end) | 410 | const struct hpsb_address_ops *ops, |
411 | u64 start, u64 end) | ||
411 | { | 412 | { |
412 | struct hpsb_address_serve *as; | 413 | struct hpsb_address_serve *as; |
413 | struct list_head *lh; | 414 | struct list_head *lh; |
@@ -420,7 +421,7 @@ int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, | |||
420 | return 0; | 421 | return 0; |
421 | } | 422 | } |
422 | 423 | ||
423 | as = kmalloc(sizeof(*as), GFP_ATOMIC); | 424 | as = kmalloc(sizeof(*as), GFP_KERNEL); |
424 | if (!as) | 425 | if (!as) |
425 | return 0; | 426 | return 0; |
426 | 427 | ||
@@ -477,7 +478,7 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, | |||
477 | return retval; | 478 | return retval; |
478 | } | 479 | } |
479 | 480 | ||
480 | static struct hpsb_address_ops dummy_ops; | 481 | const static struct hpsb_address_ops dummy_ops; |
481 | 482 | ||
482 | /* dummy address spaces as lower and upper bounds of the host's a.s. list */ | 483 | /* dummy address spaces as lower and upper bounds of the host's a.s. list */ |
483 | static void init_hpsb_highlevel(struct hpsb_host *host) | 484 | static void init_hpsb_highlevel(struct hpsb_host *host) |
diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h index bc5d0854c17e..9dba89fc60ad 100644 --- a/drivers/ieee1394/highlevel.h +++ b/drivers/ieee1394/highlevel.h | |||
@@ -15,7 +15,7 @@ struct hpsb_host; | |||
15 | struct hpsb_address_serve { | 15 | struct hpsb_address_serve { |
16 | struct list_head host_list; /* per host list */ | 16 | struct list_head host_list; /* per host list */ |
17 | struct list_head hl_list; /* hpsb_highlevel list */ | 17 | struct list_head hl_list; /* hpsb_highlevel list */ |
18 | struct hpsb_address_ops *op; | 18 | const struct hpsb_address_ops *op; |
19 | struct hpsb_host *host; | 19 | struct hpsb_host *host; |
20 | u64 start; /* first address handled, quadlet aligned */ | 20 | u64 start; /* first address handled, quadlet aligned */ |
21 | u64 end; /* first address behind, quadlet aligned */ | 21 | u64 end; /* first address behind, quadlet aligned */ |
@@ -119,11 +119,12 @@ void hpsb_unregister_highlevel(struct hpsb_highlevel *hl); | |||
119 | 119 | ||
120 | u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, | 120 | u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl, |
121 | struct hpsb_host *host, | 121 | struct hpsb_host *host, |
122 | struct hpsb_address_ops *ops, | 122 | const struct hpsb_address_ops *ops, |
123 | u64 size, u64 alignment, | 123 | u64 size, u64 alignment, |
124 | u64 start, u64 end); | 124 | u64 start, u64 end); |
125 | int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, | 125 | int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, |
126 | struct hpsb_address_ops *ops, u64 start, u64 end); | 126 | const struct hpsb_address_ops *ops, |
127 | u64 start, u64 end); | ||
127 | int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, | 128 | int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, |
128 | u64 start); | 129 | u64 start); |
129 | 130 | ||
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c index 237d0c9d69c6..e947d8ffac85 100644 --- a/drivers/ieee1394/hosts.c +++ b/drivers/ieee1394/hosts.c | |||
@@ -34,18 +34,18 @@ static void delayed_reset_bus(struct work_struct *work) | |||
34 | { | 34 | { |
35 | struct hpsb_host *host = | 35 | struct hpsb_host *host = |
36 | container_of(work, struct hpsb_host, delayed_reset.work); | 36 | container_of(work, struct hpsb_host, delayed_reset.work); |
37 | int generation = host->csr.generation + 1; | 37 | u8 generation = host->csr.generation + 1; |
38 | 38 | ||
39 | /* The generation field rolls over to 2 rather than 0 per IEEE | 39 | /* The generation field rolls over to 2 rather than 0 per IEEE |
40 | * 1394a-2000. */ | 40 | * 1394a-2000. */ |
41 | if (generation > 0xf || generation < 2) | 41 | if (generation > 0xf || generation < 2) |
42 | generation = 2; | 42 | generation = 2; |
43 | 43 | ||
44 | CSR_SET_BUS_INFO_GENERATION(host->csr.rom, generation); | 44 | csr_set_bus_info_generation(host->csr.rom, generation); |
45 | if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) { | 45 | if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) { |
46 | /* CSR image creation failed. | 46 | /* CSR image creation failed. |
47 | * Reset generation field and do not issue a bus reset. */ | 47 | * Reset generation field and do not issue a bus reset. */ |
48 | CSR_SET_BUS_INFO_GENERATION(host->csr.rom, | 48 | csr_set_bus_info_generation(host->csr.rom, |
49 | host->csr.generation); | 49 | host->csr.generation); |
50 | return; | 50 | return; |
51 | } | 51 | } |
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h index dd229950acca..49c359022c54 100644 --- a/drivers/ieee1394/hosts.h +++ b/drivers/ieee1394/hosts.h | |||
@@ -154,7 +154,7 @@ struct hpsb_host_driver { | |||
154 | * to set the hardware ConfigROM if the hardware supports handling | 154 | * to set the hardware ConfigROM if the hardware supports handling |
155 | * reads to the ConfigROM on its own. */ | 155 | * reads to the ConfigROM on its own. */ |
156 | void (*set_hw_config_rom)(struct hpsb_host *host, | 156 | void (*set_hw_config_rom)(struct hpsb_host *host, |
157 | quadlet_t *config_rom); | 157 | __be32 *config_rom); |
158 | 158 | ||
159 | /* This function shall implement packet transmission based on | 159 | /* This function shall implement packet transmission based on |
160 | * packet->type. It shall CRC both parts of the packet (unless | 160 | * packet->type. It shall CRC both parts of the packet (unless |
diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h index 40492074c013..e0ae0d3d747f 100644 --- a/drivers/ieee1394/ieee1394.h +++ b/drivers/ieee1394/ieee1394.h | |||
@@ -121,6 +121,9 @@ extern const char *hpsb_speedto_str[]; | |||
121 | 121 | ||
122 | #include <asm/byteorder.h> | 122 | #include <asm/byteorder.h> |
123 | 123 | ||
124 | /* '1' '3' '9' '4' in ASCII */ | ||
125 | #define IEEE1394_BUSID_MAGIC cpu_to_be32(0x31333934) | ||
126 | |||
124 | #ifdef __BIG_ENDIAN_BITFIELD | 127 | #ifdef __BIG_ENDIAN_BITFIELD |
125 | 128 | ||
126 | struct selfid { | 129 | struct selfid { |
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 79ef5fd928ae..906c5a98d814 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -67,7 +67,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr, | |||
67 | for (i = IEEE1394_SPEED_100; i <= old_speed; i++) { | 67 | for (i = IEEE1394_SPEED_100; i <= old_speed; i++) { |
68 | *speed = i; | 68 | *speed = i; |
69 | error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, | 69 | error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, |
70 | &q, sizeof(quadlet_t)); | 70 | &q, 4); |
71 | if (error) | 71 | if (error) |
72 | break; | 72 | break; |
73 | *buffer = q; | 73 | *buffer = q; |
@@ -85,7 +85,7 @@ static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr, | |||
85 | return error; | 85 | return error; |
86 | } | 86 | } |
87 | 87 | ||
88 | static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, | 88 | static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, |
89 | void *buffer, void *__ci) | 89 | void *buffer, void *__ci) |
90 | { | 90 | { |
91 | struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci; | 91 | struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci; |
@@ -93,7 +93,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, | |||
93 | 93 | ||
94 | for (i = 1; ; i++) { | 94 | for (i = 1; ; i++) { |
95 | error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, | 95 | error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, |
96 | buffer, length); | 96 | buffer, 4); |
97 | if (!error) { | 97 | if (!error) { |
98 | ci->speed_unverified = 0; | 98 | ci->speed_unverified = 0; |
99 | break; | 99 | break; |
@@ -104,7 +104,7 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, | |||
104 | 104 | ||
105 | /* The ieee1394_core guessed the node's speed capability from | 105 | /* The ieee1394_core guessed the node's speed capability from |
106 | * the self ID. Check whether a lower speed works. */ | 106 | * the self ID. Check whether a lower speed works. */ |
107 | if (ci->speed_unverified && length == sizeof(quadlet_t)) { | 107 | if (ci->speed_unverified) { |
108 | error = nodemgr_check_speed(ci, addr, buffer); | 108 | error = nodemgr_check_speed(ci, addr, buffer); |
109 | if (!error) | 109 | if (!error) |
110 | break; | 110 | break; |
@@ -115,20 +115,8 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, | |||
115 | return error; | 115 | return error; |
116 | } | 116 | } |
117 | 117 | ||
118 | #define OUI_FREECOM_TECHNOLOGIES_GMBH 0x0001db | ||
119 | |||
120 | static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci) | ||
121 | { | ||
122 | /* Freecom FireWire Hard Drive firmware bug */ | ||
123 | if (be32_to_cpu(bus_info_data[3]) >> 8 == OUI_FREECOM_TECHNOLOGIES_GMBH) | ||
124 | return 0; | ||
125 | |||
126 | return (be32_to_cpu(bus_info_data[2]) >> 8) & 0x3; | ||
127 | } | ||
128 | |||
129 | static struct csr1212_bus_ops nodemgr_csr_ops = { | 118 | static struct csr1212_bus_ops nodemgr_csr_ops = { |
130 | .bus_read = nodemgr_bus_read, | 119 | .bus_read = nodemgr_bus_read, |
131 | .get_max_rom = nodemgr_get_max_rom | ||
132 | }; | 120 | }; |
133 | 121 | ||
134 | 122 | ||
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index 4f287a3561ba..15ea09733e84 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h | |||
@@ -31,9 +31,6 @@ struct csr1212_keyval; | |||
31 | struct hpsb_host; | 31 | struct hpsb_host; |
32 | struct ieee1394_device_id; | 32 | struct ieee1394_device_id; |
33 | 33 | ||
34 | /* '1' '3' '9' '4' in ASCII */ | ||
35 | #define IEEE1394_BUSID_MAGIC __constant_cpu_to_be32(0x31333934) | ||
36 | |||
37 | /* This is the start of a Node entry structure. It should be a stable API | 34 | /* This is the start of a Node entry structure. It should be a stable API |
38 | * for which to gather info from the Node Manager about devices attached | 35 | * for which to gather info from the Node Manager about devices attached |
39 | * to the bus. */ | 36 | * to the bus. */ |
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index e509e13cb7a7..65c1429e4129 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c | |||
@@ -2973,7 +2973,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, | |||
2973 | return 0; | 2973 | return 0; |
2974 | } | 2974 | } |
2975 | 2975 | ||
2976 | static void ohci_set_hw_config_rom(struct hpsb_host *host, quadlet_t *config_rom) | 2976 | static void ohci_set_hw_config_rom(struct hpsb_host *host, __be32 *config_rom) |
2977 | { | 2977 | { |
2978 | struct ti_ohci *ohci = host->hostdata; | 2978 | struct ti_ohci *ohci = host->hostdata; |
2979 | 2979 | ||
@@ -3199,15 +3199,16 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, | |||
3199 | /* Now enable LPS, which we need in order to start accessing | 3199 | /* Now enable LPS, which we need in order to start accessing |
3200 | * most of the registers. In fact, on some cards (ALI M5251), | 3200 | * most of the registers. In fact, on some cards (ALI M5251), |
3201 | * accessing registers in the SClk domain without LPS enabled | 3201 | * accessing registers in the SClk domain without LPS enabled |
3202 | * will lock up the machine. Wait 50msec to make sure we have | 3202 | * will lock up the machine. */ |
3203 | * full link enabled. */ | ||
3204 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); | 3203 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); |
3205 | 3204 | ||
3206 | /* Disable and clear interrupts */ | 3205 | /* Disable and clear interrupts */ |
3207 | reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); | 3206 | reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); |
3208 | reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); | 3207 | reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); |
3209 | 3208 | ||
3210 | mdelay(50); | 3209 | /* Flush MMIO writes and wait to make sure we have full link enabled. */ |
3210 | reg_read(ohci, OHCI1394_Version); | ||
3211 | msleep(50); | ||
3211 | 3212 | ||
3212 | /* Determine the number of available IR and IT contexts. */ | 3213 | /* Determine the number of available IR and IT contexts. */ |
3213 | ohci->nb_iso_rcv_ctx = | 3214 | ohci->nb_iso_rcv_ctx = |
@@ -3233,8 +3234,9 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev, | |||
3233 | * we need to get to that "no event", so enough should be initialized | 3234 | * we need to get to that "no event", so enough should be initialized |
3234 | * by that point. | 3235 | * by that point. |
3235 | */ | 3236 | */ |
3236 | if (request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED, | 3237 | err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED, |
3237 | OHCI1394_DRIVER_NAME, ohci)) { | 3238 | OHCI1394_DRIVER_NAME, ohci); |
3239 | if (err) { | ||
3238 | PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq); | 3240 | PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq); |
3239 | goto err; | 3241 | goto err; |
3240 | } | 3242 | } |
@@ -3381,6 +3383,7 @@ static int ohci1394_pci_suspend(struct pci_dev *dev, pm_message_t state) | |||
3381 | ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT); | 3383 | ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT); |
3382 | ohci_soft_reset(ohci); | 3384 | ohci_soft_reset(ohci); |
3383 | 3385 | ||
3386 | free_irq(dev->irq, ohci); | ||
3384 | err = pci_save_state(dev); | 3387 | err = pci_save_state(dev); |
3385 | if (err) { | 3388 | if (err) { |
3386 | PRINT(KERN_ERR, "pci_save_state failed with %d", err); | 3389 | PRINT(KERN_ERR, "pci_save_state failed with %d", err); |
@@ -3420,7 +3423,16 @@ static int ohci1394_pci_resume(struct pci_dev *dev) | |||
3420 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); | 3423 | reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); |
3421 | reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); | 3424 | reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); |
3422 | reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); | 3425 | reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); |
3423 | mdelay(50); | 3426 | reg_read(ohci, OHCI1394_Version); |
3427 | msleep(50); | ||
3428 | |||
3429 | err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED, | ||
3430 | OHCI1394_DRIVER_NAME, ohci); | ||
3431 | if (err) { | ||
3432 | PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq); | ||
3433 | return err; | ||
3434 | } | ||
3435 | |||
3424 | ohci_initialize(ohci); | 3436 | ohci_initialize(ohci); |
3425 | 3437 | ||
3426 | hpsb_resume_host(ohci->host); | 3438 | hpsb_resume_host(ohci->host); |
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c index 7aee1ac97c80..dc15cadb06ef 100644 --- a/drivers/ieee1394/pcilynx.c +++ b/drivers/ieee1394/pcilynx.c | |||
@@ -1463,7 +1463,7 @@ static int __devinit add_card(struct pci_dev *dev, | |||
1463 | 1463 | ||
1464 | /* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */ | 1464 | /* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */ |
1465 | if (((be32_to_cpu(lynx->bus_info_block[0]) & 0xffff0000) == 0x04040000) && | 1465 | if (((be32_to_cpu(lynx->bus_info_block[0]) & 0xffff0000) == 0x04040000) && |
1466 | (lynx->bus_info_block[1] == __constant_cpu_to_be32(0x31333934))) | 1466 | (lynx->bus_info_block[1] == IEEE1394_BUSID_MAGIC)) |
1467 | { | 1467 | { |
1468 | PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from"); | 1468 | PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from"); |
1469 | } else { | 1469 | } else { |
diff --git a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h index ec27321f6724..693a169acea3 100644 --- a/drivers/ieee1394/pcilynx.h +++ b/drivers/ieee1394/pcilynx.h | |||
@@ -52,7 +52,7 @@ struct ti_lynx { | |||
52 | void __iomem *local_rom; | 52 | void __iomem *local_rom; |
53 | void __iomem *local_ram; | 53 | void __iomem *local_ram; |
54 | void __iomem *aux_port; | 54 | void __iomem *aux_port; |
55 | quadlet_t bus_info_block[5]; | 55 | __be32 bus_info_block[5]; |
56 | 56 | ||
57 | /* | 57 | /* |
58 | * use local RAM of LOCALRAM_SIZE bytes for PCLs, which allows for | 58 | * use local RAM of LOCALRAM_SIZE bytes for PCLs, which allows for |
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index bf7e761c12b1..bad66c65b0d6 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c | |||
@@ -90,7 +90,7 @@ static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, | |||
90 | static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, | 90 | static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, |
91 | u64 addr, octlet_t data, octlet_t arg, int ext_tcode, | 91 | u64 addr, octlet_t data, octlet_t arg, int ext_tcode, |
92 | u16 flags); | 92 | u16 flags); |
93 | static struct hpsb_address_ops arm_ops = { | 93 | const static struct hpsb_address_ops arm_ops = { |
94 | .read = arm_read, | 94 | .read = arm_read, |
95 | .write = arm_write, | 95 | .write = arm_write, |
96 | .lock = arm_lock, | 96 | .lock = arm_lock, |
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index a373c18cf7b8..ab1034ccb7fb 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
@@ -265,7 +265,7 @@ static struct hpsb_highlevel sbp2_highlevel = { | |||
265 | .host_reset = sbp2_host_reset, | 265 | .host_reset = sbp2_host_reset, |
266 | }; | 266 | }; |
267 | 267 | ||
268 | static struct hpsb_address_ops sbp2_ops = { | 268 | const static struct hpsb_address_ops sbp2_ops = { |
269 | .write = sbp2_handle_status_write | 269 | .write = sbp2_handle_status_write |
270 | }; | 270 | }; |
271 | 271 | ||
@@ -275,7 +275,7 @@ static int sbp2_handle_physdma_write(struct hpsb_host *, int, int, quadlet_t *, | |||
275 | static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64, | 275 | static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64, |
276 | size_t, u16); | 276 | size_t, u16); |
277 | 277 | ||
278 | static struct hpsb_address_ops sbp2_physdma_ops = { | 278 | const static struct hpsb_address_ops sbp2_physdma_ops = { |
279 | .read = sbp2_handle_physdma_read, | 279 | .read = sbp2_handle_physdma_read, |
280 | .write = sbp2_handle_physdma_write, | 280 | .write = sbp2_handle_physdma_write, |
281 | }; | 281 | }; |
diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index a3c5af1d7ec0..de5263beab4a 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c | |||
@@ -367,7 +367,7 @@ int mlx4_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata) | |||
367 | if (err) | 367 | if (err) |
368 | goto out; | 368 | goto out; |
369 | } else { | 369 | } else { |
370 | /* Can't be smaller then the number of outstanding CQEs */ | 370 | /* Can't be smaller than the number of outstanding CQEs */ |
371 | outst_cqe = mlx4_ib_get_outstanding_cqes(cq); | 371 | outst_cqe = mlx4_ib_get_outstanding_cqes(cq); |
372 | if (entries < outst_cqe + 1) { | 372 | if (entries < outst_cqe + 1) { |
373 | err = 0; | 373 | err = 0; |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index f6e9f39a527b..c3c8b9bc40ae 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -65,7 +65,7 @@ MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and | |||
65 | 65 | ||
66 | /* | 66 | /* |
67 | * Scancode to keycode tables. These are just the default setting, and | 67 | * Scancode to keycode tables. These are just the default setting, and |
68 | * are loadable via an userland utility. | 68 | * are loadable via a userland utility. |
69 | */ | 69 | */ |
70 | 70 | ||
71 | static const unsigned short atkbd_set2_keycode[512] = { | 71 | static const unsigned short atkbd_set2_keycode[512] = { |
diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index d82f7f727f7a..71b82434264d 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c | |||
@@ -57,7 +57,7 @@ static enum apanel_chip device_chip[APANEL_DEV_MAX]; | |||
57 | 57 | ||
58 | struct apanel { | 58 | struct apanel { |
59 | struct input_polled_dev *ipdev; | 59 | struct input_polled_dev *ipdev; |
60 | struct i2c_client client; | 60 | struct i2c_client *client; |
61 | unsigned short keymap[MAX_PANEL_KEYS]; | 61 | unsigned short keymap[MAX_PANEL_KEYS]; |
62 | u16 nkeys; | 62 | u16 nkeys; |
63 | u16 led_bits; | 63 | u16 led_bits; |
@@ -66,16 +66,7 @@ struct apanel { | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | 68 | ||
69 | static int apanel_probe(struct i2c_adapter *, int, int); | 69 | static int apanel_probe(struct i2c_client *, const struct i2c_device_id *); |
70 | |||
71 | /* for now, we only support one address */ | ||
72 | static unsigned short normal_i2c[] = {0, I2C_CLIENT_END}; | ||
73 | static unsigned short ignore = I2C_CLIENT_END; | ||
74 | static struct i2c_client_address_data addr_data = { | ||
75 | .normal_i2c = normal_i2c, | ||
76 | .probe = &ignore, | ||
77 | .ignore = &ignore, | ||
78 | }; | ||
79 | 70 | ||
80 | static void report_key(struct input_dev *input, unsigned keycode) | 71 | static void report_key(struct input_dev *input, unsigned keycode) |
81 | { | 72 | { |
@@ -103,12 +94,12 @@ static void apanel_poll(struct input_polled_dev *ipdev) | |||
103 | s32 data; | 94 | s32 data; |
104 | int i; | 95 | int i; |
105 | 96 | ||
106 | data = i2c_smbus_read_word_data(&ap->client, cmd); | 97 | data = i2c_smbus_read_word_data(ap->client, cmd); |
107 | if (data < 0) | 98 | if (data < 0) |
108 | return; /* ignore errors (due to ACPI??) */ | 99 | return; /* ignore errors (due to ACPI??) */ |
109 | 100 | ||
110 | /* write back to clear latch */ | 101 | /* write back to clear latch */ |
111 | i2c_smbus_write_word_data(&ap->client, cmd, 0); | 102 | i2c_smbus_write_word_data(ap->client, cmd, 0); |
112 | 103 | ||
113 | if (!data) | 104 | if (!data) |
114 | return; | 105 | return; |
@@ -124,7 +115,7 @@ static void led_update(struct work_struct *work) | |||
124 | { | 115 | { |
125 | struct apanel *ap = container_of(work, struct apanel, led_work); | 116 | struct apanel *ap = container_of(work, struct apanel, led_work); |
126 | 117 | ||
127 | i2c_smbus_write_word_data(&ap->client, 0x10, ap->led_bits); | 118 | i2c_smbus_write_word_data(ap->client, 0x10, ap->led_bits); |
128 | } | 119 | } |
129 | 120 | ||
130 | static void mail_led_set(struct led_classdev *led, | 121 | static void mail_led_set(struct led_classdev *led, |
@@ -140,7 +131,7 @@ static void mail_led_set(struct led_classdev *led, | |||
140 | schedule_work(&ap->led_work); | 131 | schedule_work(&ap->led_work); |
141 | } | 132 | } |
142 | 133 | ||
143 | static int apanel_detach_client(struct i2c_client *client) | 134 | static int apanel_remove(struct i2c_client *client) |
144 | { | 135 | { |
145 | struct apanel *ap = i2c_get_clientdata(client); | 136 | struct apanel *ap = i2c_get_clientdata(client); |
146 | 137 | ||
@@ -148,43 +139,33 @@ static int apanel_detach_client(struct i2c_client *client) | |||
148 | led_classdev_unregister(&ap->mail_led); | 139 | led_classdev_unregister(&ap->mail_led); |
149 | 140 | ||
150 | input_unregister_polled_device(ap->ipdev); | 141 | input_unregister_polled_device(ap->ipdev); |
151 | i2c_detach_client(&ap->client); | ||
152 | input_free_polled_device(ap->ipdev); | 142 | input_free_polled_device(ap->ipdev); |
153 | 143 | ||
154 | return 0; | 144 | return 0; |
155 | } | 145 | } |
156 | 146 | ||
157 | /* Function is invoked for every i2c adapter. */ | ||
158 | static int apanel_attach_adapter(struct i2c_adapter *adap) | ||
159 | { | ||
160 | dev_dbg(&adap->dev, APANEL ": attach adapter id=%d\n", adap->id); | ||
161 | |||
162 | /* Our device is connected only to i801 on laptop */ | ||
163 | if (adap->id != I2C_HW_SMBUS_I801) | ||
164 | return -ENODEV; | ||
165 | |||
166 | return i2c_probe(adap, &addr_data, apanel_probe); | ||
167 | } | ||
168 | |||
169 | static void apanel_shutdown(struct i2c_client *client) | 147 | static void apanel_shutdown(struct i2c_client *client) |
170 | { | 148 | { |
171 | apanel_detach_client(client); | 149 | apanel_remove(client); |
172 | } | 150 | } |
173 | 151 | ||
152 | static struct i2c_device_id apanel_id[] = { | ||
153 | { "fujitsu_apanel", 0 }, | ||
154 | { } | ||
155 | }; | ||
156 | MODULE_DEVICE_TABLE(i2c, apanel_id); | ||
157 | |||
174 | static struct i2c_driver apanel_driver = { | 158 | static struct i2c_driver apanel_driver = { |
175 | .driver = { | 159 | .driver = { |
176 | .name = APANEL, | 160 | .name = APANEL, |
177 | }, | 161 | }, |
178 | .attach_adapter = &apanel_attach_adapter, | 162 | .probe = &apanel_probe, |
179 | .detach_client = &apanel_detach_client, | 163 | .remove = &apanel_remove, |
180 | .shutdown = &apanel_shutdown, | 164 | .shutdown = &apanel_shutdown, |
165 | .id_table = apanel_id, | ||
181 | }; | 166 | }; |
182 | 167 | ||
183 | static struct apanel apanel = { | 168 | static struct apanel apanel = { |
184 | .client = { | ||
185 | .driver = &apanel_driver, | ||
186 | .name = APANEL, | ||
187 | }, | ||
188 | .keymap = { | 169 | .keymap = { |
189 | [0] = KEY_MAIL, | 170 | [0] = KEY_MAIL, |
190 | [1] = KEY_WWW, | 171 | [1] = KEY_WWW, |
@@ -204,7 +185,8 @@ static struct apanel apanel = { | |||
204 | }; | 185 | }; |
205 | 186 | ||
206 | /* NB: Only one panel on the i2c. */ | 187 | /* NB: Only one panel on the i2c. */ |
207 | static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | 188 | static int apanel_probe(struct i2c_client *client, |
189 | const struct i2c_device_id *id) | ||
208 | { | 190 | { |
209 | struct apanel *ap; | 191 | struct apanel *ap; |
210 | struct input_polled_dev *ipdev; | 192 | struct input_polled_dev *ipdev; |
@@ -212,9 +194,6 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | |||
212 | u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; | 194 | u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; |
213 | int i, err = -ENOMEM; | 195 | int i, err = -ENOMEM; |
214 | 196 | ||
215 | dev_dbg(&bus->dev, APANEL ": probe adapter %p addr %d kind %d\n", | ||
216 | bus, address, kind); | ||
217 | |||
218 | ap = &apanel; | 197 | ap = &apanel; |
219 | 198 | ||
220 | ipdev = input_allocate_polled_device(); | 199 | ipdev = input_allocate_polled_device(); |
@@ -222,18 +201,13 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | |||
222 | goto out1; | 201 | goto out1; |
223 | 202 | ||
224 | ap->ipdev = ipdev; | 203 | ap->ipdev = ipdev; |
225 | ap->client.adapter = bus; | 204 | ap->client = client; |
226 | ap->client.addr = address; | ||
227 | |||
228 | i2c_set_clientdata(&ap->client, ap); | ||
229 | 205 | ||
230 | err = i2c_attach_client(&ap->client); | 206 | i2c_set_clientdata(client, ap); |
231 | if (err) | ||
232 | goto out2; | ||
233 | 207 | ||
234 | err = i2c_smbus_write_word_data(&ap->client, cmd, 0); | 208 | err = i2c_smbus_write_word_data(client, cmd, 0); |
235 | if (err) { | 209 | if (err) { |
236 | dev_warn(&ap->client.dev, APANEL ": smbus write error %d\n", | 210 | dev_warn(&client->dev, APANEL ": smbus write error %d\n", |
237 | err); | 211 | err); |
238 | goto out3; | 212 | goto out3; |
239 | } | 213 | } |
@@ -246,7 +220,7 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | |||
246 | idev->name = APANEL_NAME " buttons"; | 220 | idev->name = APANEL_NAME " buttons"; |
247 | idev->phys = "apanel/input0"; | 221 | idev->phys = "apanel/input0"; |
248 | idev->id.bustype = BUS_HOST; | 222 | idev->id.bustype = BUS_HOST; |
249 | idev->dev.parent = &ap->client.dev; | 223 | idev->dev.parent = &client->dev; |
250 | 224 | ||
251 | set_bit(EV_KEY, idev->evbit); | 225 | set_bit(EV_KEY, idev->evbit); |
252 | 226 | ||
@@ -264,7 +238,7 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | |||
264 | 238 | ||
265 | INIT_WORK(&ap->led_work, led_update); | 239 | INIT_WORK(&ap->led_work, led_update); |
266 | if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { | 240 | if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { |
267 | err = led_classdev_register(&ap->client.dev, &ap->mail_led); | 241 | err = led_classdev_register(&client->dev, &ap->mail_led); |
268 | if (err) | 242 | if (err) |
269 | goto out4; | 243 | goto out4; |
270 | } | 244 | } |
@@ -273,8 +247,6 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | |||
273 | out4: | 247 | out4: |
274 | input_unregister_polled_device(ipdev); | 248 | input_unregister_polled_device(ipdev); |
275 | out3: | 249 | out3: |
276 | i2c_detach_client(&ap->client); | ||
277 | out2: | ||
278 | input_free_polled_device(ipdev); | 250 | input_free_polled_device(ipdev); |
279 | out1: | 251 | out1: |
280 | return err; | 252 | return err; |
@@ -301,6 +273,7 @@ static int __init apanel_init(void) | |||
301 | void __iomem *bios; | 273 | void __iomem *bios; |
302 | const void __iomem *p; | 274 | const void __iomem *p; |
303 | u8 devno; | 275 | u8 devno; |
276 | unsigned char i2c_addr; | ||
304 | int found = 0; | 277 | int found = 0; |
305 | 278 | ||
306 | bios = ioremap(0xF0000, 0x10000); /* Can't fail */ | 279 | bios = ioremap(0xF0000, 0x10000); /* Can't fail */ |
@@ -313,7 +286,7 @@ static int __init apanel_init(void) | |||
313 | 286 | ||
314 | /* just use the first address */ | 287 | /* just use the first address */ |
315 | p += 8; | 288 | p += 8; |
316 | normal_i2c[0] = readb(p+3) >> 1; | 289 | i2c_addr = readb(p + 3) >> 1; |
317 | 290 | ||
318 | for ( ; (devno = readb(p)) & 0x7f; p += 4) { | 291 | for ( ; (devno = readb(p)) & 0x7f; p += 4) { |
319 | unsigned char method, slave, chip; | 292 | unsigned char method, slave, chip; |
@@ -322,7 +295,7 @@ static int __init apanel_init(void) | |||
322 | chip = readb(p + 2); | 295 | chip = readb(p + 2); |
323 | slave = readb(p + 3) >> 1; | 296 | slave = readb(p + 3) >> 1; |
324 | 297 | ||
325 | if (slave != normal_i2c[0]) { | 298 | if (slave != i2c_addr) { |
326 | pr_notice(APANEL ": only one SMBus slave " | 299 | pr_notice(APANEL ": only one SMBus slave " |
327 | "address supported, skiping device...\n"); | 300 | "address supported, skiping device...\n"); |
328 | continue; | 301 | continue; |
diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c index 4342e77814b5..fa67d782c3c3 100644 --- a/drivers/input/touchscreen/da9034-ts.c +++ b/drivers/input/touchscreen/da9034-ts.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
19 | #include <linux/workqueue.h> | ||
19 | #include <linux/mfd/da903x.h> | 20 | #include <linux/mfd/da903x.h> |
20 | 21 | ||
21 | #define DA9034_MANUAL_CTRL 0x50 | 22 | #define DA9034_MANUAL_CTRL 0x50 |
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig index b52659620d50..173cf55c64d0 100644 --- a/drivers/macintosh/Kconfig +++ b/drivers/macintosh/Kconfig | |||
@@ -138,7 +138,7 @@ config PMAC_BACKLIGHT | |||
138 | Say Y here to enable Macintosh specific extensions of the generic | 138 | Say Y here to enable Macintosh specific extensions of the generic |
139 | backlight code. With this enabled, the brightness keys on older | 139 | backlight code. With this enabled, the brightness keys on older |
140 | PowerBooks will be enabled so you can change the screen brightness. | 140 | PowerBooks will be enabled so you can change the screen brightness. |
141 | Newer models should use an userspace daemon like pbbuttonsd. | 141 | Newer models should use a userspace daemon like pbbuttonsd. |
142 | 142 | ||
143 | config PMAC_BACKLIGHT_LEGACY | 143 | config PMAC_BACKLIGHT_LEGACY |
144 | bool "Provide legacy ioctl's on /dev/pmu for the backlight" | 144 | bool "Provide legacy ioctl's on /dev/pmu for the backlight" |
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 34a39d2e4703..46fd573a4f15 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -569,7 +569,6 @@ static int cafe_smbus_setup(struct cafe_camera *cam) | |||
569 | 569 | ||
570 | cafe_smbus_enable_irq(cam); | 570 | cafe_smbus_enable_irq(cam); |
571 | adap->id = I2C_HW_SMBUS_CAFE; | 571 | adap->id = I2C_HW_SMBUS_CAFE; |
572 | adap->class = I2C_CLASS_CAM_DIGITAL; | ||
573 | adap->owner = THIS_MODULE; | 572 | adap->owner = THIS_MODULE; |
574 | adap->client_register = cafe_smbus_attach; | 573 | adap->client_register = cafe_smbus_attach; |
575 | adap->client_unregister = cafe_smbus_detach; | 574 | adap->client_unregister = cafe_smbus_detach; |
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index ca26b0c50cf2..05c14a29375a 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c | |||
@@ -1347,7 +1347,6 @@ static struct i2c_driver ov7670_driver = { | |||
1347 | .name = "ov7670", | 1347 | .name = "ov7670", |
1348 | }, | 1348 | }, |
1349 | .id = I2C_DRIVERID_OV7670, | 1349 | .id = I2C_DRIVERID_OV7670, |
1350 | .class = I2C_CLASS_CAM_DIGITAL, | ||
1351 | .attach_adapter = ov7670_attach, | 1350 | .attach_adapter = ov7670_attach, |
1352 | .detach_client = ov7670_detach, | 1351 | .detach_client = ov7670_detach, |
1353 | .command = ov7670_command, | 1352 | .command = ov7670_command, |
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c index 2c4acbf5a4fe..c841f4e4fbe4 100644 --- a/drivers/media/video/ovcamchip/ovcamchip_core.c +++ b/drivers/media/video/ovcamchip/ovcamchip_core.c | |||
@@ -405,7 +405,6 @@ static struct i2c_driver driver = { | |||
405 | .name = "ovcamchip", | 405 | .name = "ovcamchip", |
406 | }, | 406 | }, |
407 | .id = I2C_DRIVERID_OVCAMCHIP, | 407 | .id = I2C_DRIVERID_OVCAMCHIP, |
408 | .class = I2C_CLASS_CAM_DIGITAL, | ||
409 | .attach_adapter = ovcamchip_attach, | 408 | .attach_adapter = ovcamchip_attach, |
410 | .detach_client = ovcamchip_detach, | 409 | .detach_client = ovcamchip_detach, |
411 | .command = ovcamchip_command, | 410 | .command = ovcamchip_command, |
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 8fb92ac78c7b..fa304e5f252a 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -3655,7 +3655,7 @@ void pvr2_hdw_device_reset(struct pvr2_hdw *hdw) | |||
3655 | int ret; | 3655 | int ret; |
3656 | pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset..."); | 3656 | pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset..."); |
3657 | ret = usb_lock_device_for_reset(hdw->usb_dev,NULL); | 3657 | ret = usb_lock_device_for_reset(hdw->usb_dev,NULL); |
3658 | if (ret == 1) { | 3658 | if (ret == 0) { |
3659 | ret = usb_reset_device(hdw->usb_dev); | 3659 | ret = usb_reset_device(hdw->usb_dev); |
3660 | usb_unlock_device(hdw->usb_dev); | 3660 | usb_unlock_device(hdw->usb_dev); |
3661 | } else { | 3661 | } else { |
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c index a3997b7d4366..105a832531f2 100644 --- a/drivers/media/video/w9968cf.c +++ b/drivers/media/video/w9968cf.c | |||
@@ -1553,7 +1553,6 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam) | |||
1553 | 1553 | ||
1554 | static struct i2c_adapter adap = { | 1554 | static struct i2c_adapter adap = { |
1555 | .id = I2C_HW_SMBUS_W9968CF, | 1555 | .id = I2C_HW_SMBUS_W9968CF, |
1556 | .class = I2C_CLASS_CAM_DIGITAL, | ||
1557 | .owner = THIS_MODULE, | 1556 | .owner = THIS_MODULE, |
1558 | .client_register = w9968cf_i2c_attach_inform, | 1557 | .client_register = w9968cf_i2c_attach_inform, |
1559 | .client_unregister = w9968cf_i2c_detach_inform, | 1558 | .client_unregister = w9968cf_i2c_detach_inform, |
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index 1bcdbbb9e7d3..3d45817e6dcd 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c | |||
@@ -390,7 +390,7 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m, | |||
390 | * @i2o_dev: the I2O device which was added | 390 | * @i2o_dev: the I2O device which was added |
391 | * | 391 | * |
392 | * If a I2O device is added we catch the notification, because I2O classes | 392 | * If a I2O device is added we catch the notification, because I2O classes |
393 | * other then SCSI peripheral will not be received through | 393 | * other than SCSI peripheral will not be received through |
394 | * i2o_scsi_probe(). | 394 | * i2o_scsi_probe(). |
395 | */ | 395 | */ |
396 | static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) | 396 | static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev) |
diff --git a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c index fda6a4d3bf23..68a0a5b94795 100644 --- a/drivers/misc/ibmasm/event.c +++ b/drivers/misc/ibmasm/event.c | |||
@@ -50,7 +50,7 @@ static void wake_up_event_readers(struct service_processor *sp) | |||
50 | * Store the event in the circular event buffer, wake up any sleeping | 50 | * Store the event in the circular event buffer, wake up any sleeping |
51 | * event readers. | 51 | * event readers. |
52 | * There is no reader marker in the buffer, therefore readers are | 52 | * There is no reader marker in the buffer, therefore readers are |
53 | * responsible for keeping up with the writer, or they will loose events. | 53 | * responsible for keeping up with the writer, or they will lose events. |
54 | */ | 54 | */ |
55 | void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size) | 55 | void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int data_size) |
56 | { | 56 | { |
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index abdebe347383..fa57b67593ae 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * the Free Software Foundation; either version 2 of the License, or | 6 | * the Free Software Foundation; either version 2 of the License, or |
7 | * (at your option) any later version. | 7 | * (at your option) any later version. |
8 | * | 8 | * |
9 | * You need an userspace library to cooperate with this driver. It (and other | 9 | * You need a userspace library to cooperate with this driver. It (and other |
10 | * info) may be obtained here: | 10 | * info) may be obtained here: |
11 | * http://www.fi.muni.cz/~xslaby/phantom.html | 11 | * http://www.fi.muni.cz/~xslaby/phantom.html |
12 | * or alternatively, you might use OpenHaptics provided by Sensable. | 12 | * or alternatively, you might use OpenHaptics provided by Sensable. |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 7a3f2436b011..1e97916914ad 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -25,8 +25,8 @@ | |||
25 | #include <linux/stat.h> | 25 | #include <linux/stat.h> |
26 | 26 | ||
27 | #include <linux/mmc/host.h> | 27 | #include <linux/mmc/host.h> |
28 | #include <linux/atmel-mci.h> | ||
28 | 29 | ||
29 | #include <asm/atmel-mci.h> | ||
30 | #include <asm/io.h> | 30 | #include <asm/io.h> |
31 | #include <asm/unaligned.h> | 31 | #include <asm/unaligned.h> |
32 | 32 | ||
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index d38bca64bb15..d2fd550f7e09 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c | |||
@@ -34,7 +34,7 @@ | |||
34 | * aperture size, not the dram size, and the V370PDC supplies no | 34 | * aperture size, not the dram size, and the V370PDC supplies no |
35 | * other method for memory size discovery. This problem is | 35 | * other method for memory size discovery. This problem is |
36 | * mostly only relevant when compiled as a module, as the | 36 | * mostly only relevant when compiled as a module, as the |
37 | * unloading of the module with an aperture size smaller then | 37 | * unloading of the module with an aperture size smaller than |
38 | * the ram will cause the driver to detect the onboard memory | 38 | * the ram will cause the driver to detect the onboard memory |
39 | * size to be equal to the aperture size when the module is | 39 | * size to be equal to the aperture size when the module is |
40 | * reloaded. Soooo, to help, the module supports an msize | 40 | * reloaded. Soooo, to help, the module supports an msize |
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 048a606cebde..25def348e5ba 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -717,7 +717,7 @@ write_error: | |||
717 | * to the real data size, although the @buf buffer has to contain the | 717 | * to the real data size, although the @buf buffer has to contain the |
718 | * alignment. In all other cases, @len has to be aligned. | 718 | * alignment. In all other cases, @len has to be aligned. |
719 | * | 719 | * |
720 | * It is prohibited to write more then once to logical eraseblocks of static | 720 | * It is prohibited to write more than once to logical eraseblocks of static |
721 | * volumes. This function returns zero in case of success and a negative error | 721 | * volumes. This function returns zero in case of success and a negative error |
722 | * code in case of failure. | 722 | * code in case of failure. |
723 | */ | 723 | */ |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index a74118c05745..fe81039f2a7c 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
@@ -465,7 +465,7 @@ out: | |||
465 | * This function synchronously erases physical eraseblock @pnum. If @torture | 465 | * This function synchronously erases physical eraseblock @pnum. If @torture |
466 | * flag is not zero, the physical eraseblock is checked by means of writing | 466 | * flag is not zero, the physical eraseblock is checked by means of writing |
467 | * different patterns to it and reading them back. If the torturing is enabled, | 467 | * different patterns to it and reading them back. If the torturing is enabled, |
468 | * the physical eraseblock is erased more then once. | 468 | * the physical eraseblock is erased more than once. |
469 | * | 469 | * |
470 | * This function returns the number of erasures made in case of success, %-EIO | 470 | * This function returns the number of erasures made in case of success, %-EIO |
471 | * if the erasure failed or the torturing test failed, and other negative error | 471 | * if the erasure failed or the torturing test failed, and other negative error |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 41d47e1cf15c..ecde202a5a12 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
@@ -478,7 +478,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, | |||
478 | return 0; | 478 | return 0; |
479 | } else { | 479 | } else { |
480 | /* | 480 | /* |
481 | * This logical eraseblock is older then the one found | 481 | * This logical eraseblock is older than the one found |
482 | * previously. | 482 | * previously. |
483 | */ | 483 | */ |
484 | if (cmp_res & 4) | 484 | if (cmp_res & 4) |
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index 2ad940409053..8419fdccc79c 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h | |||
@@ -135,7 +135,7 @@ enum { | |||
135 | * The erase counter header takes 64 bytes and has a plenty of unused space for | 135 | * The erase counter header takes 64 bytes and has a plenty of unused space for |
136 | * future usage. The unused fields are zeroed. The @version field is used to | 136 | * future usage. The unused fields are zeroed. The @version field is used to |
137 | * indicate the version of UBI implementation which is supposed to be able to | 137 | * indicate the version of UBI implementation which is supposed to be able to |
138 | * work with this UBI image. If @version is greater then the current UBI | 138 | * work with this UBI image. If @version is greater than the current UBI |
139 | * version, the image is rejected. This may be useful in future if something | 139 | * version, the image is rejected. This may be useful in future if something |
140 | * is changed radically. This field is duplicated in the volume identifier | 140 | * is changed radically. This field is duplicated in the volume identifier |
141 | * header. | 141 | * header. |
@@ -187,7 +187,7 @@ struct ubi_ec_hdr { | |||
187 | * (sequence number) is used to distinguish between older and newer versions of | 187 | * (sequence number) is used to distinguish between older and newer versions of |
188 | * logical eraseblocks. | 188 | * logical eraseblocks. |
189 | * | 189 | * |
190 | * There are 2 situations when there may be more then one physical eraseblock | 190 | * There are 2 situations when there may be more than one physical eraseblock |
191 | * corresponding to the same logical eraseblock, i.e., having the same @vol_id | 191 | * corresponding to the same logical eraseblock, i.e., having the same @vol_id |
192 | * and @lnum values in the volume identifier header. Suppose we have a logical | 192 | * and @lnum values in the volume identifier header. Suppose we have a logical |
193 | * eraseblock L and it is mapped to the physical eraseblock P. | 193 | * eraseblock L and it is mapped to the physical eraseblock P. |
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 333c8941552f..1afc61e7455d 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c | |||
@@ -577,7 +577,7 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, | |||
577 | if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) { | 577 | if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) { |
578 | /* Auto re-size flag may be set only for one volume */ | 578 | /* Auto re-size flag may be set only for one volume */ |
579 | if (ubi->autoresize_vol_id != -1) { | 579 | if (ubi->autoresize_vol_id != -1) { |
580 | ubi_err("more then one auto-resize volume (%d " | 580 | ubi_err("more than one auto-resize volume (%d " |
581 | "and %d)", ubi->autoresize_vol_id, i); | 581 | "and %d)", ubi->autoresize_vol_id, i); |
582 | kfree(vol); | 582 | kfree(vol); |
583 | return -EINVAL; | 583 | return -EINVAL; |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 14901cb82c18..891534f8210d 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
@@ -128,7 +128,7 @@ | |||
128 | * situation when the picked physical eraseblock is constantly erased after the | 128 | * situation when the picked physical eraseblock is constantly erased after the |
129 | * data is written to it. So, we have a constant which limits the highest erase | 129 | * data is written to it. So, we have a constant which limits the highest erase |
130 | * counter of the free physical eraseblock to pick. Namely, the WL sub-system | 130 | * counter of the free physical eraseblock to pick. Namely, the WL sub-system |
131 | * does not pick eraseblocks with erase counter greater then the lowest erase | 131 | * does not pick eraseblocks with erase counter greater than the lowest erase |
132 | * counter plus %WL_FREE_MAX_DIFF. | 132 | * counter plus %WL_FREE_MAX_DIFF. |
133 | */ | 133 | */ |
134 | #define WL_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD) | 134 | #define WL_FREE_MAX_DIFF (2*UBI_WL_THRESHOLD) |
@@ -917,7 +917,7 @@ static int ensure_wear_leveling(struct ubi_device *ubi) | |||
917 | /* | 917 | /* |
918 | * We schedule wear-leveling only if the difference between the | 918 | * We schedule wear-leveling only if the difference between the |
919 | * lowest erase counter of used physical eraseblocks and a high | 919 | * lowest erase counter of used physical eraseblocks and a high |
920 | * erase counter of free physical eraseblocks is greater then | 920 | * erase counter of free physical eraseblocks is greater than |
921 | * %UBI_WL_THRESHOLD. | 921 | * %UBI_WL_THRESHOLD. |
922 | */ | 922 | */ |
923 | e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb); | 923 | e1 = rb_entry(rb_first(&ubi->used), struct ubi_wl_entry, u.rb); |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9a18270c1081..97ea7c60e002 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -2614,6 +2614,8 @@ source "drivers/net/tokenring/Kconfig" | |||
2614 | 2614 | ||
2615 | source "drivers/net/wireless/Kconfig" | 2615 | source "drivers/net/wireless/Kconfig" |
2616 | 2616 | ||
2617 | source "drivers/net/wimax/Kconfig" | ||
2618 | |||
2617 | source "drivers/net/usb/Kconfig" | 2619 | source "drivers/net/usb/Kconfig" |
2618 | 2620 | ||
2619 | source "drivers/net/pcmcia/Kconfig" | 2621 | source "drivers/net/pcmcia/Kconfig" |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index e5c34b464211..a3c5c002f224 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -263,3 +263,4 @@ obj-$(CONFIG_NIU) += niu.o | |||
263 | obj-$(CONFIG_VIRTIO_NET) += virtio_net.o | 263 | obj-$(CONFIG_VIRTIO_NET) += virtio_net.o |
264 | obj-$(CONFIG_SFC) += sfc/ | 264 | obj-$(CONFIG_SFC) += sfc/ |
265 | 265 | ||
266 | obj-$(CONFIG_WIMAX) += wimax/ | ||
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index 67de94f1f30e..fefa6ab13064 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c | |||
@@ -3359,7 +3359,7 @@ static u8 bnx2x_format_ver(u32 num, u8 *str, u16 len) | |||
3359 | u8 shift = 8*4; | 3359 | u8 shift = 8*4; |
3360 | u8 digit; | 3360 | u8 digit; |
3361 | if (len < 10) { | 3361 | if (len < 10) { |
3362 | /* Need more then 10chars for this format */ | 3362 | /* Need more than 10chars for this format */ |
3363 | *str_ptr = '\0'; | 3363 | *str_ptr = '\0'; |
3364 | return -EINVAL; | 3364 | return -EINVAL; |
3365 | } | 3365 | } |
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index d04eef53571e..e1a3fc1303ee 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c | |||
@@ -6758,7 +6758,7 @@ static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, | |||
6758 | * returns: - E1000_ERR_XXX | 6758 | * returns: - E1000_ERR_XXX |
6759 | * E1000_SUCCESS | 6759 | * E1000_SUCCESS |
6760 | * | 6760 | * |
6761 | * For phy's older then IGP, this function simply reads the polarity bit in the | 6761 | * For phy's older than IGP, this function simply reads the polarity bit in the |
6762 | * Phy Status register. For IGP phy's, this bit is valid only if link speed is | 6762 | * Phy Status register. For IGP phy's, this bit is valid only if link speed is |
6763 | * 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will | 6763 | * 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will |
6764 | * return 0. If the link speed is 1000 Mbps the polarity status is in the | 6764 | * return 0. If the link speed is 1000 Mbps the polarity status is in the |
@@ -6834,7 +6834,7 @@ static s32 e1000_check_polarity(struct e1000_hw *hw, | |||
6834 | * returns: - E1000_ERR_XXX | 6834 | * returns: - E1000_ERR_XXX |
6835 | * E1000_SUCCESS | 6835 | * E1000_SUCCESS |
6836 | * | 6836 | * |
6837 | * For phy's older then IGP, this function reads the Downshift bit in the Phy | 6837 | * For phy's older than IGP, this function reads the Downshift bit in the Phy |
6838 | * Specific Status register. For IGP phy's, it reads the Downgrade bit in the | 6838 | * Specific Status register. For IGP phy's, it reads the Downgrade bit in the |
6839 | * Link Health register. In IGP this bit is latched high, so the driver must | 6839 | * Link Health register. In IGP this bit is latched high, so the driver must |
6840 | * read it immediately after link is established. | 6840 | * read it immediately after link is established. |
diff --git a/drivers/net/slip.h b/drivers/net/slip.h index 853e0f6ec710..9ea5c11287d2 100644 --- a/drivers/net/slip.h +++ b/drivers/net/slip.h | |||
@@ -75,7 +75,7 @@ struct slip { | |||
75 | unsigned long tx_errors; /* Planned stuff */ | 75 | unsigned long tx_errors; /* Planned stuff */ |
76 | unsigned long rx_dropped; /* No memory for skb */ | 76 | unsigned long rx_dropped; /* No memory for skb */ |
77 | unsigned long tx_dropped; /* When MTU change */ | 77 | unsigned long tx_dropped; /* When MTU change */ |
78 | unsigned long rx_over_errors; /* Frame bigger then SLIP buf. */ | 78 | unsigned long rx_over_errors; /* Frame bigger than SLIP buf. */ |
79 | #ifdef SL_INCLUDE_CSLIP | 79 | #ifdef SL_INCLUDE_CSLIP |
80 | unsigned long tx_compressed; | 80 | unsigned long tx_compressed; |
81 | unsigned long rx_compressed; | 81 | unsigned long rx_compressed; |
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index a10a83a11d9f..a7a4dc4d6313 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c | |||
@@ -1004,7 +1004,7 @@ static inline void bdx_rxdb_free_elem(struct rxdb *db, int n) | |||
1004 | * skb for rx. It assumes that Rx is desabled in HW | 1004 | * skb for rx. It assumes that Rx is desabled in HW |
1005 | * funcs are grouped for better cache usage | 1005 | * funcs are grouped for better cache usage |
1006 | * | 1006 | * |
1007 | * RxD fifo is smaller then RxF fifo by design. Upon high load, RxD will be | 1007 | * RxD fifo is smaller than RxF fifo by design. Upon high load, RxD will be |
1008 | * filled and packets will be dropped by nic without getting into host or | 1008 | * filled and packets will be dropped by nic without getting into host or |
1009 | * cousing interrupt. Anyway, in that condition, host has no chance to proccess | 1009 | * cousing interrupt. Anyway, in that condition, host has no chance to proccess |
1010 | * all packets, but dropping in nic is cheaper, since it takes 0 cpu cycles | 1010 | * all packets, but dropping in nic is cheaper, since it takes 0 cpu cycles |
@@ -1826,7 +1826,7 @@ static void bdx_tx_free(struct bdx_priv *priv) | |||
1826 | * | 1826 | * |
1827 | * Pushes desc to TxD fifo and overlaps it if needed. | 1827 | * Pushes desc to TxD fifo and overlaps it if needed. |
1828 | * NOTE: this func does not check for available space. this is responsibility | 1828 | * NOTE: this func does not check for available space. this is responsibility |
1829 | * of the caller. Neither does it check that data size is smaller then | 1829 | * of the caller. Neither does it check that data size is smaller than |
1830 | * fifo size. | 1830 | * fifo size. |
1831 | */ | 1831 | */ |
1832 | static void bdx_tx_push_desc(struct bdx_priv *priv, void *data, int size) | 1832 | static void bdx_tx_push_desc(struct bdx_priv *priv, void *data, int size) |
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c index a011666342ff..50eb29ce3c87 100644 --- a/drivers/net/tokenring/smctr.c +++ b/drivers/net/tokenring/smctr.c | |||
@@ -3064,7 +3064,7 @@ static int smctr_load_node_addr(struct net_device *dev) | |||
3064 | * will consequently cause a timeout. | 3064 | * will consequently cause a timeout. |
3065 | * | 3065 | * |
3066 | * NOTE 1: If the monitor_state is MS_BEACON_TEST_STATE, all transmit | 3066 | * NOTE 1: If the monitor_state is MS_BEACON_TEST_STATE, all transmit |
3067 | * queues other then the one used for the lobe_media_test should be | 3067 | * queues other than the one used for the lobe_media_test should be |
3068 | * disabled.!? | 3068 | * disabled.!? |
3069 | * | 3069 | * |
3070 | * NOTE 2: If the monitor_state is MS_BEACON_TEST_STATE and the receive_mask | 3070 | * NOTE 2: If the monitor_state is MS_BEACON_TEST_STATE and the receive_mask |
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 2ee034f70d1c..3073ca25a0b0 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c | |||
@@ -283,9 +283,9 @@ static int kaweth_control(struct kaweth_device *kaweth, | |||
283 | 283 | ||
284 | dr->bRequestType= requesttype; | 284 | dr->bRequestType= requesttype; |
285 | dr->bRequest = request; | 285 | dr->bRequest = request; |
286 | dr->wValue = cpu_to_le16p(&value); | 286 | dr->wValue = cpu_to_le16(value); |
287 | dr->wIndex = cpu_to_le16p(&index); | 287 | dr->wIndex = cpu_to_le16(index); |
288 | dr->wLength = cpu_to_le16p(&size); | 288 | dr->wLength = cpu_to_le16(size); |
289 | 289 | ||
290 | return kaweth_internal_control_msg(kaweth->dev, | 290 | return kaweth_internal_control_msg(kaweth->dev, |
291 | pipe, | 291 | pipe, |
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 166880c113d6..d9241f1c0803 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c | |||
@@ -150,8 +150,8 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, | |||
150 | pegasus->dr.bRequestType = PEGASUS_REQT_READ; | 150 | pegasus->dr.bRequestType = PEGASUS_REQT_READ; |
151 | pegasus->dr.bRequest = PEGASUS_REQ_GET_REGS; | 151 | pegasus->dr.bRequest = PEGASUS_REQ_GET_REGS; |
152 | pegasus->dr.wValue = cpu_to_le16(0); | 152 | pegasus->dr.wValue = cpu_to_le16(0); |
153 | pegasus->dr.wIndex = cpu_to_le16p(&indx); | 153 | pegasus->dr.wIndex = cpu_to_le16(indx); |
154 | pegasus->dr.wLength = cpu_to_le16p(&size); | 154 | pegasus->dr.wLength = cpu_to_le16(size); |
155 | pegasus->ctrl_urb->transfer_buffer_length = size; | 155 | pegasus->ctrl_urb->transfer_buffer_length = size; |
156 | 156 | ||
157 | usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, | 157 | usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, |
@@ -208,8 +208,8 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, | |||
208 | pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; | 208 | pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; |
209 | pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS; | 209 | pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS; |
210 | pegasus->dr.wValue = cpu_to_le16(0); | 210 | pegasus->dr.wValue = cpu_to_le16(0); |
211 | pegasus->dr.wIndex = cpu_to_le16p(&indx); | 211 | pegasus->dr.wIndex = cpu_to_le16(indx); |
212 | pegasus->dr.wLength = cpu_to_le16p(&size); | 212 | pegasus->dr.wLength = cpu_to_le16(size); |
213 | pegasus->ctrl_urb->transfer_buffer_length = size; | 213 | pegasus->ctrl_urb->transfer_buffer_length = size; |
214 | 214 | ||
215 | usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, | 215 | usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, |
@@ -261,7 +261,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) | |||
261 | pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; | 261 | pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; |
262 | pegasus->dr.bRequest = PEGASUS_REQ_SET_REG; | 262 | pegasus->dr.bRequest = PEGASUS_REQ_SET_REG; |
263 | pegasus->dr.wValue = cpu_to_le16(data); | 263 | pegasus->dr.wValue = cpu_to_le16(data); |
264 | pegasus->dr.wIndex = cpu_to_le16p(&indx); | 264 | pegasus->dr.wIndex = cpu_to_le16(indx); |
265 | pegasus->dr.wLength = cpu_to_le16(1); | 265 | pegasus->dr.wLength = cpu_to_le16(1); |
266 | pegasus->ctrl_urb->transfer_buffer_length = 1; | 266 | pegasus->ctrl_urb->transfer_buffer_length = 1; |
267 | 267 | ||
@@ -476,7 +476,7 @@ static inline void get_node_id(pegasus_t * pegasus, __u8 * id) | |||
476 | 476 | ||
477 | for (i = 0; i < 3; i++) { | 477 | for (i = 0; i < 3; i++) { |
478 | read_eprom_word(pegasus, i, &w16); | 478 | read_eprom_word(pegasus, i, &w16); |
479 | ((__le16 *) id)[i] = cpu_to_le16p(&w16); | 479 | ((__le16 *) id)[i] = cpu_to_le16(w16); |
480 | } | 480 | } |
481 | } | 481 | } |
482 | 482 | ||
diff --git a/drivers/net/wimax/Kconfig b/drivers/net/wimax/Kconfig new file mode 100644 index 000000000000..565018ec1e3b --- /dev/null +++ b/drivers/net/wimax/Kconfig | |||
@@ -0,0 +1,17 @@ | |||
1 | # | ||
2 | # WiMAX LAN device drivers configuration | ||
3 | # | ||
4 | |||
5 | |||
6 | comment "Enable WiMAX (Networking options) to see the WiMAX drivers" | ||
7 | depends on WIMAX = n | ||
8 | |||
9 | if WIMAX | ||
10 | |||
11 | menu "WiMAX Wireless Broadband devices" | ||
12 | |||
13 | source "drivers/net/wimax/i2400m/Kconfig" | ||
14 | |||
15 | endmenu | ||
16 | |||
17 | endif | ||
diff --git a/drivers/net/wimax/Makefile b/drivers/net/wimax/Makefile new file mode 100644 index 000000000000..992bc02bc016 --- /dev/null +++ b/drivers/net/wimax/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | |||
2 | obj-$(CONFIG_WIMAX_I2400M) += i2400m/ | ||
3 | |||
4 | # (from Sam Ravnborg) force kbuild to create built-in.o | ||
5 | obj- := dummy.o | ||
diff --git a/drivers/net/wimax/i2400m/Kconfig b/drivers/net/wimax/i2400m/Kconfig new file mode 100644 index 000000000000..d623b3d99a4b --- /dev/null +++ b/drivers/net/wimax/i2400m/Kconfig | |||
@@ -0,0 +1,49 @@ | |||
1 | |||
2 | config WIMAX_I2400M | ||
3 | tristate | ||
4 | depends on WIMAX | ||
5 | select FW_LOADER | ||
6 | |||
7 | comment "Enable USB support to see WiMAX USB drivers" | ||
8 | depends on USB = n | ||
9 | |||
10 | comment "Enable MMC support to see WiMAX SDIO drivers" | ||
11 | depends on MMC = n | ||
12 | |||
13 | config WIMAX_I2400M_USB | ||
14 | tristate "Intel Wireless WiMAX Connection 2400 over USB (including 5x50)" | ||
15 | depends on WIMAX && USB | ||
16 | select WIMAX_I2400M | ||
17 | help | ||
18 | Select if you have a device based on the Intel WiMAX | ||
19 | Connection 2400 over USB (like any of the Intel Wireless | ||
20 | WiMAX/WiFi Link 5x50 series). | ||
21 | |||
22 | If unsure, it is safe to select M (module). | ||
23 | |||
24 | config WIMAX_I2400M_SDIO | ||
25 | tristate "Intel Wireless WiMAX Connection 2400 over SDIO" | ||
26 | depends on WIMAX && MMC | ||
27 | select WIMAX_I2400M | ||
28 | help | ||
29 | Select if you have a device based on the Intel WiMAX | ||
30 | Connection 2400 over SDIO. | ||
31 | |||
32 | If unsure, it is safe to select M (module). | ||
33 | |||
34 | config WIMAX_I2400M_DEBUG_LEVEL | ||
35 | int "WiMAX i2400m debug level" | ||
36 | depends on WIMAX_I2400M | ||
37 | default 8 | ||
38 | help | ||
39 | |||
40 | Select the maximum debug verbosity level to be compiled into | ||
41 | the WiMAX i2400m driver code. | ||
42 | |||
43 | By default, this is disabled at runtime and can be | ||
44 | selectively enabled at runtime for different parts of the | ||
45 | code using the sysfs debug-levels file. | ||
46 | |||
47 | If set at zero, this will compile out all the debug code. | ||
48 | |||
49 | It is recommended that it is left at 8. | ||
diff --git a/drivers/net/wimax/i2400m/Makefile b/drivers/net/wimax/i2400m/Makefile new file mode 100644 index 000000000000..1696e936cf5a --- /dev/null +++ b/drivers/net/wimax/i2400m/Makefile | |||
@@ -0,0 +1,29 @@ | |||
1 | |||
2 | obj-$(CONFIG_WIMAX_I2400M) += i2400m.o | ||
3 | obj-$(CONFIG_WIMAX_I2400M_USB) += i2400m-usb.o | ||
4 | obj-$(CONFIG_WIMAX_I2400M_SDIO) += i2400m-sdio.o | ||
5 | |||
6 | i2400m-y := \ | ||
7 | control.o \ | ||
8 | driver.o \ | ||
9 | fw.o \ | ||
10 | op-rfkill.o \ | ||
11 | netdev.o \ | ||
12 | tx.o \ | ||
13 | rx.o | ||
14 | |||
15 | i2400m-$(CONFIG_DEBUG_FS) += debugfs.o | ||
16 | |||
17 | i2400m-usb-y := \ | ||
18 | usb-fw.o \ | ||
19 | usb-notif.o \ | ||
20 | usb-tx.o \ | ||
21 | usb-rx.o \ | ||
22 | usb.o | ||
23 | |||
24 | |||
25 | i2400m-sdio-y := \ | ||
26 | sdio.o \ | ||
27 | sdio-tx.o \ | ||
28 | sdio-fw.o \ | ||
29 | sdio-rx.o | ||
diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c new file mode 100644 index 000000000000..d3d37fed6893 --- /dev/null +++ b/drivers/net/wimax/i2400m/control.c | |||
@@ -0,0 +1,1291 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Miscellaneous control functions for managing the device | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
37 | * - Initial implementation | ||
38 | * | ||
39 | * This is a collection of functions used to control the device (plus | ||
40 | * a few helpers). | ||
41 | * | ||
42 | * There are utilities for handling TLV buffers, hooks on the device's | ||
43 | * reports to act on device changes of state [i2400m_report_hook()], | ||
44 | * on acks to commands [i2400m_msg_ack_hook()], a helper for sending | ||
45 | * commands to the device and blocking until a reply arrives | ||
46 | * [i2400m_msg_to_dev()], a few high level commands for manipulating | ||
47 | * the device state, powersving mode and configuration plus the | ||
48 | * routines to setup the device once communication is stablished with | ||
49 | * it [i2400m_dev_initialize()]. | ||
50 | * | ||
51 | * ROADMAP | ||
52 | * | ||
53 | * i2400m_dev_initalize() Called by i2400m_dev_start() | ||
54 | * i2400m_set_init_config() | ||
55 | * i2400m_firmware_check() | ||
56 | * i2400m_cmd_get_state() | ||
57 | * i2400m_dev_shutdown() Called by i2400m_dev_stop() | ||
58 | * i2400m->bus_reset() | ||
59 | * | ||
60 | * i2400m_{cmd,get,set}_*() | ||
61 | * i2400m_msg_to_dev() | ||
62 | * i2400m_msg_check_status() | ||
63 | * | ||
64 | * i2400m_report_hook() Called on reception of an event | ||
65 | * i2400m_report_state_hook() | ||
66 | * i2400m_tlv_buffer_walk() | ||
67 | * i2400m_tlv_match() | ||
68 | * i2400m_report_tlv_system_state() | ||
69 | * i2400m_report_tlv_rf_switches_status() | ||
70 | * i2400m_report_tlv_media_status() | ||
71 | * i2400m_cmd_enter_powersave() | ||
72 | * | ||
73 | * i2400m_msg_ack_hook() Called on reception of a reply to a | ||
74 | * command, get or set | ||
75 | */ | ||
76 | |||
77 | #include <stdarg.h> | ||
78 | #include "i2400m.h" | ||
79 | #include <linux/kernel.h> | ||
80 | #include <linux/wimax/i2400m.h> | ||
81 | |||
82 | |||
83 | #define D_SUBMODULE control | ||
84 | #include "debug-levels.h" | ||
85 | |||
86 | |||
87 | /* | ||
88 | * Return if a TLV is of a give type and size | ||
89 | * | ||
90 | * @tlv_hdr: pointer to the TLV | ||
91 | * @tlv_type: type of the TLV we are looking for | ||
92 | * @tlv_size: expected size of the TLV we are looking for (if -1, | ||
93 | * don't check the size). This includes the header | ||
94 | * Returns: 0 if the TLV matches | ||
95 | * < 0 if it doesn't match at all | ||
96 | * > 0 total TLV + payload size, if the type matches, but not | ||
97 | * the size | ||
98 | */ | ||
99 | static | ||
100 | ssize_t i2400m_tlv_match(const struct i2400m_tlv_hdr *tlv, | ||
101 | enum i2400m_tlv tlv_type, ssize_t tlv_size) | ||
102 | { | ||
103 | if (le16_to_cpu(tlv->type) != tlv_type) /* Not our type? skip */ | ||
104 | return -1; | ||
105 | if (tlv_size != -1 | ||
106 | && le16_to_cpu(tlv->length) + sizeof(*tlv) != tlv_size) { | ||
107 | size_t size = le16_to_cpu(tlv->length) + sizeof(*tlv); | ||
108 | printk(KERN_WARNING "W: tlv type 0x%x mismatched because of " | ||
109 | "size (got %zu vs %zu expected)\n", | ||
110 | tlv_type, size, tlv_size); | ||
111 | return size; | ||
112 | } | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | |||
117 | /* | ||
118 | * Given a buffer of TLVs, iterate over them | ||
119 | * | ||
120 | * @i2400m: device instance | ||
121 | * @tlv_buf: pointer to the beginning of the TLV buffer | ||
122 | * @buf_size: buffer size in bytes | ||
123 | * @tlv_pos: seek position; this is assumed to be a pointer returned | ||
124 | * by i2400m_tlv_buffer_walk() [and thus, validated]. The | ||
125 | * TLV returned will be the one following this one. | ||
126 | * | ||
127 | * Usage: | ||
128 | * | ||
129 | * tlv_itr = NULL; | ||
130 | * while (tlv_itr = i2400m_tlv_buffer_walk(i2400m, buf, size, tlv_itr)) { | ||
131 | * ... | ||
132 | * // Do stuff with tlv_itr, DON'T MODIFY IT | ||
133 | * ... | ||
134 | * } | ||
135 | */ | ||
136 | static | ||
137 | const struct i2400m_tlv_hdr *i2400m_tlv_buffer_walk( | ||
138 | struct i2400m *i2400m, | ||
139 | const void *tlv_buf, size_t buf_size, | ||
140 | const struct i2400m_tlv_hdr *tlv_pos) | ||
141 | { | ||
142 | struct device *dev = i2400m_dev(i2400m); | ||
143 | const struct i2400m_tlv_hdr *tlv_top = tlv_buf + buf_size; | ||
144 | size_t offset, length, avail_size; | ||
145 | unsigned type; | ||
146 | |||
147 | if (tlv_pos == NULL) /* Take the first one? */ | ||
148 | tlv_pos = tlv_buf; | ||
149 | else /* Nope, the next one */ | ||
150 | tlv_pos = (void *) tlv_pos | ||
151 | + le16_to_cpu(tlv_pos->length) + sizeof(*tlv_pos); | ||
152 | if (tlv_pos == tlv_top) { /* buffer done */ | ||
153 | tlv_pos = NULL; | ||
154 | goto error_beyond_end; | ||
155 | } | ||
156 | if (tlv_pos > tlv_top) { | ||
157 | tlv_pos = NULL; | ||
158 | WARN_ON(1); | ||
159 | goto error_beyond_end; | ||
160 | } | ||
161 | offset = (void *) tlv_pos - (void *) tlv_buf; | ||
162 | avail_size = buf_size - offset; | ||
163 | if (avail_size < sizeof(*tlv_pos)) { | ||
164 | dev_err(dev, "HW BUG? tlv_buf %p [%zu bytes], tlv @%zu: " | ||
165 | "short header\n", tlv_buf, buf_size, offset); | ||
166 | goto error_short_header; | ||
167 | } | ||
168 | type = le16_to_cpu(tlv_pos->type); | ||
169 | length = le16_to_cpu(tlv_pos->length); | ||
170 | if (avail_size < sizeof(*tlv_pos) + length) { | ||
171 | dev_err(dev, "HW BUG? tlv_buf %p [%zu bytes], " | ||
172 | "tlv type 0x%04x @%zu: " | ||
173 | "short data (%zu bytes vs %zu needed)\n", | ||
174 | tlv_buf, buf_size, type, offset, avail_size, | ||
175 | sizeof(*tlv_pos) + length); | ||
176 | goto error_short_header; | ||
177 | } | ||
178 | error_short_header: | ||
179 | error_beyond_end: | ||
180 | return tlv_pos; | ||
181 | } | ||
182 | |||
183 | |||
184 | /* | ||
185 | * Find a TLV in a buffer of sequential TLVs | ||
186 | * | ||
187 | * @i2400m: device descriptor | ||
188 | * @tlv_hdr: pointer to the first TLV in the sequence | ||
189 | * @size: size of the buffer in bytes; all TLVs are assumed to fit | ||
190 | * fully in the buffer (otherwise we'll complain). | ||
191 | * @tlv_type: type of the TLV we are looking for | ||
192 | * @tlv_size: expected size of the TLV we are looking for (if -1, | ||
193 | * don't check the size). This includes the header | ||
194 | * | ||
195 | * Returns: NULL if the TLV is not found, otherwise a pointer to | ||
196 | * it. If the sizes don't match, an error is printed and NULL | ||
197 | * returned. | ||
198 | */ | ||
199 | static | ||
200 | const struct i2400m_tlv_hdr *i2400m_tlv_find( | ||
201 | struct i2400m *i2400m, | ||
202 | const struct i2400m_tlv_hdr *tlv_hdr, size_t size, | ||
203 | enum i2400m_tlv tlv_type, ssize_t tlv_size) | ||
204 | { | ||
205 | ssize_t match; | ||
206 | struct device *dev = i2400m_dev(i2400m); | ||
207 | const struct i2400m_tlv_hdr *tlv = NULL; | ||
208 | while ((tlv = i2400m_tlv_buffer_walk(i2400m, tlv_hdr, size, tlv))) { | ||
209 | match = i2400m_tlv_match(tlv, tlv_type, tlv_size); | ||
210 | if (match == 0) /* found it :) */ | ||
211 | break; | ||
212 | if (match > 0) | ||
213 | dev_warn(dev, "TLV type 0x%04x found with size " | ||
214 | "mismatch (%zu vs %zu needed)\n", | ||
215 | tlv_type, match, tlv_size); | ||
216 | } | ||
217 | return tlv; | ||
218 | } | ||
219 | |||
220 | |||
221 | static const struct | ||
222 | { | ||
223 | char *msg; | ||
224 | int errno; | ||
225 | } ms_to_errno[I2400M_MS_MAX] = { | ||
226 | [I2400M_MS_DONE_OK] = { "", 0 }, | ||
227 | [I2400M_MS_DONE_IN_PROGRESS] = { "", 0 }, | ||
228 | [I2400M_MS_INVALID_OP] = { "invalid opcode", -ENOSYS }, | ||
229 | [I2400M_MS_BAD_STATE] = { "invalid state", -EILSEQ }, | ||
230 | [I2400M_MS_ILLEGAL_VALUE] = { "illegal value", -EINVAL }, | ||
231 | [I2400M_MS_MISSING_PARAMS] = { "missing parameters", -ENOMSG }, | ||
232 | [I2400M_MS_VERSION_ERROR] = { "bad version", -EIO }, | ||
233 | [I2400M_MS_ACCESSIBILITY_ERROR] = { "accesibility error", -EIO }, | ||
234 | [I2400M_MS_BUSY] = { "busy", -EBUSY }, | ||
235 | [I2400M_MS_CORRUPTED_TLV] = { "corrupted TLV", -EILSEQ }, | ||
236 | [I2400M_MS_UNINITIALIZED] = { "not unitialized", -EILSEQ }, | ||
237 | [I2400M_MS_UNKNOWN_ERROR] = { "unknown error", -EIO }, | ||
238 | [I2400M_MS_PRODUCTION_ERROR] = { "production error", -EIO }, | ||
239 | [I2400M_MS_NO_RF] = { "no RF", -EIO }, | ||
240 | [I2400M_MS_NOT_READY_FOR_POWERSAVE] = | ||
241 | { "not ready for powersave", -EACCES }, | ||
242 | [I2400M_MS_THERMAL_CRITICAL] = { "thermal critical", -EL3HLT }, | ||
243 | }; | ||
244 | |||
245 | |||
246 | /* | ||
247 | * i2400m_msg_check_status - translate a message's status code | ||
248 | * | ||
249 | * @i2400m: device descriptor | ||
250 | * @l3l4_hdr: message header | ||
251 | * @strbuf: buffer to place a formatted error message (unless NULL). | ||
252 | * @strbuf_size: max amount of available space; larger messages will | ||
253 | * be truncated. | ||
254 | * | ||
255 | * Returns: errno code corresponding to the status code in @l3l4_hdr | ||
256 | * and a message in @strbuf describing the error. | ||
257 | */ | ||
258 | int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *l3l4_hdr, | ||
259 | char *strbuf, size_t strbuf_size) | ||
260 | { | ||
261 | int result; | ||
262 | enum i2400m_ms status = le16_to_cpu(l3l4_hdr->status); | ||
263 | const char *str; | ||
264 | |||
265 | if (status == 0) | ||
266 | return 0; | ||
267 | if (status > ARRAY_SIZE(ms_to_errno)) { | ||
268 | str = "unknown status code"; | ||
269 | result = -EBADR; | ||
270 | } else { | ||
271 | str = ms_to_errno[status].msg; | ||
272 | result = ms_to_errno[status].errno; | ||
273 | } | ||
274 | if (strbuf) | ||
275 | snprintf(strbuf, strbuf_size, "%s (%d)", str, status); | ||
276 | return result; | ||
277 | } | ||
278 | |||
279 | |||
280 | /* | ||
281 | * Act on a TLV System State reported by the device | ||
282 | * | ||
283 | * @i2400m: device descriptor | ||
284 | * @ss: validated System State TLV | ||
285 | */ | ||
286 | static | ||
287 | void i2400m_report_tlv_system_state(struct i2400m *i2400m, | ||
288 | const struct i2400m_tlv_system_state *ss) | ||
289 | { | ||
290 | struct device *dev = i2400m_dev(i2400m); | ||
291 | struct wimax_dev *wimax_dev = &i2400m->wimax_dev; | ||
292 | enum i2400m_system_state i2400m_state = le32_to_cpu(ss->state); | ||
293 | |||
294 | d_fnstart(3, dev, "(i2400m %p ss %p [%u])\n", i2400m, ss, i2400m_state); | ||
295 | |||
296 | if (unlikely(i2400m->ready == 0)) /* act if up */ | ||
297 | goto out; | ||
298 | if (i2400m->state != i2400m_state) { | ||
299 | i2400m->state = i2400m_state; | ||
300 | wake_up_all(&i2400m->state_wq); | ||
301 | } | ||
302 | switch (i2400m_state) { | ||
303 | case I2400M_SS_UNINITIALIZED: | ||
304 | case I2400M_SS_INIT: | ||
305 | case I2400M_SS_CONFIG: | ||
306 | case I2400M_SS_PRODUCTION: | ||
307 | wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED); | ||
308 | break; | ||
309 | |||
310 | case I2400M_SS_RF_OFF: | ||
311 | case I2400M_SS_RF_SHUTDOWN: | ||
312 | wimax_state_change(wimax_dev, WIMAX_ST_RADIO_OFF); | ||
313 | break; | ||
314 | |||
315 | case I2400M_SS_READY: | ||
316 | case I2400M_SS_STANDBY: | ||
317 | case I2400M_SS_SLEEPACTIVE: | ||
318 | wimax_state_change(wimax_dev, WIMAX_ST_READY); | ||
319 | break; | ||
320 | |||
321 | case I2400M_SS_CONNECTING: | ||
322 | case I2400M_SS_WIMAX_CONNECTED: | ||
323 | wimax_state_change(wimax_dev, WIMAX_ST_READY); | ||
324 | break; | ||
325 | |||
326 | case I2400M_SS_SCAN: | ||
327 | case I2400M_SS_OUT_OF_ZONE: | ||
328 | wimax_state_change(wimax_dev, WIMAX_ST_SCANNING); | ||
329 | break; | ||
330 | |||
331 | case I2400M_SS_IDLE: | ||
332 | d_printf(1, dev, "entering BS-negotiated idle mode\n"); | ||
333 | case I2400M_SS_DISCONNECTING: | ||
334 | case I2400M_SS_DATA_PATH_CONNECTED: | ||
335 | wimax_state_change(wimax_dev, WIMAX_ST_CONNECTED); | ||
336 | break; | ||
337 | |||
338 | default: | ||
339 | /* Huh? just in case, shut it down */ | ||
340 | dev_err(dev, "HW BUG? unknown state %u: shutting down\n", | ||
341 | i2400m_state); | ||
342 | i2400m->bus_reset(i2400m, I2400M_RT_WARM); | ||
343 | break; | ||
344 | }; | ||
345 | out: | ||
346 | d_fnend(3, dev, "(i2400m %p ss %p [%u]) = void\n", | ||
347 | i2400m, ss, i2400m_state); | ||
348 | } | ||
349 | |||
350 | |||
351 | /* | ||
352 | * Parse and act on a TLV Media Status sent by the device | ||
353 | * | ||
354 | * @i2400m: device descriptor | ||
355 | * @ms: validated Media Status TLV | ||
356 | * | ||
357 | * This will set the carrier up on down based on the device's link | ||
358 | * report. This is done asides of what the WiMAX stack does based on | ||
359 | * the device's state as sometimes we need to do a link-renew (the BS | ||
360 | * wants us to renew a DHCP lease, for example). | ||
361 | * | ||
362 | * In fact, doc says that everytime we get a link-up, we should do a | ||
363 | * DHCP negotiation... | ||
364 | */ | ||
365 | static | ||
366 | void i2400m_report_tlv_media_status(struct i2400m *i2400m, | ||
367 | const struct i2400m_tlv_media_status *ms) | ||
368 | { | ||
369 | struct device *dev = i2400m_dev(i2400m); | ||
370 | struct wimax_dev *wimax_dev = &i2400m->wimax_dev; | ||
371 | struct net_device *net_dev = wimax_dev->net_dev; | ||
372 | enum i2400m_media_status status = le32_to_cpu(ms->media_status); | ||
373 | |||
374 | d_fnstart(3, dev, "(i2400m %p ms %p [%u])\n", i2400m, ms, status); | ||
375 | |||
376 | if (unlikely(i2400m->ready == 0)) /* act if up */ | ||
377 | goto out; | ||
378 | switch (status) { | ||
379 | case I2400M_MEDIA_STATUS_LINK_UP: | ||
380 | netif_carrier_on(net_dev); | ||
381 | break; | ||
382 | case I2400M_MEDIA_STATUS_LINK_DOWN: | ||
383 | netif_carrier_off(net_dev); | ||
384 | break; | ||
385 | /* | ||
386 | * This is the network telling us we need to retrain the DHCP | ||
387 | * lease -- so far, we are trusting the WiMAX Network Service | ||
388 | * in user space to pick this up and poke the DHCP client. | ||
389 | */ | ||
390 | case I2400M_MEDIA_STATUS_LINK_RENEW: | ||
391 | netif_carrier_on(net_dev); | ||
392 | break; | ||
393 | default: | ||
394 | dev_err(dev, "HW BUG? unknown media status %u\n", | ||
395 | status); | ||
396 | }; | ||
397 | out: | ||
398 | d_fnend(3, dev, "(i2400m %p ms %p [%u]) = void\n", | ||
399 | i2400m, ms, status); | ||
400 | } | ||
401 | |||
402 | |||
403 | /* | ||
404 | * Parse a 'state report' and extract carrier on/off information | ||
405 | * | ||
406 | * @i2400m: device descriptor | ||
407 | * @l3l4_hdr: pointer to message; it has been already validated for | ||
408 | * consistent size. | ||
409 | * @size: size of the message (header + payload). The header length | ||
410 | * declaration is assumed to be congruent with @size (as in | ||
411 | * sizeof(*l3l4_hdr) + l3l4_hdr->length == size) | ||
412 | * | ||
413 | * Extract from the report state the system state TLV and infer from | ||
414 | * there if we have a carrier or not. Update our local state and tell | ||
415 | * netdev. | ||
416 | * | ||
417 | * When setting the carrier, it's fine to set OFF twice (for example), | ||
418 | * as netif_carrier_off() will not generate two OFF events (just on | ||
419 | * the transitions). | ||
420 | */ | ||
421 | static | ||
422 | void i2400m_report_state_hook(struct i2400m *i2400m, | ||
423 | const struct i2400m_l3l4_hdr *l3l4_hdr, | ||
424 | size_t size, const char *tag) | ||
425 | { | ||
426 | struct device *dev = i2400m_dev(i2400m); | ||
427 | const struct i2400m_tlv_hdr *tlv; | ||
428 | const struct i2400m_tlv_system_state *ss; | ||
429 | const struct i2400m_tlv_rf_switches_status *rfss; | ||
430 | const struct i2400m_tlv_media_status *ms; | ||
431 | size_t tlv_size = le16_to_cpu(l3l4_hdr->length); | ||
432 | |||
433 | d_fnstart(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s)\n", | ||
434 | i2400m, l3l4_hdr, size, tag); | ||
435 | tlv = NULL; | ||
436 | |||
437 | while ((tlv = i2400m_tlv_buffer_walk(i2400m, &l3l4_hdr->pl, | ||
438 | tlv_size, tlv))) { | ||
439 | if (0 == i2400m_tlv_match(tlv, I2400M_TLV_SYSTEM_STATE, | ||
440 | sizeof(*ss))) { | ||
441 | ss = container_of(tlv, typeof(*ss), hdr); | ||
442 | d_printf(2, dev, "%s: system state TLV " | ||
443 | "found (0x%04x), state 0x%08x\n", | ||
444 | tag, I2400M_TLV_SYSTEM_STATE, | ||
445 | le32_to_cpu(ss->state)); | ||
446 | i2400m_report_tlv_system_state(i2400m, ss); | ||
447 | } | ||
448 | if (0 == i2400m_tlv_match(tlv, I2400M_TLV_RF_STATUS, | ||
449 | sizeof(*rfss))) { | ||
450 | rfss = container_of(tlv, typeof(*rfss), hdr); | ||
451 | d_printf(2, dev, "%s: RF status TLV " | ||
452 | "found (0x%04x), sw 0x%02x hw 0x%02x\n", | ||
453 | tag, I2400M_TLV_RF_STATUS, | ||
454 | le32_to_cpu(rfss->sw_rf_switch), | ||
455 | le32_to_cpu(rfss->hw_rf_switch)); | ||
456 | i2400m_report_tlv_rf_switches_status(i2400m, rfss); | ||
457 | } | ||
458 | if (0 == i2400m_tlv_match(tlv, I2400M_TLV_MEDIA_STATUS, | ||
459 | sizeof(*ms))) { | ||
460 | ms = container_of(tlv, typeof(*ms), hdr); | ||
461 | d_printf(2, dev, "%s: Media Status TLV: %u\n", | ||
462 | tag, le32_to_cpu(ms->media_status)); | ||
463 | i2400m_report_tlv_media_status(i2400m, ms); | ||
464 | } | ||
465 | } | ||
466 | d_fnend(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s) = void\n", | ||
467 | i2400m, l3l4_hdr, size, tag); | ||
468 | } | ||
469 | |||
470 | |||
471 | /* | ||
472 | * i2400m_report_hook - (maybe) act on a report | ||
473 | * | ||
474 | * @i2400m: device descriptor | ||
475 | * @l3l4_hdr: pointer to message; it has been already validated for | ||
476 | * consistent size. | ||
477 | * @size: size of the message (header + payload). The header length | ||
478 | * declaration is assumed to be congruent with @size (as in | ||
479 | * sizeof(*l3l4_hdr) + l3l4_hdr->length == size) | ||
480 | * | ||
481 | * Extract information we might need (like carrien on/off) from a | ||
482 | * device report. | ||
483 | */ | ||
484 | void i2400m_report_hook(struct i2400m *i2400m, | ||
485 | const struct i2400m_l3l4_hdr *l3l4_hdr, size_t size) | ||
486 | { | ||
487 | struct device *dev = i2400m_dev(i2400m); | ||
488 | unsigned msg_type; | ||
489 | |||
490 | d_fnstart(3, dev, "(i2400m %p l3l4_hdr %p size %zu)\n", | ||
491 | i2400m, l3l4_hdr, size); | ||
492 | /* Chew on the message, we might need some information from | ||
493 | * here */ | ||
494 | msg_type = le16_to_cpu(l3l4_hdr->type); | ||
495 | switch (msg_type) { | ||
496 | case I2400M_MT_REPORT_STATE: /* carrier detection... */ | ||
497 | i2400m_report_state_hook(i2400m, | ||
498 | l3l4_hdr, size, "REPORT STATE"); | ||
499 | break; | ||
500 | /* If the device is ready for power save, then ask it to do | ||
501 | * it. */ | ||
502 | case I2400M_MT_REPORT_POWERSAVE_READY: /* zzzzz */ | ||
503 | if (l3l4_hdr->status == cpu_to_le16(I2400M_MS_DONE_OK)) { | ||
504 | d_printf(1, dev, "ready for powersave, requesting\n"); | ||
505 | i2400m_cmd_enter_powersave(i2400m); | ||
506 | } | ||
507 | break; | ||
508 | }; | ||
509 | d_fnend(3, dev, "(i2400m %p l3l4_hdr %p size %zu) = void\n", | ||
510 | i2400m, l3l4_hdr, size); | ||
511 | } | ||
512 | |||
513 | |||
514 | /* | ||
515 | * i2400m_msg_ack_hook - process cmd/set/get ack for internal status | ||
516 | * | ||
517 | * @i2400m: device descriptor | ||
518 | * @l3l4_hdr: pointer to message; it has been already validated for | ||
519 | * consistent size. | ||
520 | * @size: size of the message | ||
521 | * | ||
522 | * Extract information we might need from acks to commands and act on | ||
523 | * it. This is akin to i2400m_report_hook(). Note most of this | ||
524 | * processing should be done in the function that calls the | ||
525 | * command. This is here for some cases where it can't happen... | ||
526 | */ | ||
527 | void i2400m_msg_ack_hook(struct i2400m *i2400m, | ||
528 | const struct i2400m_l3l4_hdr *l3l4_hdr, size_t size) | ||
529 | { | ||
530 | int result; | ||
531 | struct device *dev = i2400m_dev(i2400m); | ||
532 | unsigned ack_type, ack_status; | ||
533 | char strerr[32]; | ||
534 | |||
535 | /* Chew on the message, we might need some information from | ||
536 | * here */ | ||
537 | ack_type = le16_to_cpu(l3l4_hdr->type); | ||
538 | ack_status = le16_to_cpu(l3l4_hdr->status); | ||
539 | switch (ack_type) { | ||
540 | case I2400M_MT_CMD_ENTER_POWERSAVE: | ||
541 | /* This is just left here for the sake of example, as | ||
542 | * the processing is done somewhere else. */ | ||
543 | if (0) { | ||
544 | result = i2400m_msg_check_status( | ||
545 | l3l4_hdr, strerr, sizeof(strerr)); | ||
546 | if (result >= 0) | ||
547 | d_printf(1, dev, "ready for power save: %zd\n", | ||
548 | size); | ||
549 | } | ||
550 | break; | ||
551 | }; | ||
552 | return; | ||
553 | } | ||
554 | |||
555 | |||
556 | /* | ||
557 | * i2400m_msg_size_check() - verify message size and header are congruent | ||
558 | * | ||
559 | * It is ok if the total message size is larger than the expected | ||
560 | * size, as there can be padding. | ||
561 | */ | ||
562 | int i2400m_msg_size_check(struct i2400m *i2400m, | ||
563 | const struct i2400m_l3l4_hdr *l3l4_hdr, | ||
564 | size_t msg_size) | ||
565 | { | ||
566 | int result; | ||
567 | struct device *dev = i2400m_dev(i2400m); | ||
568 | size_t expected_size; | ||
569 | d_fnstart(4, dev, "(i2400m %p l3l4_hdr %p msg_size %zu)\n", | ||
570 | i2400m, l3l4_hdr, msg_size); | ||
571 | if (msg_size < sizeof(*l3l4_hdr)) { | ||
572 | dev_err(dev, "bad size for message header " | ||
573 | "(expected at least %zu, got %zu)\n", | ||
574 | (size_t) sizeof(*l3l4_hdr), msg_size); | ||
575 | result = -EIO; | ||
576 | goto error_hdr_size; | ||
577 | } | ||
578 | expected_size = le16_to_cpu(l3l4_hdr->length) + sizeof(*l3l4_hdr); | ||
579 | if (msg_size < expected_size) { | ||
580 | dev_err(dev, "bad size for message code 0x%04x (expected %zu, " | ||
581 | "got %zu)\n", le16_to_cpu(l3l4_hdr->type), | ||
582 | expected_size, msg_size); | ||
583 | result = -EIO; | ||
584 | } else | ||
585 | result = 0; | ||
586 | error_hdr_size: | ||
587 | d_fnend(4, dev, | ||
588 | "(i2400m %p l3l4_hdr %p msg_size %zu) = %d\n", | ||
589 | i2400m, l3l4_hdr, msg_size, result); | ||
590 | return result; | ||
591 | } | ||
592 | |||
593 | |||
594 | |||
595 | /* | ||
596 | * Cancel a wait for a command ACK | ||
597 | * | ||
598 | * @i2400m: device descriptor | ||
599 | * @code: [negative] errno code to cancel with (don't use | ||
600 | * -EINPROGRESS) | ||
601 | * | ||
602 | * If there is an ack already filled out, free it. | ||
603 | */ | ||
604 | void i2400m_msg_to_dev_cancel_wait(struct i2400m *i2400m, int code) | ||
605 | { | ||
606 | struct sk_buff *ack_skb; | ||
607 | unsigned long flags; | ||
608 | |||
609 | spin_lock_irqsave(&i2400m->rx_lock, flags); | ||
610 | ack_skb = i2400m->ack_skb; | ||
611 | if (ack_skb && !IS_ERR(ack_skb)) | ||
612 | kfree(ack_skb); | ||
613 | i2400m->ack_skb = ERR_PTR(code); | ||
614 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | ||
615 | } | ||
616 | |||
617 | |||
618 | /** | ||
619 | * i2400m_msg_to_dev - Send a control message to the device and get a response | ||
620 | * | ||
621 | * @i2400m: device descriptor | ||
622 | * | ||
623 | * @msg_skb: an skb * | ||
624 | * | ||
625 | * @buf: pointer to the buffer containing the message to be sent; it | ||
626 | * has to start with a &struct i2400M_l3l4_hdr and then | ||
627 | * followed by the payload. Once this function returns, the | ||
628 | * buffer can be reused. | ||
629 | * | ||
630 | * @buf_len: buffer size | ||
631 | * | ||
632 | * Returns: | ||
633 | * | ||
634 | * Pointer to skb containing the ack message. You need to check the | ||
635 | * pointer with IS_ERR(), as it might be an error code. Error codes | ||
636 | * could happen because: | ||
637 | * | ||
638 | * - the message wasn't formatted correctly | ||
639 | * - couldn't send the message | ||
640 | * - failed waiting for a response | ||
641 | * - the ack message wasn't formatted correctly | ||
642 | * | ||
643 | * The returned skb has been allocated with wimax_msg_to_user_alloc(), | ||
644 | * it contains the reponse in a netlink attribute and is ready to be | ||
645 | * passed up to user space with wimax_msg_to_user_send(). To access | ||
646 | * the payload and its length, use wimax_msg_{data,len}() on the skb. | ||
647 | * | ||
648 | * The skb has to be freed with kfree_skb() once done. | ||
649 | * | ||
650 | * Description: | ||
651 | * | ||
652 | * This function delivers a message/command to the device and waits | ||
653 | * for an ack to be received. The format is described in | ||
654 | * linux/wimax/i2400m.h. In summary, a command/get/set is followed by an | ||
655 | * ack. | ||
656 | * | ||
657 | * This function will not check the ack status, that's left up to the | ||
658 | * caller. Once done with the ack skb, it has to be kfree_skb()ed. | ||
659 | * | ||
660 | * The i2400m handles only one message at the same time, thus we need | ||
661 | * the mutex to exclude other players. | ||
662 | * | ||
663 | * We write the message and then wait for an answer to come back. The | ||
664 | * RX path intercepts control messages and handles them in | ||
665 | * i2400m_rx_ctl(). Reports (notifications) are (maybe) processed | ||
666 | * locally and then forwarded (as needed) to user space on the WiMAX | ||
667 | * stack message pipe. Acks are saved and passed back to us through an | ||
668 | * skb in i2400m->ack_skb which is ready to be given to generic | ||
669 | * netlink if need be. | ||
670 | */ | ||
671 | struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m, | ||
672 | const void *buf, size_t buf_len) | ||
673 | { | ||
674 | int result; | ||
675 | struct device *dev = i2400m_dev(i2400m); | ||
676 | const struct i2400m_l3l4_hdr *msg_l3l4_hdr; | ||
677 | struct sk_buff *ack_skb; | ||
678 | const struct i2400m_l3l4_hdr *ack_l3l4_hdr; | ||
679 | size_t ack_len; | ||
680 | int ack_timeout; | ||
681 | unsigned msg_type; | ||
682 | unsigned long flags; | ||
683 | |||
684 | d_fnstart(3, dev, "(i2400m %p buf %p len %zu)\n", | ||
685 | i2400m, buf, buf_len); | ||
686 | |||
687 | if (i2400m->boot_mode) | ||
688 | return ERR_PTR(-ENODEV); | ||
689 | |||
690 | msg_l3l4_hdr = buf; | ||
691 | /* Check msg & payload consistency */ | ||
692 | result = i2400m_msg_size_check(i2400m, msg_l3l4_hdr, buf_len); | ||
693 | if (result < 0) | ||
694 | goto error_bad_msg; | ||
695 | msg_type = le16_to_cpu(msg_l3l4_hdr->type); | ||
696 | d_printf(1, dev, "CMD/GET/SET 0x%04x %zu bytes\n", | ||
697 | msg_type, buf_len); | ||
698 | d_dump(2, dev, buf, buf_len); | ||
699 | |||
700 | /* Setup the completion, ack_skb ("we are waiting") and send | ||
701 | * the message to the device */ | ||
702 | mutex_lock(&i2400m->msg_mutex); | ||
703 | spin_lock_irqsave(&i2400m->rx_lock, flags); | ||
704 | i2400m->ack_skb = ERR_PTR(-EINPROGRESS); | ||
705 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | ||
706 | init_completion(&i2400m->msg_completion); | ||
707 | result = i2400m_tx(i2400m, buf, buf_len, I2400M_PT_CTRL); | ||
708 | if (result < 0) { | ||
709 | dev_err(dev, "can't send message 0x%04x: %d\n", | ||
710 | le16_to_cpu(msg_l3l4_hdr->type), result); | ||
711 | goto error_tx; | ||
712 | } | ||
713 | |||
714 | /* Some commands take longer to execute because of crypto ops, | ||
715 | * so we give them some more leeway on timeout */ | ||
716 | switch (msg_type) { | ||
717 | case I2400M_MT_GET_TLS_OPERATION_RESULT: | ||
718 | case I2400M_MT_CMD_SEND_EAP_RESPONSE: | ||
719 | ack_timeout = 5 * HZ; | ||
720 | break; | ||
721 | default: | ||
722 | ack_timeout = HZ; | ||
723 | }; | ||
724 | |||
725 | /* The RX path in rx.c will put any response for this message | ||
726 | * in i2400m->ack_skb and wake us up. If we cancel the wait, | ||
727 | * we need to change the value of i2400m->ack_skb to something | ||
728 | * not -EINPROGRESS so RX knows there is no one waiting. */ | ||
729 | result = wait_for_completion_interruptible_timeout( | ||
730 | &i2400m->msg_completion, ack_timeout); | ||
731 | if (result == 0) { | ||
732 | dev_err(dev, "timeout waiting for reply to message 0x%04x\n", | ||
733 | msg_type); | ||
734 | result = -ETIMEDOUT; | ||
735 | i2400m_msg_to_dev_cancel_wait(i2400m, result); | ||
736 | goto error_wait_for_completion; | ||
737 | } else if (result < 0) { | ||
738 | dev_err(dev, "error waiting for reply to message 0x%04x: %d\n", | ||
739 | msg_type, result); | ||
740 | i2400m_msg_to_dev_cancel_wait(i2400m, result); | ||
741 | goto error_wait_for_completion; | ||
742 | } | ||
743 | |||
744 | /* Pull out the ack data from i2400m->ack_skb -- see if it is | ||
745 | * an error and act accordingly */ | ||
746 | spin_lock_irqsave(&i2400m->rx_lock, flags); | ||
747 | ack_skb = i2400m->ack_skb; | ||
748 | if (IS_ERR(ack_skb)) | ||
749 | result = PTR_ERR(ack_skb); | ||
750 | else | ||
751 | result = 0; | ||
752 | i2400m->ack_skb = NULL; | ||
753 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | ||
754 | if (result < 0) | ||
755 | goto error_ack_status; | ||
756 | ack_l3l4_hdr = wimax_msg_data_len(ack_skb, &ack_len); | ||
757 | |||
758 | /* Check the ack and deliver it if it is ok */ | ||
759 | result = i2400m_msg_size_check(i2400m, ack_l3l4_hdr, ack_len); | ||
760 | if (result < 0) { | ||
761 | dev_err(dev, "HW BUG? reply to message 0x%04x: %d\n", | ||
762 | msg_type, result); | ||
763 | goto error_bad_ack_len; | ||
764 | } | ||
765 | if (msg_type != le16_to_cpu(ack_l3l4_hdr->type)) { | ||
766 | dev_err(dev, "HW BUG? bad reply 0x%04x to message 0x%04x\n", | ||
767 | le16_to_cpu(ack_l3l4_hdr->type), msg_type); | ||
768 | result = -EIO; | ||
769 | goto error_bad_ack_type; | ||
770 | } | ||
771 | i2400m_msg_ack_hook(i2400m, ack_l3l4_hdr, ack_len); | ||
772 | mutex_unlock(&i2400m->msg_mutex); | ||
773 | d_fnend(3, dev, "(i2400m %p buf %p len %zu) = %p\n", | ||
774 | i2400m, buf, buf_len, ack_skb); | ||
775 | return ack_skb; | ||
776 | |||
777 | error_bad_ack_type: | ||
778 | error_bad_ack_len: | ||
779 | kfree_skb(ack_skb); | ||
780 | error_ack_status: | ||
781 | error_wait_for_completion: | ||
782 | error_tx: | ||
783 | mutex_unlock(&i2400m->msg_mutex); | ||
784 | error_bad_msg: | ||
785 | d_fnend(3, dev, "(i2400m %p buf %p len %zu) = %d\n", | ||
786 | i2400m, buf, buf_len, result); | ||
787 | return ERR_PTR(result); | ||
788 | } | ||
789 | |||
790 | |||
791 | /* | ||
792 | * Definitions for the Enter Power Save command | ||
793 | * | ||
794 | * The Enter Power Save command requests the device to go into power | ||
795 | * saving mode. The device will ack or nak the command depending on it | ||
796 | * being ready for it. If it acks, we tell the USB subsystem to | ||
797 | * | ||
798 | * As well, the device might request to go into power saving mode by | ||
799 | * sending a report (REPORT_POWERSAVE_READY), in which case, we issue | ||
800 | * this command. The hookups in the RX coder allow | ||
801 | */ | ||
802 | enum { | ||
803 | I2400M_WAKEUP_ENABLED = 0x01, | ||
804 | I2400M_WAKEUP_DISABLED = 0x02, | ||
805 | I2400M_TLV_TYPE_WAKEUP_MODE = 144, | ||
806 | }; | ||
807 | |||
808 | struct i2400m_cmd_enter_power_save { | ||
809 | struct i2400m_l3l4_hdr hdr; | ||
810 | struct i2400m_tlv_hdr tlv; | ||
811 | __le32 val; | ||
812 | } __attribute__((packed)); | ||
813 | |||
814 | |||
815 | /* | ||
816 | * Request entering power save | ||
817 | * | ||
818 | * This command is (mainly) executed when the device indicates that it | ||
819 | * is ready to go into powersave mode via a REPORT_POWERSAVE_READY. | ||
820 | */ | ||
821 | int i2400m_cmd_enter_powersave(struct i2400m *i2400m) | ||
822 | { | ||
823 | int result; | ||
824 | struct device *dev = i2400m_dev(i2400m); | ||
825 | struct sk_buff *ack_skb; | ||
826 | struct i2400m_cmd_enter_power_save *cmd; | ||
827 | char strerr[32]; | ||
828 | |||
829 | result = -ENOMEM; | ||
830 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
831 | if (cmd == NULL) | ||
832 | goto error_alloc; | ||
833 | cmd->hdr.type = cpu_to_le16(I2400M_MT_CMD_ENTER_POWERSAVE); | ||
834 | cmd->hdr.length = cpu_to_le16(sizeof(*cmd) - sizeof(cmd->hdr)); | ||
835 | cmd->hdr.version = cpu_to_le16(I2400M_L3L4_VERSION); | ||
836 | cmd->tlv.type = cpu_to_le16(I2400M_TLV_TYPE_WAKEUP_MODE); | ||
837 | cmd->tlv.length = cpu_to_le16(sizeof(cmd->val)); | ||
838 | cmd->val = cpu_to_le32(I2400M_WAKEUP_ENABLED); | ||
839 | |||
840 | ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd)); | ||
841 | result = PTR_ERR(ack_skb); | ||
842 | if (IS_ERR(ack_skb)) { | ||
843 | dev_err(dev, "Failed to issue 'Enter power save' command: %d\n", | ||
844 | result); | ||
845 | goto error_msg_to_dev; | ||
846 | } | ||
847 | result = i2400m_msg_check_status(wimax_msg_data(ack_skb), | ||
848 | strerr, sizeof(strerr)); | ||
849 | if (result == -EACCES) | ||
850 | d_printf(1, dev, "Cannot enter power save mode\n"); | ||
851 | else if (result < 0) | ||
852 | dev_err(dev, "'Enter power save' (0x%04x) command failed: " | ||
853 | "%d - %s\n", I2400M_MT_CMD_ENTER_POWERSAVE, | ||
854 | result, strerr); | ||
855 | else | ||
856 | d_printf(1, dev, "device ready to power save\n"); | ||
857 | kfree_skb(ack_skb); | ||
858 | error_msg_to_dev: | ||
859 | kfree(cmd); | ||
860 | error_alloc: | ||
861 | return result; | ||
862 | } | ||
863 | EXPORT_SYMBOL_GPL(i2400m_cmd_enter_powersave); | ||
864 | |||
865 | |||
866 | /* | ||
867 | * Definitions for getting device information | ||
868 | */ | ||
869 | enum { | ||
870 | I2400M_TLV_DETAILED_DEVICE_INFO = 140 | ||
871 | }; | ||
872 | |||
873 | /** | ||
874 | * i2400m_get_device_info - Query the device for detailed device information | ||
875 | * | ||
876 | * @i2400m: device descriptor | ||
877 | * | ||
878 | * Returns: an skb whose skb->data points to a 'struct | ||
879 | * i2400m_tlv_detailed_device_info'. When done, kfree_skb() it. The | ||
880 | * skb is *guaranteed* to contain the whole TLV data structure. | ||
881 | * | ||
882 | * On error, IS_ERR(skb) is true and ERR_PTR(skb) is the error | ||
883 | * code. | ||
884 | */ | ||
885 | struct sk_buff *i2400m_get_device_info(struct i2400m *i2400m) | ||
886 | { | ||
887 | int result; | ||
888 | struct device *dev = i2400m_dev(i2400m); | ||
889 | struct sk_buff *ack_skb; | ||
890 | struct i2400m_l3l4_hdr *cmd; | ||
891 | const struct i2400m_l3l4_hdr *ack; | ||
892 | size_t ack_len; | ||
893 | const struct i2400m_tlv_hdr *tlv; | ||
894 | const struct i2400m_tlv_detailed_device_info *ddi; | ||
895 | char strerr[32]; | ||
896 | |||
897 | ack_skb = ERR_PTR(-ENOMEM); | ||
898 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
899 | if (cmd == NULL) | ||
900 | goto error_alloc; | ||
901 | cmd->type = cpu_to_le16(I2400M_MT_GET_DEVICE_INFO); | ||
902 | cmd->length = 0; | ||
903 | cmd->version = cpu_to_le16(I2400M_L3L4_VERSION); | ||
904 | |||
905 | ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd)); | ||
906 | if (IS_ERR(ack_skb)) { | ||
907 | dev_err(dev, "Failed to issue 'get device info' command: %ld\n", | ||
908 | PTR_ERR(ack_skb)); | ||
909 | goto error_msg_to_dev; | ||
910 | } | ||
911 | ack = wimax_msg_data_len(ack_skb, &ack_len); | ||
912 | result = i2400m_msg_check_status(ack, strerr, sizeof(strerr)); | ||
913 | if (result < 0) { | ||
914 | dev_err(dev, "'get device info' (0x%04x) command failed: " | ||
915 | "%d - %s\n", I2400M_MT_GET_DEVICE_INFO, result, | ||
916 | strerr); | ||
917 | goto error_cmd_failed; | ||
918 | } | ||
919 | tlv = i2400m_tlv_find(i2400m, ack->pl, ack_len - sizeof(*ack), | ||
920 | I2400M_TLV_DETAILED_DEVICE_INFO, sizeof(*ddi)); | ||
921 | if (tlv == NULL) { | ||
922 | dev_err(dev, "GET DEVICE INFO: " | ||
923 | "detailed device info TLV not found (0x%04x)\n", | ||
924 | I2400M_TLV_DETAILED_DEVICE_INFO); | ||
925 | result = -EIO; | ||
926 | goto error_no_tlv; | ||
927 | } | ||
928 | skb_pull(ack_skb, (void *) tlv - (void *) ack_skb->data); | ||
929 | error_msg_to_dev: | ||
930 | kfree(cmd); | ||
931 | error_alloc: | ||
932 | return ack_skb; | ||
933 | |||
934 | error_no_tlv: | ||
935 | error_cmd_failed: | ||
936 | kfree_skb(ack_skb); | ||
937 | kfree(cmd); | ||
938 | return ERR_PTR(result); | ||
939 | } | ||
940 | |||
941 | |||
942 | /* Firmware interface versions we support */ | ||
943 | enum { | ||
944 | I2400M_HDIv_MAJOR = 9, | ||
945 | I2400M_HDIv_MAJOR_2 = 8, | ||
946 | I2400M_HDIv_MINOR = 1, | ||
947 | }; | ||
948 | |||
949 | |||
950 | /** | ||
951 | * i2400m_firmware_check - check firmware versions are compatible with | ||
952 | * the driver | ||
953 | * | ||
954 | * @i2400m: device descriptor | ||
955 | * | ||
956 | * Returns: 0 if ok, < 0 errno code an error and a message in the | ||
957 | * kernel log. | ||
958 | * | ||
959 | * Long function, but quite simple; first chunk launches the command | ||
960 | * and double checks the reply for the right TLV. Then we process the | ||
961 | * TLV (where the meat is). | ||
962 | */ | ||
963 | int i2400m_firmware_check(struct i2400m *i2400m) | ||
964 | { | ||
965 | int result; | ||
966 | struct device *dev = i2400m_dev(i2400m); | ||
967 | struct sk_buff *ack_skb; | ||
968 | struct i2400m_l3l4_hdr *cmd; | ||
969 | const struct i2400m_l3l4_hdr *ack; | ||
970 | size_t ack_len; | ||
971 | const struct i2400m_tlv_hdr *tlv; | ||
972 | const struct i2400m_tlv_l4_message_versions *l4mv; | ||
973 | char strerr[32]; | ||
974 | unsigned major, minor, branch; | ||
975 | |||
976 | result = -ENOMEM; | ||
977 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
978 | if (cmd == NULL) | ||
979 | goto error_alloc; | ||
980 | cmd->type = cpu_to_le16(I2400M_MT_GET_LM_VERSION); | ||
981 | cmd->length = 0; | ||
982 | cmd->version = cpu_to_le16(I2400M_L3L4_VERSION); | ||
983 | |||
984 | ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd)); | ||
985 | if (IS_ERR(ack_skb)) { | ||
986 | result = PTR_ERR(ack_skb); | ||
987 | dev_err(dev, "Failed to issue 'get lm version' command: %-d\n", | ||
988 | result); | ||
989 | goto error_msg_to_dev; | ||
990 | } | ||
991 | ack = wimax_msg_data_len(ack_skb, &ack_len); | ||
992 | result = i2400m_msg_check_status(ack, strerr, sizeof(strerr)); | ||
993 | if (result < 0) { | ||
994 | dev_err(dev, "'get lm version' (0x%04x) command failed: " | ||
995 | "%d - %s\n", I2400M_MT_GET_LM_VERSION, result, | ||
996 | strerr); | ||
997 | goto error_cmd_failed; | ||
998 | } | ||
999 | tlv = i2400m_tlv_find(i2400m, ack->pl, ack_len - sizeof(*ack), | ||
1000 | I2400M_TLV_L4_MESSAGE_VERSIONS, sizeof(*l4mv)); | ||
1001 | if (tlv == NULL) { | ||
1002 | dev_err(dev, "get lm version: TLV not found (0x%04x)\n", | ||
1003 | I2400M_TLV_L4_MESSAGE_VERSIONS); | ||
1004 | result = -EIO; | ||
1005 | goto error_no_tlv; | ||
1006 | } | ||
1007 | l4mv = container_of(tlv, typeof(*l4mv), hdr); | ||
1008 | major = le16_to_cpu(l4mv->major); | ||
1009 | minor = le16_to_cpu(l4mv->minor); | ||
1010 | branch = le16_to_cpu(l4mv->branch); | ||
1011 | result = -EINVAL; | ||
1012 | if (major != I2400M_HDIv_MAJOR | ||
1013 | && major != I2400M_HDIv_MAJOR_2) { | ||
1014 | dev_err(dev, "unsupported major fw interface version " | ||
1015 | "%u.%u.%u\n", major, minor, branch); | ||
1016 | goto error_bad_major; | ||
1017 | } | ||
1018 | if (major == I2400M_HDIv_MAJOR_2) | ||
1019 | dev_err(dev, "deprecated major fw interface version " | ||
1020 | "%u.%u.%u\n", major, minor, branch); | ||
1021 | result = 0; | ||
1022 | if (minor != I2400M_HDIv_MINOR) | ||
1023 | dev_warn(dev, "untested minor fw firmware version %u.%u.%u\n", | ||
1024 | major, minor, branch); | ||
1025 | error_bad_major: | ||
1026 | dev_info(dev, "firmware interface version %u.%u.%u\n", | ||
1027 | major, minor, branch); | ||
1028 | error_no_tlv: | ||
1029 | error_cmd_failed: | ||
1030 | kfree_skb(ack_skb); | ||
1031 | error_msg_to_dev: | ||
1032 | kfree(cmd); | ||
1033 | error_alloc: | ||
1034 | return result; | ||
1035 | } | ||
1036 | |||
1037 | |||
1038 | /* | ||
1039 | * Send an DoExitIdle command to the device to ask it to go out of | ||
1040 | * basestation-idle mode. | ||
1041 | * | ||
1042 | * @i2400m: device descriptor | ||
1043 | * | ||
1044 | * This starts a renegotiation with the basestation that might involve | ||
1045 | * another crypto handshake with user space. | ||
1046 | * | ||
1047 | * Returns: 0 if ok, < 0 errno code on error. | ||
1048 | */ | ||
1049 | int i2400m_cmd_exit_idle(struct i2400m *i2400m) | ||
1050 | { | ||
1051 | int result; | ||
1052 | struct device *dev = i2400m_dev(i2400m); | ||
1053 | struct sk_buff *ack_skb; | ||
1054 | struct i2400m_l3l4_hdr *cmd; | ||
1055 | char strerr[32]; | ||
1056 | |||
1057 | result = -ENOMEM; | ||
1058 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1059 | if (cmd == NULL) | ||
1060 | goto error_alloc; | ||
1061 | cmd->type = cpu_to_le16(I2400M_MT_CMD_EXIT_IDLE); | ||
1062 | cmd->length = 0; | ||
1063 | cmd->version = cpu_to_le16(I2400M_L3L4_VERSION); | ||
1064 | |||
1065 | ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd)); | ||
1066 | result = PTR_ERR(ack_skb); | ||
1067 | if (IS_ERR(ack_skb)) { | ||
1068 | dev_err(dev, "Failed to issue 'exit idle' command: %d\n", | ||
1069 | result); | ||
1070 | goto error_msg_to_dev; | ||
1071 | } | ||
1072 | result = i2400m_msg_check_status(wimax_msg_data(ack_skb), | ||
1073 | strerr, sizeof(strerr)); | ||
1074 | kfree_skb(ack_skb); | ||
1075 | error_msg_to_dev: | ||
1076 | kfree(cmd); | ||
1077 | error_alloc: | ||
1078 | return result; | ||
1079 | |||
1080 | } | ||
1081 | |||
1082 | |||
1083 | /* | ||
1084 | * Query the device for its state, update the WiMAX stack's idea of it | ||
1085 | * | ||
1086 | * @i2400m: device descriptor | ||
1087 | * | ||
1088 | * Returns: 0 if ok, < 0 errno code on error. | ||
1089 | * | ||
1090 | * Executes a 'Get State' command and parses the returned | ||
1091 | * TLVs. | ||
1092 | * | ||
1093 | * Because this is almost identical to a 'Report State', we use | ||
1094 | * i2400m_report_state_hook() to parse the answer. This will set the | ||
1095 | * carrier state, as well as the RF Kill switches state. | ||
1096 | */ | ||
1097 | int i2400m_cmd_get_state(struct i2400m *i2400m) | ||
1098 | { | ||
1099 | int result; | ||
1100 | struct device *dev = i2400m_dev(i2400m); | ||
1101 | struct sk_buff *ack_skb; | ||
1102 | struct i2400m_l3l4_hdr *cmd; | ||
1103 | const struct i2400m_l3l4_hdr *ack; | ||
1104 | size_t ack_len; | ||
1105 | char strerr[32]; | ||
1106 | |||
1107 | result = -ENOMEM; | ||
1108 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1109 | if (cmd == NULL) | ||
1110 | goto error_alloc; | ||
1111 | cmd->type = cpu_to_le16(I2400M_MT_GET_STATE); | ||
1112 | cmd->length = 0; | ||
1113 | cmd->version = cpu_to_le16(I2400M_L3L4_VERSION); | ||
1114 | |||
1115 | ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd)); | ||
1116 | if (IS_ERR(ack_skb)) { | ||
1117 | dev_err(dev, "Failed to issue 'get state' command: %ld\n", | ||
1118 | PTR_ERR(ack_skb)); | ||
1119 | result = PTR_ERR(ack_skb); | ||
1120 | goto error_msg_to_dev; | ||
1121 | } | ||
1122 | ack = wimax_msg_data_len(ack_skb, &ack_len); | ||
1123 | result = i2400m_msg_check_status(ack, strerr, sizeof(strerr)); | ||
1124 | if (result < 0) { | ||
1125 | dev_err(dev, "'get state' (0x%04x) command failed: " | ||
1126 | "%d - %s\n", I2400M_MT_GET_STATE, result, strerr); | ||
1127 | goto error_cmd_failed; | ||
1128 | } | ||
1129 | i2400m_report_state_hook(i2400m, ack, ack_len - sizeof(*ack), | ||
1130 | "GET STATE"); | ||
1131 | result = 0; | ||
1132 | kfree_skb(ack_skb); | ||
1133 | error_cmd_failed: | ||
1134 | error_msg_to_dev: | ||
1135 | kfree(cmd); | ||
1136 | error_alloc: | ||
1137 | return result; | ||
1138 | } | ||
1139 | EXPORT_SYMBOL_GPL(i2400m_cmd_get_state); | ||
1140 | |||
1141 | |||
1142 | /** | ||
1143 | * Set basic configuration settings | ||
1144 | * | ||
1145 | * @i2400m: device descriptor | ||
1146 | * @args: array of pointers to the TLV headers to send for | ||
1147 | * configuration (each followed by its payload). | ||
1148 | * TLV headers and payloads must be properly initialized, with the | ||
1149 | * right endianess (LE). | ||
1150 | * @arg_size: number of pointers in the @args array | ||
1151 | */ | ||
1152 | int i2400m_set_init_config(struct i2400m *i2400m, | ||
1153 | const struct i2400m_tlv_hdr **arg, size_t args) | ||
1154 | { | ||
1155 | int result; | ||
1156 | struct device *dev = i2400m_dev(i2400m); | ||
1157 | struct sk_buff *ack_skb; | ||
1158 | struct i2400m_l3l4_hdr *cmd; | ||
1159 | char strerr[32]; | ||
1160 | unsigned argc, argsize, tlv_size; | ||
1161 | const struct i2400m_tlv_hdr *tlv_hdr; | ||
1162 | void *buf, *itr; | ||
1163 | |||
1164 | d_fnstart(3, dev, "(i2400m %p arg %p args %zu)\n", i2400m, arg, args); | ||
1165 | result = 0; | ||
1166 | if (args == 0) | ||
1167 | goto none; | ||
1168 | /* Compute the size of all the TLVs, so we can alloc a | ||
1169 | * contiguous command block to copy them. */ | ||
1170 | argsize = 0; | ||
1171 | for (argc = 0; argc < args; argc++) { | ||
1172 | tlv_hdr = arg[argc]; | ||
1173 | argsize += sizeof(*tlv_hdr) + le16_to_cpu(tlv_hdr->length); | ||
1174 | } | ||
1175 | WARN_ON(argc >= 9); /* As per hw spec */ | ||
1176 | |||
1177 | /* Alloc the space for the command and TLVs*/ | ||
1178 | result = -ENOMEM; | ||
1179 | buf = kzalloc(sizeof(*cmd) + argsize, GFP_KERNEL); | ||
1180 | if (buf == NULL) | ||
1181 | goto error_alloc; | ||
1182 | cmd = buf; | ||
1183 | cmd->type = cpu_to_le16(I2400M_MT_SET_INIT_CONFIG); | ||
1184 | cmd->length = cpu_to_le16(argsize); | ||
1185 | cmd->version = cpu_to_le16(I2400M_L3L4_VERSION); | ||
1186 | |||
1187 | /* Copy the TLVs */ | ||
1188 | itr = buf + sizeof(*cmd); | ||
1189 | for (argc = 0; argc < args; argc++) { | ||
1190 | tlv_hdr = arg[argc]; | ||
1191 | tlv_size = sizeof(*tlv_hdr) + le16_to_cpu(tlv_hdr->length); | ||
1192 | memcpy(itr, tlv_hdr, tlv_size); | ||
1193 | itr += tlv_size; | ||
1194 | } | ||
1195 | |||
1196 | /* Send the message! */ | ||
1197 | ack_skb = i2400m_msg_to_dev(i2400m, buf, sizeof(*cmd) + argsize); | ||
1198 | result = PTR_ERR(ack_skb); | ||
1199 | if (IS_ERR(ack_skb)) { | ||
1200 | dev_err(dev, "Failed to issue 'init config' command: %d\n", | ||
1201 | result); | ||
1202 | |||
1203 | goto error_msg_to_dev; | ||
1204 | } | ||
1205 | result = i2400m_msg_check_status(wimax_msg_data(ack_skb), | ||
1206 | strerr, sizeof(strerr)); | ||
1207 | if (result < 0) | ||
1208 | dev_err(dev, "'init config' (0x%04x) command failed: %d - %s\n", | ||
1209 | I2400M_MT_SET_INIT_CONFIG, result, strerr); | ||
1210 | kfree_skb(ack_skb); | ||
1211 | error_msg_to_dev: | ||
1212 | kfree(buf); | ||
1213 | error_alloc: | ||
1214 | none: | ||
1215 | d_fnend(3, dev, "(i2400m %p arg %p args %zu) = %d\n", | ||
1216 | i2400m, arg, args, result); | ||
1217 | return result; | ||
1218 | |||
1219 | } | ||
1220 | EXPORT_SYMBOL_GPL(i2400m_set_init_config); | ||
1221 | |||
1222 | |||
1223 | /** | ||
1224 | * i2400m_dev_initialize - Initialize the device once communications are ready | ||
1225 | * | ||
1226 | * @i2400m: device descriptor | ||
1227 | * | ||
1228 | * Returns: 0 if ok, < 0 errno code on error. | ||
1229 | * | ||
1230 | * Configures the device to work the way we like it. | ||
1231 | * | ||
1232 | * At the point of this call, the device is registered with the WiMAX | ||
1233 | * and netdev stacks, firmware is uploaded and we can talk to the | ||
1234 | * device normally. | ||
1235 | */ | ||
1236 | int i2400m_dev_initialize(struct i2400m *i2400m) | ||
1237 | { | ||
1238 | int result; | ||
1239 | struct device *dev = i2400m_dev(i2400m); | ||
1240 | struct i2400m_tlv_config_idle_parameters idle_params; | ||
1241 | const struct i2400m_tlv_hdr *args[9]; | ||
1242 | unsigned argc = 0; | ||
1243 | |||
1244 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
1245 | /* Useless for now...might change */ | ||
1246 | if (i2400m_idle_mode_disabled) { | ||
1247 | idle_params.hdr.type = | ||
1248 | cpu_to_le16(I2400M_TLV_CONFIG_IDLE_PARAMETERS); | ||
1249 | idle_params.hdr.length = cpu_to_le16( | ||
1250 | sizeof(idle_params) - sizeof(idle_params.hdr)); | ||
1251 | idle_params.idle_timeout = 0; | ||
1252 | idle_params.idle_paging_interval = 0; | ||
1253 | args[argc++] = &idle_params.hdr; | ||
1254 | } | ||
1255 | result = i2400m_set_init_config(i2400m, args, argc); | ||
1256 | if (result < 0) | ||
1257 | goto error; | ||
1258 | result = i2400m_firmware_check(i2400m); /* fw versions ok? */ | ||
1259 | if (result < 0) | ||
1260 | goto error; | ||
1261 | /* | ||
1262 | * Update state: Here it just calls a get state; parsing the | ||
1263 | * result (System State TLV and RF Status TLV [done in the rx | ||
1264 | * path hooks]) will set the hardware and software RF-Kill | ||
1265 | * status. | ||
1266 | */ | ||
1267 | result = i2400m_cmd_get_state(i2400m); | ||
1268 | error: | ||
1269 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); | ||
1270 | return result; | ||
1271 | } | ||
1272 | |||
1273 | |||
1274 | /** | ||
1275 | * i2400m_dev_shutdown - Shutdown a running device | ||
1276 | * | ||
1277 | * @i2400m: device descriptor | ||
1278 | * | ||
1279 | * Gracefully stops the device, moving it to the lowest power | ||
1280 | * consumption state possible. | ||
1281 | */ | ||
1282 | void i2400m_dev_shutdown(struct i2400m *i2400m) | ||
1283 | { | ||
1284 | int result = -ENODEV; | ||
1285 | struct device *dev = i2400m_dev(i2400m); | ||
1286 | |||
1287 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
1288 | result = i2400m->bus_reset(i2400m, I2400M_RT_WARM); | ||
1289 | d_fnend(3, dev, "(i2400m %p) = void [%d]\n", i2400m, result); | ||
1290 | return; | ||
1291 | } | ||
diff --git a/drivers/net/wimax/i2400m/debug-levels.h b/drivers/net/wimax/i2400m/debug-levels.h new file mode 100644 index 000000000000..3183baa16a52 --- /dev/null +++ b/drivers/net/wimax/i2400m/debug-levels.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Debug levels control file for the i2400m module | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com> | ||
7 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License version | ||
11 | * 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301, USA. | ||
22 | */ | ||
23 | #ifndef __debug_levels__h__ | ||
24 | #define __debug_levels__h__ | ||
25 | |||
26 | /* Maximum compile and run time debug level for all submodules */ | ||
27 | #define D_MODULENAME i2400m | ||
28 | #define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL | ||
29 | |||
30 | #include <linux/wimax/debug.h> | ||
31 | |||
32 | /* List of all the enabled modules */ | ||
33 | enum d_module { | ||
34 | D_SUBMODULE_DECLARE(control), | ||
35 | D_SUBMODULE_DECLARE(driver), | ||
36 | D_SUBMODULE_DECLARE(debugfs), | ||
37 | D_SUBMODULE_DECLARE(fw), | ||
38 | D_SUBMODULE_DECLARE(netdev), | ||
39 | D_SUBMODULE_DECLARE(rfkill), | ||
40 | D_SUBMODULE_DECLARE(rx), | ||
41 | D_SUBMODULE_DECLARE(tx), | ||
42 | }; | ||
43 | |||
44 | |||
45 | #endif /* #ifndef __debug_levels__h__ */ | ||
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c new file mode 100644 index 000000000000..626632985977 --- /dev/null +++ b/drivers/net/wimax/i2400m/debugfs.c | |||
@@ -0,0 +1,392 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Debugfs interfaces to manipulate driver and device information | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007 Intel Corporation <linux-wimax@intel.com> | ||
7 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License version | ||
11 | * 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/debugfs.h> | ||
25 | #include <linux/netdevice.h> | ||
26 | #include <linux/etherdevice.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/device.h> | ||
29 | #include "i2400m.h" | ||
30 | |||
31 | |||
32 | #define D_SUBMODULE debugfs | ||
33 | #include "debug-levels.h" | ||
34 | |||
35 | static | ||
36 | int debugfs_netdev_queue_stopped_get(void *data, u64 *val) | ||
37 | { | ||
38 | struct i2400m *i2400m = data; | ||
39 | *val = netif_queue_stopped(i2400m->wimax_dev.net_dev); | ||
40 | return 0; | ||
41 | } | ||
42 | DEFINE_SIMPLE_ATTRIBUTE(fops_netdev_queue_stopped, | ||
43 | debugfs_netdev_queue_stopped_get, | ||
44 | NULL, "%llu\n"); | ||
45 | |||
46 | |||
47 | static | ||
48 | struct dentry *debugfs_create_netdev_queue_stopped( | ||
49 | const char *name, struct dentry *parent, struct i2400m *i2400m) | ||
50 | { | ||
51 | return debugfs_create_file(name, 0400, parent, i2400m, | ||
52 | &fops_netdev_queue_stopped); | ||
53 | } | ||
54 | |||
55 | |||
56 | /* | ||
57 | * inode->i_private has the @data argument to debugfs_create_file() | ||
58 | */ | ||
59 | static | ||
60 | int i2400m_stats_open(struct inode *inode, struct file *filp) | ||
61 | { | ||
62 | filp->private_data = inode->i_private; | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * We don't allow partial reads of this file, as then the reader would | ||
68 | * get weirdly confused data as it is updated. | ||
69 | * | ||
70 | * So or you read it all or nothing; if you try to read with an offset | ||
71 | * != 0, we consider you are done reading. | ||
72 | */ | ||
73 | static | ||
74 | ssize_t i2400m_rx_stats_read(struct file *filp, char __user *buffer, | ||
75 | size_t count, loff_t *ppos) | ||
76 | { | ||
77 | struct i2400m *i2400m = filp->private_data; | ||
78 | char buf[128]; | ||
79 | unsigned long flags; | ||
80 | |||
81 | if (*ppos != 0) | ||
82 | return 0; | ||
83 | if (count < sizeof(buf)) | ||
84 | return -ENOSPC; | ||
85 | spin_lock_irqsave(&i2400m->rx_lock, flags); | ||
86 | snprintf(buf, sizeof(buf), "%u %u %u %u %u %u %u\n", | ||
87 | i2400m->rx_pl_num, i2400m->rx_pl_min, | ||
88 | i2400m->rx_pl_max, i2400m->rx_num, | ||
89 | i2400m->rx_size_acc, | ||
90 | i2400m->rx_size_min, i2400m->rx_size_max); | ||
91 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | ||
92 | return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); | ||
93 | } | ||
94 | |||
95 | |||
96 | /* Any write clears the stats */ | ||
97 | static | ||
98 | ssize_t i2400m_rx_stats_write(struct file *filp, const char __user *buffer, | ||
99 | size_t count, loff_t *ppos) | ||
100 | { | ||
101 | struct i2400m *i2400m = filp->private_data; | ||
102 | unsigned long flags; | ||
103 | |||
104 | spin_lock_irqsave(&i2400m->rx_lock, flags); | ||
105 | i2400m->rx_pl_num = 0; | ||
106 | i2400m->rx_pl_max = 0; | ||
107 | i2400m->rx_pl_min = UINT_MAX; | ||
108 | i2400m->rx_num = 0; | ||
109 | i2400m->rx_size_acc = 0; | ||
110 | i2400m->rx_size_min = UINT_MAX; | ||
111 | i2400m->rx_size_max = 0; | ||
112 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | ||
113 | return count; | ||
114 | } | ||
115 | |||
116 | static | ||
117 | const struct file_operations i2400m_rx_stats_fops = { | ||
118 | .owner = THIS_MODULE, | ||
119 | .open = i2400m_stats_open, | ||
120 | .read = i2400m_rx_stats_read, | ||
121 | .write = i2400m_rx_stats_write, | ||
122 | }; | ||
123 | |||
124 | |||
125 | /* See i2400m_rx_stats_read() */ | ||
126 | static | ||
127 | ssize_t i2400m_tx_stats_read(struct file *filp, char __user *buffer, | ||
128 | size_t count, loff_t *ppos) | ||
129 | { | ||
130 | struct i2400m *i2400m = filp->private_data; | ||
131 | char buf[128]; | ||
132 | unsigned long flags; | ||
133 | |||
134 | if (*ppos != 0) | ||
135 | return 0; | ||
136 | if (count < sizeof(buf)) | ||
137 | return -ENOSPC; | ||
138 | spin_lock_irqsave(&i2400m->tx_lock, flags); | ||
139 | snprintf(buf, sizeof(buf), "%u %u %u %u %u %u %u\n", | ||
140 | i2400m->tx_pl_num, i2400m->tx_pl_min, | ||
141 | i2400m->tx_pl_max, i2400m->tx_num, | ||
142 | i2400m->tx_size_acc, | ||
143 | i2400m->tx_size_min, i2400m->tx_size_max); | ||
144 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | ||
145 | return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf)); | ||
146 | } | ||
147 | |||
148 | /* Any write clears the stats */ | ||
149 | static | ||
150 | ssize_t i2400m_tx_stats_write(struct file *filp, const char __user *buffer, | ||
151 | size_t count, loff_t *ppos) | ||
152 | { | ||
153 | struct i2400m *i2400m = filp->private_data; | ||
154 | unsigned long flags; | ||
155 | |||
156 | spin_lock_irqsave(&i2400m->tx_lock, flags); | ||
157 | i2400m->tx_pl_num = 0; | ||
158 | i2400m->tx_pl_max = 0; | ||
159 | i2400m->tx_pl_min = UINT_MAX; | ||
160 | i2400m->tx_num = 0; | ||
161 | i2400m->tx_size_acc = 0; | ||
162 | i2400m->tx_size_min = UINT_MAX; | ||
163 | i2400m->tx_size_max = 0; | ||
164 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | ||
165 | return count; | ||
166 | } | ||
167 | |||
168 | static | ||
169 | const struct file_operations i2400m_tx_stats_fops = { | ||
170 | .owner = THIS_MODULE, | ||
171 | .open = i2400m_stats_open, | ||
172 | .read = i2400m_tx_stats_read, | ||
173 | .write = i2400m_tx_stats_write, | ||
174 | }; | ||
175 | |||
176 | |||
177 | /* Write 1 to ask the device to go into suspend */ | ||
178 | static | ||
179 | int debugfs_i2400m_suspend_set(void *data, u64 val) | ||
180 | { | ||
181 | int result; | ||
182 | struct i2400m *i2400m = data; | ||
183 | result = i2400m_cmd_enter_powersave(i2400m); | ||
184 | if (result >= 0) | ||
185 | result = 0; | ||
186 | return result; | ||
187 | } | ||
188 | DEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_suspend, | ||
189 | NULL, debugfs_i2400m_suspend_set, | ||
190 | "%llu\n"); | ||
191 | |||
192 | static | ||
193 | struct dentry *debugfs_create_i2400m_suspend( | ||
194 | const char *name, struct dentry *parent, struct i2400m *i2400m) | ||
195 | { | ||
196 | return debugfs_create_file(name, 0200, parent, i2400m, | ||
197 | &fops_i2400m_suspend); | ||
198 | } | ||
199 | |||
200 | |||
201 | /* | ||
202 | * Reset the device | ||
203 | * | ||
204 | * Write 0 to ask the device to soft reset, 1 to cold reset, 2 to bus | ||
205 | * reset (as defined by enum i2400m_reset_type). | ||
206 | */ | ||
207 | static | ||
208 | int debugfs_i2400m_reset_set(void *data, u64 val) | ||
209 | { | ||
210 | int result; | ||
211 | struct i2400m *i2400m = data; | ||
212 | enum i2400m_reset_type rt = val; | ||
213 | switch(rt) { | ||
214 | case I2400M_RT_WARM: | ||
215 | case I2400M_RT_COLD: | ||
216 | case I2400M_RT_BUS: | ||
217 | result = i2400m->bus_reset(i2400m, rt); | ||
218 | if (result >= 0) | ||
219 | result = 0; | ||
220 | default: | ||
221 | result = -EINVAL; | ||
222 | } | ||
223 | return result; | ||
224 | } | ||
225 | DEFINE_SIMPLE_ATTRIBUTE(fops_i2400m_reset, | ||
226 | NULL, debugfs_i2400m_reset_set, | ||
227 | "%llu\n"); | ||
228 | |||
229 | static | ||
230 | struct dentry *debugfs_create_i2400m_reset( | ||
231 | const char *name, struct dentry *parent, struct i2400m *i2400m) | ||
232 | { | ||
233 | return debugfs_create_file(name, 0200, parent, i2400m, | ||
234 | &fops_i2400m_reset); | ||
235 | } | ||
236 | |||
237 | /* | ||
238 | * Debug levels control; see debug.h | ||
239 | */ | ||
240 | struct d_level D_LEVEL[] = { | ||
241 | D_SUBMODULE_DEFINE(control), | ||
242 | D_SUBMODULE_DEFINE(driver), | ||
243 | D_SUBMODULE_DEFINE(debugfs), | ||
244 | D_SUBMODULE_DEFINE(fw), | ||
245 | D_SUBMODULE_DEFINE(netdev), | ||
246 | D_SUBMODULE_DEFINE(rfkill), | ||
247 | D_SUBMODULE_DEFINE(rx), | ||
248 | D_SUBMODULE_DEFINE(tx), | ||
249 | }; | ||
250 | size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); | ||
251 | |||
252 | #define __debugfs_register(prefix, name, parent) \ | ||
253 | do { \ | ||
254 | result = d_level_register_debugfs(prefix, name, parent); \ | ||
255 | if (result < 0) \ | ||
256 | goto error; \ | ||
257 | } while (0) | ||
258 | |||
259 | |||
260 | int i2400m_debugfs_add(struct i2400m *i2400m) | ||
261 | { | ||
262 | int result; | ||
263 | struct device *dev = i2400m_dev(i2400m); | ||
264 | struct dentry *dentry = i2400m->wimax_dev.debugfs_dentry; | ||
265 | struct dentry *fd; | ||
266 | |||
267 | dentry = debugfs_create_dir("i2400m", dentry); | ||
268 | result = PTR_ERR(dentry); | ||
269 | if (IS_ERR(dentry)) { | ||
270 | if (result == -ENODEV) | ||
271 | result = 0; /* No debugfs support */ | ||
272 | goto error; | ||
273 | } | ||
274 | i2400m->debugfs_dentry = dentry; | ||
275 | __debugfs_register("dl_", control, dentry); | ||
276 | __debugfs_register("dl_", driver, dentry); | ||
277 | __debugfs_register("dl_", debugfs, dentry); | ||
278 | __debugfs_register("dl_", fw, dentry); | ||
279 | __debugfs_register("dl_", netdev, dentry); | ||
280 | __debugfs_register("dl_", rfkill, dentry); | ||
281 | __debugfs_register("dl_", rx, dentry); | ||
282 | __debugfs_register("dl_", tx, dentry); | ||
283 | |||
284 | fd = debugfs_create_size_t("tx_in", 0400, dentry, | ||
285 | &i2400m->tx_in); | ||
286 | result = PTR_ERR(fd); | ||
287 | if (IS_ERR(fd) && result != -ENODEV) { | ||
288 | dev_err(dev, "Can't create debugfs entry " | ||
289 | "tx_in: %d\n", result); | ||
290 | goto error; | ||
291 | } | ||
292 | |||
293 | fd = debugfs_create_size_t("tx_out", 0400, dentry, | ||
294 | &i2400m->tx_out); | ||
295 | result = PTR_ERR(fd); | ||
296 | if (IS_ERR(fd) && result != -ENODEV) { | ||
297 | dev_err(dev, "Can't create debugfs entry " | ||
298 | "tx_out: %d\n", result); | ||
299 | goto error; | ||
300 | } | ||
301 | |||
302 | fd = debugfs_create_u32("state", 0600, dentry, | ||
303 | &i2400m->state); | ||
304 | result = PTR_ERR(fd); | ||
305 | if (IS_ERR(fd) && result != -ENODEV) { | ||
306 | dev_err(dev, "Can't create debugfs entry " | ||
307 | "state: %d\n", result); | ||
308 | goto error; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * Trace received messages from user space | ||
313 | * | ||
314 | * In order to tap the bidirectional message stream in the | ||
315 | * 'msg' pipe, user space can read from the 'msg' pipe; | ||
316 | * however, due to limitations in libnl, we can't know what | ||
317 | * the different applications are sending down to the kernel. | ||
318 | * | ||
319 | * So we have this hack where the driver will echo any message | ||
320 | * received on the msg pipe from user space [through a call to | ||
321 | * wimax_dev->op_msg_from_user() into | ||
322 | * i2400m_op_msg_from_user()] into the 'trace' pipe that this | ||
323 | * driver creates. | ||
324 | * | ||
325 | * So then, reading from both the 'trace' and 'msg' pipes in | ||
326 | * user space will provide a full dump of the traffic. | ||
327 | * | ||
328 | * Write 1 to activate, 0 to clear. | ||
329 | * | ||
330 | * It is not really very atomic, but it is also not too | ||
331 | * critical. | ||
332 | */ | ||
333 | fd = debugfs_create_u8("trace_msg_from_user", 0600, dentry, | ||
334 | &i2400m->trace_msg_from_user); | ||
335 | result = PTR_ERR(fd); | ||
336 | if (IS_ERR(fd) && result != -ENODEV) { | ||
337 | dev_err(dev, "Can't create debugfs entry " | ||
338 | "trace_msg_from_user: %d\n", result); | ||
339 | goto error; | ||
340 | } | ||
341 | |||
342 | fd = debugfs_create_netdev_queue_stopped("netdev_queue_stopped", | ||
343 | dentry, i2400m); | ||
344 | result = PTR_ERR(fd); | ||
345 | if (IS_ERR(fd) && result != -ENODEV) { | ||
346 | dev_err(dev, "Can't create debugfs entry " | ||
347 | "netdev_queue_stopped: %d\n", result); | ||
348 | goto error; | ||
349 | } | ||
350 | |||
351 | fd = debugfs_create_file("rx_stats", 0600, dentry, i2400m, | ||
352 | &i2400m_rx_stats_fops); | ||
353 | result = PTR_ERR(fd); | ||
354 | if (IS_ERR(fd) && result != -ENODEV) { | ||
355 | dev_err(dev, "Can't create debugfs entry " | ||
356 | "rx_stats: %d\n", result); | ||
357 | goto error; | ||
358 | } | ||
359 | |||
360 | fd = debugfs_create_file("tx_stats", 0600, dentry, i2400m, | ||
361 | &i2400m_tx_stats_fops); | ||
362 | result = PTR_ERR(fd); | ||
363 | if (IS_ERR(fd) && result != -ENODEV) { | ||
364 | dev_err(dev, "Can't create debugfs entry " | ||
365 | "tx_stats: %d\n", result); | ||
366 | goto error; | ||
367 | } | ||
368 | |||
369 | fd = debugfs_create_i2400m_suspend("suspend", dentry, i2400m); | ||
370 | result = PTR_ERR(fd); | ||
371 | if (IS_ERR(fd) && result != -ENODEV) { | ||
372 | dev_err(dev, "Can't create debugfs entry suspend: %d\n", | ||
373 | result); | ||
374 | goto error; | ||
375 | } | ||
376 | |||
377 | fd = debugfs_create_i2400m_reset("reset", dentry, i2400m); | ||
378 | result = PTR_ERR(fd); | ||
379 | if (IS_ERR(fd) && result != -ENODEV) { | ||
380 | dev_err(dev, "Can't create debugfs entry reset: %d\n", result); | ||
381 | goto error; | ||
382 | } | ||
383 | |||
384 | result = 0; | ||
385 | error: | ||
386 | return result; | ||
387 | } | ||
388 | |||
389 | void i2400m_debugfs_rm(struct i2400m *i2400m) | ||
390 | { | ||
391 | debugfs_remove_recursive(i2400m->debugfs_dentry); | ||
392 | } | ||
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c new file mode 100644 index 000000000000..5f98047e18cf --- /dev/null +++ b/drivers/net/wimax/i2400m/driver.c | |||
@@ -0,0 +1,728 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Generic probe/disconnect, reset and message passing | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com> | ||
7 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License version | ||
11 | * 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301, USA. | ||
22 | * | ||
23 | * | ||
24 | * See i2400m.h for driver documentation. This contains helpers for | ||
25 | * the driver model glue [_setup()/_release()], handling device resets | ||
26 | * [_dev_reset_handle()], and the backends for the WiMAX stack ops | ||
27 | * reset [_op_reset()] and message from user [_op_msg_from_user()]. | ||
28 | * | ||
29 | * ROADMAP: | ||
30 | * | ||
31 | * i2400m_op_msg_from_user() | ||
32 | * i2400m_msg_to_dev() | ||
33 | * wimax_msg_to_user_send() | ||
34 | * | ||
35 | * i2400m_op_reset() | ||
36 | * i240m->bus_reset() | ||
37 | * | ||
38 | * i2400m_dev_reset_handle() | ||
39 | * __i2400m_dev_reset_handle() | ||
40 | * __i2400m_dev_stop() | ||
41 | * __i2400m_dev_start() | ||
42 | * | ||
43 | * i2400m_setup() | ||
44 | * i2400m_bootrom_init() | ||
45 | * register_netdev() | ||
46 | * i2400m_dev_start() | ||
47 | * __i2400m_dev_start() | ||
48 | * i2400m_dev_bootstrap() | ||
49 | * i2400m_tx_setup() | ||
50 | * i2400m->bus_dev_start() | ||
51 | * i2400m_check_mac_addr() | ||
52 | * wimax_dev_add() | ||
53 | * | ||
54 | * i2400m_release() | ||
55 | * wimax_dev_rm() | ||
56 | * i2400m_dev_stop() | ||
57 | * __i2400m_dev_stop() | ||
58 | * i2400m_dev_shutdown() | ||
59 | * i2400m->bus_dev_stop() | ||
60 | * i2400m_tx_release() | ||
61 | * unregister_netdev() | ||
62 | */ | ||
63 | #include "i2400m.h" | ||
64 | #include <linux/wimax/i2400m.h> | ||
65 | #include <linux/module.h> | ||
66 | #include <linux/moduleparam.h> | ||
67 | |||
68 | #define D_SUBMODULE driver | ||
69 | #include "debug-levels.h" | ||
70 | |||
71 | |||
72 | int i2400m_idle_mode_disabled; /* 0 (idle mode enabled) by default */ | ||
73 | module_param_named(idle_mode_disabled, i2400m_idle_mode_disabled, int, 0644); | ||
74 | MODULE_PARM_DESC(idle_mode_disabled, | ||
75 | "If true, the device will not enable idle mode negotiation " | ||
76 | "with the base station (when connected) to save power."); | ||
77 | |||
78 | /** | ||
79 | * i2400m_queue_work - schedule work on a i2400m's queue | ||
80 | * | ||
81 | * @i2400m: device descriptor | ||
82 | * | ||
83 | * @fn: function to run to execute work. It gets passed a 'struct | ||
84 | * work_struct' that is wrapped in a 'struct i2400m_work'. Once | ||
85 | * done, you have to (1) i2400m_put(i2400m_work->i2400m) and then | ||
86 | * (2) kfree(i2400m_work). | ||
87 | * | ||
88 | * @gfp_flags: GFP flags for memory allocation. | ||
89 | * | ||
90 | * @pl: pointer to a payload buffer that you want to pass to the _work | ||
91 | * function. Use this to pack (for example) a struct with extra | ||
92 | * arguments. | ||
93 | * | ||
94 | * @pl_size: size of the payload buffer. | ||
95 | * | ||
96 | * We do this quite often, so this just saves typing; allocate a | ||
97 | * wrapper for a i2400m, get a ref to it, pack arguments and launch | ||
98 | * the work. | ||
99 | * | ||
100 | * A usual workflow is: | ||
101 | * | ||
102 | * struct my_work_args { | ||
103 | * void *something; | ||
104 | * int whatever; | ||
105 | * }; | ||
106 | * ... | ||
107 | * | ||
108 | * struct my_work_args my_args = { | ||
109 | * .something = FOO, | ||
110 | * .whaetever = BLAH | ||
111 | * }; | ||
112 | * i2400m_queue_work(i2400m, 1, my_work_function, GFP_KERNEL, | ||
113 | * &args, sizeof(args)) | ||
114 | * | ||
115 | * And now the work function can unpack the arguments and call the | ||
116 | * real function (or do the job itself): | ||
117 | * | ||
118 | * static | ||
119 | * void my_work_fn((struct work_struct *ws) | ||
120 | * { | ||
121 | * struct i2400m_work *iw = | ||
122 | * container_of(ws, struct i2400m_work, ws); | ||
123 | * struct my_work_args *my_args = (void *) iw->pl; | ||
124 | * | ||
125 | * my_work(iw->i2400m, my_args->something, my_args->whatevert); | ||
126 | * } | ||
127 | */ | ||
128 | int i2400m_queue_work(struct i2400m *i2400m, | ||
129 | void (*fn)(struct work_struct *), gfp_t gfp_flags, | ||
130 | const void *pl, size_t pl_size) | ||
131 | { | ||
132 | int result; | ||
133 | struct i2400m_work *iw; | ||
134 | |||
135 | BUG_ON(i2400m->work_queue == NULL); | ||
136 | result = -ENOMEM; | ||
137 | iw = kzalloc(sizeof(*iw) + pl_size, gfp_flags); | ||
138 | if (iw == NULL) | ||
139 | goto error_kzalloc; | ||
140 | iw->i2400m = i2400m_get(i2400m); | ||
141 | memcpy(iw->pl, pl, pl_size); | ||
142 | INIT_WORK(&iw->ws, fn); | ||
143 | result = queue_work(i2400m->work_queue, &iw->ws); | ||
144 | error_kzalloc: | ||
145 | return result; | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(i2400m_queue_work); | ||
148 | |||
149 | |||
150 | /* | ||
151 | * Schedule i2400m's specific work on the system's queue. | ||
152 | * | ||
153 | * Used for a few cases where we really need it; otherwise, identical | ||
154 | * to i2400m_queue_work(). | ||
155 | * | ||
156 | * Returns < 0 errno code on error, 1 if ok. | ||
157 | * | ||
158 | * If it returns zero, something really bad happened, as it means the | ||
159 | * works struct was already queued, but we have just allocated it, so | ||
160 | * it should not happen. | ||
161 | */ | ||
162 | int i2400m_schedule_work(struct i2400m *i2400m, | ||
163 | void (*fn)(struct work_struct *), gfp_t gfp_flags) | ||
164 | { | ||
165 | int result; | ||
166 | struct i2400m_work *iw; | ||
167 | |||
168 | BUG_ON(i2400m->work_queue == NULL); | ||
169 | result = -ENOMEM; | ||
170 | iw = kzalloc(sizeof(*iw), gfp_flags); | ||
171 | if (iw == NULL) | ||
172 | goto error_kzalloc; | ||
173 | iw->i2400m = i2400m_get(i2400m); | ||
174 | INIT_WORK(&iw->ws, fn); | ||
175 | result = schedule_work(&iw->ws); | ||
176 | if (result == 0) | ||
177 | result = -ENXIO; | ||
178 | error_kzalloc: | ||
179 | return result; | ||
180 | } | ||
181 | |||
182 | |||
183 | /* | ||
184 | * WiMAX stack operation: relay a message from user space | ||
185 | * | ||
186 | * @wimax_dev: device descriptor | ||
187 | * @pipe_name: named pipe the message is for | ||
188 | * @msg_buf: pointer to the message bytes | ||
189 | * @msg_len: length of the buffer | ||
190 | * @genl_info: passed by the generic netlink layer | ||
191 | * | ||
192 | * The WiMAX stack will call this function when a message was received | ||
193 | * from user space. | ||
194 | * | ||
195 | * For the i2400m, this is an L3L4 message, as specified in | ||
196 | * include/linux/wimax/i2400m.h, and thus prefixed with a 'struct | ||
197 | * i2400m_l3l4_hdr'. Driver (and device) expect the messages to be | ||
198 | * coded in Little Endian. | ||
199 | * | ||
200 | * This function just verifies that the header declaration and the | ||
201 | * payload are consistent and then deals with it, either forwarding it | ||
202 | * to the device or procesing it locally. | ||
203 | * | ||
204 | * In the i2400m, messages are basically commands that will carry an | ||
205 | * ack, so we use i2400m_msg_to_dev() and then deliver the ack back to | ||
206 | * user space. The rx.c code might intercept the response and use it | ||
207 | * to update the driver's state, but then it will pass it on so it can | ||
208 | * be relayed back to user space. | ||
209 | * | ||
210 | * Note that asynchronous events from the device are processed and | ||
211 | * sent to user space in rx.c. | ||
212 | */ | ||
213 | static | ||
214 | int i2400m_op_msg_from_user(struct wimax_dev *wimax_dev, | ||
215 | const char *pipe_name, | ||
216 | const void *msg_buf, size_t msg_len, | ||
217 | const struct genl_info *genl_info) | ||
218 | { | ||
219 | int result; | ||
220 | struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev); | ||
221 | struct device *dev = i2400m_dev(i2400m); | ||
222 | struct sk_buff *ack_skb; | ||
223 | |||
224 | d_fnstart(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p " | ||
225 | "msg_len %zu genl_info %p)\n", wimax_dev, i2400m, | ||
226 | msg_buf, msg_len, genl_info); | ||
227 | ack_skb = i2400m_msg_to_dev(i2400m, msg_buf, msg_len); | ||
228 | result = PTR_ERR(ack_skb); | ||
229 | if (IS_ERR(ack_skb)) | ||
230 | goto error_msg_to_dev; | ||
231 | if (unlikely(i2400m->trace_msg_from_user)) | ||
232 | wimax_msg(&i2400m->wimax_dev, "trace", | ||
233 | msg_buf, msg_len, GFP_KERNEL); | ||
234 | result = wimax_msg_send(&i2400m->wimax_dev, ack_skb); | ||
235 | error_msg_to_dev: | ||
236 | d_fnend(4, dev, "(wimax_dev %p [i2400m %p] msg_buf %p msg_len %zu " | ||
237 | "genl_info %p) = %d\n", wimax_dev, i2400m, msg_buf, msg_len, | ||
238 | genl_info, result); | ||
239 | return result; | ||
240 | } | ||
241 | |||
242 | |||
243 | /* | ||
244 | * Context to wait for a reset to finalize | ||
245 | */ | ||
246 | struct i2400m_reset_ctx { | ||
247 | struct completion completion; | ||
248 | int result; | ||
249 | }; | ||
250 | |||
251 | |||
252 | /* | ||
253 | * WiMAX stack operation: reset a device | ||
254 | * | ||
255 | * @wimax_dev: device descriptor | ||
256 | * | ||
257 | * See the documentation for wimax_reset() and wimax_dev->op_reset for | ||
258 | * the requirements of this function. The WiMAX stack guarantees | ||
259 | * serialization on calls to this function. | ||
260 | * | ||
261 | * Do a warm reset on the device; if it fails, resort to a cold reset | ||
262 | * and return -ENODEV. On successful warm reset, we need to block | ||
263 | * until it is complete. | ||
264 | * | ||
265 | * The bus-driver implementation of reset takes care of falling back | ||
266 | * to cold reset if warm fails. | ||
267 | */ | ||
268 | static | ||
269 | int i2400m_op_reset(struct wimax_dev *wimax_dev) | ||
270 | { | ||
271 | int result; | ||
272 | struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev); | ||
273 | struct device *dev = i2400m_dev(i2400m); | ||
274 | struct i2400m_reset_ctx ctx = { | ||
275 | .completion = COMPLETION_INITIALIZER_ONSTACK(ctx.completion), | ||
276 | .result = 0, | ||
277 | }; | ||
278 | |||
279 | d_fnstart(4, dev, "(wimax_dev %p)\n", wimax_dev); | ||
280 | mutex_lock(&i2400m->init_mutex); | ||
281 | i2400m->reset_ctx = &ctx; | ||
282 | mutex_unlock(&i2400m->init_mutex); | ||
283 | result = i2400m->bus_reset(i2400m, I2400M_RT_WARM); | ||
284 | if (result < 0) | ||
285 | goto out; | ||
286 | result = wait_for_completion_timeout(&ctx.completion, 4*HZ); | ||
287 | if (result == 0) | ||
288 | result = -ETIMEDOUT; | ||
289 | else if (result > 0) | ||
290 | result = ctx.result; | ||
291 | /* if result < 0, pass it on */ | ||
292 | mutex_lock(&i2400m->init_mutex); | ||
293 | i2400m->reset_ctx = NULL; | ||
294 | mutex_unlock(&i2400m->init_mutex); | ||
295 | out: | ||
296 | d_fnend(4, dev, "(wimax_dev %p) = %d\n", wimax_dev, result); | ||
297 | return result; | ||
298 | } | ||
299 | |||
300 | |||
301 | /* | ||
302 | * Check the MAC address we got from boot mode is ok | ||
303 | * | ||
304 | * @i2400m: device descriptor | ||
305 | * | ||
306 | * Returns: 0 if ok, < 0 errno code on error. | ||
307 | */ | ||
308 | static | ||
309 | int i2400m_check_mac_addr(struct i2400m *i2400m) | ||
310 | { | ||
311 | int result; | ||
312 | struct device *dev = i2400m_dev(i2400m); | ||
313 | struct sk_buff *skb; | ||
314 | const struct i2400m_tlv_detailed_device_info *ddi; | ||
315 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; | ||
316 | const unsigned char zeromac[ETH_ALEN] = { 0 }; | ||
317 | |||
318 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
319 | skb = i2400m_get_device_info(i2400m); | ||
320 | if (IS_ERR(skb)) { | ||
321 | result = PTR_ERR(skb); | ||
322 | dev_err(dev, "Cannot verify MAC address, error reading: %d\n", | ||
323 | result); | ||
324 | goto error; | ||
325 | } | ||
326 | /* Extract MAC addresss */ | ||
327 | ddi = (void *) skb->data; | ||
328 | BUILD_BUG_ON(ETH_ALEN != sizeof(ddi->mac_address)); | ||
329 | d_printf(2, dev, "GET DEVICE INFO: mac addr " | ||
330 | "%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
331 | ddi->mac_address[0], ddi->mac_address[1], | ||
332 | ddi->mac_address[2], ddi->mac_address[3], | ||
333 | ddi->mac_address[4], ddi->mac_address[5]); | ||
334 | if (!memcmp(net_dev->perm_addr, ddi->mac_address, | ||
335 | sizeof(ddi->mac_address))) | ||
336 | goto ok; | ||
337 | dev_warn(dev, "warning: device reports a different MAC address " | ||
338 | "to that of boot mode's\n"); | ||
339 | dev_warn(dev, "device reports %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
340 | ddi->mac_address[0], ddi->mac_address[1], | ||
341 | ddi->mac_address[2], ddi->mac_address[3], | ||
342 | ddi->mac_address[4], ddi->mac_address[5]); | ||
343 | dev_warn(dev, "boot mode reported %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
344 | net_dev->perm_addr[0], net_dev->perm_addr[1], | ||
345 | net_dev->perm_addr[2], net_dev->perm_addr[3], | ||
346 | net_dev->perm_addr[4], net_dev->perm_addr[5]); | ||
347 | if (!memcmp(zeromac, ddi->mac_address, sizeof(zeromac))) | ||
348 | dev_err(dev, "device reports an invalid MAC address, " | ||
349 | "not updating\n"); | ||
350 | else { | ||
351 | dev_warn(dev, "updating MAC address\n"); | ||
352 | net_dev->addr_len = ETH_ALEN; | ||
353 | memcpy(net_dev->perm_addr, ddi->mac_address, ETH_ALEN); | ||
354 | memcpy(net_dev->dev_addr, ddi->mac_address, ETH_ALEN); | ||
355 | } | ||
356 | ok: | ||
357 | result = 0; | ||
358 | kfree_skb(skb); | ||
359 | error: | ||
360 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); | ||
361 | return result; | ||
362 | } | ||
363 | |||
364 | |||
365 | /** | ||
366 | * __i2400m_dev_start - Bring up driver communication with the device | ||
367 | * | ||
368 | * @i2400m: device descriptor | ||
369 | * @flags: boot mode flags | ||
370 | * | ||
371 | * Returns: 0 if ok, < 0 errno code on error. | ||
372 | * | ||
373 | * Uploads firmware and brings up all the resources needed to be able | ||
374 | * to communicate with the device. | ||
375 | * | ||
376 | * TX needs to be setup before the bus-specific code (otherwise on | ||
377 | * shutdown, the bus-tx code could try to access it). | ||
378 | */ | ||
379 | static | ||
380 | int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags) | ||
381 | { | ||
382 | int result; | ||
383 | struct wimax_dev *wimax_dev = &i2400m->wimax_dev; | ||
384 | struct net_device *net_dev = wimax_dev->net_dev; | ||
385 | struct device *dev = i2400m_dev(i2400m); | ||
386 | int times = 3; | ||
387 | |||
388 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
389 | retry: | ||
390 | result = i2400m_dev_bootstrap(i2400m, flags); | ||
391 | if (result < 0) { | ||
392 | dev_err(dev, "cannot bootstrap device: %d\n", result); | ||
393 | goto error_bootstrap; | ||
394 | } | ||
395 | result = i2400m_tx_setup(i2400m); | ||
396 | if (result < 0) | ||
397 | goto error_tx_setup; | ||
398 | result = i2400m->bus_dev_start(i2400m); | ||
399 | if (result < 0) | ||
400 | goto error_bus_dev_start; | ||
401 | i2400m->work_queue = create_singlethread_workqueue(wimax_dev->name); | ||
402 | if (i2400m->work_queue == NULL) { | ||
403 | result = -ENOMEM; | ||
404 | dev_err(dev, "cannot create workqueue\n"); | ||
405 | goto error_create_workqueue; | ||
406 | } | ||
407 | /* At this point is ok to send commands to the device */ | ||
408 | result = i2400m_check_mac_addr(i2400m); | ||
409 | if (result < 0) | ||
410 | goto error_check_mac_addr; | ||
411 | i2400m->ready = 1; | ||
412 | wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED); | ||
413 | result = i2400m_dev_initialize(i2400m); | ||
414 | if (result < 0) | ||
415 | goto error_dev_initialize; | ||
416 | /* At this point, reports will come for the device and set it | ||
417 | * to the right state if it is different than UNINITIALIZED */ | ||
418 | d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n", | ||
419 | net_dev, i2400m, result); | ||
420 | return result; | ||
421 | |||
422 | error_dev_initialize: | ||
423 | error_check_mac_addr: | ||
424 | destroy_workqueue(i2400m->work_queue); | ||
425 | error_create_workqueue: | ||
426 | i2400m->bus_dev_stop(i2400m); | ||
427 | error_bus_dev_start: | ||
428 | i2400m_tx_release(i2400m); | ||
429 | error_tx_setup: | ||
430 | error_bootstrap: | ||
431 | if (result == -ERESTARTSYS && times-- > 0) { | ||
432 | flags = I2400M_BRI_SOFT; | ||
433 | goto retry; | ||
434 | } | ||
435 | d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n", | ||
436 | net_dev, i2400m, result); | ||
437 | return result; | ||
438 | } | ||
439 | |||
440 | |||
441 | static | ||
442 | int i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri bm_flags) | ||
443 | { | ||
444 | int result; | ||
445 | mutex_lock(&i2400m->init_mutex); /* Well, start the device */ | ||
446 | result = __i2400m_dev_start(i2400m, bm_flags); | ||
447 | if (result >= 0) | ||
448 | i2400m->updown = 1; | ||
449 | mutex_unlock(&i2400m->init_mutex); | ||
450 | return result; | ||
451 | } | ||
452 | |||
453 | |||
454 | /** | ||
455 | * i2400m_dev_stop - Tear down driver communication with the device | ||
456 | * | ||
457 | * @i2400m: device descriptor | ||
458 | * | ||
459 | * Returns: 0 if ok, < 0 errno code on error. | ||
460 | * | ||
461 | * Releases all the resources allocated to communicate with the device. | ||
462 | */ | ||
463 | static | ||
464 | void __i2400m_dev_stop(struct i2400m *i2400m) | ||
465 | { | ||
466 | struct wimax_dev *wimax_dev = &i2400m->wimax_dev; | ||
467 | struct device *dev = i2400m_dev(i2400m); | ||
468 | |||
469 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
470 | wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING); | ||
471 | i2400m_dev_shutdown(i2400m); | ||
472 | i2400m->ready = 0; | ||
473 | destroy_workqueue(i2400m->work_queue); | ||
474 | i2400m->bus_dev_stop(i2400m); | ||
475 | i2400m_tx_release(i2400m); | ||
476 | wimax_state_change(wimax_dev, WIMAX_ST_DOWN); | ||
477 | d_fnend(3, dev, "(i2400m %p) = 0\n", i2400m); | ||
478 | } | ||
479 | |||
480 | |||
481 | /* | ||
482 | * Watch out -- we only need to stop if there is a need for it. The | ||
483 | * device could have reset itself and failed to come up again (see | ||
484 | * _i2400m_dev_reset_handle()). | ||
485 | */ | ||
486 | static | ||
487 | void i2400m_dev_stop(struct i2400m *i2400m) | ||
488 | { | ||
489 | mutex_lock(&i2400m->init_mutex); | ||
490 | if (i2400m->updown) { | ||
491 | __i2400m_dev_stop(i2400m); | ||
492 | i2400m->updown = 0; | ||
493 | } | ||
494 | mutex_unlock(&i2400m->init_mutex); | ||
495 | } | ||
496 | |||
497 | |||
498 | /* | ||
499 | * The device has rebooted; fix up the device and the driver | ||
500 | * | ||
501 | * Tear down the driver communication with the device, reload the | ||
502 | * firmware and reinitialize the communication with the device. | ||
503 | * | ||
504 | * If someone calls a reset when the device's firmware is down, in | ||
505 | * theory we won't see it because we are not listening. However, just | ||
506 | * in case, leave the code to handle it. | ||
507 | * | ||
508 | * If there is a reset context, use it; this means someone is waiting | ||
509 | * for us to tell him when the reset operation is complete and the | ||
510 | * device is ready to rock again. | ||
511 | * | ||
512 | * NOTE: if we are in the process of bringing up or down the | ||
513 | * communication with the device [running i2400m_dev_start() or | ||
514 | * _stop()], don't do anything, let it fail and handle it. | ||
515 | * | ||
516 | * This function is ran always in a thread context | ||
517 | */ | ||
518 | static | ||
519 | void __i2400m_dev_reset_handle(struct work_struct *ws) | ||
520 | { | ||
521 | int result; | ||
522 | struct i2400m_work *iw = container_of(ws, struct i2400m_work, ws); | ||
523 | struct i2400m *i2400m = iw->i2400m; | ||
524 | struct device *dev = i2400m_dev(i2400m); | ||
525 | enum wimax_st wimax_state; | ||
526 | struct i2400m_reset_ctx *ctx = i2400m->reset_ctx; | ||
527 | |||
528 | d_fnstart(3, dev, "(ws %p i2400m %p)\n", ws, i2400m); | ||
529 | result = 0; | ||
530 | if (mutex_trylock(&i2400m->init_mutex) == 0) { | ||
531 | /* We are still in i2400m_dev_start() [let it fail] or | ||
532 | * i2400m_dev_stop() [we are shutting down anyway, so | ||
533 | * ignore it] or we are resetting somewhere else. */ | ||
534 | dev_err(dev, "device rebooted\n"); | ||
535 | i2400m_msg_to_dev_cancel_wait(i2400m, -ERESTARTSYS); | ||
536 | complete(&i2400m->msg_completion); | ||
537 | goto out; | ||
538 | } | ||
539 | wimax_state = wimax_state_get(&i2400m->wimax_dev); | ||
540 | if (wimax_state < WIMAX_ST_UNINITIALIZED) { | ||
541 | dev_info(dev, "device rebooted: it is down, ignoring\n"); | ||
542 | goto out_unlock; /* ifconfig up/down wasn't called */ | ||
543 | } | ||
544 | dev_err(dev, "device rebooted: reinitializing driver\n"); | ||
545 | __i2400m_dev_stop(i2400m); | ||
546 | i2400m->updown = 0; | ||
547 | result = __i2400m_dev_start(i2400m, | ||
548 | I2400M_BRI_SOFT | I2400M_BRI_MAC_REINIT); | ||
549 | if (result < 0) { | ||
550 | dev_err(dev, "device reboot: cannot start the device: %d\n", | ||
551 | result); | ||
552 | result = i2400m->bus_reset(i2400m, I2400M_RT_BUS); | ||
553 | if (result >= 0) | ||
554 | result = -ENODEV; | ||
555 | } else | ||
556 | i2400m->updown = 1; | ||
557 | out_unlock: | ||
558 | if (i2400m->reset_ctx) { | ||
559 | ctx->result = result; | ||
560 | complete(&ctx->completion); | ||
561 | } | ||
562 | mutex_unlock(&i2400m->init_mutex); | ||
563 | out: | ||
564 | i2400m_put(i2400m); | ||
565 | kfree(iw); | ||
566 | d_fnend(3, dev, "(ws %p i2400m %p) = void\n", ws, i2400m); | ||
567 | return; | ||
568 | } | ||
569 | |||
570 | |||
571 | /** | ||
572 | * i2400m_dev_reset_handle - Handle a device's reset in a thread context | ||
573 | * | ||
574 | * Schedule a device reset handling out on a thread context, so it | ||
575 | * is safe to call from atomic context. We can't use the i2400m's | ||
576 | * queue as we are going to destroy it and reinitialize it as part of | ||
577 | * the driver bringup/bringup process. | ||
578 | * | ||
579 | * See __i2400m_dev_reset_handle() for details; that takes care of | ||
580 | * reinitializing the driver to handle the reset, calling into the | ||
581 | * bus-specific functions ops as needed. | ||
582 | */ | ||
583 | int i2400m_dev_reset_handle(struct i2400m *i2400m) | ||
584 | { | ||
585 | return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle, | ||
586 | GFP_ATOMIC); | ||
587 | } | ||
588 | EXPORT_SYMBOL_GPL(i2400m_dev_reset_handle); | ||
589 | |||
590 | |||
591 | /** | ||
592 | * i2400m_setup - bus-generic setup function for the i2400m device | ||
593 | * | ||
594 | * @i2400m: device descriptor (bus-specific parts have been initialized) | ||
595 | * | ||
596 | * Returns: 0 if ok, < 0 errno code on error. | ||
597 | * | ||
598 | * Initializes the bus-generic parts of the i2400m driver; the | ||
599 | * bus-specific parts have been initialized, function pointers filled | ||
600 | * out by the bus-specific probe function. | ||
601 | * | ||
602 | * As well, this registers the WiMAX and net device nodes. Once this | ||
603 | * function returns, the device is operative and has to be ready to | ||
604 | * receive and send network traffic and WiMAX control operations. | ||
605 | */ | ||
606 | int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) | ||
607 | { | ||
608 | int result = -ENODEV; | ||
609 | struct device *dev = i2400m_dev(i2400m); | ||
610 | struct wimax_dev *wimax_dev = &i2400m->wimax_dev; | ||
611 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; | ||
612 | |||
613 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
614 | |||
615 | snprintf(wimax_dev->name, sizeof(wimax_dev->name), | ||
616 | "i2400m-%s:%s", dev->bus->name, dev->bus_id); | ||
617 | |||
618 | i2400m->bm_cmd_buf = kzalloc(I2400M_BM_CMD_BUF_SIZE, GFP_KERNEL); | ||
619 | if (i2400m->bm_cmd_buf == NULL) { | ||
620 | dev_err(dev, "cannot allocate USB command buffer\n"); | ||
621 | goto error_bm_cmd_kzalloc; | ||
622 | } | ||
623 | i2400m->bm_ack_buf = kzalloc(I2400M_BM_ACK_BUF_SIZE, GFP_KERNEL); | ||
624 | if (i2400m->bm_ack_buf == NULL) { | ||
625 | dev_err(dev, "cannot allocate USB ack buffer\n"); | ||
626 | goto error_bm_ack_buf_kzalloc; | ||
627 | } | ||
628 | result = i2400m_bootrom_init(i2400m, bm_flags); | ||
629 | if (result < 0) { | ||
630 | dev_err(dev, "read mac addr: bootrom init " | ||
631 | "failed: %d\n", result); | ||
632 | goto error_bootrom_init; | ||
633 | } | ||
634 | result = i2400m_read_mac_addr(i2400m); | ||
635 | if (result < 0) | ||
636 | goto error_read_mac_addr; | ||
637 | |||
638 | result = register_netdev(net_dev); /* Okey dokey, bring it up */ | ||
639 | if (result < 0) { | ||
640 | dev_err(dev, "cannot register i2400m network device: %d\n", | ||
641 | result); | ||
642 | goto error_register_netdev; | ||
643 | } | ||
644 | netif_carrier_off(net_dev); | ||
645 | |||
646 | result = i2400m_dev_start(i2400m, bm_flags); | ||
647 | if (result < 0) | ||
648 | goto error_dev_start; | ||
649 | |||
650 | i2400m->wimax_dev.op_msg_from_user = i2400m_op_msg_from_user; | ||
651 | i2400m->wimax_dev.op_rfkill_sw_toggle = i2400m_op_rfkill_sw_toggle; | ||
652 | i2400m->wimax_dev.op_reset = i2400m_op_reset; | ||
653 | result = wimax_dev_add(&i2400m->wimax_dev, net_dev); | ||
654 | if (result < 0) | ||
655 | goto error_wimax_dev_add; | ||
656 | /* User space needs to do some init stuff */ | ||
657 | wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED); | ||
658 | |||
659 | /* Now setup all that requires a registered net and wimax device. */ | ||
660 | result = i2400m_debugfs_add(i2400m); | ||
661 | if (result < 0) { | ||
662 | dev_err(dev, "cannot setup i2400m's debugfs: %d\n", result); | ||
663 | goto error_debugfs_setup; | ||
664 | } | ||
665 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); | ||
666 | return result; | ||
667 | |||
668 | error_debugfs_setup: | ||
669 | wimax_dev_rm(&i2400m->wimax_dev); | ||
670 | error_wimax_dev_add: | ||
671 | i2400m_dev_stop(i2400m); | ||
672 | error_dev_start: | ||
673 | unregister_netdev(net_dev); | ||
674 | error_register_netdev: | ||
675 | error_read_mac_addr: | ||
676 | error_bootrom_init: | ||
677 | kfree(i2400m->bm_ack_buf); | ||
678 | error_bm_ack_buf_kzalloc: | ||
679 | kfree(i2400m->bm_cmd_buf); | ||
680 | error_bm_cmd_kzalloc: | ||
681 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); | ||
682 | return result; | ||
683 | } | ||
684 | EXPORT_SYMBOL_GPL(i2400m_setup); | ||
685 | |||
686 | |||
687 | /** | ||
688 | * i2400m_release - release the bus-generic driver resources | ||
689 | * | ||
690 | * Sends a disconnect message and undoes any setup done by i2400m_setup() | ||
691 | */ | ||
692 | void i2400m_release(struct i2400m *i2400m) | ||
693 | { | ||
694 | struct device *dev = i2400m_dev(i2400m); | ||
695 | |||
696 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
697 | netif_stop_queue(i2400m->wimax_dev.net_dev); | ||
698 | |||
699 | i2400m_debugfs_rm(i2400m); | ||
700 | wimax_dev_rm(&i2400m->wimax_dev); | ||
701 | i2400m_dev_stop(i2400m); | ||
702 | unregister_netdev(i2400m->wimax_dev.net_dev); | ||
703 | kfree(i2400m->bm_ack_buf); | ||
704 | kfree(i2400m->bm_cmd_buf); | ||
705 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | ||
706 | } | ||
707 | EXPORT_SYMBOL_GPL(i2400m_release); | ||
708 | |||
709 | |||
710 | static | ||
711 | int __init i2400m_driver_init(void) | ||
712 | { | ||
713 | return 0; | ||
714 | } | ||
715 | module_init(i2400m_driver_init); | ||
716 | |||
717 | static | ||
718 | void __exit i2400m_driver_exit(void) | ||
719 | { | ||
720 | /* for scheds i2400m_dev_reset_handle() */ | ||
721 | flush_scheduled_work(); | ||
722 | return; | ||
723 | } | ||
724 | module_exit(i2400m_driver_exit); | ||
725 | |||
726 | MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>"); | ||
727 | MODULE_DESCRIPTION("Intel 2400M WiMAX networking bus-generic driver"); | ||
728 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c new file mode 100644 index 000000000000..1d8271f34c38 --- /dev/null +++ b/drivers/net/wimax/i2400m/fw.c | |||
@@ -0,0 +1,1095 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Firmware uploader | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
37 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
38 | * - Initial implementation | ||
39 | * | ||
40 | * | ||
41 | * THE PROCEDURE | ||
42 | * | ||
43 | * (this is decribed for USB, but for SDIO is similar) | ||
44 | * | ||
45 | * The 2400m works in two modes: boot-mode or normal mode. In boot | ||
46 | * mode we can execute only a handful of commands targeted at | ||
47 | * uploading the firmware and launching it. | ||
48 | * | ||
49 | * The 2400m enters boot mode when it is first connected to the | ||
50 | * system, when it crashes and when you ask it to reboot. There are | ||
51 | * two submodes of the boot mode: signed and non-signed. Signed takes | ||
52 | * firmwares signed with a certain private key, non-signed takes any | ||
53 | * firmware. Normal hardware takes only signed firmware. | ||
54 | * | ||
55 | * Upon entrance to boot mode, the device sends a few zero length | ||
56 | * packets (ZLPs) on the notification endpoint, then a reboot barker | ||
57 | * (4 le32 words with value I2400M_{S,N}BOOT_BARKER). We ack it by | ||
58 | * sending the same barker on the bulk out endpoint. The device acks | ||
59 | * with a reboot ack barker (4 le32 words with value 0xfeedbabe) and | ||
60 | * then the device is fully rebooted. At this point we can upload the | ||
61 | * firmware. | ||
62 | * | ||
63 | * This process is accomplished by the i2400m_bootrom_init() | ||
64 | * function. All the device interaction happens through the | ||
65 | * i2400m_bm_cmd() [boot mode command]. Special return values will | ||
66 | * indicate if the device resets. | ||
67 | * | ||
68 | * After this, we read the MAC address and then (if needed) | ||
69 | * reinitialize the device. We need to read it ahead of time because | ||
70 | * in the future, we might not upload the firmware until userspace | ||
71 | * 'ifconfig up's the device. | ||
72 | * | ||
73 | * We can then upload the firmware file. The file is composed of a BCF | ||
74 | * header (basic data, keys and signatures) and a list of write | ||
75 | * commands and payloads. We first upload the header | ||
76 | * [i2400m_dnload_init()] and then pass the commands and payloads | ||
77 | * verbatim to the i2400m_bm_cmd() function | ||
78 | * [i2400m_dnload_bcf()]. Then we tell the device to jump to the new | ||
79 | * firmware [i2400m_dnload_finalize()]. | ||
80 | * | ||
81 | * Once firmware is uploaded, we are good to go :) | ||
82 | * | ||
83 | * When we don't know in which mode we are, we first try by sending a | ||
84 | * warm reset request that will take us to boot-mode. If we time out | ||
85 | * waiting for a reboot barker, that means maybe we are already in | ||
86 | * boot mode, so we send a reboot barker. | ||
87 | * | ||
88 | * COMMAND EXECUTION | ||
89 | * | ||
90 | * This code (and process) is single threaded; for executing commands, | ||
91 | * we post a URB to the notification endpoint, post the command, wait | ||
92 | * for data on the notification buffer. We don't need to worry about | ||
93 | * others as we know we are the only ones in there. | ||
94 | * | ||
95 | * BACKEND IMPLEMENTATION | ||
96 | * | ||
97 | * This code is bus-generic; the bus-specific driver provides back end | ||
98 | * implementations to send a boot mode command to the device and to | ||
99 | * read an acknolwedgement from it (or an asynchronous notification) | ||
100 | * from it. | ||
101 | * | ||
102 | * ROADMAP | ||
103 | * | ||
104 | * i2400m_dev_bootstrap Called by __i2400m_dev_start() | ||
105 | * request_firmware | ||
106 | * i2400m_fw_check | ||
107 | * i2400m_fw_dnload | ||
108 | * release_firmware | ||
109 | * | ||
110 | * i2400m_fw_dnload | ||
111 | * i2400m_bootrom_init | ||
112 | * i2400m_bm_cmd | ||
113 | * i2400m->bus_reset | ||
114 | * i2400m_dnload_init | ||
115 | * i2400m_dnload_init_signed | ||
116 | * i2400m_dnload_init_nonsigned | ||
117 | * i2400m_download_chunk | ||
118 | * i2400m_bm_cmd | ||
119 | * i2400m_dnload_bcf | ||
120 | * i2400m_bm_cmd | ||
121 | * i2400m_dnload_finalize | ||
122 | * i2400m_bm_cmd | ||
123 | * | ||
124 | * i2400m_bm_cmd | ||
125 | * i2400m->bus_bm_cmd_send() | ||
126 | * i2400m->bus_bm_wait_for_ack | ||
127 | * __i2400m_bm_ack_verify | ||
128 | * | ||
129 | * i2400m_bm_cmd_prepare Used by bus-drivers to prep | ||
130 | * commands before sending | ||
131 | */ | ||
132 | #include <linux/firmware.h> | ||
133 | #include <linux/sched.h> | ||
134 | #include <linux/usb.h> | ||
135 | #include "i2400m.h" | ||
136 | |||
137 | |||
138 | #define D_SUBMODULE fw | ||
139 | #include "debug-levels.h" | ||
140 | |||
141 | |||
142 | static const __le32 i2400m_ACK_BARKER[4] = { | ||
143 | __constant_cpu_to_le32(I2400M_ACK_BARKER), | ||
144 | __constant_cpu_to_le32(I2400M_ACK_BARKER), | ||
145 | __constant_cpu_to_le32(I2400M_ACK_BARKER), | ||
146 | __constant_cpu_to_le32(I2400M_ACK_BARKER) | ||
147 | }; | ||
148 | |||
149 | |||
150 | /** | ||
151 | * Prepare a boot-mode command for delivery | ||
152 | * | ||
153 | * @cmd: pointer to bootrom header to prepare | ||
154 | * | ||
155 | * Computes checksum if so needed. After calling this function, DO NOT | ||
156 | * modify the command or header as the checksum won't work anymore. | ||
157 | * | ||
158 | * We do it from here because some times we cannot do it in the | ||
159 | * original context the command was sent (it is a const), so when we | ||
160 | * copy it to our staging buffer, we add the checksum there. | ||
161 | */ | ||
162 | void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *cmd) | ||
163 | { | ||
164 | if (i2400m_brh_get_use_checksum(cmd)) { | ||
165 | int i; | ||
166 | u32 checksum = 0; | ||
167 | const u32 *checksum_ptr = (void *) cmd->payload; | ||
168 | for (i = 0; i < cmd->data_size / 4; i++) | ||
169 | checksum += cpu_to_le32(*checksum_ptr++); | ||
170 | checksum += cmd->command + cmd->target_addr + cmd->data_size; | ||
171 | cmd->block_checksum = cpu_to_le32(checksum); | ||
172 | } | ||
173 | } | ||
174 | EXPORT_SYMBOL_GPL(i2400m_bm_cmd_prepare); | ||
175 | |||
176 | |||
177 | /* | ||
178 | * Verify the ack data received | ||
179 | * | ||
180 | * Given a reply to a boot mode command, chew it and verify everything | ||
181 | * is ok. | ||
182 | * | ||
183 | * @opcode: opcode which generated this ack. For error messages. | ||
184 | * @ack: pointer to ack data we received | ||
185 | * @ack_size: size of that data buffer | ||
186 | * @flags: I2400M_BM_CMD_* flags we called the command with. | ||
187 | * | ||
188 | * Way too long function -- maybe it should be further split | ||
189 | */ | ||
190 | static | ||
191 | ssize_t __i2400m_bm_ack_verify(struct i2400m *i2400m, int opcode, | ||
192 | struct i2400m_bootrom_header *ack, | ||
193 | size_t ack_size, int flags) | ||
194 | { | ||
195 | ssize_t result = -ENOMEM; | ||
196 | struct device *dev = i2400m_dev(i2400m); | ||
197 | |||
198 | d_fnstart(8, dev, "(i2400m %p opcode %d ack %p size %zu)\n", | ||
199 | i2400m, opcode, ack, ack_size); | ||
200 | if (ack_size < sizeof(*ack)) { | ||
201 | result = -EIO; | ||
202 | dev_err(dev, "boot-mode cmd %d: HW BUG? notification didn't " | ||
203 | "return enough data (%zu bytes vs %zu expected)\n", | ||
204 | opcode, ack_size, sizeof(*ack)); | ||
205 | goto error_ack_short; | ||
206 | } | ||
207 | if (ack_size == sizeof(i2400m_NBOOT_BARKER) | ||
208 | && memcmp(ack, i2400m_NBOOT_BARKER, sizeof(*ack)) == 0) { | ||
209 | result = -ERESTARTSYS; | ||
210 | i2400m->sboot = 0; | ||
211 | d_printf(6, dev, "boot-mode cmd %d: " | ||
212 | "HW non-signed boot barker\n", opcode); | ||
213 | goto error_reboot; | ||
214 | } | ||
215 | if (ack_size == sizeof(i2400m_SBOOT_BARKER) | ||
216 | && memcmp(ack, i2400m_SBOOT_BARKER, sizeof(*ack)) == 0) { | ||
217 | result = -ERESTARTSYS; | ||
218 | i2400m->sboot = 1; | ||
219 | d_printf(6, dev, "boot-mode cmd %d: HW signed reboot barker\n", | ||
220 | opcode); | ||
221 | goto error_reboot; | ||
222 | } | ||
223 | if (ack_size == sizeof(i2400m_ACK_BARKER) | ||
224 | && memcmp(ack, i2400m_ACK_BARKER, sizeof(*ack)) == 0) { | ||
225 | result = -EISCONN; | ||
226 | d_printf(3, dev, "boot-mode cmd %d: HW reboot ack barker\n", | ||
227 | opcode); | ||
228 | goto error_reboot_ack; | ||
229 | } | ||
230 | result = 0; | ||
231 | if (flags & I2400M_BM_CMD_RAW) | ||
232 | goto out_raw; | ||
233 | ack->data_size = le32_to_cpu(ack->data_size); | ||
234 | ack->target_addr = le32_to_cpu(ack->target_addr); | ||
235 | ack->block_checksum = le32_to_cpu(ack->block_checksum); | ||
236 | d_printf(5, dev, "boot-mode cmd %d: notification for opcode %u " | ||
237 | "response %u csum %u rr %u da %u\n", | ||
238 | opcode, i2400m_brh_get_opcode(ack), | ||
239 | i2400m_brh_get_response(ack), | ||
240 | i2400m_brh_get_use_checksum(ack), | ||
241 | i2400m_brh_get_response_required(ack), | ||
242 | i2400m_brh_get_direct_access(ack)); | ||
243 | result = -EIO; | ||
244 | if (i2400m_brh_get_signature(ack) != 0xcbbc) { | ||
245 | dev_err(dev, "boot-mode cmd %d: HW BUG? wrong signature " | ||
246 | "0x%04x\n", opcode, i2400m_brh_get_signature(ack)); | ||
247 | goto error_ack_signature; | ||
248 | } | ||
249 | if (opcode != -1 && opcode != i2400m_brh_get_opcode(ack)) { | ||
250 | dev_err(dev, "boot-mode cmd %d: HW BUG? " | ||
251 | "received response for opcode %u, expected %u\n", | ||
252 | opcode, i2400m_brh_get_opcode(ack), opcode); | ||
253 | goto error_ack_opcode; | ||
254 | } | ||
255 | if (i2400m_brh_get_response(ack) != 0) { /* failed? */ | ||
256 | dev_err(dev, "boot-mode cmd %d: error; hw response %u\n", | ||
257 | opcode, i2400m_brh_get_response(ack)); | ||
258 | goto error_ack_failed; | ||
259 | } | ||
260 | if (ack_size < ack->data_size + sizeof(*ack)) { | ||
261 | dev_err(dev, "boot-mode cmd %d: SW BUG " | ||
262 | "driver provided only %zu bytes for %zu bytes " | ||
263 | "of data\n", opcode, ack_size, | ||
264 | (size_t) le32_to_cpu(ack->data_size) + sizeof(*ack)); | ||
265 | goto error_ack_short_buffer; | ||
266 | } | ||
267 | result = ack_size; | ||
268 | /* Don't you love this stack of empty targets? Well, I don't | ||
269 | * either, but it helps track exactly who comes in here and | ||
270 | * why :) */ | ||
271 | error_ack_short_buffer: | ||
272 | error_ack_failed: | ||
273 | error_ack_opcode: | ||
274 | error_ack_signature: | ||
275 | out_raw: | ||
276 | error_reboot_ack: | ||
277 | error_reboot: | ||
278 | error_ack_short: | ||
279 | d_fnend(8, dev, "(i2400m %p opcode %d ack %p size %zu) = %d\n", | ||
280 | i2400m, opcode, ack, ack_size, (int) result); | ||
281 | return result; | ||
282 | } | ||
283 | |||
284 | |||
285 | /** | ||
286 | * i2400m_bm_cmd - Execute a boot mode command | ||
287 | * | ||
288 | * @cmd: buffer containing the command data (pointing at the header). | ||
289 | * This data can be ANYWHERE (for USB, we will copy it to an | ||
290 | * specific buffer). Make sure everything is in proper little | ||
291 | * endian. | ||
292 | * | ||
293 | * A raw buffer can be also sent, just cast it and set flags to | ||
294 | * I2400M_BM_CMD_RAW. | ||
295 | * | ||
296 | * This function will generate a checksum for you if the | ||
297 | * checksum bit in the command is set (unless I2400M_BM_CMD_RAW | ||
298 | * is set). | ||
299 | * | ||
300 | * You can use the i2400m->bm_cmd_buf to stage your commands and | ||
301 | * send them. | ||
302 | * | ||
303 | * If NULL, no command is sent (we just wait for an ack). | ||
304 | * | ||
305 | * @cmd_size: size of the command. Will be auto padded to the | ||
306 | * bus-specific drivers padding requirements. | ||
307 | * | ||
308 | * @ack: buffer where to place the acknowledgement. If it is a regular | ||
309 | * command response, all fields will be returned with the right, | ||
310 | * native endianess. | ||
311 | * | ||
312 | * You *cannot* use i2400m->bm_ack_buf for this buffer. | ||
313 | * | ||
314 | * @ack_size: size of @ack, 16 aligned; you need to provide at least | ||
315 | * sizeof(*ack) bytes and then enough to contain the return data | ||
316 | * from the command | ||
317 | * | ||
318 | * @flags: see I2400M_BM_CMD_* above. | ||
319 | * | ||
320 | * @returns: bytes received by the notification; if < 0, an errno code | ||
321 | * denoting an error or: | ||
322 | * | ||
323 | * -ERESTARTSYS The device has rebooted | ||
324 | * | ||
325 | * Executes a boot-mode command and waits for a response, doing basic | ||
326 | * validation on it; if a zero length response is received, it retries | ||
327 | * waiting for a response until a non-zero one is received (timing out | ||
328 | * after %I2400M_BOOT_RETRIES retries). | ||
329 | */ | ||
330 | static | ||
331 | ssize_t i2400m_bm_cmd(struct i2400m *i2400m, | ||
332 | const struct i2400m_bootrom_header *cmd, size_t cmd_size, | ||
333 | struct i2400m_bootrom_header *ack, size_t ack_size, | ||
334 | int flags) | ||
335 | { | ||
336 | ssize_t result = -ENOMEM, rx_bytes; | ||
337 | struct device *dev = i2400m_dev(i2400m); | ||
338 | int opcode = cmd == NULL ? -1 : i2400m_brh_get_opcode(cmd); | ||
339 | |||
340 | d_fnstart(6, dev, "(i2400m %p cmd %p size %zu ack %p size %zu)\n", | ||
341 | i2400m, cmd, cmd_size, ack, ack_size); | ||
342 | BUG_ON(ack_size < sizeof(*ack)); | ||
343 | BUG_ON(i2400m->boot_mode == 0); | ||
344 | |||
345 | if (cmd != NULL) { /* send the command */ | ||
346 | memcpy(i2400m->bm_cmd_buf, cmd, cmd_size); | ||
347 | result = i2400m->bus_bm_cmd_send(i2400m, cmd, cmd_size, flags); | ||
348 | if (result < 0) | ||
349 | goto error_cmd_send; | ||
350 | if ((flags & I2400M_BM_CMD_RAW) == 0) | ||
351 | d_printf(5, dev, | ||
352 | "boot-mode cmd %d csum %u rr %u da %u: " | ||
353 | "addr 0x%04x size %u block csum 0x%04x\n", | ||
354 | opcode, i2400m_brh_get_use_checksum(cmd), | ||
355 | i2400m_brh_get_response_required(cmd), | ||
356 | i2400m_brh_get_direct_access(cmd), | ||
357 | cmd->target_addr, cmd->data_size, | ||
358 | cmd->block_checksum); | ||
359 | } | ||
360 | result = i2400m->bus_bm_wait_for_ack(i2400m, ack, ack_size); | ||
361 | if (result < 0) { | ||
362 | dev_err(dev, "boot-mode cmd %d: error waiting for an ack: %d\n", | ||
363 | opcode, (int) result); /* bah, %zd doesn't work */ | ||
364 | goto error_wait_for_ack; | ||
365 | } | ||
366 | rx_bytes = result; | ||
367 | /* verify the ack and read more if neccessary [result is the | ||
368 | * final amount of bytes we get in the ack] */ | ||
369 | result = __i2400m_bm_ack_verify(i2400m, opcode, ack, ack_size, flags); | ||
370 | if (result < 0) | ||
371 | goto error_bad_ack; | ||
372 | /* Don't you love this stack of empty targets? Well, I don't | ||
373 | * either, but it helps track exactly who comes in here and | ||
374 | * why :) */ | ||
375 | result = rx_bytes; | ||
376 | error_bad_ack: | ||
377 | error_wait_for_ack: | ||
378 | error_cmd_send: | ||
379 | d_fnend(6, dev, "(i2400m %p cmd %p size %zu ack %p size %zu) = %d\n", | ||
380 | i2400m, cmd, cmd_size, ack, ack_size, (int) result); | ||
381 | return result; | ||
382 | } | ||
383 | |||
384 | |||
385 | /** | ||
386 | * i2400m_download_chunk - write a single chunk of data to the device's memory | ||
387 | * | ||
388 | * @i2400m: device descriptor | ||
389 | * @buf: the buffer to write | ||
390 | * @buf_len: length of the buffer to write | ||
391 | * @addr: address in the device memory space | ||
392 | * @direct: bootrom write mode | ||
393 | * @do_csum: should a checksum validation be performed | ||
394 | */ | ||
395 | static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk, | ||
396 | size_t __chunk_len, unsigned long addr, | ||
397 | unsigned int direct, unsigned int do_csum) | ||
398 | { | ||
399 | int ret; | ||
400 | size_t chunk_len = ALIGN(__chunk_len, I2400M_PL_PAD); | ||
401 | struct device *dev = i2400m_dev(i2400m); | ||
402 | struct { | ||
403 | struct i2400m_bootrom_header cmd; | ||
404 | u8 cmd_payload[chunk_len]; | ||
405 | } __attribute__((packed)) *buf; | ||
406 | struct i2400m_bootrom_header ack; | ||
407 | |||
408 | d_fnstart(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx " | ||
409 | "direct %u do_csum %u)\n", i2400m, chunk, __chunk_len, | ||
410 | addr, direct, do_csum); | ||
411 | buf = i2400m->bm_cmd_buf; | ||
412 | memcpy(buf->cmd_payload, chunk, __chunk_len); | ||
413 | memset(buf->cmd_payload + __chunk_len, 0xad, chunk_len - __chunk_len); | ||
414 | |||
415 | buf->cmd.command = i2400m_brh_command(I2400M_BRH_WRITE, | ||
416 | __chunk_len & 0x3 ? 0 : do_csum, | ||
417 | __chunk_len & 0xf ? 0 : direct); | ||
418 | buf->cmd.target_addr = cpu_to_le32(addr); | ||
419 | buf->cmd.data_size = cpu_to_le32(__chunk_len); | ||
420 | ret = i2400m_bm_cmd(i2400m, &buf->cmd, sizeof(buf->cmd) + chunk_len, | ||
421 | &ack, sizeof(ack), 0); | ||
422 | if (ret >= 0) | ||
423 | ret = 0; | ||
424 | d_fnend(5, dev, "(i2400m %p chunk %p __chunk_len %zu addr 0x%08lx " | ||
425 | "direct %u do_csum %u) = %d\n", i2400m, chunk, __chunk_len, | ||
426 | addr, direct, do_csum, ret); | ||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | |||
431 | /* | ||
432 | * Download a BCF file's sections to the device | ||
433 | * | ||
434 | * @i2400m: device descriptor | ||
435 | * @bcf: pointer to firmware data (followed by the payloads). Assumed | ||
436 | * verified and consistent. | ||
437 | * @bcf_len: length (in bytes) of the @bcf buffer. | ||
438 | * | ||
439 | * Returns: < 0 errno code on error or the offset to the jump instruction. | ||
440 | * | ||
441 | * Given a BCF file, downloads each section (a command and a payload) | ||
442 | * to the device's address space. Actually, it just executes each | ||
443 | * command i the BCF file. | ||
444 | * | ||
445 | * The section size has to be aligned to 4 bytes AND the padding has | ||
446 | * to be taken from the firmware file, as the signature takes it into | ||
447 | * account. | ||
448 | */ | ||
449 | static | ||
450 | ssize_t i2400m_dnload_bcf(struct i2400m *i2400m, | ||
451 | const struct i2400m_bcf_hdr *bcf, size_t bcf_len) | ||
452 | { | ||
453 | ssize_t ret; | ||
454 | struct device *dev = i2400m_dev(i2400m); | ||
455 | size_t offset, /* iterator offset */ | ||
456 | data_size, /* Size of the data payload */ | ||
457 | section_size, /* Size of the whole section (cmd + payload) */ | ||
458 | section = 1; | ||
459 | const struct i2400m_bootrom_header *bh; | ||
460 | struct i2400m_bootrom_header ack; | ||
461 | |||
462 | d_fnstart(3, dev, "(i2400m %p bcf %p bcf_len %zu)\n", | ||
463 | i2400m, bcf, bcf_len); | ||
464 | /* Iterate over the command blocks in the BCF file that start | ||
465 | * after the header */ | ||
466 | offset = le32_to_cpu(bcf->header_len) * sizeof(u32); | ||
467 | while (1) { /* start sending the file */ | ||
468 | bh = (void *) bcf + offset; | ||
469 | data_size = le32_to_cpu(bh->data_size); | ||
470 | section_size = ALIGN(sizeof(*bh) + data_size, 4); | ||
471 | d_printf(7, dev, | ||
472 | "downloading section #%zu (@%zu %zu B) to 0x%08x\n", | ||
473 | section, offset, sizeof(*bh) + data_size, | ||
474 | le32_to_cpu(bh->target_addr)); | ||
475 | if (i2400m_brh_get_opcode(bh) == I2400M_BRH_SIGNED_JUMP) { | ||
476 | /* Secure boot needs to stop here */ | ||
477 | d_printf(5, dev, "signed jump found @%zu\n", offset); | ||
478 | break; | ||
479 | } | ||
480 | if (offset + section_size == bcf_len) | ||
481 | /* Non-secure boot stops here */ | ||
482 | break; | ||
483 | if (offset + section_size > bcf_len) { | ||
484 | dev_err(dev, "fw %s: bad section #%zu, " | ||
485 | "end (@%zu) beyond EOF (@%zu)\n", | ||
486 | i2400m->bus_fw_name, section, | ||
487 | offset + section_size, bcf_len); | ||
488 | ret = -EINVAL; | ||
489 | goto error_section_beyond_eof; | ||
490 | } | ||
491 | __i2400m_msleep(20); | ||
492 | ret = i2400m_bm_cmd(i2400m, bh, section_size, | ||
493 | &ack, sizeof(ack), I2400M_BM_CMD_RAW); | ||
494 | if (ret < 0) { | ||
495 | dev_err(dev, "fw %s: section #%zu (@%zu %zu B) " | ||
496 | "failed %d\n", i2400m->bus_fw_name, section, | ||
497 | offset, sizeof(*bh) + data_size, (int) ret); | ||
498 | goto error_send; | ||
499 | } | ||
500 | offset += section_size; | ||
501 | section++; | ||
502 | } | ||
503 | ret = offset; | ||
504 | error_section_beyond_eof: | ||
505 | error_send: | ||
506 | d_fnend(3, dev, "(i2400m %p bcf %p bcf_len %zu) = %d\n", | ||
507 | i2400m, bcf, bcf_len, (int) ret); | ||
508 | return ret; | ||
509 | } | ||
510 | |||
511 | |||
512 | /* | ||
513 | * Do the final steps of uploading firmware | ||
514 | * | ||
515 | * Depending on the boot mode (signed vs non-signed), different | ||
516 | * actions need to be taken. | ||
517 | */ | ||
518 | static | ||
519 | int i2400m_dnload_finalize(struct i2400m *i2400m, | ||
520 | const struct i2400m_bcf_hdr *bcf, size_t offset) | ||
521 | { | ||
522 | int ret = 0; | ||
523 | struct device *dev = i2400m_dev(i2400m); | ||
524 | struct i2400m_bootrom_header *cmd, ack; | ||
525 | struct { | ||
526 | struct i2400m_bootrom_header cmd; | ||
527 | u8 cmd_pl[0]; | ||
528 | } __attribute__((packed)) *cmd_buf; | ||
529 | size_t signature_block_offset, signature_block_size; | ||
530 | |||
531 | d_fnstart(3, dev, "offset %zu\n", offset); | ||
532 | cmd = (void *) bcf + offset; | ||
533 | if (i2400m->sboot == 0) { | ||
534 | struct i2400m_bootrom_header jump_ack; | ||
535 | d_printf(3, dev, "unsecure boot, jumping to 0x%08x\n", | ||
536 | le32_to_cpu(cmd->target_addr)); | ||
537 | i2400m_brh_set_opcode(cmd, I2400M_BRH_JUMP); | ||
538 | cmd->data_size = 0; | ||
539 | ret = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd), | ||
540 | &jump_ack, sizeof(jump_ack), 0); | ||
541 | } else { | ||
542 | d_printf(3, dev, "secure boot, jumping to 0x%08x\n", | ||
543 | le32_to_cpu(cmd->target_addr)); | ||
544 | cmd_buf = i2400m->bm_cmd_buf; | ||
545 | memcpy(&cmd_buf->cmd, cmd, sizeof(*cmd)); | ||
546 | signature_block_offset = | ||
547 | sizeof(*bcf) | ||
548 | + le32_to_cpu(bcf->key_size) * sizeof(u32) | ||
549 | + le32_to_cpu(bcf->exponent_size) * sizeof(u32); | ||
550 | signature_block_size = | ||
551 | le32_to_cpu(bcf->modulus_size) * sizeof(u32); | ||
552 | memcpy(cmd_buf->cmd_pl, (void *) bcf + signature_block_offset, | ||
553 | signature_block_size); | ||
554 | ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd, | ||
555 | sizeof(cmd_buf->cmd) + signature_block_size, | ||
556 | &ack, sizeof(ack), I2400M_BM_CMD_RAW); | ||
557 | } | ||
558 | d_fnend(3, dev, "returning %d\n", ret); | ||
559 | return ret; | ||
560 | } | ||
561 | |||
562 | |||
563 | /** | ||
564 | * i2400m_bootrom_init - Reboots a powered device into boot mode | ||
565 | * | ||
566 | * @i2400m: device descriptor | ||
567 | * @flags: | ||
568 | * I2400M_BRI_SOFT: a reboot notification has been seen | ||
569 | * already, so don't wait for it. | ||
570 | * | ||
571 | * I2400M_BRI_NO_REBOOT: Don't send a reboot command, but wait | ||
572 | * for a reboot barker notification. This is a one shot; if | ||
573 | * the state machine needs to send a reboot command it will. | ||
574 | * | ||
575 | * Returns: | ||
576 | * | ||
577 | * < 0 errno code on error, 0 if ok. | ||
578 | * | ||
579 | * i2400m->sboot set to 0 for unsecure boot process, 1 for secure | ||
580 | * boot process. | ||
581 | * | ||
582 | * Description: | ||
583 | * | ||
584 | * Tries hard enough to put the device in boot-mode. There are two | ||
585 | * main phases to this: | ||
586 | * | ||
587 | * a. (1) send a reboot command and (2) get a reboot barker | ||
588 | * b. (1) ack the reboot sending a reboot barker and (2) getting an | ||
589 | * ack barker in return | ||
590 | * | ||
591 | * We want to skip (a) in some cases [soft]. The state machine is | ||
592 | * horrible, but it is basically: on each phase, send what has to be | ||
593 | * sent (if any), wait for the answer and act on the answer. We might | ||
594 | * have to backtrack and retry, so we keep a max tries counter for | ||
595 | * that. | ||
596 | * | ||
597 | * If we get a timeout after sending a warm reset, we do it again. | ||
598 | */ | ||
599 | int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags) | ||
600 | { | ||
601 | int result; | ||
602 | struct device *dev = i2400m_dev(i2400m); | ||
603 | struct i2400m_bootrom_header *cmd; | ||
604 | struct i2400m_bootrom_header ack; | ||
605 | int count = I2400M_BOOT_RETRIES; | ||
606 | int ack_timeout_cnt = 1; | ||
607 | |||
608 | BUILD_BUG_ON(sizeof(*cmd) != sizeof(i2400m_NBOOT_BARKER)); | ||
609 | BUILD_BUG_ON(sizeof(ack) != sizeof(i2400m_ACK_BARKER)); | ||
610 | |||
611 | d_fnstart(4, dev, "(i2400m %p flags 0x%08x)\n", i2400m, flags); | ||
612 | result = -ENOMEM; | ||
613 | cmd = i2400m->bm_cmd_buf; | ||
614 | if (flags & I2400M_BRI_SOFT) | ||
615 | goto do_reboot_ack; | ||
616 | do_reboot: | ||
617 | if (--count < 0) | ||
618 | goto error_timeout; | ||
619 | d_printf(4, dev, "device reboot: reboot command [%d # left]\n", | ||
620 | count); | ||
621 | if ((flags & I2400M_BRI_NO_REBOOT) == 0) | ||
622 | i2400m->bus_reset(i2400m, I2400M_RT_WARM); | ||
623 | result = i2400m_bm_cmd(i2400m, NULL, 0, &ack, sizeof(ack), | ||
624 | I2400M_BM_CMD_RAW); | ||
625 | flags &= ~I2400M_BRI_NO_REBOOT; | ||
626 | switch (result) { | ||
627 | case -ERESTARTSYS: | ||
628 | d_printf(4, dev, "device reboot: got reboot barker\n"); | ||
629 | break; | ||
630 | case -EISCONN: /* we don't know how it got here...but we follow it */ | ||
631 | d_printf(4, dev, "device reboot: got ack barker - whatever\n"); | ||
632 | goto do_reboot; | ||
633 | case -ETIMEDOUT: /* device has timed out, we might be in boot | ||
634 | * mode already and expecting an ack, let's try | ||
635 | * that */ | ||
636 | dev_info(dev, "warm reset timed out, trying an ack\n"); | ||
637 | goto do_reboot_ack; | ||
638 | case -EPROTO: | ||
639 | case -ESHUTDOWN: /* dev is gone */ | ||
640 | case -EINTR: /* user cancelled */ | ||
641 | goto error_dev_gone; | ||
642 | default: | ||
643 | dev_err(dev, "device reboot: error %d while waiting " | ||
644 | "for reboot barker - rebooting\n", result); | ||
645 | goto do_reboot; | ||
646 | } | ||
647 | /* At this point we ack back with 4 REBOOT barkers and expect | ||
648 | * 4 ACK barkers. This is ugly, as we send a raw command -- | ||
649 | * hence the cast. _bm_cmd() will catch the reboot ack | ||
650 | * notification and report it as -EISCONN. */ | ||
651 | do_reboot_ack: | ||
652 | d_printf(4, dev, "device reboot ack: sending ack [%d # left]\n", count); | ||
653 | if (i2400m->sboot == 0) | ||
654 | memcpy(cmd, i2400m_NBOOT_BARKER, | ||
655 | sizeof(i2400m_NBOOT_BARKER)); | ||
656 | else | ||
657 | memcpy(cmd, i2400m_SBOOT_BARKER, | ||
658 | sizeof(i2400m_SBOOT_BARKER)); | ||
659 | result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd), | ||
660 | &ack, sizeof(ack), I2400M_BM_CMD_RAW); | ||
661 | switch (result) { | ||
662 | case -ERESTARTSYS: | ||
663 | d_printf(4, dev, "reboot ack: got reboot barker - retrying\n"); | ||
664 | if (--count < 0) | ||
665 | goto error_timeout; | ||
666 | goto do_reboot_ack; | ||
667 | case -EISCONN: | ||
668 | d_printf(4, dev, "reboot ack: got ack barker - good\n"); | ||
669 | break; | ||
670 | case -ETIMEDOUT: /* no response, maybe it is the other type? */ | ||
671 | if (ack_timeout_cnt-- >= 0) { | ||
672 | d_printf(4, dev, "reboot ack timedout: " | ||
673 | "trying the other type?\n"); | ||
674 | i2400m->sboot = !i2400m->sboot; | ||
675 | goto do_reboot_ack; | ||
676 | } else { | ||
677 | dev_err(dev, "reboot ack timedout too long: " | ||
678 | "trying reboot\n"); | ||
679 | goto do_reboot; | ||
680 | } | ||
681 | break; | ||
682 | case -EPROTO: | ||
683 | case -ESHUTDOWN: /* dev is gone */ | ||
684 | goto error_dev_gone; | ||
685 | default: | ||
686 | dev_err(dev, "device reboot ack: error %d while waiting for " | ||
687 | "reboot ack barker - rebooting\n", result); | ||
688 | goto do_reboot; | ||
689 | } | ||
690 | d_printf(2, dev, "device reboot ack: got ack barker - boot done\n"); | ||
691 | result = 0; | ||
692 | exit_timeout: | ||
693 | error_dev_gone: | ||
694 | d_fnend(4, dev, "(i2400m %p flags 0x%08x) = %d\n", | ||
695 | i2400m, flags, result); | ||
696 | return result; | ||
697 | |||
698 | error_timeout: | ||
699 | dev_err(dev, "Timed out waiting for reboot ack, resetting\n"); | ||
700 | i2400m->bus_reset(i2400m, I2400M_RT_BUS); | ||
701 | result = -ETIMEDOUT; | ||
702 | goto exit_timeout; | ||
703 | } | ||
704 | |||
705 | |||
706 | /* | ||
707 | * Read the MAC addr | ||
708 | * | ||
709 | * The position this function reads is fixed in device memory and | ||
710 | * always available, even without firmware. | ||
711 | * | ||
712 | * Note we specify we want to read only six bytes, but provide space | ||
713 | * for 16, as we always get it rounded up. | ||
714 | */ | ||
715 | int i2400m_read_mac_addr(struct i2400m *i2400m) | ||
716 | { | ||
717 | int result; | ||
718 | struct device *dev = i2400m_dev(i2400m); | ||
719 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; | ||
720 | struct i2400m_bootrom_header *cmd; | ||
721 | struct { | ||
722 | struct i2400m_bootrom_header ack; | ||
723 | u8 ack_pl[16]; | ||
724 | } __attribute__((packed)) ack_buf; | ||
725 | |||
726 | d_fnstart(5, dev, "(i2400m %p)\n", i2400m); | ||
727 | cmd = i2400m->bm_cmd_buf; | ||
728 | cmd->command = i2400m_brh_command(I2400M_BRH_READ, 0, 1); | ||
729 | cmd->target_addr = cpu_to_le32(0x00203fe8); | ||
730 | cmd->data_size = cpu_to_le32(6); | ||
731 | result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd), | ||
732 | &ack_buf.ack, sizeof(ack_buf), 0); | ||
733 | if (result < 0) { | ||
734 | dev_err(dev, "BM: read mac addr failed: %d\n", result); | ||
735 | goto error_read_mac; | ||
736 | } | ||
737 | d_printf(2, dev, | ||
738 | "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
739 | ack_buf.ack_pl[0], ack_buf.ack_pl[1], | ||
740 | ack_buf.ack_pl[2], ack_buf.ack_pl[3], | ||
741 | ack_buf.ack_pl[4], ack_buf.ack_pl[5]); | ||
742 | if (i2400m->bus_bm_mac_addr_impaired == 1) { | ||
743 | ack_buf.ack_pl[0] = 0x00; | ||
744 | ack_buf.ack_pl[1] = 0x16; | ||
745 | ack_buf.ack_pl[2] = 0xd3; | ||
746 | get_random_bytes(&ack_buf.ack_pl[3], 3); | ||
747 | dev_err(dev, "BM is MAC addr impaired, faking MAC addr to " | ||
748 | "mac addr is %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
749 | ack_buf.ack_pl[0], ack_buf.ack_pl[1], | ||
750 | ack_buf.ack_pl[2], ack_buf.ack_pl[3], | ||
751 | ack_buf.ack_pl[4], ack_buf.ack_pl[5]); | ||
752 | result = 0; | ||
753 | } | ||
754 | net_dev->addr_len = ETH_ALEN; | ||
755 | memcpy(net_dev->perm_addr, ack_buf.ack_pl, ETH_ALEN); | ||
756 | memcpy(net_dev->dev_addr, ack_buf.ack_pl, ETH_ALEN); | ||
757 | error_read_mac: | ||
758 | d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, result); | ||
759 | return result; | ||
760 | } | ||
761 | |||
762 | |||
763 | /* | ||
764 | * Initialize a non signed boot | ||
765 | * | ||
766 | * This implies sending some magic values to the device's memory. Note | ||
767 | * we convert the values to little endian in the same array | ||
768 | * declaration. | ||
769 | */ | ||
770 | static | ||
771 | int i2400m_dnload_init_nonsigned(struct i2400m *i2400m) | ||
772 | { | ||
773 | #define POKE(a, d) { \ | ||
774 | .address = __constant_cpu_to_le32(a), \ | ||
775 | .data = __constant_cpu_to_le32(d) \ | ||
776 | } | ||
777 | static const struct { | ||
778 | __le32 address; | ||
779 | __le32 data; | ||
780 | } i2400m_pokes[] = { | ||
781 | POKE(0x081A58, 0xA7810230), | ||
782 | POKE(0x080040, 0x00000000), | ||
783 | POKE(0x080048, 0x00000082), | ||
784 | POKE(0x08004C, 0x0000081F), | ||
785 | POKE(0x080054, 0x00000085), | ||
786 | POKE(0x080058, 0x00000180), | ||
787 | POKE(0x08005C, 0x00000018), | ||
788 | POKE(0x080060, 0x00000010), | ||
789 | POKE(0x080574, 0x00000001), | ||
790 | POKE(0x080550, 0x00000005), | ||
791 | POKE(0xAE0000, 0x00000000), | ||
792 | }; | ||
793 | #undef POKE | ||
794 | unsigned i; | ||
795 | int ret; | ||
796 | struct device *dev = i2400m_dev(i2400m); | ||
797 | |||
798 | dev_warn(dev, "WARNING!!! non-signed boot UNTESTED PATH!\n"); | ||
799 | |||
800 | d_fnstart(5, dev, "(i2400m %p)\n", i2400m); | ||
801 | for (i = 0; i < ARRAY_SIZE(i2400m_pokes); i++) { | ||
802 | ret = i2400m_download_chunk(i2400m, &i2400m_pokes[i].data, | ||
803 | sizeof(i2400m_pokes[i].data), | ||
804 | i2400m_pokes[i].address, 1, 1); | ||
805 | if (ret < 0) | ||
806 | break; | ||
807 | } | ||
808 | d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret); | ||
809 | return ret; | ||
810 | } | ||
811 | |||
812 | |||
813 | /* | ||
814 | * Initialize the signed boot process | ||
815 | * | ||
816 | * @i2400m: device descriptor | ||
817 | * | ||
818 | * @bcf_hdr: pointer to the firmware header; assumes it is fully in | ||
819 | * memory (it has gone through basic validation). | ||
820 | * | ||
821 | * Returns: 0 if ok, < 0 errno code on error, -ERESTARTSYS if the hw | ||
822 | * rebooted. | ||
823 | * | ||
824 | * This writes the firmware BCF header to the device using the | ||
825 | * HASH_PAYLOAD_ONLY command. | ||
826 | */ | ||
827 | static | ||
828 | int i2400m_dnload_init_signed(struct i2400m *i2400m, | ||
829 | const struct i2400m_bcf_hdr *bcf_hdr) | ||
830 | { | ||
831 | int ret; | ||
832 | struct device *dev = i2400m_dev(i2400m); | ||
833 | struct { | ||
834 | struct i2400m_bootrom_header cmd; | ||
835 | struct i2400m_bcf_hdr cmd_pl; | ||
836 | } __attribute__((packed)) *cmd_buf; | ||
837 | struct i2400m_bootrom_header ack; | ||
838 | |||
839 | d_fnstart(5, dev, "(i2400m %p bcf_hdr %p)\n", i2400m, bcf_hdr); | ||
840 | cmd_buf = i2400m->bm_cmd_buf; | ||
841 | cmd_buf->cmd.command = | ||
842 | i2400m_brh_command(I2400M_BRH_HASH_PAYLOAD_ONLY, 0, 0); | ||
843 | cmd_buf->cmd.target_addr = 0; | ||
844 | cmd_buf->cmd.data_size = cpu_to_le32(sizeof(cmd_buf->cmd_pl)); | ||
845 | memcpy(&cmd_buf->cmd_pl, bcf_hdr, sizeof(*bcf_hdr)); | ||
846 | ret = i2400m_bm_cmd(i2400m, &cmd_buf->cmd, sizeof(*cmd_buf), | ||
847 | &ack, sizeof(ack), 0); | ||
848 | if (ret >= 0) | ||
849 | ret = 0; | ||
850 | d_fnend(5, dev, "(i2400m %p bcf_hdr %p) = %d\n", i2400m, bcf_hdr, ret); | ||
851 | return ret; | ||
852 | } | ||
853 | |||
854 | |||
855 | /* | ||
856 | * Initialize the firmware download at the device size | ||
857 | * | ||
858 | * Multiplex to the one that matters based on the device's mode | ||
859 | * (signed or non-signed). | ||
860 | */ | ||
861 | static | ||
862 | int i2400m_dnload_init(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf) | ||
863 | { | ||
864 | int result; | ||
865 | struct device *dev = i2400m_dev(i2400m); | ||
866 | u32 module_id = le32_to_cpu(bcf->module_id); | ||
867 | |||
868 | if (i2400m->sboot == 0 | ||
869 | && (module_id & I2400M_BCF_MOD_ID_POKES) == 0) { | ||
870 | /* non-signed boot process without pokes */ | ||
871 | result = i2400m_dnload_init_nonsigned(i2400m); | ||
872 | if (result == -ERESTARTSYS) | ||
873 | return result; | ||
874 | if (result < 0) | ||
875 | dev_err(dev, "fw %s: non-signed download " | ||
876 | "initialization failed: %d\n", | ||
877 | i2400m->bus_fw_name, result); | ||
878 | } else if (i2400m->sboot == 0 | ||
879 | && (module_id & I2400M_BCF_MOD_ID_POKES)) { | ||
880 | /* non-signed boot process with pokes, nothing to do */ | ||
881 | result = 0; | ||
882 | } else { /* signed boot process */ | ||
883 | result = i2400m_dnload_init_signed(i2400m, bcf); | ||
884 | if (result == -ERESTARTSYS) | ||
885 | return result; | ||
886 | if (result < 0) | ||
887 | dev_err(dev, "fw %s: signed boot download " | ||
888 | "initialization failed: %d\n", | ||
889 | i2400m->bus_fw_name, result); | ||
890 | } | ||
891 | return result; | ||
892 | } | ||
893 | |||
894 | |||
895 | /* | ||
896 | * Run quick consistency tests on the firmware file | ||
897 | * | ||
898 | * Check for the firmware being made for the i2400m device, | ||
899 | * etc...These checks are mostly informative, as the device will make | ||
900 | * them too; but the driver's response is more informative on what | ||
901 | * went wrong. | ||
902 | */ | ||
903 | static | ||
904 | int i2400m_fw_check(struct i2400m *i2400m, | ||
905 | const struct i2400m_bcf_hdr *bcf, | ||
906 | size_t bcf_size) | ||
907 | { | ||
908 | int result; | ||
909 | struct device *dev = i2400m_dev(i2400m); | ||
910 | unsigned module_type, header_len, major_version, minor_version, | ||
911 | module_id, module_vendor, date, size; | ||
912 | |||
913 | /* Check hard errors */ | ||
914 | result = -EINVAL; | ||
915 | if (bcf_size < sizeof(*bcf)) { /* big enough header? */ | ||
916 | dev_err(dev, "firmware %s too short: " | ||
917 | "%zu B vs %zu (at least) expected\n", | ||
918 | i2400m->bus_fw_name, bcf_size, sizeof(*bcf)); | ||
919 | goto error; | ||
920 | } | ||
921 | |||
922 | module_type = bcf->module_type; | ||
923 | header_len = sizeof(u32) * le32_to_cpu(bcf->header_len); | ||
924 | major_version = le32_to_cpu(bcf->header_version) & 0xffff0000 >> 16; | ||
925 | minor_version = le32_to_cpu(bcf->header_version) & 0x0000ffff; | ||
926 | module_id = le32_to_cpu(bcf->module_id); | ||
927 | module_vendor = le32_to_cpu(bcf->module_vendor); | ||
928 | date = le32_to_cpu(bcf->date); | ||
929 | size = sizeof(u32) * le32_to_cpu(bcf->size); | ||
930 | |||
931 | if (bcf_size != size) { /* annoyingly paranoid */ | ||
932 | dev_err(dev, "firmware %s: bad size, got " | ||
933 | "%zu B vs %u expected\n", | ||
934 | i2400m->bus_fw_name, bcf_size, size); | ||
935 | goto error; | ||
936 | } | ||
937 | |||
938 | d_printf(2, dev, "type 0x%x id 0x%x vendor 0x%x; header v%u.%u (%zu B) " | ||
939 | "date %08x (%zu B)\n", | ||
940 | module_type, module_id, module_vendor, | ||
941 | major_version, minor_version, (size_t) header_len, | ||
942 | date, (size_t) size); | ||
943 | |||
944 | if (module_type != 6) { /* built for the right hardware? */ | ||
945 | dev_err(dev, "bad fw %s: unexpected module type 0x%x; " | ||
946 | "aborting\n", i2400m->bus_fw_name, module_type); | ||
947 | goto error; | ||
948 | } | ||
949 | |||
950 | /* Check soft-er errors */ | ||
951 | result = 0; | ||
952 | if (module_vendor != 0x8086) | ||
953 | dev_err(dev, "bad fw %s? unexpected vendor 0x%04x\n", | ||
954 | i2400m->bus_fw_name, module_vendor); | ||
955 | if (date < 0x20080300) | ||
956 | dev_err(dev, "bad fw %s? build date too old %08x\n", | ||
957 | i2400m->bus_fw_name, date); | ||
958 | error: | ||
959 | return result; | ||
960 | } | ||
961 | |||
962 | |||
963 | /* | ||
964 | * Download the firmware to the device | ||
965 | * | ||
966 | * @i2400m: device descriptor | ||
967 | * @bcf: pointer to loaded (and minimally verified for consistency) | ||
968 | * firmware | ||
969 | * @bcf_size: size of the @bcf buffer (header plus payloads) | ||
970 | * | ||
971 | * The process for doing this is described in this file's header. | ||
972 | * | ||
973 | * Note we only reinitialize boot-mode if the flags say so. Some hw | ||
974 | * iterations need it, some don't. In any case, if we loop, we always | ||
975 | * need to reinitialize the boot room, hence the flags modification. | ||
976 | */ | ||
977 | static | ||
978 | int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf, | ||
979 | size_t bcf_size, enum i2400m_bri flags) | ||
980 | { | ||
981 | int ret = 0; | ||
982 | struct device *dev = i2400m_dev(i2400m); | ||
983 | int count = I2400M_BOOT_RETRIES; | ||
984 | |||
985 | d_fnstart(5, dev, "(i2400m %p bcf %p size %zu)\n", | ||
986 | i2400m, bcf, bcf_size); | ||
987 | i2400m->boot_mode = 1; | ||
988 | hw_reboot: | ||
989 | if (count-- == 0) { | ||
990 | ret = -ERESTARTSYS; | ||
991 | dev_err(dev, "device rebooted too many times, aborting\n"); | ||
992 | goto error_too_many_reboots; | ||
993 | } | ||
994 | if (flags & I2400M_BRI_MAC_REINIT) { | ||
995 | ret = i2400m_bootrom_init(i2400m, flags); | ||
996 | if (ret < 0) { | ||
997 | dev_err(dev, "bootrom init failed: %d\n", ret); | ||
998 | goto error_bootrom_init; | ||
999 | } | ||
1000 | } | ||
1001 | flags |= I2400M_BRI_MAC_REINIT; | ||
1002 | |||
1003 | /* | ||
1004 | * Initialize the download, push the bytes to the device and | ||
1005 | * then jump to the new firmware. Note @ret is passed with the | ||
1006 | * offset of the jump instruction to _dnload_finalize() | ||
1007 | */ | ||
1008 | ret = i2400m_dnload_init(i2400m, bcf); /* Init device's dnload */ | ||
1009 | if (ret == -ERESTARTSYS) | ||
1010 | goto error_dev_rebooted; | ||
1011 | if (ret < 0) | ||
1012 | goto error_dnload_init; | ||
1013 | |||
1014 | ret = i2400m_dnload_bcf(i2400m, bcf, bcf_size); | ||
1015 | if (ret == -ERESTARTSYS) | ||
1016 | goto error_dev_rebooted; | ||
1017 | if (ret < 0) { | ||
1018 | dev_err(dev, "fw %s: download failed: %d\n", | ||
1019 | i2400m->bus_fw_name, ret); | ||
1020 | goto error_dnload_bcf; | ||
1021 | } | ||
1022 | |||
1023 | ret = i2400m_dnload_finalize(i2400m, bcf, ret); | ||
1024 | if (ret == -ERESTARTSYS) | ||
1025 | goto error_dev_rebooted; | ||
1026 | if (ret < 0) { | ||
1027 | dev_err(dev, "fw %s: " | ||
1028 | "download finalization failed: %d\n", | ||
1029 | i2400m->bus_fw_name, ret); | ||
1030 | goto error_dnload_finalize; | ||
1031 | } | ||
1032 | |||
1033 | d_printf(2, dev, "fw %s successfully uploaded\n", | ||
1034 | i2400m->bus_fw_name); | ||
1035 | i2400m->boot_mode = 0; | ||
1036 | error_dnload_finalize: | ||
1037 | error_dnload_bcf: | ||
1038 | error_dnload_init: | ||
1039 | error_bootrom_init: | ||
1040 | error_too_many_reboots: | ||
1041 | d_fnend(5, dev, "(i2400m %p bcf %p size %zu) = %d\n", | ||
1042 | i2400m, bcf, bcf_size, ret); | ||
1043 | return ret; | ||
1044 | |||
1045 | error_dev_rebooted: | ||
1046 | dev_err(dev, "device rebooted, %d tries left\n", count); | ||
1047 | /* we got the notification already, no need to wait for it again */ | ||
1048 | flags |= I2400M_BRI_SOFT; | ||
1049 | goto hw_reboot; | ||
1050 | } | ||
1051 | |||
1052 | |||
1053 | /** | ||
1054 | * i2400m_dev_bootstrap - Bring the device to a known state and upload firmware | ||
1055 | * | ||
1056 | * @i2400m: device descriptor | ||
1057 | * | ||
1058 | * Returns: >= 0 if ok, < 0 errno code on error. | ||
1059 | * | ||
1060 | * This sets up the firmware upload environment, loads the firmware | ||
1061 | * file from disk, verifies and then calls the firmware upload process | ||
1062 | * per se. | ||
1063 | * | ||
1064 | * Can be called either from probe, or after a warm reset. Can not be | ||
1065 | * called from within an interrupt. All the flow in this code is | ||
1066 | * single-threade; all I/Os are synchronous. | ||
1067 | */ | ||
1068 | int i2400m_dev_bootstrap(struct i2400m *i2400m, enum i2400m_bri flags) | ||
1069 | { | ||
1070 | int ret = 0; | ||
1071 | struct device *dev = i2400m_dev(i2400m); | ||
1072 | const struct firmware *fw; | ||
1073 | const struct i2400m_bcf_hdr *bcf; /* Firmware data */ | ||
1074 | |||
1075 | d_fnstart(5, dev, "(i2400m %p)\n", i2400m); | ||
1076 | /* Load firmware files to memory. */ | ||
1077 | ret = request_firmware(&fw, i2400m->bus_fw_name, dev); | ||
1078 | if (ret) { | ||
1079 | dev_err(dev, "fw %s: request failed: %d\n", | ||
1080 | i2400m->bus_fw_name, ret); | ||
1081 | goto error_fw_req; | ||
1082 | } | ||
1083 | bcf = (void *) fw->data; | ||
1084 | |||
1085 | ret = i2400m_fw_check(i2400m, bcf, fw->size); | ||
1086 | if (ret < 0) | ||
1087 | goto error_fw_bad; | ||
1088 | ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags); | ||
1089 | error_fw_bad: | ||
1090 | release_firmware(fw); | ||
1091 | error_fw_req: | ||
1092 | d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret); | ||
1093 | return ret; | ||
1094 | } | ||
1095 | EXPORT_SYMBOL_GPL(i2400m_dev_bootstrap); | ||
diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h new file mode 100644 index 000000000000..08c2fb739234 --- /dev/null +++ b/drivers/net/wimax/i2400m/i2400m-sdio.h | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * SDIO-specific i2400m driver definitions | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Brian Bian <brian.bian@intel.com> | ||
37 | * Dirk Brandewie <dirk.j.brandewie@intel.com> | ||
38 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
39 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
40 | * - Initial implementation | ||
41 | * | ||
42 | * | ||
43 | * This driver implements the bus-specific part of the i2400m for | ||
44 | * SDIO. Check i2400m.h for a generic driver description. | ||
45 | * | ||
46 | * ARCHITECTURE | ||
47 | * | ||
48 | * This driver sits under the bus-generic i2400m driver, providing the | ||
49 | * connection to the device. | ||
50 | * | ||
51 | * When probed, all the function pointers are setup and then the | ||
52 | * bus-generic code called. The generic driver will then use the | ||
53 | * provided pointers for uploading firmware (i2400ms_bus_bm*() in | ||
54 | * sdio-fw.c) and then setting up the device (i2400ms_dev_*() in | ||
55 | * sdio.c). | ||
56 | * | ||
57 | * Once firmware is uploaded, TX functions (sdio-tx.c) are called when | ||
58 | * data is ready for transmission in the TX fifo; then the SDIO IRQ is | ||
59 | * fired and data is available (sdio-rx.c), it is sent to the generic | ||
60 | * driver for processing with i2400m_rx. | ||
61 | */ | ||
62 | |||
63 | #ifndef __I2400M_SDIO_H__ | ||
64 | #define __I2400M_SDIO_H__ | ||
65 | |||
66 | #include "i2400m.h" | ||
67 | |||
68 | /* Host-Device interface for SDIO */ | ||
69 | enum { | ||
70 | I2400MS_BLK_SIZE = 256, | ||
71 | I2400MS_PL_SIZE_MAX = 0x3E00, | ||
72 | |||
73 | I2400MS_DATA_ADDR = 0x0, | ||
74 | I2400MS_INTR_STATUS_ADDR = 0x13, | ||
75 | I2400MS_INTR_CLEAR_ADDR = 0x13, | ||
76 | I2400MS_INTR_ENABLE_ADDR = 0x14, | ||
77 | I2400MS_INTR_GET_SIZE_ADDR = 0x2C, | ||
78 | /* The number of ticks to wait for the device to signal that | ||
79 | * it is ready */ | ||
80 | I2400MS_INIT_SLEEP_INTERVAL = 10, | ||
81 | }; | ||
82 | |||
83 | |||
84 | /** | ||
85 | * struct i2400ms - descriptor for a SDIO connected i2400m | ||
86 | * | ||
87 | * @i2400m: bus-generic i2400m implementation; has to be first (see | ||
88 | * it's documentation in i2400m.h). | ||
89 | * | ||
90 | * @func: pointer to our SDIO function | ||
91 | * | ||
92 | * @tx_worker: workqueue struct used to TX data when the bus-generic | ||
93 | * code signals packets are pending for transmission to the device. | ||
94 | * | ||
95 | * @tx_workqueue: workqeueue used for data TX; we don't use the | ||
96 | * system's workqueue as that might cause deadlocks with code in | ||
97 | * the bus-generic driver. | ||
98 | */ | ||
99 | struct i2400ms { | ||
100 | struct i2400m i2400m; /* FIRST! See doc */ | ||
101 | struct sdio_func *func; | ||
102 | |||
103 | struct work_struct tx_worker; | ||
104 | struct workqueue_struct *tx_workqueue; | ||
105 | char tx_wq_name[32]; | ||
106 | |||
107 | struct dentry *debugfs_dentry; | ||
108 | }; | ||
109 | |||
110 | |||
111 | static inline | ||
112 | void i2400ms_init(struct i2400ms *i2400ms) | ||
113 | { | ||
114 | i2400m_init(&i2400ms->i2400m); | ||
115 | } | ||
116 | |||
117 | |||
118 | extern int i2400ms_rx_setup(struct i2400ms *); | ||
119 | extern void i2400ms_rx_release(struct i2400ms *); | ||
120 | extern ssize_t __i2400ms_rx_get_size(struct i2400ms *); | ||
121 | |||
122 | extern int i2400ms_tx_setup(struct i2400ms *); | ||
123 | extern void i2400ms_tx_release(struct i2400ms *); | ||
124 | extern void i2400ms_bus_tx_kick(struct i2400m *); | ||
125 | |||
126 | extern ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *, | ||
127 | const struct i2400m_bootrom_header *, | ||
128 | size_t, int); | ||
129 | extern ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *, | ||
130 | struct i2400m_bootrom_header *, | ||
131 | size_t); | ||
132 | #endif /* #ifndef __I2400M_SDIO_H__ */ | ||
diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h new file mode 100644 index 000000000000..6f76558b170f --- /dev/null +++ b/drivers/net/wimax/i2400m/i2400m-usb.h | |||
@@ -0,0 +1,264 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * USB-specific i2400m driver definitions | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
37 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
38 | * - Initial implementation | ||
39 | * | ||
40 | * | ||
41 | * This driver implements the bus-specific part of the i2400m for | ||
42 | * USB. Check i2400m.h for a generic driver description. | ||
43 | * | ||
44 | * ARCHITECTURE | ||
45 | * | ||
46 | * This driver listens to notifications sent from the notification | ||
47 | * endpoint (in usb-notif.c); when data is ready to read, the code in | ||
48 | * there schedules a read from the device (usb-rx.c) and then passes | ||
49 | * the data to the generic RX code (rx.c). | ||
50 | * | ||
51 | * When the generic driver needs to send data (network or control), it | ||
52 | * queues up in the TX FIFO (tx.c) and that will notify the driver | ||
53 | * through the i2400m->bus_tx_kick() callback | ||
54 | * (usb-tx.c:i2400mu_bus_tx_kick) which will send the items in the | ||
55 | * FIFO queue. | ||
56 | * | ||
57 | * This driver, as well, implements the USB-specific ops for the generic | ||
58 | * driver to be able to setup/teardown communication with the device | ||
59 | * [i2400m_bus_dev_start() and i2400m_bus_dev_stop()], reseting the | ||
60 | * device [i2400m_bus_reset()] and performing firmware upload | ||
61 | * [i2400m_bus_bm_cmd() and i2400_bus_bm_wait_for_ack()]. | ||
62 | */ | ||
63 | |||
64 | #ifndef __I2400M_USB_H__ | ||
65 | #define __I2400M_USB_H__ | ||
66 | |||
67 | #include "i2400m.h" | ||
68 | #include <linux/kthread.h> | ||
69 | |||
70 | |||
71 | /* | ||
72 | * Error Density Count: cheapo error density (over time) counter | ||
73 | * | ||
74 | * Originally by Reinette Chatre <reinette.chatre@intel.com> | ||
75 | * | ||
76 | * Embed an 'struct edc' somewhere. Each time there is a soft or | ||
77 | * retryable error, call edc_inc() and check if the error top | ||
78 | * watermark has been reached. | ||
79 | */ | ||
80 | enum { | ||
81 | EDC_MAX_ERRORS = 10, | ||
82 | EDC_ERROR_TIMEFRAME = HZ, | ||
83 | }; | ||
84 | |||
85 | /* error density counter */ | ||
86 | struct edc { | ||
87 | unsigned long timestart; | ||
88 | u16 errorcount; | ||
89 | }; | ||
90 | |||
91 | static inline void edc_init(struct edc *edc) | ||
92 | { | ||
93 | edc->timestart = jiffies; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * edc_inc - report a soft error and check if we are over the watermark | ||
98 | * | ||
99 | * @edc: pointer to error density counter. | ||
100 | * @max_err: maximum number of errors we can accept over the timeframe | ||
101 | * @timeframe: lenght of the timeframe (in jiffies). | ||
102 | * | ||
103 | * Returns: !0 1 if maximum acceptable errors per timeframe has been | ||
104 | * exceeded. 0 otherwise. | ||
105 | * | ||
106 | * This is way to determine if the number of acceptable errors per time | ||
107 | * period has been exceeded. It is not accurate as there are cases in which | ||
108 | * this scheme will not work, for example if there are periodic occurences | ||
109 | * of errors that straddle updates to the start time. This scheme is | ||
110 | * sufficient for our usage. | ||
111 | * | ||
112 | * To use, embed a 'struct edc' somewhere, initialize it with | ||
113 | * edc_init() and when an error hits: | ||
114 | * | ||
115 | * if (do_something_fails_with_a_soft_error) { | ||
116 | * if (edc_inc(&my->edc, MAX_ERRORS, MAX_TIMEFRAME)) | ||
117 | * Ops, hard error, do something about it | ||
118 | * else | ||
119 | * Retry or ignore, depending on whatever | ||
120 | * } | ||
121 | */ | ||
122 | static inline int edc_inc(struct edc *edc, u16 max_err, u16 timeframe) | ||
123 | { | ||
124 | unsigned long now; | ||
125 | |||
126 | now = jiffies; | ||
127 | if (now - edc->timestart > timeframe) { | ||
128 | edc->errorcount = 1; | ||
129 | edc->timestart = now; | ||
130 | } else if (++edc->errorcount > max_err) { | ||
131 | edc->errorcount = 0; | ||
132 | edc->timestart = now; | ||
133 | return 1; | ||
134 | } | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | /* Host-Device interface for USB */ | ||
139 | enum { | ||
140 | I2400MU_MAX_NOTIFICATION_LEN = 256, | ||
141 | I2400MU_BLK_SIZE = 16, | ||
142 | I2400MU_PL_SIZE_MAX = 0x3EFF, | ||
143 | |||
144 | /* Endpoints */ | ||
145 | I2400MU_EP_BULK_OUT = 0, | ||
146 | I2400MU_EP_NOTIFICATION, | ||
147 | I2400MU_EP_RESET_COLD, | ||
148 | I2400MU_EP_BULK_IN, | ||
149 | }; | ||
150 | |||
151 | |||
152 | /** | ||
153 | * struct i2400mu - descriptor for a USB connected i2400m | ||
154 | * | ||
155 | * @i2400m: bus-generic i2400m implementation; has to be first (see | ||
156 | * it's documentation in i2400m.h). | ||
157 | * | ||
158 | * @usb_dev: pointer to our USB device | ||
159 | * | ||
160 | * @usb_iface: pointer to our USB interface | ||
161 | * | ||
162 | * @urb_edc: error density counter; used to keep a density-on-time tab | ||
163 | * on how many soft (retryable or ignorable) errors we get. If we | ||
164 | * go over the threshold, we consider the bus transport is failing | ||
165 | * too much and reset. | ||
166 | * | ||
167 | * @notif_urb: URB for receiving notifications from the device. | ||
168 | * | ||
169 | * @tx_kthread: thread we use for data TX. We use a thread because in | ||
170 | * order to do deep power saving and put the device to sleep, we | ||
171 | * need to call usb_autopm_*() [blocking functions]. | ||
172 | * | ||
173 | * @tx_wq: waitqueue for the TX kthread to sleep when there is no data | ||
174 | * to be sent; when more data is available, it is woken up by | ||
175 | * i2400mu_bus_tx_kick(). | ||
176 | * | ||
177 | * @rx_kthread: thread we use for data RX. We use a thread because in | ||
178 | * order to do deep power saving and put the device to sleep, we | ||
179 | * need to call usb_autopm_*() [blocking functions]. | ||
180 | * | ||
181 | * @rx_wq: waitqueue for the RX kthread to sleep when there is no data | ||
182 | * to receive. When data is available, it is woken up by | ||
183 | * usb-notif.c:i2400mu_notification_grok(). | ||
184 | * | ||
185 | * @rx_pending_count: number of rx-data-ready notifications that were | ||
186 | * still not handled by the RX kthread. | ||
187 | * | ||
188 | * @rx_size: current RX buffer size that is being used. | ||
189 | * | ||
190 | * @rx_size_acc: accumulator of the sizes of the previous read | ||
191 | * transactions. | ||
192 | * | ||
193 | * @rx_size_cnt: number of read transactions accumulated in | ||
194 | * @rx_size_acc. | ||
195 | * | ||
196 | * @do_autopm: disable(0)/enable(>0) calling the | ||
197 | * usb_autopm_get/put_interface() barriers when executing | ||
198 | * commands. See doc in i2400mu_suspend() for more information. | ||
199 | * | ||
200 | * @rx_size_auto_shrink: if true, the rx_size is shrinked | ||
201 | * automatically based on the average size of the received | ||
202 | * transactions. This allows the receive code to allocate smaller | ||
203 | * chunks of memory and thus reduce pressure on the memory | ||
204 | * allocator by not wasting so much space. By default it is | ||
205 | * enabled. | ||
206 | * | ||
207 | * @debugfs_dentry: hookup for debugfs files. | ||
208 | * These have to be in a separate directory, a child of | ||
209 | * (wimax_dev->debugfs_dentry) so they can be removed when the | ||
210 | * module unloads, as we don't keep each dentry. | ||
211 | */ | ||
212 | struct i2400mu { | ||
213 | struct i2400m i2400m; /* FIRST! See doc */ | ||
214 | |||
215 | struct usb_device *usb_dev; | ||
216 | struct usb_interface *usb_iface; | ||
217 | struct edc urb_edc; /* Error density counter */ | ||
218 | |||
219 | struct urb *notif_urb; | ||
220 | struct task_struct *tx_kthread; | ||
221 | wait_queue_head_t tx_wq; | ||
222 | |||
223 | struct task_struct *rx_kthread; | ||
224 | wait_queue_head_t rx_wq; | ||
225 | atomic_t rx_pending_count; | ||
226 | size_t rx_size, rx_size_acc, rx_size_cnt; | ||
227 | atomic_t do_autopm; | ||
228 | u8 rx_size_auto_shrink; | ||
229 | |||
230 | struct dentry *debugfs_dentry; | ||
231 | }; | ||
232 | |||
233 | |||
234 | static inline | ||
235 | void i2400mu_init(struct i2400mu *i2400mu) | ||
236 | { | ||
237 | i2400m_init(&i2400mu->i2400m); | ||
238 | edc_init(&i2400mu->urb_edc); | ||
239 | init_waitqueue_head(&i2400mu->tx_wq); | ||
240 | atomic_set(&i2400mu->rx_pending_count, 0); | ||
241 | init_waitqueue_head(&i2400mu->rx_wq); | ||
242 | i2400mu->rx_size = PAGE_SIZE - sizeof(struct skb_shared_info); | ||
243 | atomic_set(&i2400mu->do_autopm, 1); | ||
244 | i2400mu->rx_size_auto_shrink = 1; | ||
245 | } | ||
246 | |||
247 | extern int i2400mu_notification_setup(struct i2400mu *); | ||
248 | extern void i2400mu_notification_release(struct i2400mu *); | ||
249 | |||
250 | extern int i2400mu_rx_setup(struct i2400mu *); | ||
251 | extern void i2400mu_rx_release(struct i2400mu *); | ||
252 | extern void i2400mu_rx_kick(struct i2400mu *); | ||
253 | |||
254 | extern int i2400mu_tx_setup(struct i2400mu *); | ||
255 | extern void i2400mu_tx_release(struct i2400mu *); | ||
256 | extern void i2400mu_bus_tx_kick(struct i2400m *); | ||
257 | |||
258 | extern ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *, | ||
259 | const struct i2400m_bootrom_header *, | ||
260 | size_t, int); | ||
261 | extern ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *, | ||
262 | struct i2400m_bootrom_header *, | ||
263 | size_t); | ||
264 | #endif /* #ifndef __I2400M_USB_H__ */ | ||
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h new file mode 100644 index 000000000000..067c871cc226 --- /dev/null +++ b/drivers/net/wimax/i2400m/i2400m.h | |||
@@ -0,0 +1,755 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Declarations for bus-generic internal APIs | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
37 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
38 | * - Initial implementation | ||
39 | * | ||
40 | * | ||
41 | * GENERAL DRIVER ARCHITECTURE | ||
42 | * | ||
43 | * The i2400m driver is split in the following two major parts: | ||
44 | * | ||
45 | * - bus specific driver | ||
46 | * - bus generic driver (this part) | ||
47 | * | ||
48 | * The bus specific driver sets up stuff specific to the bus the | ||
49 | * device is connected to (USB, SDIO, PCI, tam-tam...non-authoritative | ||
50 | * nor binding list) which is basically the device-model management | ||
51 | * (probe/disconnect, etc), moving data from device to kernel and | ||
52 | * back, doing the power saving details and reseting the device. | ||
53 | * | ||
54 | * For details on each bus-specific driver, see it's include file, | ||
55 | * i2400m-BUSNAME.h | ||
56 | * | ||
57 | * The bus-generic functionality break up is: | ||
58 | * | ||
59 | * - Firmware upload: fw.c - takes care of uploading firmware to the | ||
60 | * device. bus-specific driver just needs to provides a way to | ||
61 | * execute boot-mode commands and to reset the device. | ||
62 | * | ||
63 | * - RX handling: rx.c - receives data from the bus-specific code and | ||
64 | * feeds it to the network or WiMAX stack or uses it to modify | ||
65 | * the driver state. bus-specific driver only has to receive | ||
66 | * frames and pass them to this module. | ||
67 | * | ||
68 | * - TX handling: tx.c - manages the TX FIFO queue and provides means | ||
69 | * for the bus-specific TX code to pull data from the FIFO | ||
70 | * queue. bus-specific code just pulls frames from this module | ||
71 | * to sends them to the device. | ||
72 | * | ||
73 | * - netdev glue: netdev.c - interface with Linux networking | ||
74 | * stack. Pass around data frames, and configure when the | ||
75 | * device is up and running or shutdown (through ifconfig up / | ||
76 | * down). Bus-generic only. | ||
77 | * | ||
78 | * - control ops: control.c - implements various commmands for | ||
79 | * controlling the device. bus-generic only. | ||
80 | * | ||
81 | * - device model glue: driver.c - implements helpers for the | ||
82 | * device-model glue done by the bus-specific layer | ||
83 | * (setup/release the driver resources), turning the device on | ||
84 | * and off, handling the device reboots/resets and a few simple | ||
85 | * WiMAX stack ops. | ||
86 | * | ||
87 | * Code is also broken up in linux-glue / device-glue. | ||
88 | * | ||
89 | * Linux glue contains functions that deal mostly with gluing with the | ||
90 | * rest of the Linux kernel. | ||
91 | * | ||
92 | * Device-glue are functions that deal mostly with the way the device | ||
93 | * does things and talk the device's language. | ||
94 | * | ||
95 | * device-glue code is licensed BSD so other open source OSes can take | ||
96 | * it to implement their drivers. | ||
97 | * | ||
98 | * | ||
99 | * APIs AND HEADER FILES | ||
100 | * | ||
101 | * This bus generic code exports three APIs: | ||
102 | * | ||
103 | * - HDI (host-device interface) definitions common to all busses | ||
104 | * (include/linux/wimax/i2400m.h); these can be also used by user | ||
105 | * space code. | ||
106 | * - internal API for the bus-generic code | ||
107 | * - external API for the bus-specific drivers | ||
108 | * | ||
109 | * | ||
110 | * LIFE CYCLE: | ||
111 | * | ||
112 | * When the bus-specific driver probes, it allocates a network device | ||
113 | * with enough space for it's data structue, that must contain a | ||
114 | * &struct i2400m at the top. | ||
115 | * | ||
116 | * On probe, it needs to fill the i2400m members marked as [fill], as | ||
117 | * well as i2400m->wimax_dev.net_dev and call i2400m_setup(). The | ||
118 | * i2400m driver will only register with the WiMAX and network stacks; | ||
119 | * the only access done to the device is to read the MAC address so we | ||
120 | * can register a network device. This calls i2400m_dev_start() to | ||
121 | * load firmware, setup communication with the device and configure it | ||
122 | * for operation. | ||
123 | * | ||
124 | * At this point, control and data communications are possible. | ||
125 | * | ||
126 | * On disconnect/driver unload, the bus-specific disconnect function | ||
127 | * calls i2400m_release() to undo i2400m_setup(). i2400m_dev_stop() | ||
128 | * shuts the firmware down and releases resources uses to communicate | ||
129 | * with the device. | ||
130 | * | ||
131 | * While the device is up, it might reset. The bus-specific driver has | ||
132 | * to catch that situation and call i2400m_dev_reset_handle() to deal | ||
133 | * with it (reset the internal driver structures and go back to square | ||
134 | * one). | ||
135 | */ | ||
136 | |||
137 | #ifndef __I2400M_H__ | ||
138 | #define __I2400M_H__ | ||
139 | |||
140 | #include <linux/usb.h> | ||
141 | #include <linux/netdevice.h> | ||
142 | #include <linux/completion.h> | ||
143 | #include <linux/rwsem.h> | ||
144 | #include <asm/atomic.h> | ||
145 | #include <net/wimax.h> | ||
146 | #include <linux/wimax/i2400m.h> | ||
147 | #include <asm/byteorder.h> | ||
148 | |||
149 | /* Misc constants */ | ||
150 | enum { | ||
151 | /* Firmware uploading */ | ||
152 | I2400M_BOOT_RETRIES = 3, | ||
153 | /* Size of the Boot Mode Command buffer */ | ||
154 | I2400M_BM_CMD_BUF_SIZE = 16 * 1024, | ||
155 | I2400M_BM_ACK_BUF_SIZE = 256, | ||
156 | }; | ||
157 | |||
158 | |||
159 | /* Firmware version we request when pulling the fw image file */ | ||
160 | #define I2400M_FW_VERSION "1.3" | ||
161 | |||
162 | |||
163 | /** | ||
164 | * i2400m_reset_type - methods to reset a device | ||
165 | * | ||
166 | * @I2400M_RT_WARM: Reset without device disconnection, device handles | ||
167 | * are kept valid but state is back to power on, with firmware | ||
168 | * re-uploaded. | ||
169 | * @I2400M_RT_COLD: Tell the device to disconnect itself from the bus | ||
170 | * and reconnect. Renders all device handles invalid. | ||
171 | * @I2400M_RT_BUS: Tells the bus to reset the device; last measure | ||
172 | * used when both types above don't work. | ||
173 | */ | ||
174 | enum i2400m_reset_type { | ||
175 | I2400M_RT_WARM, /* first measure */ | ||
176 | I2400M_RT_COLD, /* second measure */ | ||
177 | I2400M_RT_BUS, /* call in artillery */ | ||
178 | }; | ||
179 | |||
180 | struct i2400m_reset_ctx; | ||
181 | |||
182 | /** | ||
183 | * struct i2400m - descriptor for an Intel 2400m | ||
184 | * | ||
185 | * Members marked with [fill] must be filled out/initialized before | ||
186 | * calling i2400m_setup(). | ||
187 | * | ||
188 | * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16, | ||
189 | * so we have a tx_blk_size variable that the bus layer sets to | ||
190 | * tell the engine how much of that we need. | ||
191 | * | ||
192 | * @bus_pl_size_max: [fill] Maximum payload size. | ||
193 | * | ||
194 | * @bus_dev_start: [fill] Function called by the bus-generic code | ||
195 | * [i2400m_dev_start()] to setup the bus-specific communications | ||
196 | * to the the device. See LIFE CYCLE above. | ||
197 | * | ||
198 | * NOTE: Doesn't need to upload the firmware, as that is taken | ||
199 | * care of by the bus-generic code. | ||
200 | * | ||
201 | * @bus_dev_stop: [fill] Function called by the bus-generic code | ||
202 | * [i2400m_dev_stop()] to shutdown the bus-specific communications | ||
203 | * to the the device. See LIFE CYCLE above. | ||
204 | * | ||
205 | * This function does not need to reset the device, just tear down | ||
206 | * all the host resources created to handle communication with | ||
207 | * the device. | ||
208 | * | ||
209 | * @bus_tx_kick: [fill] Function called by the bus-generic code to let | ||
210 | * the bus-specific code know that there is data available in the | ||
211 | * TX FIFO for transmission to the device. | ||
212 | * | ||
213 | * This function cannot sleep. | ||
214 | * | ||
215 | * @bus_reset: [fill] Function called by the bus-generic code to reset | ||
216 | * the device in in various ways. Doesn't need to wait for the | ||
217 | * reset to finish. | ||
218 | * | ||
219 | * If warm or cold reset fail, this function is expected to do a | ||
220 | * bus-specific reset (eg: USB reset) to get the device to a | ||
221 | * working state (even if it implies device disconecction). | ||
222 | * | ||
223 | * Note the warm reset is used by the firmware uploader to | ||
224 | * reinitialize the device. | ||
225 | * | ||
226 | * IMPORTANT: this is called very early in the device setup | ||
227 | * process, so it cannot rely on common infrastructure being laid | ||
228 | * out. | ||
229 | * | ||
230 | * @bus_bm_cmd_send: [fill] Function called to send a boot-mode | ||
231 | * command. Flags are defined in 'enum i2400m_bm_cmd_flags'. This | ||
232 | * is synchronous and has to return 0 if ok or < 0 errno code in | ||
233 | * any error condition. | ||
234 | * | ||
235 | * @bus_bm_wait_for_ack: [fill] Function called to wait for a | ||
236 | * boot-mode notification (that can be a response to a previously | ||
237 | * issued command or an asynchronous one). Will read until all the | ||
238 | * indicated size is read or timeout. Reading more or less data | ||
239 | * than asked for is an error condition. Return 0 if ok, < 0 errno | ||
240 | * code on error. | ||
241 | * | ||
242 | * The caller to this function will check if the response is a | ||
243 | * barker that indicates the device going into reset mode. | ||
244 | * | ||
245 | * @bus_fw_name: [fill] name of the firmware image (in most cases, | ||
246 | * they are all the same for a single release, except that they | ||
247 | * have the type of the bus embedded in the name (eg: | ||
248 | * i2400m-fw-X-VERSION.sbcf, where X is the bus name). | ||
249 | * | ||
250 | * @bus_bm_mac_addr_impaired: [fill] Set to true if the device's MAC | ||
251 | * address provided in boot mode is kind of broken and needs to | ||
252 | * be re-read later on. | ||
253 | * | ||
254 | * | ||
255 | * @wimax_dev: WiMAX generic device for linkage into the kernel WiMAX | ||
256 | * stack. Due to the way a net_device is allocated, we need to | ||
257 | * force this to be the first field so that we can get from | ||
258 | * netdev_priv() the right pointer. | ||
259 | * | ||
260 | * @state: device's state (as reported by it) | ||
261 | * | ||
262 | * @state_wq: waitqueue that is woken up whenever the state changes | ||
263 | * | ||
264 | * @tx_lock: spinlock to protect TX members | ||
265 | * | ||
266 | * @tx_buf: FIFO buffer for TX; we queue data here | ||
267 | * | ||
268 | * @tx_in: FIFO index for incoming data. Note this doesn't wrap around | ||
269 | * and it is always greater than @tx_out. | ||
270 | * | ||
271 | * @tx_out: FIFO index for outgoing data | ||
272 | * | ||
273 | * @tx_msg: current TX message that is active in the FIFO for | ||
274 | * appending payloads. | ||
275 | * | ||
276 | * @tx_sequence: current sequence number for TX messages from the | ||
277 | * device to the host. | ||
278 | * | ||
279 | * @tx_msg_size: size of the current message being transmitted by the | ||
280 | * bus-specific code. | ||
281 | * | ||
282 | * @tx_pl_num: total number of payloads sent | ||
283 | * | ||
284 | * @tx_pl_max: maximum number of payloads sent in a TX message | ||
285 | * | ||
286 | * @tx_pl_min: minimum number of payloads sent in a TX message | ||
287 | * | ||
288 | * @tx_num: number of TX messages sent | ||
289 | * | ||
290 | * @tx_size_acc: number of bytes in all TX messages sent | ||
291 | * (this is different to net_dev's statistics as it also counts | ||
292 | * control messages). | ||
293 | * | ||
294 | * @tx_size_min: smallest TX message sent. | ||
295 | * | ||
296 | * @tx_size_max: biggest TX message sent. | ||
297 | * | ||
298 | * @rx_lock: spinlock to protect RX members | ||
299 | * | ||
300 | * @rx_pl_num: total number of payloads received | ||
301 | * | ||
302 | * @rx_pl_max: maximum number of payloads received in a RX message | ||
303 | * | ||
304 | * @rx_pl_min: minimum number of payloads received in a RX message | ||
305 | * | ||
306 | * @rx_num: number of RX messages received | ||
307 | * | ||
308 | * @rx_size_acc: number of bytes in all RX messages received | ||
309 | * (this is different to net_dev's statistics as it also counts | ||
310 | * control messages). | ||
311 | * | ||
312 | * @rx_size_min: smallest RX message received. | ||
313 | * | ||
314 | * @rx_size_max: buggest RX message received. | ||
315 | * | ||
316 | * @init_mutex: Mutex used for serializing the device bringup | ||
317 | * sequence; this way if the device reboots in the middle, we | ||
318 | * don't try to do a bringup again while we are tearing down the | ||
319 | * one that failed. | ||
320 | * | ||
321 | * Can't reuse @msg_mutex because from within the bringup sequence | ||
322 | * we need to send messages to the device and thus use @msg_mutex. | ||
323 | * | ||
324 | * @msg_mutex: mutex used to send control commands to the device (we | ||
325 | * only allow one at a time, per host-device interface design). | ||
326 | * | ||
327 | * @msg_completion: used to wait for an ack to a control command sent | ||
328 | * to the device. | ||
329 | * | ||
330 | * @ack_skb: used to store the actual ack to a control command if the | ||
331 | * reception of the command was successful. Otherwise, a ERR_PTR() | ||
332 | * errno code that indicates what failed with the ack reception. | ||
333 | * | ||
334 | * Only valid after @msg_completion is woken up. Only updateable | ||
335 | * if @msg_completion is armed. Only touched by | ||
336 | * i2400m_msg_to_dev(). | ||
337 | * | ||
338 | * Protected by @rx_lock. In theory the command execution flow is | ||
339 | * sequential, but in case the device sends an out-of-phase or | ||
340 | * very delayed response, we need to avoid it trampling current | ||
341 | * execution. | ||
342 | * | ||
343 | * @bm_cmd_buf: boot mode command buffer for composing firmware upload | ||
344 | * commands. | ||
345 | * | ||
346 | * USB can't r/w to stack, vmalloc, etc...as well, we end up | ||
347 | * having to alloc/free a lot to compose commands, so we use these | ||
348 | * for stagging and not having to realloc all the time. | ||
349 | * | ||
350 | * This assumes the code always runs serialized. Only one thread | ||
351 | * can call i2400m_bm_cmd() at the same time. | ||
352 | * | ||
353 | * @bm_ack_buf: boot mode acknoledge buffer for staging reception of | ||
354 | * responses to commands. | ||
355 | * | ||
356 | * See @bm_cmd_buf. | ||
357 | * | ||
358 | * @work_queue: work queue for processing device reports. This | ||
359 | * workqueue cannot be used for processing TX or RX to the device, | ||
360 | * as from it we'll process device reports, which might require | ||
361 | * further communication with the device. | ||
362 | * | ||
363 | * @debugfs_dentry: hookup for debugfs files. | ||
364 | * These have to be in a separate directory, a child of | ||
365 | * (wimax_dev->debugfs_dentry) so they can be removed when the | ||
366 | * module unloads, as we don't keep each dentry. | ||
367 | */ | ||
368 | struct i2400m { | ||
369 | struct wimax_dev wimax_dev; /* FIRST! See doc */ | ||
370 | |||
371 | unsigned updown:1; /* Network device is up or down */ | ||
372 | unsigned boot_mode:1; /* is the device in boot mode? */ | ||
373 | unsigned sboot:1; /* signed or unsigned fw boot */ | ||
374 | unsigned ready:1; /* all probing steps done */ | ||
375 | u8 trace_msg_from_user; /* echo rx msgs to 'trace' pipe */ | ||
376 | /* typed u8 so debugfs/u8 can tweak */ | ||
377 | enum i2400m_system_state state; | ||
378 | wait_queue_head_t state_wq; /* Woken up when on state updates */ | ||
379 | |||
380 | size_t bus_tx_block_size; | ||
381 | size_t bus_pl_size_max; | ||
382 | int (*bus_dev_start)(struct i2400m *); | ||
383 | void (*bus_dev_stop)(struct i2400m *); | ||
384 | void (*bus_tx_kick)(struct i2400m *); | ||
385 | int (*bus_reset)(struct i2400m *, enum i2400m_reset_type); | ||
386 | ssize_t (*bus_bm_cmd_send)(struct i2400m *, | ||
387 | const struct i2400m_bootrom_header *, | ||
388 | size_t, int flags); | ||
389 | ssize_t (*bus_bm_wait_for_ack)(struct i2400m *, | ||
390 | struct i2400m_bootrom_header *, size_t); | ||
391 | const char *bus_fw_name; | ||
392 | unsigned bus_bm_mac_addr_impaired:1; | ||
393 | |||
394 | spinlock_t tx_lock; /* protect TX state */ | ||
395 | void *tx_buf; | ||
396 | size_t tx_in, tx_out; | ||
397 | struct i2400m_msg_hdr *tx_msg; | ||
398 | size_t tx_sequence, tx_msg_size; | ||
399 | /* TX stats */ | ||
400 | unsigned tx_pl_num, tx_pl_max, tx_pl_min, | ||
401 | tx_num, tx_size_acc, tx_size_min, tx_size_max; | ||
402 | |||
403 | /* RX stats */ | ||
404 | spinlock_t rx_lock; /* protect RX state */ | ||
405 | unsigned rx_pl_num, rx_pl_max, rx_pl_min, | ||
406 | rx_num, rx_size_acc, rx_size_min, rx_size_max; | ||
407 | |||
408 | struct mutex msg_mutex; /* serialize command execution */ | ||
409 | struct completion msg_completion; | ||
410 | struct sk_buff *ack_skb; /* protected by rx_lock */ | ||
411 | |||
412 | void *bm_ack_buf; /* for receiving acks over USB */ | ||
413 | void *bm_cmd_buf; /* for issuing commands over USB */ | ||
414 | |||
415 | struct workqueue_struct *work_queue; | ||
416 | |||
417 | struct mutex init_mutex; /* protect bringup seq */ | ||
418 | struct i2400m_reset_ctx *reset_ctx; /* protected by init_mutex */ | ||
419 | |||
420 | struct work_struct wake_tx_ws; | ||
421 | struct sk_buff *wake_tx_skb; | ||
422 | |||
423 | struct dentry *debugfs_dentry; | ||
424 | }; | ||
425 | |||
426 | |||
427 | /* | ||
428 | * Initialize a 'struct i2400m' from all zeroes | ||
429 | * | ||
430 | * This is a bus-generic API call. | ||
431 | */ | ||
432 | static inline | ||
433 | void i2400m_init(struct i2400m *i2400m) | ||
434 | { | ||
435 | wimax_dev_init(&i2400m->wimax_dev); | ||
436 | |||
437 | i2400m->boot_mode = 1; | ||
438 | init_waitqueue_head(&i2400m->state_wq); | ||
439 | |||
440 | spin_lock_init(&i2400m->tx_lock); | ||
441 | i2400m->tx_pl_min = UINT_MAX; | ||
442 | i2400m->tx_size_min = UINT_MAX; | ||
443 | |||
444 | spin_lock_init(&i2400m->rx_lock); | ||
445 | i2400m->rx_pl_min = UINT_MAX; | ||
446 | i2400m->rx_size_min = UINT_MAX; | ||
447 | |||
448 | mutex_init(&i2400m->msg_mutex); | ||
449 | init_completion(&i2400m->msg_completion); | ||
450 | |||
451 | mutex_init(&i2400m->init_mutex); | ||
452 | /* wake_tx_ws is initialized in i2400m_tx_setup() */ | ||
453 | } | ||
454 | |||
455 | |||
456 | /* | ||
457 | * Bus-generic internal APIs | ||
458 | * ------------------------- | ||
459 | */ | ||
460 | |||
461 | static inline | ||
462 | struct i2400m *wimax_dev_to_i2400m(struct wimax_dev *wimax_dev) | ||
463 | { | ||
464 | return container_of(wimax_dev, struct i2400m, wimax_dev); | ||
465 | } | ||
466 | |||
467 | static inline | ||
468 | struct i2400m *net_dev_to_i2400m(struct net_device *net_dev) | ||
469 | { | ||
470 | return wimax_dev_to_i2400m(netdev_priv(net_dev)); | ||
471 | } | ||
472 | |||
473 | /* | ||
474 | * Boot mode support | ||
475 | */ | ||
476 | |||
477 | /** | ||
478 | * i2400m_bm_cmd_flags - flags to i2400m_bm_cmd() | ||
479 | * | ||
480 | * @I2400M_BM_CMD_RAW: send the command block as-is, without doing any | ||
481 | * extra processing for adding CRC. | ||
482 | */ | ||
483 | enum i2400m_bm_cmd_flags { | ||
484 | I2400M_BM_CMD_RAW = 1 << 2, | ||
485 | }; | ||
486 | |||
487 | /** | ||
488 | * i2400m_bri - Boot-ROM indicators | ||
489 | * | ||
490 | * Flags for i2400m_bootrom_init() and i2400m_dev_bootstrap() [which | ||
491 | * are passed from things like i2400m_setup()]. Can be combined with | ||
492 | * |. | ||
493 | * | ||
494 | * @I2400M_BRI_SOFT: The device rebooted already and a reboot | ||
495 | * barker received, proceed directly to ack the boot sequence. | ||
496 | * @I2400M_BRI_NO_REBOOT: Do not reboot the device and proceed | ||
497 | * directly to wait for a reboot barker from the device. | ||
498 | * @I2400M_BRI_MAC_REINIT: We need to reinitialize the boot | ||
499 | * rom after reading the MAC adress. This is quite a dirty hack, | ||
500 | * if you ask me -- the device requires the bootrom to be | ||
501 | * intialized after reading the MAC address. | ||
502 | */ | ||
503 | enum i2400m_bri { | ||
504 | I2400M_BRI_SOFT = 1 << 1, | ||
505 | I2400M_BRI_NO_REBOOT = 1 << 2, | ||
506 | I2400M_BRI_MAC_REINIT = 1 << 3, | ||
507 | }; | ||
508 | |||
509 | extern void i2400m_bm_cmd_prepare(struct i2400m_bootrom_header *); | ||
510 | extern int i2400m_dev_bootstrap(struct i2400m *, enum i2400m_bri); | ||
511 | extern int i2400m_read_mac_addr(struct i2400m *); | ||
512 | extern int i2400m_bootrom_init(struct i2400m *, enum i2400m_bri); | ||
513 | |||
514 | /* Make/grok boot-rom header commands */ | ||
515 | |||
516 | static inline | ||
517 | __le32 i2400m_brh_command(enum i2400m_brh_opcode opcode, unsigned use_checksum, | ||
518 | unsigned direct_access) | ||
519 | { | ||
520 | return cpu_to_le32( | ||
521 | I2400M_BRH_SIGNATURE | ||
522 | | (direct_access ? I2400M_BRH_DIRECT_ACCESS : 0) | ||
523 | | I2400M_BRH_RESPONSE_REQUIRED /* response always required */ | ||
524 | | (use_checksum ? I2400M_BRH_USE_CHECKSUM : 0) | ||
525 | | (opcode & I2400M_BRH_OPCODE_MASK)); | ||
526 | } | ||
527 | |||
528 | static inline | ||
529 | void i2400m_brh_set_opcode(struct i2400m_bootrom_header *hdr, | ||
530 | enum i2400m_brh_opcode opcode) | ||
531 | { | ||
532 | hdr->command = cpu_to_le32( | ||
533 | (le32_to_cpu(hdr->command) & ~I2400M_BRH_OPCODE_MASK) | ||
534 | | (opcode & I2400M_BRH_OPCODE_MASK)); | ||
535 | } | ||
536 | |||
537 | static inline | ||
538 | unsigned i2400m_brh_get_opcode(const struct i2400m_bootrom_header *hdr) | ||
539 | { | ||
540 | return le32_to_cpu(hdr->command) & I2400M_BRH_OPCODE_MASK; | ||
541 | } | ||
542 | |||
543 | static inline | ||
544 | unsigned i2400m_brh_get_response(const struct i2400m_bootrom_header *hdr) | ||
545 | { | ||
546 | return (le32_to_cpu(hdr->command) & I2400M_BRH_RESPONSE_MASK) | ||
547 | >> I2400M_BRH_RESPONSE_SHIFT; | ||
548 | } | ||
549 | |||
550 | static inline | ||
551 | unsigned i2400m_brh_get_use_checksum(const struct i2400m_bootrom_header *hdr) | ||
552 | { | ||
553 | return le32_to_cpu(hdr->command) & I2400M_BRH_USE_CHECKSUM; | ||
554 | } | ||
555 | |||
556 | static inline | ||
557 | unsigned i2400m_brh_get_response_required( | ||
558 | const struct i2400m_bootrom_header *hdr) | ||
559 | { | ||
560 | return le32_to_cpu(hdr->command) & I2400M_BRH_RESPONSE_REQUIRED; | ||
561 | } | ||
562 | |||
563 | static inline | ||
564 | unsigned i2400m_brh_get_direct_access(const struct i2400m_bootrom_header *hdr) | ||
565 | { | ||
566 | return le32_to_cpu(hdr->command) & I2400M_BRH_DIRECT_ACCESS; | ||
567 | } | ||
568 | |||
569 | static inline | ||
570 | unsigned i2400m_brh_get_signature(const struct i2400m_bootrom_header *hdr) | ||
571 | { | ||
572 | return (le32_to_cpu(hdr->command) & I2400M_BRH_SIGNATURE_MASK) | ||
573 | >> I2400M_BRH_SIGNATURE_SHIFT; | ||
574 | } | ||
575 | |||
576 | |||
577 | /* | ||
578 | * Driver / device setup and internal functions | ||
579 | */ | ||
580 | extern void i2400m_netdev_setup(struct net_device *net_dev); | ||
581 | extern int i2400m_tx_setup(struct i2400m *); | ||
582 | extern void i2400m_wake_tx_work(struct work_struct *); | ||
583 | extern void i2400m_tx_release(struct i2400m *); | ||
584 | |||
585 | extern void i2400m_net_rx(struct i2400m *, struct sk_buff *, unsigned, | ||
586 | const void *, int); | ||
587 | enum i2400m_pt; | ||
588 | extern int i2400m_tx(struct i2400m *, const void *, size_t, enum i2400m_pt); | ||
589 | |||
590 | #ifdef CONFIG_DEBUG_FS | ||
591 | extern int i2400m_debugfs_add(struct i2400m *); | ||
592 | extern void i2400m_debugfs_rm(struct i2400m *); | ||
593 | #else | ||
594 | static inline int i2400m_debugfs_add(struct i2400m *i2400m) | ||
595 | { | ||
596 | return 0; | ||
597 | } | ||
598 | static inline void i2400m_debugfs_rm(struct i2400m *i2400m) {} | ||
599 | #endif | ||
600 | |||
601 | /* Called by _dev_start()/_dev_stop() to initialize the device itself */ | ||
602 | extern int i2400m_dev_initialize(struct i2400m *); | ||
603 | extern void i2400m_dev_shutdown(struct i2400m *); | ||
604 | |||
605 | extern struct attribute_group i2400m_dev_attr_group; | ||
606 | |||
607 | extern int i2400m_schedule_work(struct i2400m *, | ||
608 | void (*)(struct work_struct *), gfp_t); | ||
609 | |||
610 | /* HDI message's payload description handling */ | ||
611 | |||
612 | static inline | ||
613 | size_t i2400m_pld_size(const struct i2400m_pld *pld) | ||
614 | { | ||
615 | return I2400M_PLD_SIZE_MASK & le32_to_cpu(pld->val); | ||
616 | } | ||
617 | |||
618 | static inline | ||
619 | enum i2400m_pt i2400m_pld_type(const struct i2400m_pld *pld) | ||
620 | { | ||
621 | return (I2400M_PLD_TYPE_MASK & le32_to_cpu(pld->val)) | ||
622 | >> I2400M_PLD_TYPE_SHIFT; | ||
623 | } | ||
624 | |||
625 | static inline | ||
626 | void i2400m_pld_set(struct i2400m_pld *pld, size_t size, | ||
627 | enum i2400m_pt type) | ||
628 | { | ||
629 | pld->val = cpu_to_le32( | ||
630 | ((type << I2400M_PLD_TYPE_SHIFT) & I2400M_PLD_TYPE_MASK) | ||
631 | | (size & I2400M_PLD_SIZE_MASK)); | ||
632 | } | ||
633 | |||
634 | |||
635 | /* | ||
636 | * API for the bus-specific drivers | ||
637 | * -------------------------------- | ||
638 | */ | ||
639 | |||
640 | static inline | ||
641 | struct i2400m *i2400m_get(struct i2400m *i2400m) | ||
642 | { | ||
643 | dev_hold(i2400m->wimax_dev.net_dev); | ||
644 | return i2400m; | ||
645 | } | ||
646 | |||
647 | static inline | ||
648 | void i2400m_put(struct i2400m *i2400m) | ||
649 | { | ||
650 | dev_put(i2400m->wimax_dev.net_dev); | ||
651 | } | ||
652 | |||
653 | extern int i2400m_dev_reset_handle(struct i2400m *); | ||
654 | |||
655 | /* | ||
656 | * _setup()/_release() are called by the probe/disconnect functions of | ||
657 | * the bus-specific drivers. | ||
658 | */ | ||
659 | extern int i2400m_setup(struct i2400m *, enum i2400m_bri bm_flags); | ||
660 | extern void i2400m_release(struct i2400m *); | ||
661 | |||
662 | extern int i2400m_rx(struct i2400m *, struct sk_buff *); | ||
663 | extern struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *, size_t *); | ||
664 | extern void i2400m_tx_msg_sent(struct i2400m *); | ||
665 | |||
666 | static const __le32 i2400m_NBOOT_BARKER[4] = { | ||
667 | __constant_cpu_to_le32(I2400M_NBOOT_BARKER), | ||
668 | __constant_cpu_to_le32(I2400M_NBOOT_BARKER), | ||
669 | __constant_cpu_to_le32(I2400M_NBOOT_BARKER), | ||
670 | __constant_cpu_to_le32(I2400M_NBOOT_BARKER) | ||
671 | }; | ||
672 | |||
673 | static const __le32 i2400m_SBOOT_BARKER[4] = { | ||
674 | __constant_cpu_to_le32(I2400M_SBOOT_BARKER), | ||
675 | __constant_cpu_to_le32(I2400M_SBOOT_BARKER), | ||
676 | __constant_cpu_to_le32(I2400M_SBOOT_BARKER), | ||
677 | __constant_cpu_to_le32(I2400M_SBOOT_BARKER) | ||
678 | }; | ||
679 | |||
680 | |||
681 | /* | ||
682 | * Utility functions | ||
683 | */ | ||
684 | |||
685 | static inline | ||
686 | struct device *i2400m_dev(struct i2400m *i2400m) | ||
687 | { | ||
688 | return i2400m->wimax_dev.net_dev->dev.parent; | ||
689 | } | ||
690 | |||
691 | /* | ||
692 | * Helper for scheduling simple work functions | ||
693 | * | ||
694 | * This struct can get any kind of payload attached (normally in the | ||
695 | * form of a struct where you pack the stuff you want to pass to the | ||
696 | * _work function). | ||
697 | */ | ||
698 | struct i2400m_work { | ||
699 | struct work_struct ws; | ||
700 | struct i2400m *i2400m; | ||
701 | u8 pl[0]; | ||
702 | }; | ||
703 | extern int i2400m_queue_work(struct i2400m *, | ||
704 | void (*)(struct work_struct *), gfp_t, | ||
705 | const void *, size_t); | ||
706 | |||
707 | extern int i2400m_msg_check_status(const struct i2400m_l3l4_hdr *, | ||
708 | char *, size_t); | ||
709 | extern int i2400m_msg_size_check(struct i2400m *, | ||
710 | const struct i2400m_l3l4_hdr *, size_t); | ||
711 | extern struct sk_buff *i2400m_msg_to_dev(struct i2400m *, const void *, size_t); | ||
712 | extern void i2400m_msg_to_dev_cancel_wait(struct i2400m *, int); | ||
713 | extern void i2400m_msg_ack_hook(struct i2400m *, | ||
714 | const struct i2400m_l3l4_hdr *, size_t); | ||
715 | extern void i2400m_report_hook(struct i2400m *, | ||
716 | const struct i2400m_l3l4_hdr *, size_t); | ||
717 | extern int i2400m_cmd_enter_powersave(struct i2400m *); | ||
718 | extern int i2400m_cmd_get_state(struct i2400m *); | ||
719 | extern int i2400m_cmd_exit_idle(struct i2400m *); | ||
720 | extern struct sk_buff *i2400m_get_device_info(struct i2400m *); | ||
721 | extern int i2400m_firmware_check(struct i2400m *); | ||
722 | extern int i2400m_set_init_config(struct i2400m *, | ||
723 | const struct i2400m_tlv_hdr **, size_t); | ||
724 | |||
725 | static inline | ||
726 | struct usb_endpoint_descriptor *usb_get_epd(struct usb_interface *iface, int ep) | ||
727 | { | ||
728 | return &iface->cur_altsetting->endpoint[ep].desc; | ||
729 | } | ||
730 | |||
731 | extern int i2400m_op_rfkill_sw_toggle(struct wimax_dev *, | ||
732 | enum wimax_rf_state); | ||
733 | extern void i2400m_report_tlv_rf_switches_status( | ||
734 | struct i2400m *, const struct i2400m_tlv_rf_switches_status *); | ||
735 | |||
736 | |||
737 | /* | ||
738 | * Do a millisecond-sleep for allowing wireshark to dump all the data | ||
739 | * packets. Used only for debugging. | ||
740 | */ | ||
741 | static inline | ||
742 | void __i2400m_msleep(unsigned ms) | ||
743 | { | ||
744 | #if 1 | ||
745 | #else | ||
746 | msleep(ms); | ||
747 | #endif | ||
748 | } | ||
749 | |||
750 | /* Module parameters */ | ||
751 | |||
752 | extern int i2400m_idle_mode_disabled; | ||
753 | |||
754 | |||
755 | #endif /* #ifndef __I2400M_H__ */ | ||
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c new file mode 100644 index 000000000000..63fe708e8a31 --- /dev/null +++ b/drivers/net/wimax/i2400m/netdev.c | |||
@@ -0,0 +1,524 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Glue with the networking stack | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007 Intel Corporation <linux-wimax@intel.com> | ||
7 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
8 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License version | ||
12 | * 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
22 | * 02110-1301, USA. | ||
23 | * | ||
24 | * | ||
25 | * This implements an ethernet device for the i2400m. | ||
26 | * | ||
27 | * We fake being an ethernet device to simplify the support from user | ||
28 | * space and from the other side. The world is (sadly) configured to | ||
29 | * take in only Ethernet devices... | ||
30 | * | ||
31 | * Because of this, currently there is an copy-each-rxed-packet | ||
32 | * overhead on the RX path. Each IP packet has to be reallocated to | ||
33 | * add an ethernet header (as there is no space in what we get from | ||
34 | * the device). This is a known drawback and coming versions of the | ||
35 | * device's firmware are being changed to add header space that can be | ||
36 | * used to insert the ethernet header without having to reallocate and | ||
37 | * copy. | ||
38 | * | ||
39 | * TX error handling is tricky; because we have to FIFO/queue the | ||
40 | * buffers for transmission (as the hardware likes it aggregated), we | ||
41 | * just give the skb to the TX subsystem and by the time it is | ||
42 | * transmitted, we have long forgotten about it. So we just don't care | ||
43 | * too much about it. | ||
44 | * | ||
45 | * Note that when the device is in idle mode with the basestation, we | ||
46 | * need to negotiate coming back up online. That involves negotiation | ||
47 | * and possible user space interaction. Thus, we defer to a workqueue | ||
48 | * to do all that. By default, we only queue a single packet and drop | ||
49 | * the rest, as potentially the time to go back from idle to normal is | ||
50 | * long. | ||
51 | * | ||
52 | * ROADMAP | ||
53 | * | ||
54 | * i2400m_open Called on ifconfig up | ||
55 | * i2400m_stop Called on ifconfig down | ||
56 | * | ||
57 | * i2400m_hard_start_xmit Called by the network stack to send a packet | ||
58 | * i2400m_net_wake_tx Wake up device from basestation-IDLE & TX | ||
59 | * i2400m_wake_tx_work | ||
60 | * i2400m_cmd_exit_idle | ||
61 | * i2400m_tx | ||
62 | * i2400m_net_tx TX a data frame | ||
63 | * i2400m_tx | ||
64 | * | ||
65 | * i2400m_change_mtu Called on ifconfig mtu XXX | ||
66 | * | ||
67 | * i2400m_tx_timeout Called when the device times out | ||
68 | * | ||
69 | * i2400m_net_rx Called by the RX code when a data frame is | ||
70 | * available. | ||
71 | * i2400m_netdev_setup Called to setup all the netdev stuff from | ||
72 | * alloc_netdev. | ||
73 | */ | ||
74 | #include <linux/if_arp.h> | ||
75 | #include <linux/netdevice.h> | ||
76 | #include "i2400m.h" | ||
77 | |||
78 | |||
79 | #define D_SUBMODULE netdev | ||
80 | #include "debug-levels.h" | ||
81 | |||
82 | enum { | ||
83 | /* netdev interface */ | ||
84 | /* | ||
85 | * Out of NWG spec (R1_v1.2.2), 3.3.3 ASN Bearer Plane MTU Size | ||
86 | * | ||
87 | * The MTU is 1400 or less | ||
88 | */ | ||
89 | I2400M_MAX_MTU = 1400, | ||
90 | I2400M_TX_TIMEOUT = HZ, | ||
91 | I2400M_TX_QLEN = 5, | ||
92 | }; | ||
93 | |||
94 | |||
95 | static | ||
96 | int i2400m_open(struct net_device *net_dev) | ||
97 | { | ||
98 | int result; | ||
99 | struct i2400m *i2400m = net_dev_to_i2400m(net_dev); | ||
100 | struct device *dev = i2400m_dev(i2400m); | ||
101 | |||
102 | d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m); | ||
103 | if (i2400m->ready == 0) { | ||
104 | dev_err(dev, "Device is still initializing\n"); | ||
105 | result = -EBUSY; | ||
106 | } else | ||
107 | result = 0; | ||
108 | d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n", | ||
109 | net_dev, i2400m, result); | ||
110 | return result; | ||
111 | } | ||
112 | |||
113 | |||
114 | /* | ||
115 | * | ||
116 | * On kernel versions where cancel_work_sync() didn't return anything, | ||
117 | * we rely on wake_tx_skb() being non-NULL. | ||
118 | */ | ||
119 | static | ||
120 | int i2400m_stop(struct net_device *net_dev) | ||
121 | { | ||
122 | struct i2400m *i2400m = net_dev_to_i2400m(net_dev); | ||
123 | struct device *dev = i2400m_dev(i2400m); | ||
124 | |||
125 | d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m); | ||
126 | /* See i2400m_hard_start_xmit(), references are taken there | ||
127 | * and here we release them if the work was still | ||
128 | * pending. Note we can't differentiate work not pending vs | ||
129 | * never scheduled, so the NULL check does that. */ | ||
130 | if (cancel_work_sync(&i2400m->wake_tx_ws) == 0 | ||
131 | && i2400m->wake_tx_skb != NULL) { | ||
132 | unsigned long flags; | ||
133 | struct sk_buff *wake_tx_skb; | ||
134 | spin_lock_irqsave(&i2400m->tx_lock, flags); | ||
135 | wake_tx_skb = i2400m->wake_tx_skb; /* compat help */ | ||
136 | i2400m->wake_tx_skb = NULL; /* compat help */ | ||
137 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | ||
138 | i2400m_put(i2400m); | ||
139 | kfree_skb(wake_tx_skb); | ||
140 | } | ||
141 | d_fnend(3, dev, "(net_dev %p [i2400m %p]) = 0\n", net_dev, i2400m); | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | |||
146 | /* | ||
147 | * Wake up the device and transmit a held SKB, then restart the net queue | ||
148 | * | ||
149 | * When the device goes into basestation-idle mode, we need to tell it | ||
150 | * to exit that mode; it will negotiate with the base station, user | ||
151 | * space may have to intervene to rehandshake crypto and then tell us | ||
152 | * when it is ready to transmit the packet we have "queued". Still we | ||
153 | * need to give it sometime after it reports being ok. | ||
154 | * | ||
155 | * On error, there is not much we can do. If the error was on TX, we | ||
156 | * still wake the queue up to see if the next packet will be luckier. | ||
157 | * | ||
158 | * If _cmd_exit_idle() fails...well, it could be many things; most | ||
159 | * commonly it is that something else took the device out of IDLE mode | ||
160 | * (for example, the base station). In that case we get an -EILSEQ and | ||
161 | * we are just going to ignore that one. If the device is back to | ||
162 | * connected, then fine -- if it is someother state, the packet will | ||
163 | * be dropped anyway. | ||
164 | */ | ||
165 | void i2400m_wake_tx_work(struct work_struct *ws) | ||
166 | { | ||
167 | int result; | ||
168 | struct i2400m *i2400m = container_of(ws, struct i2400m, wake_tx_ws); | ||
169 | struct device *dev = i2400m_dev(i2400m); | ||
170 | struct sk_buff *skb = i2400m->wake_tx_skb; | ||
171 | unsigned long flags; | ||
172 | |||
173 | spin_lock_irqsave(&i2400m->tx_lock, flags); | ||
174 | skb = i2400m->wake_tx_skb; | ||
175 | i2400m->wake_tx_skb = NULL; | ||
176 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | ||
177 | |||
178 | d_fnstart(3, dev, "(ws %p i2400m %p skb %p)\n", ws, i2400m, skb); | ||
179 | result = -EINVAL; | ||
180 | if (skb == NULL) { | ||
181 | dev_err(dev, "WAKE&TX: skb dissapeared!\n"); | ||
182 | goto out_put; | ||
183 | } | ||
184 | result = i2400m_cmd_exit_idle(i2400m); | ||
185 | if (result == -EILSEQ) | ||
186 | result = 0; | ||
187 | if (result < 0) { | ||
188 | dev_err(dev, "WAKE&TX: device didn't get out of idle: " | ||
189 | "%d\n", result); | ||
190 | goto error; | ||
191 | } | ||
192 | result = wait_event_timeout(i2400m->state_wq, | ||
193 | i2400m->state != I2400M_SS_IDLE, 5 * HZ); | ||
194 | if (result == 0) | ||
195 | result = -ETIMEDOUT; | ||
196 | if (result < 0) { | ||
197 | dev_err(dev, "WAKE&TX: error waiting for device to exit IDLE: " | ||
198 | "%d\n", result); | ||
199 | goto error; | ||
200 | } | ||
201 | msleep(20); /* device still needs some time or it drops it */ | ||
202 | result = i2400m_tx(i2400m, skb->data, skb->len, I2400M_PT_DATA); | ||
203 | netif_wake_queue(i2400m->wimax_dev.net_dev); | ||
204 | error: | ||
205 | kfree_skb(skb); /* refcount transferred by _hard_start_xmit() */ | ||
206 | out_put: | ||
207 | i2400m_put(i2400m); | ||
208 | d_fnend(3, dev, "(ws %p i2400m %p skb %p) = void [%d]\n", | ||
209 | ws, i2400m, skb, result); | ||
210 | } | ||
211 | |||
212 | |||
213 | /* | ||
214 | * Prepare the data payload TX header | ||
215 | * | ||
216 | * The i2400m expects a 4 byte header in front of a data packet. | ||
217 | * | ||
218 | * Because we pretend to be an ethernet device, this packet comes with | ||
219 | * an ethernet header. Pull it and push our header. | ||
220 | */ | ||
221 | static | ||
222 | void i2400m_tx_prep_header(struct sk_buff *skb) | ||
223 | { | ||
224 | struct i2400m_pl_data_hdr *pl_hdr; | ||
225 | skb_pull(skb, ETH_HLEN); | ||
226 | pl_hdr = (struct i2400m_pl_data_hdr *) skb_push(skb, sizeof(*pl_hdr)); | ||
227 | pl_hdr->reserved = 0; | ||
228 | } | ||
229 | |||
230 | |||
231 | /* | ||
232 | * TX an skb to an idle device | ||
233 | * | ||
234 | * When the device is in basestation-idle mode, we need to wake it up | ||
235 | * and then TX. So we queue a work_struct for doing so. | ||
236 | * | ||
237 | * We need to get an extra ref for the skb (so it is not dropped), as | ||
238 | * well as be careful not to queue more than one request (won't help | ||
239 | * at all). If more than one request comes or there are errors, we | ||
240 | * just drop the packets (see i2400m_hard_start_xmit()). | ||
241 | */ | ||
242 | static | ||
243 | int i2400m_net_wake_tx(struct i2400m *i2400m, struct net_device *net_dev, | ||
244 | struct sk_buff *skb) | ||
245 | { | ||
246 | int result; | ||
247 | struct device *dev = i2400m_dev(i2400m); | ||
248 | unsigned long flags; | ||
249 | |||
250 | d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev); | ||
251 | if (net_ratelimit()) { | ||
252 | d_printf(3, dev, "WAKE&NETTX: " | ||
253 | "skb %p sending %d bytes to radio\n", | ||
254 | skb, skb->len); | ||
255 | d_dump(4, dev, skb->data, skb->len); | ||
256 | } | ||
257 | /* We hold a ref count for i2400m and skb, so when | ||
258 | * stopping() the device, we need to cancel that work | ||
259 | * and if pending, release those resources. */ | ||
260 | result = 0; | ||
261 | spin_lock_irqsave(&i2400m->tx_lock, flags); | ||
262 | if (!work_pending(&i2400m->wake_tx_ws)) { | ||
263 | netif_stop_queue(net_dev); | ||
264 | i2400m_get(i2400m); | ||
265 | i2400m->wake_tx_skb = skb_get(skb); /* transfer ref count */ | ||
266 | i2400m_tx_prep_header(skb); | ||
267 | result = schedule_work(&i2400m->wake_tx_ws); | ||
268 | WARN_ON(result == 0); | ||
269 | } | ||
270 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | ||
271 | if (result == 0) { | ||
272 | /* Yes, this happens even if we stopped the | ||
273 | * queue -- blame the queue disciplines that | ||
274 | * queue without looking -- I guess there is a reason | ||
275 | * for that. */ | ||
276 | if (net_ratelimit()) | ||
277 | d_printf(1, dev, "NETTX: device exiting idle, " | ||
278 | "dropping skb %p, queue running %d\n", | ||
279 | skb, netif_queue_stopped(net_dev)); | ||
280 | result = -EBUSY; | ||
281 | } | ||
282 | d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result); | ||
283 | return result; | ||
284 | } | ||
285 | |||
286 | |||
287 | /* | ||
288 | * Transmit a packet to the base station on behalf of the network stack. | ||
289 | * | ||
290 | * Returns: 0 if ok, < 0 errno code on error. | ||
291 | * | ||
292 | * We need to pull the ethernet header and add the hardware header, | ||
293 | * which is currently set to all zeroes and reserved. | ||
294 | */ | ||
295 | static | ||
296 | int i2400m_net_tx(struct i2400m *i2400m, struct net_device *net_dev, | ||
297 | struct sk_buff *skb) | ||
298 | { | ||
299 | int result; | ||
300 | struct device *dev = i2400m_dev(i2400m); | ||
301 | |||
302 | d_fnstart(3, dev, "(i2400m %p net_dev %p skb %p)\n", | ||
303 | i2400m, net_dev, skb); | ||
304 | /* FIXME: check eth hdr, only IPv4 is routed by the device as of now */ | ||
305 | net_dev->trans_start = jiffies; | ||
306 | i2400m_tx_prep_header(skb); | ||
307 | d_printf(3, dev, "NETTX: skb %p sending %d bytes to radio\n", | ||
308 | skb, skb->len); | ||
309 | d_dump(4, dev, skb->data, skb->len); | ||
310 | result = i2400m_tx(i2400m, skb->data, skb->len, I2400M_PT_DATA); | ||
311 | d_fnend(3, dev, "(i2400m %p net_dev %p skb %p) = %d\n", | ||
312 | i2400m, net_dev, skb, result); | ||
313 | return result; | ||
314 | } | ||
315 | |||
316 | |||
317 | /* | ||
318 | * Transmit a packet to the base station on behalf of the network stack | ||
319 | * | ||
320 | * | ||
321 | * Returns: NETDEV_TX_OK (always, even in case of error) | ||
322 | * | ||
323 | * In case of error, we just drop it. Reasons: | ||
324 | * | ||
325 | * - we add a hw header to each skb, and if the network stack | ||
326 | * retries, we have no way to know if that skb has it or not. | ||
327 | * | ||
328 | * - network protocols have their own drop-recovery mechanisms | ||
329 | * | ||
330 | * - there is not much else we can do | ||
331 | * | ||
332 | * If the device is idle, we need to wake it up; that is an operation | ||
333 | * that will sleep. See i2400m_net_wake_tx() for details. | ||
334 | */ | ||
335 | static | ||
336 | int i2400m_hard_start_xmit(struct sk_buff *skb, | ||
337 | struct net_device *net_dev) | ||
338 | { | ||
339 | int result; | ||
340 | struct i2400m *i2400m = net_dev_to_i2400m(net_dev); | ||
341 | struct device *dev = i2400m_dev(i2400m); | ||
342 | |||
343 | d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev); | ||
344 | if (i2400m->state == I2400M_SS_IDLE) | ||
345 | result = i2400m_net_wake_tx(i2400m, net_dev, skb); | ||
346 | else | ||
347 | result = i2400m_net_tx(i2400m, net_dev, skb); | ||
348 | if (result < 0) | ||
349 | net_dev->stats.tx_dropped++; | ||
350 | else { | ||
351 | net_dev->stats.tx_packets++; | ||
352 | net_dev->stats.tx_bytes += skb->len; | ||
353 | } | ||
354 | kfree_skb(skb); | ||
355 | result = NETDEV_TX_OK; | ||
356 | d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result); | ||
357 | return result; | ||
358 | } | ||
359 | |||
360 | |||
361 | static | ||
362 | int i2400m_change_mtu(struct net_device *net_dev, int new_mtu) | ||
363 | { | ||
364 | int result; | ||
365 | struct i2400m *i2400m = net_dev_to_i2400m(net_dev); | ||
366 | struct device *dev = i2400m_dev(i2400m); | ||
367 | |||
368 | if (new_mtu >= I2400M_MAX_MTU) { | ||
369 | dev_err(dev, "Cannot change MTU to %d (max is %d)\n", | ||
370 | new_mtu, I2400M_MAX_MTU); | ||
371 | result = -EINVAL; | ||
372 | } else { | ||
373 | net_dev->mtu = new_mtu; | ||
374 | result = 0; | ||
375 | } | ||
376 | return result; | ||
377 | } | ||
378 | |||
379 | |||
380 | static | ||
381 | void i2400m_tx_timeout(struct net_device *net_dev) | ||
382 | { | ||
383 | /* | ||
384 | * We might want to kick the device | ||
385 | * | ||
386 | * There is not much we can do though, as the device requires | ||
387 | * that we send the data aggregated. By the time we receive | ||
388 | * this, there might be data pending to be sent or not... | ||
389 | */ | ||
390 | net_dev->stats.tx_errors++; | ||
391 | return; | ||
392 | } | ||
393 | |||
394 | |||
395 | /* | ||
396 | * Create a fake ethernet header | ||
397 | * | ||
398 | * For emulating an ethernet device, every received IP header has to | ||
399 | * be prefixed with an ethernet header. | ||
400 | * | ||
401 | * What we receive has (potentially) many IP packets concatenated with | ||
402 | * no ETH_HLEN bytes prefixed. Thus there is no space for an eth | ||
403 | * header. | ||
404 | * | ||
405 | * We would have to reallocate or do ugly fragment tricks in order to | ||
406 | * add it. | ||
407 | * | ||
408 | * But what we do is use the header space of the RX transaction | ||
409 | * (*msg_hdr) as we don't need it anymore; then we'll point all the | ||
410 | * data skbs there, as they share the same backing store. | ||
411 | * | ||
412 | * We only support IPv4 for v3 firmware. | ||
413 | */ | ||
414 | static | ||
415 | void i2400m_rx_fake_eth_header(struct net_device *net_dev, | ||
416 | void *_eth_hdr) | ||
417 | { | ||
418 | struct ethhdr *eth_hdr = _eth_hdr; | ||
419 | |||
420 | memcpy(eth_hdr->h_dest, net_dev->dev_addr, sizeof(eth_hdr->h_dest)); | ||
421 | memset(eth_hdr->h_source, 0, sizeof(eth_hdr->h_dest)); | ||
422 | eth_hdr->h_proto = __constant_cpu_to_be16(ETH_P_IP); | ||
423 | } | ||
424 | |||
425 | |||
426 | /* | ||
427 | * i2400m_net_rx - pass a network packet to the stack | ||
428 | * | ||
429 | * @i2400m: device instance | ||
430 | * @skb_rx: the skb where the buffer pointed to by @buf is | ||
431 | * @i: 1 if payload is the only one | ||
432 | * @buf: pointer to the buffer containing the data | ||
433 | * @len: buffer's length | ||
434 | * | ||
435 | * We just clone the skb and set it up so that it's skb->data pointer | ||
436 | * points to "buf" and it's length. | ||
437 | * | ||
438 | * Note that if the payload is the last (or the only one) in a | ||
439 | * multi-payload message, we don't clone the SKB but just reuse it. | ||
440 | * | ||
441 | * This function is normally run from a thread context. However, we | ||
442 | * still use netif_rx() instead of netif_receive_skb() as was | ||
443 | * recommended in the mailing list. Reason is in some stress tests | ||
444 | * when sending/receiving a lot of data we seem to hit a softlock in | ||
445 | * the kernel's TCP implementation [aroudn tcp_delay_timer()]. Using | ||
446 | * netif_rx() took care of the issue. | ||
447 | * | ||
448 | * This is, of course, still open to do more research on why running | ||
449 | * with netif_receive_skb() hits this softlock. FIXME. | ||
450 | * | ||
451 | * FIXME: currently we don't do any efforts at distinguishing if what | ||
452 | * we got was an IPv4 or IPv6 header, to setup the protocol field | ||
453 | * correctly. | ||
454 | */ | ||
455 | void i2400m_net_rx(struct i2400m *i2400m, struct sk_buff *skb_rx, | ||
456 | unsigned i, const void *buf, int buf_len) | ||
457 | { | ||
458 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; | ||
459 | struct device *dev = i2400m_dev(i2400m); | ||
460 | struct sk_buff *skb; | ||
461 | |||
462 | d_fnstart(2, dev, "(i2400m %p buf %p buf_len %d)\n", | ||
463 | i2400m, buf, buf_len); | ||
464 | if (i) { | ||
465 | skb = skb_get(skb_rx); | ||
466 | d_printf(2, dev, "RX: reusing first payload skb %p\n", skb); | ||
467 | skb_pull(skb, buf - (void *) skb->data); | ||
468 | skb_trim(skb, (void *) skb_end_pointer(skb) - buf); | ||
469 | } else { | ||
470 | /* Yes, this is bad -- a lot of overhead -- see | ||
471 | * comments at the top of the file */ | ||
472 | skb = __netdev_alloc_skb(net_dev, buf_len, GFP_KERNEL); | ||
473 | if (skb == NULL) { | ||
474 | dev_err(dev, "NETRX: no memory to realloc skb\n"); | ||
475 | net_dev->stats.rx_dropped++; | ||
476 | goto error_skb_realloc; | ||
477 | } | ||
478 | memcpy(skb_put(skb, buf_len), buf, buf_len); | ||
479 | } | ||
480 | i2400m_rx_fake_eth_header(i2400m->wimax_dev.net_dev, | ||
481 | skb->data - ETH_HLEN); | ||
482 | skb_set_mac_header(skb, -ETH_HLEN); | ||
483 | skb->dev = i2400m->wimax_dev.net_dev; | ||
484 | skb->protocol = htons(ETH_P_IP); | ||
485 | net_dev->stats.rx_packets++; | ||
486 | net_dev->stats.rx_bytes += buf_len; | ||
487 | d_printf(3, dev, "NETRX: receiving %d bytes to network stack\n", | ||
488 | buf_len); | ||
489 | d_dump(4, dev, buf, buf_len); | ||
490 | netif_rx_ni(skb); /* see notes in function header */ | ||
491 | error_skb_realloc: | ||
492 | d_fnend(2, dev, "(i2400m %p buf %p buf_len %d) = void\n", | ||
493 | i2400m, buf, buf_len); | ||
494 | } | ||
495 | |||
496 | |||
497 | /** | ||
498 | * i2400m_netdev_setup - Setup setup @net_dev's i2400m private data | ||
499 | * | ||
500 | * Called by alloc_netdev() | ||
501 | */ | ||
502 | void i2400m_netdev_setup(struct net_device *net_dev) | ||
503 | { | ||
504 | d_fnstart(3, NULL, "(net_dev %p)\n", net_dev); | ||
505 | ether_setup(net_dev); | ||
506 | net_dev->mtu = I2400M_MAX_MTU; | ||
507 | net_dev->tx_queue_len = I2400M_TX_QLEN; | ||
508 | net_dev->features = | ||
509 | NETIF_F_VLAN_CHALLENGED | ||
510 | | NETIF_F_HIGHDMA; | ||
511 | net_dev->flags = | ||
512 | IFF_NOARP /* i2400m is apure IP device */ | ||
513 | & (~IFF_BROADCAST /* i2400m is P2P */ | ||
514 | & ~IFF_MULTICAST); | ||
515 | net_dev->watchdog_timeo = I2400M_TX_TIMEOUT; | ||
516 | net_dev->open = i2400m_open; | ||
517 | net_dev->stop = i2400m_stop; | ||
518 | net_dev->hard_start_xmit = i2400m_hard_start_xmit; | ||
519 | net_dev->change_mtu = i2400m_change_mtu; | ||
520 | net_dev->tx_timeout = i2400m_tx_timeout; | ||
521 | d_fnend(3, NULL, "(net_dev %p) = void\n", net_dev); | ||
522 | } | ||
523 | EXPORT_SYMBOL_GPL(i2400m_netdev_setup); | ||
524 | |||
diff --git a/drivers/net/wimax/i2400m/op-rfkill.c b/drivers/net/wimax/i2400m/op-rfkill.c new file mode 100644 index 000000000000..487ec58cea46 --- /dev/null +++ b/drivers/net/wimax/i2400m/op-rfkill.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Implement backend for the WiMAX stack rfkill support | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com> | ||
7 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License version | ||
11 | * 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301, USA. | ||
22 | * | ||
23 | * | ||
24 | * The WiMAX kernel stack integrates into RF-Kill and keeps the | ||
25 | * switches's status. We just need to: | ||
26 | * | ||
27 | * - report changes in the HW RF Kill switch [with | ||
28 | * wimax_rfkill_{sw,hw}_report(), which happens when we detect those | ||
29 | * indications coming through hardware reports]. We also do it on | ||
30 | * initialization to let the stack know the intial HW state. | ||
31 | * | ||
32 | * - implement indications from the stack to change the SW RF Kill | ||
33 | * switch (coming from sysfs, the wimax stack or user space). | ||
34 | */ | ||
35 | #include "i2400m.h" | ||
36 | #include <linux/wimax/i2400m.h> | ||
37 | |||
38 | |||
39 | |||
40 | #define D_SUBMODULE rfkill | ||
41 | #include "debug-levels.h" | ||
42 | |||
43 | /* | ||
44 | * Return true if the i2400m radio is in the requested wimax_rf_state state | ||
45 | * | ||
46 | */ | ||
47 | static | ||
48 | int i2400m_radio_is(struct i2400m *i2400m, enum wimax_rf_state state) | ||
49 | { | ||
50 | if (state == WIMAX_RF_OFF) | ||
51 | return i2400m->state == I2400M_SS_RF_OFF | ||
52 | || i2400m->state == I2400M_SS_RF_SHUTDOWN; | ||
53 | else if (state == WIMAX_RF_ON) | ||
54 | /* state == WIMAX_RF_ON */ | ||
55 | return i2400m->state != I2400M_SS_RF_OFF | ||
56 | && i2400m->state != I2400M_SS_RF_SHUTDOWN; | ||
57 | else | ||
58 | BUG(); | ||
59 | } | ||
60 | |||
61 | |||
62 | /* | ||
63 | * WiMAX stack operation: implement SW RFKill toggling | ||
64 | * | ||
65 | * @wimax_dev: device descriptor | ||
66 | * @skb: skb where the message has been received; skb->data is | ||
67 | * expected to point to the message payload. | ||
68 | * @genl_info: passed by the generic netlink layer | ||
69 | * | ||
70 | * Generic Netlink will call this function when a message is sent from | ||
71 | * userspace to change the software RF-Kill switch status. | ||
72 | * | ||
73 | * This function will set the device's sofware RF-Kill switch state to | ||
74 | * match what is requested. | ||
75 | * | ||
76 | * NOTE: the i2400m has a strict state machine; we can only set the | ||
77 | * RF-Kill switch when it is on, the HW RF-Kill is on and the | ||
78 | * device is initialized. So we ignore errors steaming from not | ||
79 | * being in the right state (-EILSEQ). | ||
80 | */ | ||
81 | int i2400m_op_rfkill_sw_toggle(struct wimax_dev *wimax_dev, | ||
82 | enum wimax_rf_state state) | ||
83 | { | ||
84 | int result; | ||
85 | struct i2400m *i2400m = wimax_dev_to_i2400m(wimax_dev); | ||
86 | struct device *dev = i2400m_dev(i2400m); | ||
87 | struct sk_buff *ack_skb; | ||
88 | struct { | ||
89 | struct i2400m_l3l4_hdr hdr; | ||
90 | struct i2400m_tlv_rf_operation sw_rf; | ||
91 | } __attribute__((packed)) *cmd; | ||
92 | char strerr[32]; | ||
93 | |||
94 | d_fnstart(4, dev, "(wimax_dev %p state %d)\n", wimax_dev, state); | ||
95 | |||
96 | result = -ENOMEM; | ||
97 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
98 | if (cmd == NULL) | ||
99 | goto error_alloc; | ||
100 | cmd->hdr.type = cpu_to_le16(I2400M_MT_CMD_RF_CONTROL); | ||
101 | cmd->hdr.length = sizeof(cmd->sw_rf); | ||
102 | cmd->hdr.version = cpu_to_le16(I2400M_L3L4_VERSION); | ||
103 | cmd->sw_rf.hdr.type = cpu_to_le16(I2400M_TLV_RF_OPERATION); | ||
104 | cmd->sw_rf.hdr.length = cpu_to_le16(sizeof(cmd->sw_rf.status)); | ||
105 | switch (state) { | ||
106 | case WIMAX_RF_OFF: /* RFKILL ON, radio OFF */ | ||
107 | cmd->sw_rf.status = cpu_to_le32(2); | ||
108 | break; | ||
109 | case WIMAX_RF_ON: /* RFKILL OFF, radio ON */ | ||
110 | cmd->sw_rf.status = cpu_to_le32(1); | ||
111 | break; | ||
112 | default: | ||
113 | BUG(); | ||
114 | } | ||
115 | |||
116 | ack_skb = i2400m_msg_to_dev(i2400m, cmd, sizeof(*cmd)); | ||
117 | result = PTR_ERR(ack_skb); | ||
118 | if (IS_ERR(ack_skb)) { | ||
119 | dev_err(dev, "Failed to issue 'RF Control' command: %d\n", | ||
120 | result); | ||
121 | goto error_msg_to_dev; | ||
122 | } | ||
123 | result = i2400m_msg_check_status(wimax_msg_data(ack_skb), | ||
124 | strerr, sizeof(strerr)); | ||
125 | if (result < 0) { | ||
126 | dev_err(dev, "'RF Control' (0x%04x) command failed: %d - %s\n", | ||
127 | I2400M_MT_CMD_RF_CONTROL, result, strerr); | ||
128 | goto error_cmd; | ||
129 | } | ||
130 | |||
131 | /* Now we wait for the state to change to RADIO_OFF or RADIO_ON */ | ||
132 | result = wait_event_timeout( | ||
133 | i2400m->state_wq, i2400m_radio_is(i2400m, state), | ||
134 | 5 * HZ); | ||
135 | if (result == 0) | ||
136 | result = -ETIMEDOUT; | ||
137 | if (result < 0) | ||
138 | dev_err(dev, "Error waiting for device to toggle RF state: " | ||
139 | "%d\n", result); | ||
140 | result = 0; | ||
141 | error_cmd: | ||
142 | kfree_skb(ack_skb); | ||
143 | error_msg_to_dev: | ||
144 | error_alloc: | ||
145 | d_fnend(4, dev, "(wimax_dev %p state %d) = %d\n", | ||
146 | wimax_dev, state, result); | ||
147 | return result; | ||
148 | } | ||
149 | |||
150 | |||
151 | /* | ||
152 | * Inform the WiMAX stack of changes in the RF Kill switches reported | ||
153 | * by the device | ||
154 | * | ||
155 | * @i2400m: device descriptor | ||
156 | * @rfss: TLV for RF Switches status; already validated | ||
157 | * | ||
158 | * NOTE: the reports on RF switch status cannot be trusted | ||
159 | * or used until the device is in a state of RADIO_OFF | ||
160 | * or greater. | ||
161 | */ | ||
162 | void i2400m_report_tlv_rf_switches_status( | ||
163 | struct i2400m *i2400m, | ||
164 | const struct i2400m_tlv_rf_switches_status *rfss) | ||
165 | { | ||
166 | struct device *dev = i2400m_dev(i2400m); | ||
167 | enum i2400m_rf_switch_status hw, sw; | ||
168 | enum wimax_st wimax_state; | ||
169 | |||
170 | sw = le32_to_cpu(rfss->sw_rf_switch); | ||
171 | hw = le32_to_cpu(rfss->hw_rf_switch); | ||
172 | |||
173 | d_fnstart(3, dev, "(i2400m %p rfss %p [hw %u sw %u])\n", | ||
174 | i2400m, rfss, hw, sw); | ||
175 | /* We only process rw switch evens when the device has been | ||
176 | * fully initialized */ | ||
177 | wimax_state = wimax_state_get(&i2400m->wimax_dev); | ||
178 | if (wimax_state < WIMAX_ST_RADIO_OFF) { | ||
179 | d_printf(3, dev, "ignoring RF switches report, state %u\n", | ||
180 | wimax_state); | ||
181 | goto out; | ||
182 | } | ||
183 | switch (sw) { | ||
184 | case I2400M_RF_SWITCH_ON: /* RF Kill disabled (radio on) */ | ||
185 | wimax_report_rfkill_sw(&i2400m->wimax_dev, WIMAX_RF_ON); | ||
186 | break; | ||
187 | case I2400M_RF_SWITCH_OFF: /* RF Kill enabled (radio off) */ | ||
188 | wimax_report_rfkill_sw(&i2400m->wimax_dev, WIMAX_RF_OFF); | ||
189 | break; | ||
190 | default: | ||
191 | dev_err(dev, "HW BUG? Unknown RF SW state 0x%x\n", sw); | ||
192 | } | ||
193 | |||
194 | switch (hw) { | ||
195 | case I2400M_RF_SWITCH_ON: /* RF Kill disabled (radio on) */ | ||
196 | wimax_report_rfkill_hw(&i2400m->wimax_dev, WIMAX_RF_ON); | ||
197 | break; | ||
198 | case I2400M_RF_SWITCH_OFF: /* RF Kill enabled (radio off) */ | ||
199 | wimax_report_rfkill_hw(&i2400m->wimax_dev, WIMAX_RF_OFF); | ||
200 | break; | ||
201 | default: | ||
202 | dev_err(dev, "HW BUG? Unknown RF HW state 0x%x\n", hw); | ||
203 | } | ||
204 | out: | ||
205 | d_fnend(3, dev, "(i2400m %p rfss %p [hw %u sw %u]) = void\n", | ||
206 | i2400m, rfss, hw, sw); | ||
207 | } | ||
diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c new file mode 100644 index 000000000000..6922022710ac --- /dev/null +++ b/drivers/net/wimax/i2400m/rx.c | |||
@@ -0,0 +1,534 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Handle incoming traffic and deliver it to the control or data planes | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
37 | * - Initial implementation | ||
38 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
39 | * - Use skb_clone(), break up processing in chunks | ||
40 | * - Split transport/device specific | ||
41 | * - Make buffer size dynamic to exert less memory pressure | ||
42 | * | ||
43 | * | ||
44 | * This handles the RX path. | ||
45 | * | ||
46 | * We receive an RX message from the bus-specific driver, which | ||
47 | * contains one or more payloads that have potentially different | ||
48 | * destinataries (data or control paths). | ||
49 | * | ||
50 | * So we just take that payload from the transport specific code in | ||
51 | * the form of an skb, break it up in chunks (a cloned skb each in the | ||
52 | * case of network packets) and pass it to netdev or to the | ||
53 | * command/ack handler (and from there to the WiMAX stack). | ||
54 | * | ||
55 | * PROTOCOL FORMAT | ||
56 | * | ||
57 | * The format of the buffer is: | ||
58 | * | ||
59 | * HEADER (struct i2400m_msg_hdr) | ||
60 | * PAYLOAD DESCRIPTOR 0 (struct i2400m_pld) | ||
61 | * PAYLOAD DESCRIPTOR 1 | ||
62 | * ... | ||
63 | * PAYLOAD DESCRIPTOR N | ||
64 | * PAYLOAD 0 (raw bytes) | ||
65 | * PAYLOAD 1 | ||
66 | * ... | ||
67 | * PAYLOAD N | ||
68 | * | ||
69 | * See tx.c for a deeper description on alignment requirements and | ||
70 | * other fun facts of it. | ||
71 | * | ||
72 | * ROADMAP | ||
73 | * | ||
74 | * i2400m_rx | ||
75 | * i2400m_rx_msg_hdr_check | ||
76 | * i2400m_rx_pl_descr_check | ||
77 | * i2400m_rx_payload | ||
78 | * i2400m_net_rx | ||
79 | * i2400m_rx_ctl | ||
80 | * i2400m_msg_size_check | ||
81 | * i2400m_report_hook_work [in a workqueue] | ||
82 | * i2400m_report_hook | ||
83 | * wimax_msg_to_user | ||
84 | * i2400m_rx_ctl_ack | ||
85 | * wimax_msg_to_user_alloc | ||
86 | * i2400m_rx_trace | ||
87 | * i2400m_msg_size_check | ||
88 | * wimax_msg | ||
89 | */ | ||
90 | #include <linux/kernel.h> | ||
91 | #include <linux/if_arp.h> | ||
92 | #include <linux/netdevice.h> | ||
93 | #include <linux/workqueue.h> | ||
94 | #include "i2400m.h" | ||
95 | |||
96 | |||
97 | #define D_SUBMODULE rx | ||
98 | #include "debug-levels.h" | ||
99 | |||
100 | struct i2400m_report_hook_args { | ||
101 | struct sk_buff *skb_rx; | ||
102 | const struct i2400m_l3l4_hdr *l3l4_hdr; | ||
103 | size_t size; | ||
104 | }; | ||
105 | |||
106 | |||
107 | /* | ||
108 | * Execute i2400m_report_hook in a workqueue | ||
109 | * | ||
110 | * Unpacks arguments from the deferred call, executes it and then | ||
111 | * drops the references. | ||
112 | * | ||
113 | * Obvious NOTE: References are needed because we are a separate | ||
114 | * thread; otherwise the buffer changes under us because it is | ||
115 | * released by the original caller. | ||
116 | */ | ||
117 | static | ||
118 | void i2400m_report_hook_work(struct work_struct *ws) | ||
119 | { | ||
120 | struct i2400m_work *iw = | ||
121 | container_of(ws, struct i2400m_work, ws); | ||
122 | struct i2400m_report_hook_args *args = (void *) iw->pl; | ||
123 | i2400m_report_hook(iw->i2400m, args->l3l4_hdr, args->size); | ||
124 | kfree_skb(args->skb_rx); | ||
125 | i2400m_put(iw->i2400m); | ||
126 | kfree(iw); | ||
127 | } | ||
128 | |||
129 | |||
130 | /* | ||
131 | * Process an ack to a command | ||
132 | * | ||
133 | * @i2400m: device descriptor | ||
134 | * @payload: pointer to message | ||
135 | * @size: size of the message | ||
136 | * | ||
137 | * Pass the acknodledgment (in an skb) to the thread that is waiting | ||
138 | * for it in i2400m->msg_completion. | ||
139 | * | ||
140 | * We need to coordinate properly with the thread waiting for the | ||
141 | * ack. Check if it is waiting or if it is gone. We loose the spinlock | ||
142 | * to avoid allocating on atomic contexts (yeah, could use GFP_ATOMIC, | ||
143 | * but this is not so speed critical). | ||
144 | */ | ||
145 | static | ||
146 | void i2400m_rx_ctl_ack(struct i2400m *i2400m, | ||
147 | const void *payload, size_t size) | ||
148 | { | ||
149 | struct device *dev = i2400m_dev(i2400m); | ||
150 | struct wimax_dev *wimax_dev = &i2400m->wimax_dev; | ||
151 | unsigned long flags; | ||
152 | struct sk_buff *ack_skb; | ||
153 | |||
154 | /* Anyone waiting for an answer? */ | ||
155 | spin_lock_irqsave(&i2400m->rx_lock, flags); | ||
156 | if (i2400m->ack_skb != ERR_PTR(-EINPROGRESS)) { | ||
157 | dev_err(dev, "Huh? reply to command with no waiters\n"); | ||
158 | goto error_no_waiter; | ||
159 | } | ||
160 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | ||
161 | |||
162 | ack_skb = wimax_msg_alloc(wimax_dev, NULL, payload, size, GFP_KERNEL); | ||
163 | |||
164 | /* Check waiter didn't time out waiting for the answer... */ | ||
165 | spin_lock_irqsave(&i2400m->rx_lock, flags); | ||
166 | if (i2400m->ack_skb != ERR_PTR(-EINPROGRESS)) { | ||
167 | d_printf(1, dev, "Huh? waiter for command reply cancelled\n"); | ||
168 | goto error_waiter_cancelled; | ||
169 | } | ||
170 | if (ack_skb == NULL) { | ||
171 | dev_err(dev, "CMD/GET/SET ack: cannot allocate SKB\n"); | ||
172 | i2400m->ack_skb = ERR_PTR(-ENOMEM); | ||
173 | } else | ||
174 | i2400m->ack_skb = ack_skb; | ||
175 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | ||
176 | complete(&i2400m->msg_completion); | ||
177 | return; | ||
178 | |||
179 | error_waiter_cancelled: | ||
180 | if (ack_skb) | ||
181 | kfree_skb(ack_skb); | ||
182 | error_no_waiter: | ||
183 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | |||
188 | /* | ||
189 | * Receive and process a control payload | ||
190 | * | ||
191 | * @i2400m: device descriptor | ||
192 | * @skb_rx: skb that contains the payload (for reference counting) | ||
193 | * @payload: pointer to message | ||
194 | * @size: size of the message | ||
195 | * | ||
196 | * There are two types of control RX messages: reports (asynchronous, | ||
197 | * like your every day interrupts) and 'acks' (reponses to a command, | ||
198 | * get or set request). | ||
199 | * | ||
200 | * If it is a report, we run hooks on it (to extract information for | ||
201 | * things we need to do in the driver) and then pass it over to the | ||
202 | * WiMAX stack to send it to user space. | ||
203 | * | ||
204 | * NOTE: report processing is done in a workqueue specific to the | ||
205 | * generic driver, to avoid deadlocks in the system. | ||
206 | * | ||
207 | * If it is not a report, it is an ack to a previously executed | ||
208 | * command, set or get, so wake up whoever is waiting for it from | ||
209 | * i2400m_msg_to_dev(). i2400m_rx_ctl_ack() takes care of that. | ||
210 | * | ||
211 | * Note that the sizes we pass to other functions from here are the | ||
212 | * sizes of the _l3l4_hdr + payload, not full buffer sizes, as we have | ||
213 | * verified in _msg_size_check() that they are congruent. | ||
214 | * | ||
215 | * For reports: We can't clone the original skb where the data is | ||
216 | * because we need to send this up via netlink; netlink has to add | ||
217 | * headers and we can't overwrite what's preceeding the payload...as | ||
218 | * it is another message. So we just dup them. | ||
219 | */ | ||
220 | static | ||
221 | void i2400m_rx_ctl(struct i2400m *i2400m, struct sk_buff *skb_rx, | ||
222 | const void *payload, size_t size) | ||
223 | { | ||
224 | int result; | ||
225 | struct device *dev = i2400m_dev(i2400m); | ||
226 | const struct i2400m_l3l4_hdr *l3l4_hdr = payload; | ||
227 | unsigned msg_type; | ||
228 | |||
229 | result = i2400m_msg_size_check(i2400m, l3l4_hdr, size); | ||
230 | if (result < 0) { | ||
231 | dev_err(dev, "HW BUG? device sent a bad message: %d\n", | ||
232 | result); | ||
233 | goto error_check; | ||
234 | } | ||
235 | msg_type = le16_to_cpu(l3l4_hdr->type); | ||
236 | d_printf(1, dev, "%s 0x%04x: %zu bytes\n", | ||
237 | msg_type & I2400M_MT_REPORT_MASK ? "REPORT" : "CMD/SET/GET", | ||
238 | msg_type, size); | ||
239 | d_dump(2, dev, l3l4_hdr, size); | ||
240 | if (msg_type & I2400M_MT_REPORT_MASK) { | ||
241 | /* These hooks have to be ran serialized; as well, the | ||
242 | * handling might force the execution of commands, and | ||
243 | * that might cause reentrancy issues with | ||
244 | * bus-specific subdrivers and workqueues. So we run | ||
245 | * it in a separate workqueue. */ | ||
246 | struct i2400m_report_hook_args args = { | ||
247 | .skb_rx = skb_rx, | ||
248 | .l3l4_hdr = l3l4_hdr, | ||
249 | .size = size | ||
250 | }; | ||
251 | if (unlikely(i2400m->ready == 0)) /* only send if up */ | ||
252 | return; | ||
253 | skb_get(skb_rx); | ||
254 | i2400m_queue_work(i2400m, i2400m_report_hook_work, | ||
255 | GFP_KERNEL, &args, sizeof(args)); | ||
256 | result = wimax_msg(&i2400m->wimax_dev, NULL, l3l4_hdr, size, | ||
257 | GFP_KERNEL); | ||
258 | if (result < 0) | ||
259 | dev_err(dev, "error sending report to userspace: %d\n", | ||
260 | result); | ||
261 | } else /* an ack to a CMD, GET or SET */ | ||
262 | i2400m_rx_ctl_ack(i2400m, payload, size); | ||
263 | error_check: | ||
264 | return; | ||
265 | } | ||
266 | |||
267 | |||
268 | |||
269 | |||
270 | /* | ||
271 | * Receive and send up a trace | ||
272 | * | ||
273 | * @i2400m: device descriptor | ||
274 | * @skb_rx: skb that contains the trace (for reference counting) | ||
275 | * @payload: pointer to trace message inside the skb | ||
276 | * @size: size of the message | ||
277 | * | ||
278 | * THe i2400m might produce trace information (diagnostics) and we | ||
279 | * send them through a different kernel-to-user pipe (to avoid | ||
280 | * clogging it). | ||
281 | * | ||
282 | * As in i2400m_rx_ctl(), we can't clone the original skb where the | ||
283 | * data is because we need to send this up via netlink; netlink has to | ||
284 | * add headers and we can't overwrite what's preceeding the | ||
285 | * payload...as it is another message. So we just dup them. | ||
286 | */ | ||
287 | static | ||
288 | void i2400m_rx_trace(struct i2400m *i2400m, | ||
289 | const void *payload, size_t size) | ||
290 | { | ||
291 | int result; | ||
292 | struct device *dev = i2400m_dev(i2400m); | ||
293 | struct wimax_dev *wimax_dev = &i2400m->wimax_dev; | ||
294 | const struct i2400m_l3l4_hdr *l3l4_hdr = payload; | ||
295 | unsigned msg_type; | ||
296 | |||
297 | result = i2400m_msg_size_check(i2400m, l3l4_hdr, size); | ||
298 | if (result < 0) { | ||
299 | dev_err(dev, "HW BUG? device sent a bad trace message: %d\n", | ||
300 | result); | ||
301 | goto error_check; | ||
302 | } | ||
303 | msg_type = le16_to_cpu(l3l4_hdr->type); | ||
304 | d_printf(1, dev, "Trace %s 0x%04x: %zu bytes\n", | ||
305 | msg_type & I2400M_MT_REPORT_MASK ? "REPORT" : "CMD/SET/GET", | ||
306 | msg_type, size); | ||
307 | d_dump(2, dev, l3l4_hdr, size); | ||
308 | if (unlikely(i2400m->ready == 0)) /* only send if up */ | ||
309 | return; | ||
310 | result = wimax_msg(wimax_dev, "trace", l3l4_hdr, size, GFP_KERNEL); | ||
311 | if (result < 0) | ||
312 | dev_err(dev, "error sending trace to userspace: %d\n", | ||
313 | result); | ||
314 | error_check: | ||
315 | return; | ||
316 | } | ||
317 | |||
318 | |||
319 | /* | ||
320 | * Act on a received payload | ||
321 | * | ||
322 | * @i2400m: device instance | ||
323 | * @skb_rx: skb where the transaction was received | ||
324 | * @single: 1 if there is only one payload, 0 otherwise | ||
325 | * @pld: payload descriptor | ||
326 | * @payload: payload data | ||
327 | * | ||
328 | * Upon reception of a payload, look at its guts in the payload | ||
329 | * descriptor and decide what to do with it. | ||
330 | */ | ||
331 | static | ||
332 | void i2400m_rx_payload(struct i2400m *i2400m, struct sk_buff *skb_rx, | ||
333 | unsigned single, const struct i2400m_pld *pld, | ||
334 | const void *payload) | ||
335 | { | ||
336 | struct device *dev = i2400m_dev(i2400m); | ||
337 | size_t pl_size = i2400m_pld_size(pld); | ||
338 | enum i2400m_pt pl_type = i2400m_pld_type(pld); | ||
339 | |||
340 | switch (pl_type) { | ||
341 | case I2400M_PT_DATA: | ||
342 | d_printf(3, dev, "RX: data payload %zu bytes\n", pl_size); | ||
343 | i2400m_net_rx(i2400m, skb_rx, single, payload, pl_size); | ||
344 | break; | ||
345 | case I2400M_PT_CTRL: | ||
346 | i2400m_rx_ctl(i2400m, skb_rx, payload, pl_size); | ||
347 | break; | ||
348 | case I2400M_PT_TRACE: | ||
349 | i2400m_rx_trace(i2400m, payload, pl_size); | ||
350 | break; | ||
351 | default: /* Anything else shouldn't come to the host */ | ||
352 | if (printk_ratelimit()) | ||
353 | dev_err(dev, "RX: HW BUG? unexpected payload type %u\n", | ||
354 | pl_type); | ||
355 | } | ||
356 | } | ||
357 | |||
358 | |||
359 | /* | ||
360 | * Check a received transaction's message header | ||
361 | * | ||
362 | * @i2400m: device descriptor | ||
363 | * @msg_hdr: message header | ||
364 | * @buf_size: size of the received buffer | ||
365 | * | ||
366 | * Check that the declarations done by a RX buffer message header are | ||
367 | * sane and consistent with the amount of data that was received. | ||
368 | */ | ||
369 | static | ||
370 | int i2400m_rx_msg_hdr_check(struct i2400m *i2400m, | ||
371 | const struct i2400m_msg_hdr *msg_hdr, | ||
372 | size_t buf_size) | ||
373 | { | ||
374 | int result = -EIO; | ||
375 | struct device *dev = i2400m_dev(i2400m); | ||
376 | if (buf_size < sizeof(*msg_hdr)) { | ||
377 | dev_err(dev, "RX: HW BUG? message with short header (%zu " | ||
378 | "vs %zu bytes expected)\n", buf_size, sizeof(*msg_hdr)); | ||
379 | goto error; | ||
380 | } | ||
381 | if (msg_hdr->barker != cpu_to_le32(I2400M_D2H_MSG_BARKER)) { | ||
382 | dev_err(dev, "RX: HW BUG? message received with unknown " | ||
383 | "barker 0x%08x (buf_size %zu bytes)\n", | ||
384 | le32_to_cpu(msg_hdr->barker), buf_size); | ||
385 | goto error; | ||
386 | } | ||
387 | if (msg_hdr->num_pls == 0) { | ||
388 | dev_err(dev, "RX: HW BUG? zero payload packets in message\n"); | ||
389 | goto error; | ||
390 | } | ||
391 | if (le16_to_cpu(msg_hdr->num_pls) > I2400M_MAX_PLS_IN_MSG) { | ||
392 | dev_err(dev, "RX: HW BUG? message contains more payload " | ||
393 | "than maximum; ignoring.\n"); | ||
394 | goto error; | ||
395 | } | ||
396 | result = 0; | ||
397 | error: | ||
398 | return result; | ||
399 | } | ||
400 | |||
401 | |||
402 | /* | ||
403 | * Check a payload descriptor against the received data | ||
404 | * | ||
405 | * @i2400m: device descriptor | ||
406 | * @pld: payload descriptor | ||
407 | * @pl_itr: offset (in bytes) in the received buffer the payload is | ||
408 | * located | ||
409 | * @buf_size: size of the received buffer | ||
410 | * | ||
411 | * Given a payload descriptor (part of a RX buffer), check it is sane | ||
412 | * and that the data it declares fits in the buffer. | ||
413 | */ | ||
414 | static | ||
415 | int i2400m_rx_pl_descr_check(struct i2400m *i2400m, | ||
416 | const struct i2400m_pld *pld, | ||
417 | size_t pl_itr, size_t buf_size) | ||
418 | { | ||
419 | int result = -EIO; | ||
420 | struct device *dev = i2400m_dev(i2400m); | ||
421 | size_t pl_size = i2400m_pld_size(pld); | ||
422 | enum i2400m_pt pl_type = i2400m_pld_type(pld); | ||
423 | |||
424 | if (pl_size > i2400m->bus_pl_size_max) { | ||
425 | dev_err(dev, "RX: HW BUG? payload @%zu: size %zu is " | ||
426 | "bigger than maximum %zu; ignoring message\n", | ||
427 | pl_itr, pl_size, i2400m->bus_pl_size_max); | ||
428 | goto error; | ||
429 | } | ||
430 | if (pl_itr + pl_size > buf_size) { /* enough? */ | ||
431 | dev_err(dev, "RX: HW BUG? payload @%zu: size %zu " | ||
432 | "goes beyond the received buffer " | ||
433 | "size (%zu bytes); ignoring message\n", | ||
434 | pl_itr, pl_size, buf_size); | ||
435 | goto error; | ||
436 | } | ||
437 | if (pl_type >= I2400M_PT_ILLEGAL) { | ||
438 | dev_err(dev, "RX: HW BUG? illegal payload type %u; " | ||
439 | "ignoring message\n", pl_type); | ||
440 | goto error; | ||
441 | } | ||
442 | result = 0; | ||
443 | error: | ||
444 | return result; | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
449 | * i2400m_rx - Receive a buffer of data from the device | ||
450 | * | ||
451 | * @i2400m: device descriptor | ||
452 | * @skb: skbuff where the data has been received | ||
453 | * | ||
454 | * Parse in a buffer of data that contains an RX message sent from the | ||
455 | * device. See the file header for the format. Run all checks on the | ||
456 | * buffer header, then run over each payload's descriptors, verify | ||
457 | * their consistency and act on each payload's contents. If | ||
458 | * everything is succesful, update the device's statistics. | ||
459 | * | ||
460 | * Note: You need to set the skb to contain only the length of the | ||
461 | * received buffer; for that, use skb_trim(skb, RECEIVED_SIZE). | ||
462 | * | ||
463 | * Returns: | ||
464 | * | ||
465 | * 0 if ok, < 0 errno on error | ||
466 | * | ||
467 | * If ok, this function owns now the skb and the caller DOESN'T have | ||
468 | * to run kfree_skb() on it. However, on error, the caller still owns | ||
469 | * the skb and it is responsible for releasing it. | ||
470 | */ | ||
471 | int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) | ||
472 | { | ||
473 | int i, result; | ||
474 | struct device *dev = i2400m_dev(i2400m); | ||
475 | const struct i2400m_msg_hdr *msg_hdr; | ||
476 | size_t pl_itr, pl_size, skb_len; | ||
477 | unsigned long flags; | ||
478 | unsigned num_pls; | ||
479 | |||
480 | skb_len = skb->len; | ||
481 | d_fnstart(4, dev, "(i2400m %p skb %p [size %zu])\n", | ||
482 | i2400m, skb, skb_len); | ||
483 | result = -EIO; | ||
484 | msg_hdr = (void *) skb->data; | ||
485 | result = i2400m_rx_msg_hdr_check(i2400m, msg_hdr, skb->len); | ||
486 | if (result < 0) | ||
487 | goto error_msg_hdr_check; | ||
488 | result = -EIO; | ||
489 | num_pls = le16_to_cpu(msg_hdr->num_pls); | ||
490 | pl_itr = sizeof(*msg_hdr) + /* Check payload descriptor(s) */ | ||
491 | num_pls * sizeof(msg_hdr->pld[0]); | ||
492 | pl_itr = ALIGN(pl_itr, I2400M_PL_PAD); | ||
493 | if (pl_itr > skb->len) { /* got all the payload descriptors? */ | ||
494 | dev_err(dev, "RX: HW BUG? message too short (%u bytes) for " | ||
495 | "%u payload descriptors (%zu each, total %zu)\n", | ||
496 | skb->len, num_pls, sizeof(msg_hdr->pld[0]), pl_itr); | ||
497 | goto error_pl_descr_short; | ||
498 | } | ||
499 | /* Walk each payload payload--check we really got it */ | ||
500 | for (i = 0; i < num_pls; i++) { | ||
501 | /* work around old gcc warnings */ | ||
502 | pl_size = i2400m_pld_size(&msg_hdr->pld[i]); | ||
503 | result = i2400m_rx_pl_descr_check(i2400m, &msg_hdr->pld[i], | ||
504 | pl_itr, skb->len); | ||
505 | if (result < 0) | ||
506 | goto error_pl_descr_check; | ||
507 | i2400m_rx_payload(i2400m, skb, num_pls == 1, &msg_hdr->pld[i], | ||
508 | skb->data + pl_itr); | ||
509 | pl_itr += ALIGN(pl_size, I2400M_PL_PAD); | ||
510 | cond_resched(); /* Don't monopolize */ | ||
511 | } | ||
512 | kfree_skb(skb); | ||
513 | /* Update device statistics */ | ||
514 | spin_lock_irqsave(&i2400m->rx_lock, flags); | ||
515 | i2400m->rx_pl_num += i; | ||
516 | if (i > i2400m->rx_pl_max) | ||
517 | i2400m->rx_pl_max = i; | ||
518 | if (i < i2400m->rx_pl_min) | ||
519 | i2400m->rx_pl_min = i; | ||
520 | i2400m->rx_num++; | ||
521 | i2400m->rx_size_acc += skb->len; | ||
522 | if (skb->len < i2400m->rx_size_min) | ||
523 | i2400m->rx_size_min = skb->len; | ||
524 | if (skb->len > i2400m->rx_size_max) | ||
525 | i2400m->rx_size_max = skb->len; | ||
526 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | ||
527 | error_pl_descr_check: | ||
528 | error_pl_descr_short: | ||
529 | error_msg_hdr_check: | ||
530 | d_fnend(4, dev, "(i2400m %p skb %p [size %zu]) = %d\n", | ||
531 | i2400m, skb, skb_len, result); | ||
532 | return result; | ||
533 | } | ||
534 | EXPORT_SYMBOL_GPL(i2400m_rx); | ||
diff --git a/drivers/net/wimax/i2400m/sdio-debug-levels.h b/drivers/net/wimax/i2400m/sdio-debug-levels.h new file mode 100644 index 000000000000..c51998741301 --- /dev/null +++ b/drivers/net/wimax/i2400m/sdio-debug-levels.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * debug levels control file for the i2400m module's | ||
3 | */ | ||
4 | #ifndef __debug_levels__h__ | ||
5 | #define __debug_levels__h__ | ||
6 | |||
7 | /* Maximum compile and run time debug level for all submodules */ | ||
8 | #define D_MODULENAME i2400m_sdio | ||
9 | #define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL | ||
10 | |||
11 | #include <linux/wimax/debug.h> | ||
12 | |||
13 | /* List of all the enabled modules */ | ||
14 | enum d_module { | ||
15 | D_SUBMODULE_DECLARE(main), | ||
16 | D_SUBMODULE_DECLARE(tx), | ||
17 | D_SUBMODULE_DECLARE(rx), | ||
18 | D_SUBMODULE_DECLARE(fw) | ||
19 | }; | ||
20 | |||
21 | |||
22 | #endif /* #ifndef __debug_levels__h__ */ | ||
diff --git a/drivers/net/wimax/i2400m/sdio-fw.c b/drivers/net/wimax/i2400m/sdio-fw.c new file mode 100644 index 000000000000..3487205d8f50 --- /dev/null +++ b/drivers/net/wimax/i2400m/sdio-fw.c | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Firmware uploader's SDIO specifics | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
37 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
38 | * - Initial implementation | ||
39 | * | ||
40 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
41 | * - Bus generic/specific split for USB | ||
42 | * | ||
43 | * Dirk Brandewie <dirk.j.brandewie@intel.com> | ||
44 | * - Initial implementation for SDIO | ||
45 | * | ||
46 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
47 | * - SDIO rehash for changes in the bus-driver model | ||
48 | * | ||
49 | * THE PROCEDURE | ||
50 | * | ||
51 | * See fw.c for the generic description of this procedure. | ||
52 | * | ||
53 | * This file implements only the SDIO specifics. It boils down to how | ||
54 | * to send a command and waiting for an acknowledgement from the | ||
55 | * device. We do polled reads. | ||
56 | * | ||
57 | * COMMAND EXECUTION | ||
58 | * | ||
59 | * THe generic firmware upload code will call i2400m_bus_bm_cmd_send() | ||
60 | * to send commands. | ||
61 | * | ||
62 | * The SDIO devices expects things in 256 byte blocks, so it will pad | ||
63 | * it, compute the checksum (if needed) and pass it to SDIO. | ||
64 | * | ||
65 | * ACK RECEPTION | ||
66 | * | ||
67 | * This works in polling mode -- the fw loader says when to wait for | ||
68 | * data and for that it calls i2400ms_bus_bm_wait_for_ack(). | ||
69 | * | ||
70 | * This will poll the device for data until it is received. We need to | ||
71 | * receive at least as much bytes as where asked for (although it'll | ||
72 | * always be a multiple of 256 bytes). | ||
73 | */ | ||
74 | #include <linux/mmc/sdio_func.h> | ||
75 | #include "i2400m-sdio.h" | ||
76 | |||
77 | |||
78 | #define D_SUBMODULE fw | ||
79 | #include "sdio-debug-levels.h" | ||
80 | |||
81 | /* | ||
82 | * Send a boot-mode command to the SDIO function | ||
83 | * | ||
84 | * We use a bounce buffer (i2400m->bm_cmd_buf) because we need to | ||
85 | * touch the header if the RAW flag is not set. | ||
86 | * | ||
87 | * @flags: pass thru from i2400m_bm_cmd() | ||
88 | * @return: cmd_size if ok, < 0 errno code on error. | ||
89 | * | ||
90 | * Note the command is padded to the SDIO block size for the device. | ||
91 | */ | ||
92 | ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m, | ||
93 | const struct i2400m_bootrom_header *_cmd, | ||
94 | size_t cmd_size, int flags) | ||
95 | { | ||
96 | ssize_t result; | ||
97 | struct device *dev = i2400m_dev(i2400m); | ||
98 | struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); | ||
99 | int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd); | ||
100 | struct i2400m_bootrom_header *cmd; | ||
101 | /* SDIO restriction */ | ||
102 | size_t cmd_size_a = ALIGN(cmd_size, I2400MS_BLK_SIZE); | ||
103 | |||
104 | d_fnstart(5, dev, "(i2400m %p cmd %p size %zu)\n", | ||
105 | i2400m, _cmd, cmd_size); | ||
106 | result = -E2BIG; | ||
107 | if (cmd_size > I2400M_BM_CMD_BUF_SIZE) | ||
108 | goto error_too_big; | ||
109 | |||
110 | memcpy(i2400m->bm_cmd_buf, _cmd, cmd_size); /* Prep command */ | ||
111 | cmd = i2400m->bm_cmd_buf; | ||
112 | if (cmd_size_a > cmd_size) /* Zero pad space */ | ||
113 | memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size); | ||
114 | if ((flags & I2400M_BM_CMD_RAW) == 0) { | ||
115 | if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0)) | ||
116 | dev_warn(dev, "SW BUG: response_required == 0\n"); | ||
117 | i2400m_bm_cmd_prepare(cmd); | ||
118 | } | ||
119 | d_printf(4, dev, "BM cmd %d: %zu bytes (%zu padded)\n", | ||
120 | opcode, cmd_size, cmd_size_a); | ||
121 | d_dump(5, dev, cmd, cmd_size); | ||
122 | |||
123 | sdio_claim_host(i2400ms->func); /* Send & check */ | ||
124 | result = sdio_memcpy_toio(i2400ms->func, I2400MS_DATA_ADDR, | ||
125 | i2400m->bm_cmd_buf, cmd_size_a); | ||
126 | sdio_release_host(i2400ms->func); | ||
127 | if (result < 0) { | ||
128 | dev_err(dev, "BM cmd %d: cannot send: %ld\n", | ||
129 | opcode, (long) result); | ||
130 | goto error_cmd_send; | ||
131 | } | ||
132 | result = cmd_size; | ||
133 | error_cmd_send: | ||
134 | error_too_big: | ||
135 | d_fnend(5, dev, "(i2400m %p cmd %p size %zu) = %d\n", | ||
136 | i2400m, _cmd, cmd_size, (int) result); | ||
137 | return result; | ||
138 | } | ||
139 | |||
140 | |||
141 | /* | ||
142 | * Read an ack from the device's boot-mode (polling) | ||
143 | * | ||
144 | * @i2400m: | ||
145 | * @_ack: pointer to where to store the read data | ||
146 | * @ack_size: how many bytes we should read | ||
147 | * | ||
148 | * Returns: < 0 errno code on error; otherwise, amount of received bytes. | ||
149 | * | ||
150 | * The ACK for a BM command is always at least sizeof(*ack) bytes, so | ||
151 | * check for that. We don't need to check for device reboots | ||
152 | * | ||
153 | * NOTE: We do an artificial timeout of 1 sec over the SDIO timeout; | ||
154 | * this way we have control over it...there is no way that I know | ||
155 | * of setting an SDIO transaction timeout. | ||
156 | */ | ||
157 | ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m, | ||
158 | struct i2400m_bootrom_header *ack, | ||
159 | size_t ack_size) | ||
160 | { | ||
161 | int result; | ||
162 | ssize_t rx_size; | ||
163 | u64 timeout; | ||
164 | struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); | ||
165 | struct sdio_func *func = i2400ms->func; | ||
166 | struct device *dev = &func->dev; | ||
167 | |||
168 | BUG_ON(sizeof(*ack) > ack_size); | ||
169 | |||
170 | d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n", | ||
171 | i2400m, ack, ack_size); | ||
172 | |||
173 | timeout = get_jiffies_64() + 2 * HZ; | ||
174 | sdio_claim_host(func); | ||
175 | while (1) { | ||
176 | if (time_after64(get_jiffies_64(), timeout)) { | ||
177 | rx_size = -ETIMEDOUT; | ||
178 | dev_err(dev, "timeout waiting for ack data\n"); | ||
179 | goto error_timedout; | ||
180 | } | ||
181 | |||
182 | /* Find the RX size, check if it fits or not -- it if | ||
183 | * doesn't fit, fail, as we have no way to dispose of | ||
184 | * the extra data. */ | ||
185 | rx_size = __i2400ms_rx_get_size(i2400ms); | ||
186 | if (rx_size < 0) | ||
187 | goto error_rx_get_size; | ||
188 | result = -ENOSPC; /* Check it fits */ | ||
189 | if (rx_size < sizeof(*ack)) { | ||
190 | rx_size = -EIO; | ||
191 | dev_err(dev, "HW BUG? received is too small (%zu vs " | ||
192 | "%zu needed)\n", sizeof(*ack), rx_size); | ||
193 | goto error_too_small; | ||
194 | } | ||
195 | if (rx_size > I2400M_BM_ACK_BUF_SIZE) { | ||
196 | dev_err(dev, "SW BUG? BM_ACK_BUF is too small (%u vs " | ||
197 | "%zu needed)\n", I2400M_BM_ACK_BUF_SIZE, | ||
198 | rx_size); | ||
199 | goto error_too_small; | ||
200 | } | ||
201 | |||
202 | /* Read it */ | ||
203 | result = sdio_memcpy_fromio(func, i2400m->bm_ack_buf, | ||
204 | I2400MS_DATA_ADDR, rx_size); | ||
205 | if (result == -ETIMEDOUT || result == -ETIME) | ||
206 | continue; | ||
207 | if (result < 0) { | ||
208 | dev_err(dev, "BM SDIO receive (%zu B) failed: %d\n", | ||
209 | rx_size, result); | ||
210 | goto error_read; | ||
211 | } else | ||
212 | break; | ||
213 | } | ||
214 | rx_size = min((ssize_t)ack_size, rx_size); | ||
215 | memcpy(ack, i2400m->bm_ack_buf, rx_size); | ||
216 | error_read: | ||
217 | error_too_small: | ||
218 | error_rx_get_size: | ||
219 | error_timedout: | ||
220 | sdio_release_host(func); | ||
221 | d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %ld\n", | ||
222 | i2400m, ack, ack_size, (long) rx_size); | ||
223 | return rx_size; | ||
224 | } | ||
diff --git a/drivers/net/wimax/i2400m/sdio-rx.c b/drivers/net/wimax/i2400m/sdio-rx.c new file mode 100644 index 000000000000..a3008b904f7d --- /dev/null +++ b/drivers/net/wimax/i2400m/sdio-rx.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * SDIO RX handling | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Dirk Brandewie <dirk.j.brandewie@intel.com> | ||
37 | * - Initial implementation | ||
38 | * | ||
39 | * | ||
40 | * This handles the RX path on SDIO. | ||
41 | * | ||
42 | * The SDIO bus driver calls the "irq" routine when data is available. | ||
43 | * This is not a traditional interrupt routine since the SDIO bus | ||
44 | * driver calls us from its irq thread context. Because of this | ||
45 | * sleeping in the SDIO RX IRQ routine is okay. | ||
46 | * | ||
47 | * From there on, we obtain the size of the data that is available, | ||
48 | * allocate an skb, copy it and then pass it to the generic driver's | ||
49 | * RX routine [i2400m_rx()]. | ||
50 | * | ||
51 | * ROADMAP | ||
52 | * | ||
53 | * i2400ms_irq() | ||
54 | * i2400ms_rx() | ||
55 | * __i2400ms_rx_get_size() | ||
56 | * i2400m_rx() | ||
57 | * | ||
58 | * i2400ms_rx_setup() | ||
59 | * | ||
60 | * i2400ms_rx_release() | ||
61 | */ | ||
62 | #include <linux/workqueue.h> | ||
63 | #include <linux/wait.h> | ||
64 | #include <linux/skbuff.h> | ||
65 | #include <linux/mmc/sdio.h> | ||
66 | #include <linux/mmc/sdio_func.h> | ||
67 | #include "i2400m-sdio.h" | ||
68 | |||
69 | #define D_SUBMODULE rx | ||
70 | #include "sdio-debug-levels.h" | ||
71 | |||
72 | |||
73 | /* | ||
74 | * Read and return the amount of bytes available for RX | ||
75 | * | ||
76 | * The RX size has to be read like this: byte reads of three | ||
77 | * sequential locations; then glue'em together. | ||
78 | * | ||
79 | * sdio_readl() doesn't work. | ||
80 | */ | ||
81 | ssize_t __i2400ms_rx_get_size(struct i2400ms *i2400ms) | ||
82 | { | ||
83 | int ret, cnt, val; | ||
84 | ssize_t rx_size; | ||
85 | unsigned xfer_size_addr; | ||
86 | struct sdio_func *func = i2400ms->func; | ||
87 | struct device *dev = &i2400ms->func->dev; | ||
88 | |||
89 | d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms); | ||
90 | xfer_size_addr = I2400MS_INTR_GET_SIZE_ADDR; | ||
91 | rx_size = 0; | ||
92 | for (cnt = 0; cnt < 3; cnt++) { | ||
93 | val = sdio_readb(func, xfer_size_addr + cnt, &ret); | ||
94 | if (ret < 0) { | ||
95 | dev_err(dev, "RX: Can't read byte %d of RX size from " | ||
96 | "0x%08x: %d\n", cnt, xfer_size_addr + cnt, ret); | ||
97 | rx_size = ret; | ||
98 | goto error_read; | ||
99 | } | ||
100 | rx_size = rx_size << 8 | (val & 0xff); | ||
101 | } | ||
102 | d_printf(6, dev, "RX: rx_size is %ld\n", (long) rx_size); | ||
103 | error_read: | ||
104 | d_fnend(7, dev, "(i2400ms %p) = %ld\n", i2400ms, (long) rx_size); | ||
105 | return rx_size; | ||
106 | } | ||
107 | |||
108 | |||
109 | /* | ||
110 | * Read data from the device (when in normal) | ||
111 | * | ||
112 | * Allocate an SKB of the right size, read the data in and then | ||
113 | * deliver it to the generic layer. | ||
114 | * | ||
115 | * We also check for a reboot barker. That means the device died and | ||
116 | * we have to reboot it. | ||
117 | */ | ||
118 | static | ||
119 | void i2400ms_rx(struct i2400ms *i2400ms) | ||
120 | { | ||
121 | int ret; | ||
122 | struct sdio_func *func = i2400ms->func; | ||
123 | struct device *dev = &func->dev; | ||
124 | struct i2400m *i2400m = &i2400ms->i2400m; | ||
125 | struct sk_buff *skb; | ||
126 | ssize_t rx_size; | ||
127 | |||
128 | d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms); | ||
129 | rx_size = __i2400ms_rx_get_size(i2400ms); | ||
130 | if (rx_size < 0) { | ||
131 | ret = rx_size; | ||
132 | goto error_get_size; | ||
133 | } | ||
134 | ret = -ENOMEM; | ||
135 | skb = alloc_skb(rx_size, GFP_ATOMIC); | ||
136 | if (NULL == skb) { | ||
137 | dev_err(dev, "RX: unable to alloc skb\n"); | ||
138 | goto error_alloc_skb; | ||
139 | } | ||
140 | |||
141 | ret = sdio_memcpy_fromio(func, skb->data, | ||
142 | I2400MS_DATA_ADDR, rx_size); | ||
143 | if (ret < 0) { | ||
144 | dev_err(dev, "RX: SDIO data read failed: %d\n", ret); | ||
145 | goto error_memcpy_fromio; | ||
146 | } | ||
147 | /* Check if device has reset */ | ||
148 | if (!memcmp(skb->data, i2400m_NBOOT_BARKER, | ||
149 | sizeof(i2400m_NBOOT_BARKER)) | ||
150 | || !memcmp(skb->data, i2400m_SBOOT_BARKER, | ||
151 | sizeof(i2400m_SBOOT_BARKER))) { | ||
152 | ret = i2400m_dev_reset_handle(i2400m); | ||
153 | kfree_skb(skb); | ||
154 | } else { | ||
155 | skb_put(skb, rx_size); | ||
156 | i2400m_rx(i2400m, skb); | ||
157 | } | ||
158 | d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms); | ||
159 | return; | ||
160 | |||
161 | error_memcpy_fromio: | ||
162 | kfree_skb(skb); | ||
163 | error_alloc_skb: | ||
164 | error_get_size: | ||
165 | d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret); | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | |||
170 | /* | ||
171 | * Process an interrupt from the SDIO card | ||
172 | * | ||
173 | * FIXME: need to process other events that are not just ready-to-read | ||
174 | * | ||
175 | * Checks there is data ready and then proceeds to read it. | ||
176 | */ | ||
177 | static | ||
178 | void i2400ms_irq(struct sdio_func *func) | ||
179 | { | ||
180 | int ret; | ||
181 | struct i2400ms *i2400ms = sdio_get_drvdata(func); | ||
182 | struct i2400m *i2400m = &i2400ms->i2400m; | ||
183 | struct device *dev = &func->dev; | ||
184 | int val; | ||
185 | |||
186 | d_fnstart(6, dev, "(i2400ms %p)\n", i2400ms); | ||
187 | val = sdio_readb(func, I2400MS_INTR_STATUS_ADDR, &ret); | ||
188 | if (ret < 0) { | ||
189 | dev_err(dev, "RX: Can't read interrupt status: %d\n", ret); | ||
190 | goto error_no_irq; | ||
191 | } | ||
192 | if (!val) { | ||
193 | dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n"); | ||
194 | goto error_no_irq; | ||
195 | } | ||
196 | sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret); | ||
197 | if (WARN_ON(i2400m->boot_mode != 0)) | ||
198 | dev_err(dev, "RX: SW BUG? boot mode and IRQ is up?\n"); | ||
199 | else | ||
200 | i2400ms_rx(i2400ms); | ||
201 | error_no_irq: | ||
202 | d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms); | ||
203 | return; | ||
204 | } | ||
205 | |||
206 | |||
207 | /* | ||
208 | * Setup SDIO RX | ||
209 | * | ||
210 | * Hooks up the IRQ handler and then enables IRQs. | ||
211 | */ | ||
212 | int i2400ms_rx_setup(struct i2400ms *i2400ms) | ||
213 | { | ||
214 | int result; | ||
215 | struct sdio_func *func = i2400ms->func; | ||
216 | struct device *dev = &func->dev; | ||
217 | |||
218 | d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); | ||
219 | sdio_claim_host(func); | ||
220 | result = sdio_claim_irq(func, i2400ms_irq); | ||
221 | if (result < 0) { | ||
222 | dev_err(dev, "Cannot claim IRQ: %d\n", result); | ||
223 | goto error_irq_claim; | ||
224 | } | ||
225 | result = 0; | ||
226 | sdio_writeb(func, 1, I2400MS_INTR_ENABLE_ADDR, &result); | ||
227 | if (result < 0) { | ||
228 | sdio_release_irq(func); | ||
229 | dev_err(dev, "Failed to enable interrupts %d\n", result); | ||
230 | } | ||
231 | error_irq_claim: | ||
232 | sdio_release_host(func); | ||
233 | d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); | ||
234 | return result; | ||
235 | } | ||
236 | |||
237 | |||
238 | /* | ||
239 | * Tear down SDIO RX | ||
240 | * | ||
241 | * Disables IRQs in the device and removes the IRQ handler. | ||
242 | */ | ||
243 | void i2400ms_rx_release(struct i2400ms *i2400ms) | ||
244 | { | ||
245 | int result; | ||
246 | struct sdio_func *func = i2400ms->func; | ||
247 | struct device *dev = &func->dev; | ||
248 | |||
249 | d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); | ||
250 | sdio_claim_host(func); | ||
251 | sdio_writeb(func, 0, I2400MS_INTR_ENABLE_ADDR, &result); | ||
252 | sdio_release_irq(func); | ||
253 | sdio_release_host(func); | ||
254 | d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); | ||
255 | } | ||
diff --git a/drivers/net/wimax/i2400m/sdio-tx.c b/drivers/net/wimax/i2400m/sdio-tx.c new file mode 100644 index 000000000000..5105a5ebc44f --- /dev/null +++ b/drivers/net/wimax/i2400m/sdio-tx.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * SDIO TX transaction backends | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Dirk Brandewie <dirk.j.brandewie@intel.com> | ||
37 | * - Initial implementation | ||
38 | * | ||
39 | * | ||
40 | * Takes the TX messages in the i2400m's driver TX FIFO and sends them | ||
41 | * to the device until there are no more. | ||
42 | * | ||
43 | * If we fail sending the message, we just drop it. There isn't much | ||
44 | * we can do at this point. Most of the traffic is network, which has | ||
45 | * recovery methods for dropped packets. | ||
46 | * | ||
47 | * The SDIO functions are not atomic, so we can't run from the context | ||
48 | * where i2400m->bus_tx_kick() [i2400ms_bus_tx_kick()] is being called | ||
49 | * (some times atomic). Thus, the actual TX work is deferred to a | ||
50 | * workqueue. | ||
51 | * | ||
52 | * ROADMAP | ||
53 | * | ||
54 | * i2400ms_bus_tx_kick() | ||
55 | * i2400ms_tx_submit() [through workqueue] | ||
56 | * | ||
57 | * i2400m_tx_setup() | ||
58 | * | ||
59 | * i2400m_tx_release() | ||
60 | */ | ||
61 | #include <linux/mmc/sdio_func.h> | ||
62 | #include "i2400m-sdio.h" | ||
63 | |||
64 | #define D_SUBMODULE tx | ||
65 | #include "sdio-debug-levels.h" | ||
66 | |||
67 | |||
68 | /* | ||
69 | * Pull TX transations from the TX FIFO and send them to the device | ||
70 | * until there are no more. | ||
71 | */ | ||
72 | static | ||
73 | void i2400ms_tx_submit(struct work_struct *ws) | ||
74 | { | ||
75 | int result; | ||
76 | struct i2400ms *i2400ms = container_of(ws, struct i2400ms, tx_worker); | ||
77 | struct i2400m *i2400m = &i2400ms->i2400m; | ||
78 | struct sdio_func *func = i2400ms->func; | ||
79 | struct device *dev = &func->dev; | ||
80 | struct i2400m_msg_hdr *tx_msg; | ||
81 | size_t tx_msg_size; | ||
82 | |||
83 | d_fnstart(4, dev, "(i2400ms %p, i2400m %p)\n", i2400ms, i2400ms); | ||
84 | |||
85 | while (NULL != (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size))) { | ||
86 | d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size); | ||
87 | d_dump(5, dev, tx_msg, tx_msg_size); | ||
88 | |||
89 | sdio_claim_host(func); | ||
90 | result = sdio_memcpy_toio(func, 0, tx_msg, tx_msg_size); | ||
91 | sdio_release_host(func); | ||
92 | |||
93 | i2400m_tx_msg_sent(i2400m); | ||
94 | |||
95 | if (result < 0) { | ||
96 | dev_err(dev, "TX: cannot submit TX; tx_msg @%zu %zu B:" | ||
97 | " %d\n", (void *) tx_msg - i2400m->tx_buf, | ||
98 | tx_msg_size, result); | ||
99 | } | ||
100 | |||
101 | d_printf(2, dev, "TX: %zub submitted\n", tx_msg_size); | ||
102 | } | ||
103 | |||
104 | d_fnend(4, dev, "(i2400ms %p) = void\n", i2400ms); | ||
105 | } | ||
106 | |||
107 | |||
108 | /* | ||
109 | * The generic driver notifies us that there is data ready for TX | ||
110 | * | ||
111 | * Schedule a run of i2400ms_tx_submit() to handle it. | ||
112 | */ | ||
113 | void i2400ms_bus_tx_kick(struct i2400m *i2400m) | ||
114 | { | ||
115 | struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); | ||
116 | struct device *dev = &i2400ms->func->dev; | ||
117 | |||
118 | d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m); | ||
119 | |||
120 | /* schedule tx work, this is because tx may block, therefore | ||
121 | * it has to run in a thread context. | ||
122 | */ | ||
123 | queue_work(i2400ms->tx_workqueue, &i2400ms->tx_worker); | ||
124 | |||
125 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | ||
126 | } | ||
127 | |||
128 | int i2400ms_tx_setup(struct i2400ms *i2400ms) | ||
129 | { | ||
130 | int result; | ||
131 | struct device *dev = &i2400ms->func->dev; | ||
132 | struct i2400m *i2400m = &i2400ms->i2400m; | ||
133 | |||
134 | d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); | ||
135 | |||
136 | INIT_WORK(&i2400ms->tx_worker, i2400ms_tx_submit); | ||
137 | snprintf(i2400ms->tx_wq_name, sizeof(i2400ms->tx_wq_name), | ||
138 | "%s-tx", i2400m->wimax_dev.name); | ||
139 | i2400ms->tx_workqueue = | ||
140 | create_singlethread_workqueue(i2400ms->tx_wq_name); | ||
141 | if (NULL == i2400ms->tx_workqueue) { | ||
142 | dev_err(dev, "TX: failed to create workqueue\n"); | ||
143 | result = -ENOMEM; | ||
144 | } else | ||
145 | result = 0; | ||
146 | d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); | ||
147 | return result; | ||
148 | } | ||
149 | |||
150 | void i2400ms_tx_release(struct i2400ms *i2400ms) | ||
151 | { | ||
152 | destroy_workqueue(i2400ms->tx_workqueue); | ||
153 | } | ||
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c new file mode 100644 index 000000000000..1bfa283bbd8a --- /dev/null +++ b/drivers/net/wimax/i2400m/sdio.c | |||
@@ -0,0 +1,511 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Linux driver model glue for the SDIO device, reset & fw upload | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com> | ||
7 | * Dirk Brandewie <dirk.j.brandewie@intel.com> | ||
8 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
9 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License version | ||
13 | * 2 as published by the Free Software Foundation. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
23 | * 02110-1301, USA. | ||
24 | * | ||
25 | * | ||
26 | * See i2400m-sdio.h for a general description of this driver. | ||
27 | * | ||
28 | * This file implements driver model glue, and hook ups for the | ||
29 | * generic driver to implement the bus-specific functions (device | ||
30 | * communication setup/tear down, firmware upload and resetting). | ||
31 | * | ||
32 | * ROADMAP | ||
33 | * | ||
34 | * i2400m_probe() | ||
35 | * alloc_netdev() | ||
36 | * i2400ms_netdev_setup() | ||
37 | * i2400ms_init() | ||
38 | * i2400m_netdev_setup() | ||
39 | * i2400ms_enable_function() | ||
40 | * i2400m_setup() | ||
41 | * | ||
42 | * i2400m_remove() | ||
43 | * i2400m_release() | ||
44 | * free_netdev(net_dev) | ||
45 | * | ||
46 | * i2400ms_bus_reset() Called by i2400m->bus_reset | ||
47 | * __i2400ms_reset() | ||
48 | * __i2400ms_send_barker() | ||
49 | * | ||
50 | * i2400ms_bus_dev_start() Called by i2400m_dev_start() [who is | ||
51 | * i2400ms_tx_setup() called by i2400m_setup()] | ||
52 | * i2400ms_rx_setup() | ||
53 | * | ||
54 | * i2400ms_bus_dev_stop() Called by i2400m_dev_stop() [who is | ||
55 | * i2400ms_rx_release() is called by i2400m_release()] | ||
56 | * i2400ms_tx_release() | ||
57 | * | ||
58 | */ | ||
59 | |||
60 | #include <linux/debugfs.h> | ||
61 | #include <linux/mmc/sdio.h> | ||
62 | #include <linux/mmc/sdio_func.h> | ||
63 | #include "i2400m-sdio.h" | ||
64 | #include <linux/wimax/i2400m.h> | ||
65 | |||
66 | #define D_SUBMODULE main | ||
67 | #include "sdio-debug-levels.h" | ||
68 | |||
69 | /* IOE WiMAX function timeout in seconds */ | ||
70 | static int ioe_timeout = 2; | ||
71 | module_param(ioe_timeout, int, 0); | ||
72 | |||
73 | /* Our firmware file name */ | ||
74 | #define I2400MS_FW_FILE_NAME "i2400m-fw-sdio-" I2400M_FW_VERSION ".sbcf" | ||
75 | |||
76 | /* | ||
77 | * Enable the SDIO function | ||
78 | * | ||
79 | * Tries to enable the SDIO function; might fail if it is still not | ||
80 | * ready (in some hardware, the SDIO WiMAX function is only enabled | ||
81 | * when we ask it to explicitly doing). Tries until a timeout is | ||
82 | * reached. | ||
83 | * | ||
84 | * The reverse of this is...sdio_disable_function() | ||
85 | * | ||
86 | * Returns: 0 if the SDIO function was enabled, < 0 errno code on | ||
87 | * error (-ENODEV when it was unable to enable the function). | ||
88 | */ | ||
89 | static | ||
90 | int i2400ms_enable_function(struct sdio_func *func) | ||
91 | { | ||
92 | u64 timeout; | ||
93 | int err; | ||
94 | struct device *dev = &func->dev; | ||
95 | |||
96 | d_fnstart(3, dev, "(func %p)\n", func); | ||
97 | /* Setup timeout (FIXME: This needs to read the CIS table to | ||
98 | * get a real timeout) and then wait for the device to signal | ||
99 | * it is ready */ | ||
100 | timeout = get_jiffies_64() + ioe_timeout * HZ; | ||
101 | err = -ENODEV; | ||
102 | while (err != 0 && time_before64(get_jiffies_64(), timeout)) { | ||
103 | sdio_claim_host(func); | ||
104 | err = sdio_enable_func(func); | ||
105 | if (0 == err) { | ||
106 | sdio_release_host(func); | ||
107 | d_printf(2, dev, "SDIO function enabled\n"); | ||
108 | goto function_enabled; | ||
109 | } | ||
110 | d_printf(2, dev, "SDIO function failed to enable: %d\n", err); | ||
111 | sdio_disable_func(func); | ||
112 | sdio_release_host(func); | ||
113 | msleep(I2400MS_INIT_SLEEP_INTERVAL); | ||
114 | } | ||
115 | /* If timed out, device is not there yet -- get -ENODEV so | ||
116 | * the device driver core will retry later on. */ | ||
117 | if (err == -ETIME) { | ||
118 | dev_err(dev, "Can't enable WiMAX function; " | ||
119 | " has the function been enabled?\n"); | ||
120 | err = -ENODEV; | ||
121 | } | ||
122 | function_enabled: | ||
123 | d_fnend(3, dev, "(func %p) = %d\n", func, err); | ||
124 | return err; | ||
125 | } | ||
126 | |||
127 | |||
128 | /* | ||
129 | * Setup driver resources needed to communicate with the device | ||
130 | * | ||
131 | * The fw needs some time to settle, and it was just uploaded, | ||
132 | * so give it a break first. I'd prefer to just wait for the device to | ||
133 | * send something, but seems the poking we do to enable SDIO stuff | ||
134 | * interferes with it, so just give it a break before starting... | ||
135 | */ | ||
136 | static | ||
137 | int i2400ms_bus_dev_start(struct i2400m *i2400m) | ||
138 | { | ||
139 | int result; | ||
140 | struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); | ||
141 | struct sdio_func *func = i2400ms->func; | ||
142 | struct device *dev = &func->dev; | ||
143 | |||
144 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
145 | msleep(200); | ||
146 | result = i2400ms_rx_setup(i2400ms); | ||
147 | if (result < 0) | ||
148 | goto error_rx_setup; | ||
149 | result = i2400ms_tx_setup(i2400ms); | ||
150 | if (result < 0) | ||
151 | goto error_tx_setup; | ||
152 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); | ||
153 | return result; | ||
154 | |||
155 | i2400ms_tx_release(i2400ms); | ||
156 | error_tx_setup: | ||
157 | i2400ms_rx_release(i2400ms); | ||
158 | error_rx_setup: | ||
159 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | ||
160 | return result; | ||
161 | } | ||
162 | |||
163 | |||
164 | static | ||
165 | void i2400ms_bus_dev_stop(struct i2400m *i2400m) | ||
166 | { | ||
167 | struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); | ||
168 | struct sdio_func *func = i2400ms->func; | ||
169 | struct device *dev = &func->dev; | ||
170 | |||
171 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
172 | i2400ms_rx_release(i2400ms); | ||
173 | i2400ms_tx_release(i2400ms); | ||
174 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | ||
175 | } | ||
176 | |||
177 | |||
178 | /* | ||
179 | * Sends a barker buffer to the device | ||
180 | * | ||
181 | * This helper will allocate a kmalloced buffer and use it to transmit | ||
182 | * (then free it). Reason for this is that the SDIO host controller | ||
183 | * expects alignment (unknown exactly which) which the stack won't | ||
184 | * really provide and certain arches/host-controller combinations | ||
185 | * cannot use stack/vmalloc/text areas for DMA transfers. | ||
186 | */ | ||
187 | static | ||
188 | int __i2400ms_send_barker(struct i2400ms *i2400ms, | ||
189 | const __le32 *barker, size_t barker_size) | ||
190 | { | ||
191 | int ret; | ||
192 | struct sdio_func *func = i2400ms->func; | ||
193 | struct device *dev = &func->dev; | ||
194 | void *buffer; | ||
195 | |||
196 | ret = -ENOMEM; | ||
197 | buffer = kmalloc(I2400MS_BLK_SIZE, GFP_KERNEL); | ||
198 | if (buffer == NULL) | ||
199 | goto error_kzalloc; | ||
200 | |||
201 | memcpy(buffer, barker, barker_size); | ||
202 | sdio_claim_host(func); | ||
203 | ret = sdio_memcpy_toio(func, 0, buffer, I2400MS_BLK_SIZE); | ||
204 | sdio_release_host(func); | ||
205 | |||
206 | if (ret < 0) | ||
207 | d_printf(0, dev, "E: barker error: %d\n", ret); | ||
208 | |||
209 | kfree(buffer); | ||
210 | error_kzalloc: | ||
211 | return ret; | ||
212 | } | ||
213 | |||
214 | |||
215 | /* | ||
216 | * Reset a device at different levels (warm, cold or bus) | ||
217 | * | ||
218 | * @i2400ms: device descriptor | ||
219 | * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS) | ||
220 | * | ||
221 | * FIXME: not tested -- need to confirm expected effects | ||
222 | * | ||
223 | * Warm and cold resets get an SDIO reset if they fail (unimplemented) | ||
224 | * | ||
225 | * Warm reset: | ||
226 | * | ||
227 | * The device will be fully reset internally, but won't be | ||
228 | * disconnected from the USB bus (so no reenumeration will | ||
229 | * happen). Firmware upload will be neccessary. | ||
230 | * | ||
231 | * The device will send a reboot barker in the notification endpoint | ||
232 | * that will trigger the driver to reinitialize the state | ||
233 | * automatically from notif.c:i2400m_notification_grok() into | ||
234 | * i2400m_dev_bootstrap_delayed(). | ||
235 | * | ||
236 | * Cold and bus (USB) reset: | ||
237 | * | ||
238 | * The device will be fully reset internally, disconnected from the | ||
239 | * USB bus an a reenumeration will happen. Firmware upload will be | ||
240 | * neccessary. Thus, we don't do any locking or struct | ||
241 | * reinitialization, as we are going to be fully disconnected and | ||
242 | * reenumerated. | ||
243 | * | ||
244 | * Note we need to return -ENODEV if a warm reset was requested and we | ||
245 | * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset() | ||
246 | * and wimax_dev->op_reset. | ||
247 | * | ||
248 | * WARNING: no driver state saved/fixed | ||
249 | */ | ||
250 | static | ||
251 | int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) | ||
252 | { | ||
253 | int result; | ||
254 | struct i2400ms *i2400ms = | ||
255 | container_of(i2400m, struct i2400ms, i2400m); | ||
256 | struct device *dev = i2400m_dev(i2400m); | ||
257 | static const __le32 i2400m_WARM_BOOT_BARKER[4] = { | ||
258 | __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), | ||
259 | __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), | ||
260 | __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), | ||
261 | __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), | ||
262 | }; | ||
263 | static const __le32 i2400m_COLD_BOOT_BARKER[4] = { | ||
264 | __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), | ||
265 | __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), | ||
266 | __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), | ||
267 | __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), | ||
268 | }; | ||
269 | |||
270 | if (rt == I2400M_RT_WARM) | ||
271 | result = __i2400ms_send_barker(i2400ms, i2400m_WARM_BOOT_BARKER, | ||
272 | sizeof(i2400m_WARM_BOOT_BARKER)); | ||
273 | else if (rt == I2400M_RT_COLD) | ||
274 | result = __i2400ms_send_barker(i2400ms, i2400m_COLD_BOOT_BARKER, | ||
275 | sizeof(i2400m_COLD_BOOT_BARKER)); | ||
276 | else if (rt == I2400M_RT_BUS) { | ||
277 | do_bus_reset: | ||
278 | dev_err(dev, "FIXME: SDIO bus reset not implemented\n"); | ||
279 | result = rt == I2400M_RT_WARM ? -ENODEV : -ENOSYS; | ||
280 | } else | ||
281 | BUG(); | ||
282 | if (result < 0 && rt != I2400M_RT_BUS) { | ||
283 | dev_err(dev, "%s reset failed (%d); trying SDIO reset\n", | ||
284 | rt == I2400M_RT_WARM ? "warm" : "cold", result); | ||
285 | rt = I2400M_RT_BUS; | ||
286 | goto do_bus_reset; | ||
287 | } | ||
288 | return result; | ||
289 | } | ||
290 | |||
291 | |||
292 | static | ||
293 | void i2400ms_netdev_setup(struct net_device *net_dev) | ||
294 | { | ||
295 | struct i2400m *i2400m = net_dev_to_i2400m(net_dev); | ||
296 | struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); | ||
297 | i2400ms_init(i2400ms); | ||
298 | i2400m_netdev_setup(net_dev); | ||
299 | } | ||
300 | |||
301 | |||
302 | /* | ||
303 | * Debug levels control; see debug.h | ||
304 | */ | ||
305 | struct d_level D_LEVEL[] = { | ||
306 | D_SUBMODULE_DEFINE(main), | ||
307 | D_SUBMODULE_DEFINE(tx), | ||
308 | D_SUBMODULE_DEFINE(rx), | ||
309 | D_SUBMODULE_DEFINE(fw), | ||
310 | }; | ||
311 | size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); | ||
312 | |||
313 | |||
314 | #define __debugfs_register(prefix, name, parent) \ | ||
315 | do { \ | ||
316 | result = d_level_register_debugfs(prefix, name, parent); \ | ||
317 | if (result < 0) \ | ||
318 | goto error; \ | ||
319 | } while (0) | ||
320 | |||
321 | |||
322 | static | ||
323 | int i2400ms_debugfs_add(struct i2400ms *i2400ms) | ||
324 | { | ||
325 | int result; | ||
326 | struct dentry *dentry = i2400ms->i2400m.wimax_dev.debugfs_dentry; | ||
327 | |||
328 | dentry = debugfs_create_dir("i2400m-usb", dentry); | ||
329 | result = PTR_ERR(dentry); | ||
330 | if (IS_ERR(dentry)) { | ||
331 | if (result == -ENODEV) | ||
332 | result = 0; /* No debugfs support */ | ||
333 | goto error; | ||
334 | } | ||
335 | i2400ms->debugfs_dentry = dentry; | ||
336 | __debugfs_register("dl_", main, dentry); | ||
337 | __debugfs_register("dl_", tx, dentry); | ||
338 | __debugfs_register("dl_", rx, dentry); | ||
339 | __debugfs_register("dl_", fw, dentry); | ||
340 | |||
341 | return 0; | ||
342 | |||
343 | error: | ||
344 | debugfs_remove_recursive(i2400ms->debugfs_dentry); | ||
345 | return result; | ||
346 | } | ||
347 | |||
348 | |||
349 | /* | ||
350 | * Probe a i2400m interface and register it | ||
351 | * | ||
352 | * @func: SDIO function | ||
353 | * @id: SDIO device ID | ||
354 | * @returns: 0 if ok, < 0 errno code on error. | ||
355 | * | ||
356 | * Alloc a net device, initialize the bus-specific details and then | ||
357 | * calls the bus-generic initialization routine. That will register | ||
358 | * the wimax and netdev devices, upload the firmware [using | ||
359 | * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the | ||
360 | * communication with the device and then will start to talk to it to | ||
361 | * finnish setting it up. | ||
362 | * | ||
363 | * Initialization is tricky; some instances of the hw are packed with | ||
364 | * others in a way that requires a third driver that enables the WiMAX | ||
365 | * function. In those cases, we can't enable the SDIO function and | ||
366 | * we'll return with -ENODEV. When the driver that enables the WiMAX | ||
367 | * function does its thing, it has to do a bus_rescan_devices() on the | ||
368 | * SDIO bus so this driver is called again to enumerate the WiMAX | ||
369 | * function. | ||
370 | */ | ||
371 | static | ||
372 | int i2400ms_probe(struct sdio_func *func, | ||
373 | const struct sdio_device_id *id) | ||
374 | { | ||
375 | int result; | ||
376 | struct net_device *net_dev; | ||
377 | struct device *dev = &func->dev; | ||
378 | struct i2400m *i2400m; | ||
379 | struct i2400ms *i2400ms; | ||
380 | |||
381 | /* Allocate instance [calls i2400m_netdev_setup() on it]. */ | ||
382 | result = -ENOMEM; | ||
383 | net_dev = alloc_netdev(sizeof(*i2400ms), "wmx%d", | ||
384 | i2400ms_netdev_setup); | ||
385 | if (net_dev == NULL) { | ||
386 | dev_err(dev, "no memory for network device instance\n"); | ||
387 | goto error_alloc_netdev; | ||
388 | } | ||
389 | SET_NETDEV_DEV(net_dev, dev); | ||
390 | i2400m = net_dev_to_i2400m(net_dev); | ||
391 | i2400ms = container_of(i2400m, struct i2400ms, i2400m); | ||
392 | i2400m->wimax_dev.net_dev = net_dev; | ||
393 | i2400ms->func = func; | ||
394 | sdio_set_drvdata(func, i2400ms); | ||
395 | |||
396 | i2400m->bus_tx_block_size = I2400MS_BLK_SIZE; | ||
397 | i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX; | ||
398 | i2400m->bus_dev_start = i2400ms_bus_dev_start; | ||
399 | i2400m->bus_dev_stop = i2400ms_bus_dev_stop; | ||
400 | i2400m->bus_tx_kick = i2400ms_bus_tx_kick; | ||
401 | i2400m->bus_reset = i2400ms_bus_reset; | ||
402 | i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send; | ||
403 | i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; | ||
404 | i2400m->bus_fw_name = I2400MS_FW_FILE_NAME; | ||
405 | i2400m->bus_bm_mac_addr_impaired = 1; | ||
406 | |||
407 | result = i2400ms_enable_function(i2400ms->func); | ||
408 | if (result < 0) { | ||
409 | dev_err(dev, "Cannot enable SDIO function: %d\n", result); | ||
410 | goto error_func_enable; | ||
411 | } | ||
412 | |||
413 | sdio_claim_host(func); | ||
414 | result = sdio_set_block_size(func, I2400MS_BLK_SIZE); | ||
415 | if (result < 0) { | ||
416 | dev_err(dev, "Failed to set block size: %d\n", result); | ||
417 | goto error_set_blk_size; | ||
418 | } | ||
419 | sdio_release_host(func); | ||
420 | |||
421 | result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT); | ||
422 | if (result < 0) { | ||
423 | dev_err(dev, "cannot setup device: %d\n", result); | ||
424 | goto error_setup; | ||
425 | } | ||
426 | |||
427 | result = i2400ms_debugfs_add(i2400ms); | ||
428 | if (result < 0) { | ||
429 | dev_err(dev, "cannot create SDIO debugfs: %d\n", | ||
430 | result); | ||
431 | goto error_debugfs_add; | ||
432 | } | ||
433 | return 0; | ||
434 | |||
435 | error_debugfs_add: | ||
436 | i2400m_release(i2400m); | ||
437 | error_setup: | ||
438 | sdio_set_drvdata(func, NULL); | ||
439 | sdio_claim_host(func); | ||
440 | error_set_blk_size: | ||
441 | sdio_disable_func(func); | ||
442 | sdio_release_host(func); | ||
443 | error_func_enable: | ||
444 | free_netdev(net_dev); | ||
445 | error_alloc_netdev: | ||
446 | return result; | ||
447 | } | ||
448 | |||
449 | |||
450 | static | ||
451 | void i2400ms_remove(struct sdio_func *func) | ||
452 | { | ||
453 | struct device *dev = &func->dev; | ||
454 | struct i2400ms *i2400ms = sdio_get_drvdata(func); | ||
455 | struct i2400m *i2400m = &i2400ms->i2400m; | ||
456 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; | ||
457 | |||
458 | d_fnstart(3, dev, "SDIO func %p\n", func); | ||
459 | debugfs_remove_recursive(i2400ms->debugfs_dentry); | ||
460 | i2400m_release(i2400m); | ||
461 | sdio_set_drvdata(func, NULL); | ||
462 | sdio_claim_host(func); | ||
463 | sdio_disable_func(func); | ||
464 | sdio_release_host(func); | ||
465 | free_netdev(net_dev); | ||
466 | d_fnend(3, dev, "SDIO func %p\n", func); | ||
467 | } | ||
468 | |||
469 | enum { | ||
470 | I2400MS_INTEL_VID = 0x89, | ||
471 | }; | ||
472 | |||
473 | static | ||
474 | const struct sdio_device_id i2400ms_sdio_ids[] = { | ||
475 | /* Intel: i2400m WiMAX over SDIO */ | ||
476 | { SDIO_DEVICE(I2400MS_INTEL_VID, 0x1402) }, | ||
477 | { }, /* end: all zeroes */ | ||
478 | }; | ||
479 | MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids); | ||
480 | |||
481 | |||
482 | static | ||
483 | struct sdio_driver i2400m_sdio_driver = { | ||
484 | .name = KBUILD_MODNAME, | ||
485 | .probe = i2400ms_probe, | ||
486 | .remove = i2400ms_remove, | ||
487 | .id_table = i2400ms_sdio_ids, | ||
488 | }; | ||
489 | |||
490 | |||
491 | static | ||
492 | int __init i2400ms_driver_init(void) | ||
493 | { | ||
494 | return sdio_register_driver(&i2400m_sdio_driver); | ||
495 | } | ||
496 | module_init(i2400ms_driver_init); | ||
497 | |||
498 | |||
499 | static | ||
500 | void __exit i2400ms_driver_exit(void) | ||
501 | { | ||
502 | flush_scheduled_work(); /* for the stuff we schedule */ | ||
503 | sdio_unregister_driver(&i2400m_sdio_driver); | ||
504 | } | ||
505 | module_exit(i2400ms_driver_exit); | ||
506 | |||
507 | |||
508 | MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>"); | ||
509 | MODULE_DESCRIPTION("Intel 2400M WiMAX networking for SDIO"); | ||
510 | MODULE_LICENSE("GPL"); | ||
511 | MODULE_FIRMWARE(I2400MS_FW_FILE_NAME); | ||
diff --git a/drivers/net/wimax/i2400m/tx.c b/drivers/net/wimax/i2400m/tx.c new file mode 100644 index 000000000000..613a88ffd651 --- /dev/null +++ b/drivers/net/wimax/i2400m/tx.c | |||
@@ -0,0 +1,817 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Generic (non-bus specific) TX handling | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
37 | * - Initial implementation | ||
38 | * | ||
39 | * Intel Corporation <linux-wimax@intel.com> | ||
40 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
41 | * - Rewritten to use a single FIFO to lower the memory allocation | ||
42 | * pressure and optimize cache hits when copying to the queue, as | ||
43 | * well as splitting out bus-specific code. | ||
44 | * | ||
45 | * | ||
46 | * Implements data transmission to the device; this is done through a | ||
47 | * software FIFO, as data/control frames can be coalesced (while the | ||
48 | * device is reading the previous tx transaction, others accumulate). | ||
49 | * | ||
50 | * A FIFO is used because at the end it is resource-cheaper that trying | ||
51 | * to implement scatter/gather over USB. As well, most traffic is going | ||
52 | * to be download (vs upload). | ||
53 | * | ||
54 | * The format for sending/receiving data to/from the i2400m is | ||
55 | * described in detail in rx.c:PROTOCOL FORMAT. In here we implement | ||
56 | * the transmission of that. This is split between a bus-independent | ||
57 | * part that just prepares everything and a bus-specific part that | ||
58 | * does the actual transmission over the bus to the device (in the | ||
59 | * bus-specific driver). | ||
60 | * | ||
61 | * | ||
62 | * The general format of a device-host transaction is MSG-HDR, PLD1, | ||
63 | * PLD2...PLDN, PL1, PL2,...PLN, PADDING. | ||
64 | * | ||
65 | * Because we need the send payload descriptors and then payloads and | ||
66 | * because it is kind of expensive to do scatterlists in USB (one URB | ||
67 | * per node), it becomes cheaper to append all the data to a FIFO | ||
68 | * (copying to a FIFO potentially in cache is cheaper). | ||
69 | * | ||
70 | * Then the bus-specific code takes the parts of that FIFO that are | ||
71 | * written and passes them to the device. | ||
72 | * | ||
73 | * So the concepts to keep in mind there are: | ||
74 | * | ||
75 | * We use a FIFO to queue the data in a linear buffer. We first append | ||
76 | * a MSG-HDR, space for I2400M_TX_PLD_MAX payload descriptors and then | ||
77 | * go appending payloads until we run out of space or of payload | ||
78 | * descriptors. Then we append padding to make the whole transaction a | ||
79 | * multiple of i2400m->bus_tx_block_size (as defined by the bus layer). | ||
80 | * | ||
81 | * - A TX message: a combination of a message header, payload | ||
82 | * descriptors and payloads. | ||
83 | * | ||
84 | * Open: it is marked as active (i2400m->tx_msg is valid) and we | ||
85 | * can keep adding payloads to it. | ||
86 | * | ||
87 | * Closed: we are not appending more payloads to this TX message | ||
88 | * (exahusted space in the queue, too many payloads or | ||
89 | * whichever). We have appended padding so the whole message | ||
90 | * length is aligned to i2400m->bus_tx_block_size (as set by the | ||
91 | * bus/transport layer). | ||
92 | * | ||
93 | * - Most of the time we keep a TX message open to which we append | ||
94 | * payloads. | ||
95 | * | ||
96 | * - If we are going to append and there is no more space (we are at | ||
97 | * the end of the FIFO), we close the message, mark the rest of the | ||
98 | * FIFO space unusable (skip_tail), create a new message at the | ||
99 | * beginning of the FIFO (if there is space) and append the message | ||
100 | * there. | ||
101 | * | ||
102 | * This is because we need to give linear TX messages to the bus | ||
103 | * engine. So we don't write a message to the remaining FIFO space | ||
104 | * until the tail and continue at the head of it. | ||
105 | * | ||
106 | * - We overload one of the fields in the message header to use it as | ||
107 | * 'size' of the TX message, so we can iterate over them. It also | ||
108 | * contains a flag that indicates if we have to skip it or not. | ||
109 | * When we send the buffer, we update that to its real on-the-wire | ||
110 | * value. | ||
111 | * | ||
112 | * - The MSG-HDR PLD1...PLD2 stuff has to be a size multiple of 16. | ||
113 | * | ||
114 | * It follows that if MSG-HDR says we have N messages, the whole | ||
115 | * header + descriptors is 16 + 4*N; for those to be a multiple of | ||
116 | * 16, it follows that N can be 4, 8, 12, ... (32, 48, 64, 80... | ||
117 | * bytes). | ||
118 | * | ||
119 | * So if we have only 1 payload, we have to submit a header that in | ||
120 | * all truth has space for 4. | ||
121 | * | ||
122 | * The implication is that we reserve space for 12 (64 bytes); but | ||
123 | * if we fill up only (eg) 2, our header becomes 32 bytes only. So | ||
124 | * the TX engine has to shift those 32 bytes of msg header and 2 | ||
125 | * payloads and padding so that right after it the payloads start | ||
126 | * and the TX engine has to know about that. | ||
127 | * | ||
128 | * It is cheaper to move the header up than the whole payloads down. | ||
129 | * | ||
130 | * We do this in i2400m_tx_close(). See 'i2400m_msg_hdr->offset'. | ||
131 | * | ||
132 | * - Each payload has to be size-padded to 16 bytes; before appending | ||
133 | * it, we just do it. | ||
134 | * | ||
135 | * - The whole message has to be padded to i2400m->bus_tx_block_size; | ||
136 | * we do this at close time. Thus, when reserving space for the | ||
137 | * payload, we always make sure there is also free space for this | ||
138 | * padding that sooner or later will happen. | ||
139 | * | ||
140 | * When we append a message, we tell the bus specific code to kick in | ||
141 | * TXs. It will TX (in parallel) until the buffer is exhausted--hence | ||
142 | * the lockin we do. The TX code will only send a TX message at the | ||
143 | * time (which remember, might contain more than one payload). Of | ||
144 | * course, when the bus-specific driver attempts to TX a message that | ||
145 | * is still open, it gets closed first. | ||
146 | * | ||
147 | * Gee, this is messy; well a picture. In the example below we have a | ||
148 | * partially full FIFO, with a closed message ready to be delivered | ||
149 | * (with a moved message header to make sure it is size-aligned to | ||
150 | * 16), TAIL room that was unusable (and thus is marked with a message | ||
151 | * header that says 'skip this') and at the head of the buffer, an | ||
152 | * imcomplete message with a couple of payloads. | ||
153 | * | ||
154 | * N ___________________________________________________ | ||
155 | * | | | ||
156 | * | TAIL room | | ||
157 | * | | | ||
158 | * | msg_hdr to skip (size |= 0x80000) | | ||
159 | * |---------------------------------------------------|------- | ||
160 | * | | /|\ | ||
161 | * | | | | ||
162 | * | TX message padding | | | ||
163 | * | | | | ||
164 | * | | | | ||
165 | * |- - - - - - - - - - - - - - - - - - - - - - - - - -| | | ||
166 | * | | | | ||
167 | * | payload 1 | | | ||
168 | * | | N * tx_block_size | ||
169 | * | | | | ||
170 | * |- - - - - - - - - - - - - - - - - - - - - - - - - -| | | ||
171 | * | | | | ||
172 | * | payload 1 | | | ||
173 | * | | | | ||
174 | * | | | | ||
175 | * |- - - - - - - - - - - - - - - - - - - - - - - - - -|- -|- - - - | ||
176 | * | padding 3 /|\ | | /|\ | ||
177 | * | padding 2 | | | | | ||
178 | * | pld 1 32 bytes (2 * 16) | | | | ||
179 | * | pld 0 | | | | | ||
180 | * | moved msg_hdr \|/ | \|/ | | ||
181 | * |- - - - - - - - - - - - - - - - - - - - - - - - - -|- - - | | ||
182 | * | | _PLD_SIZE | ||
183 | * | unused | | | ||
184 | * | | | | ||
185 | * |- - - - - - - - - - - - - - - - - - - - - - - - - -| | | ||
186 | * | msg_hdr (size X) [this message is closed] | \|/ | ||
187 | * |===================================================|========== <=== OUT | ||
188 | * | | | ||
189 | * | | | ||
190 | * | | | ||
191 | * | Free rooom | | ||
192 | * | | | ||
193 | * | | | ||
194 | * | | | ||
195 | * | | | ||
196 | * | | | ||
197 | * | | | ||
198 | * | | | ||
199 | * | | | ||
200 | * | | | ||
201 | * |===================================================|========== <=== IN | ||
202 | * | | | ||
203 | * | | | ||
204 | * | | | ||
205 | * | | | ||
206 | * | payload 1 | | ||
207 | * | | | ||
208 | * | | | ||
209 | * |- - - - - - - - - - - - - - - - - - - - - - - - - -| | ||
210 | * | | | ||
211 | * | payload 0 | | ||
212 | * | | | ||
213 | * | | | ||
214 | * |- - - - - - - - - - - - - - - - - - - - - - - - - -| | ||
215 | * | pld 11 /|\ | | ||
216 | * | ... | | | ||
217 | * | pld 1 64 bytes (2 * 16) | | ||
218 | * | pld 0 | | | ||
219 | * | msg_hdr (size X) \|/ [message is open] | | ||
220 | * 0 --------------------------------------------------- | ||
221 | * | ||
222 | * | ||
223 | * ROADMAP | ||
224 | * | ||
225 | * i2400m_tx_setup() Called by i2400m_setup | ||
226 | * i2400m_tx_release() Called by i2400m_release() | ||
227 | * | ||
228 | * i2400m_tx() Called to send data or control frames | ||
229 | * i2400m_tx_fifo_push() Allocates append-space in the FIFO | ||
230 | * i2400m_tx_new() Opens a new message in the FIFO | ||
231 | * i2400m_tx_fits() Checks if a new payload fits in the message | ||
232 | * i2400m_tx_close() Closes an open message in the FIFO | ||
233 | * i2400m_tx_skip_tail() Marks unusable FIFO tail space | ||
234 | * i2400m->bus_tx_kick() | ||
235 | * | ||
236 | * Now i2400m->bus_tx_kick() is the the bus-specific driver backend | ||
237 | * implementation; that would do: | ||
238 | * | ||
239 | * i2400m->bus_tx_kick() | ||
240 | * i2400m_tx_msg_get() Gets first message ready to go | ||
241 | * ...sends it... | ||
242 | * i2400m_tx_msg_sent() Ack the message is sent; repeat from | ||
243 | * _tx_msg_get() until it returns NULL | ||
244 | * (FIFO empty). | ||
245 | */ | ||
246 | #include <linux/netdevice.h> | ||
247 | #include "i2400m.h" | ||
248 | |||
249 | |||
250 | #define D_SUBMODULE tx | ||
251 | #include "debug-levels.h" | ||
252 | |||
253 | enum { | ||
254 | /** | ||
255 | * TX Buffer size | ||
256 | * | ||
257 | * Doc says maximum transaction is 16KiB. If we had 16KiB en | ||
258 | * route and 16KiB being queued, it boils down to needing | ||
259 | * 32KiB. | ||
260 | */ | ||
261 | I2400M_TX_BUF_SIZE = 32768, | ||
262 | /** | ||
263 | * Message header and payload descriptors have to be 16 | ||
264 | * aligned (16 + 4 * N = 16 * M). If we take that average sent | ||
265 | * packets are MTU size (~1400-~1500) it follows that we could | ||
266 | * fit at most 10-11 payloads in one transaction. To meet the | ||
267 | * alignment requirement, that means we need to leave space | ||
268 | * for 12 (64 bytes). To simplify, we leave space for that. If | ||
269 | * at the end there are less, we pad up to the nearest | ||
270 | * multiple of 16. | ||
271 | */ | ||
272 | I2400M_TX_PLD_MAX = 12, | ||
273 | I2400M_TX_PLD_SIZE = sizeof(struct i2400m_msg_hdr) | ||
274 | + I2400M_TX_PLD_MAX * sizeof(struct i2400m_pld), | ||
275 | I2400M_TX_SKIP = 0x80000000, | ||
276 | }; | ||
277 | |||
278 | #define TAIL_FULL ((void *)~(unsigned long)NULL) | ||
279 | |||
280 | /* | ||
281 | * Allocate @size bytes in the TX fifo, return a pointer to it | ||
282 | * | ||
283 | * @i2400m: device descriptor | ||
284 | * @size: size of the buffer we need to allocate | ||
285 | * @padding: ensure that there is at least this many bytes of free | ||
286 | * contiguous space in the fifo. This is needed because later on | ||
287 | * we might need to add padding. | ||
288 | * | ||
289 | * Returns: | ||
290 | * | ||
291 | * Pointer to the allocated space. NULL if there is no | ||
292 | * space. TAIL_FULL if there is no space at the tail but there is at | ||
293 | * the head (Case B below). | ||
294 | * | ||
295 | * These are the two basic cases we need to keep an eye for -- it is | ||
296 | * much better explained in linux/kernel/kfifo.c, but this code | ||
297 | * basically does the same. No rocket science here. | ||
298 | * | ||
299 | * Case A Case B | ||
300 | * N ___________ ___________ | ||
301 | * | tail room | | data | | ||
302 | * | | | | | ||
303 | * |<- IN ->| |<- OUT ->| | ||
304 | * | | | | | ||
305 | * | data | | room | | ||
306 | * | | | | | ||
307 | * |<- OUT ->| |<- IN ->| | ||
308 | * | | | | | ||
309 | * | head room | | data | | ||
310 | * 0 ----------- ----------- | ||
311 | * | ||
312 | * We allocate only *contiguous* space. | ||
313 | * | ||
314 | * We can allocate only from 'room'. In Case B, it is simple; in case | ||
315 | * A, we only try from the tail room; if it is not enough, we just | ||
316 | * fail and return TAIL_FULL and let the caller figure out if we wants to | ||
317 | * skip the tail room and try to allocate from the head. | ||
318 | * | ||
319 | * Note: | ||
320 | * | ||
321 | * Assumes i2400m->tx_lock is taken, and we use that as a barrier | ||
322 | * | ||
323 | * The indexes keep increasing and we reset them to zero when we | ||
324 | * pop data off the queue | ||
325 | */ | ||
326 | static | ||
327 | void *i2400m_tx_fifo_push(struct i2400m *i2400m, size_t size, size_t padding) | ||
328 | { | ||
329 | struct device *dev = i2400m_dev(i2400m); | ||
330 | size_t room, tail_room, needed_size; | ||
331 | void *ptr; | ||
332 | |||
333 | needed_size = size + padding; | ||
334 | room = I2400M_TX_BUF_SIZE - (i2400m->tx_in - i2400m->tx_out); | ||
335 | if (room < needed_size) { /* this takes care of Case B */ | ||
336 | d_printf(2, dev, "fifo push %zu/%zu: no space\n", | ||
337 | size, padding); | ||
338 | return NULL; | ||
339 | } | ||
340 | /* Is there space at the tail? */ | ||
341 | tail_room = I2400M_TX_BUF_SIZE - i2400m->tx_in % I2400M_TX_BUF_SIZE; | ||
342 | if (tail_room < needed_size) { | ||
343 | if (i2400m->tx_out % I2400M_TX_BUF_SIZE | ||
344 | < i2400m->tx_in % I2400M_TX_BUF_SIZE) { | ||
345 | d_printf(2, dev, "fifo push %zu/%zu: tail full\n", | ||
346 | size, padding); | ||
347 | return TAIL_FULL; /* There might be head space */ | ||
348 | } else { | ||
349 | d_printf(2, dev, "fifo push %zu/%zu: no head space\n", | ||
350 | size, padding); | ||
351 | return NULL; /* There is no space */ | ||
352 | } | ||
353 | } | ||
354 | ptr = i2400m->tx_buf + i2400m->tx_in % I2400M_TX_BUF_SIZE; | ||
355 | d_printf(2, dev, "fifo push %zu/%zu: at @%zu\n", size, padding, | ||
356 | i2400m->tx_in % I2400M_TX_BUF_SIZE); | ||
357 | i2400m->tx_in += size; | ||
358 | return ptr; | ||
359 | } | ||
360 | |||
361 | |||
362 | /* | ||
363 | * Mark the tail of the FIFO buffer as 'to-skip' | ||
364 | * | ||
365 | * We should never hit the BUG_ON() because all the sizes we push to | ||
366 | * the FIFO are padded to be a multiple of 16 -- the size of *msg | ||
367 | * (I2400M_PL_PAD for the payloads, I2400M_TX_PLD_SIZE for the | ||
368 | * header). | ||
369 | * | ||
370 | * Note: | ||
371 | * | ||
372 | * Assumes i2400m->tx_lock is taken, and we use that as a barrier | ||
373 | */ | ||
374 | static | ||
375 | void i2400m_tx_skip_tail(struct i2400m *i2400m) | ||
376 | { | ||
377 | struct device *dev = i2400m_dev(i2400m); | ||
378 | size_t tx_in = i2400m->tx_in % I2400M_TX_BUF_SIZE; | ||
379 | size_t tail_room = I2400M_TX_BUF_SIZE - tx_in; | ||
380 | struct i2400m_msg_hdr *msg = i2400m->tx_buf + tx_in; | ||
381 | BUG_ON(tail_room < sizeof(*msg)); | ||
382 | msg->size = tail_room | I2400M_TX_SKIP; | ||
383 | d_printf(2, dev, "skip tail: skipping %zu bytes @%zu\n", | ||
384 | tail_room, tx_in); | ||
385 | i2400m->tx_in += tail_room; | ||
386 | } | ||
387 | |||
388 | |||
389 | /* | ||
390 | * Check if a skb will fit in the TX queue's current active TX | ||
391 | * message (if there are still descriptors left unused). | ||
392 | * | ||
393 | * Returns: | ||
394 | * 0 if the message won't fit, 1 if it will. | ||
395 | * | ||
396 | * Note: | ||
397 | * | ||
398 | * Assumes a TX message is active (i2400m->tx_msg). | ||
399 | * | ||
400 | * Assumes i2400m->tx_lock is taken, and we use that as a barrier | ||
401 | */ | ||
402 | static | ||
403 | unsigned i2400m_tx_fits(struct i2400m *i2400m) | ||
404 | { | ||
405 | struct i2400m_msg_hdr *msg_hdr = i2400m->tx_msg; | ||
406 | return le16_to_cpu(msg_hdr->num_pls) < I2400M_TX_PLD_MAX; | ||
407 | |||
408 | } | ||
409 | |||
410 | |||
411 | /* | ||
412 | * Start a new TX message header in the queue. | ||
413 | * | ||
414 | * Reserve memory from the base FIFO engine and then just initialize | ||
415 | * the message header. | ||
416 | * | ||
417 | * We allocate the biggest TX message header we might need (one that'd | ||
418 | * fit I2400M_TX_PLD_MAX payloads) -- when it is closed it will be | ||
419 | * 'ironed it out' and the unneeded parts removed. | ||
420 | * | ||
421 | * NOTE: | ||
422 | * | ||
423 | * Assumes that the previous message is CLOSED (eg: either | ||
424 | * there was none or 'i2400m_tx_close()' was called on it). | ||
425 | * | ||
426 | * Assumes i2400m->tx_lock is taken, and we use that as a barrier | ||
427 | */ | ||
428 | static | ||
429 | void i2400m_tx_new(struct i2400m *i2400m) | ||
430 | { | ||
431 | struct device *dev = i2400m_dev(i2400m); | ||
432 | struct i2400m_msg_hdr *tx_msg; | ||
433 | BUG_ON(i2400m->tx_msg != NULL); | ||
434 | try_head: | ||
435 | tx_msg = i2400m_tx_fifo_push(i2400m, I2400M_TX_PLD_SIZE, 0); | ||
436 | if (tx_msg == NULL) | ||
437 | goto out; | ||
438 | else if (tx_msg == TAIL_FULL) { | ||
439 | i2400m_tx_skip_tail(i2400m); | ||
440 | d_printf(2, dev, "new TX message: tail full, trying head\n"); | ||
441 | goto try_head; | ||
442 | } | ||
443 | memset(tx_msg, 0, I2400M_TX_PLD_SIZE); | ||
444 | tx_msg->size = I2400M_TX_PLD_SIZE; | ||
445 | out: | ||
446 | i2400m->tx_msg = tx_msg; | ||
447 | d_printf(2, dev, "new TX message: %p @%zu\n", | ||
448 | tx_msg, (void *) tx_msg - i2400m->tx_buf); | ||
449 | } | ||
450 | |||
451 | |||
452 | /* | ||
453 | * Finalize the current TX message header | ||
454 | * | ||
455 | * Sets the message header to be at the proper location depending on | ||
456 | * how many descriptors we have (check documentation at the file's | ||
457 | * header for more info on that). | ||
458 | * | ||
459 | * Appends padding bytes to make sure the whole TX message (counting | ||
460 | * from the 'relocated' message header) is aligned to | ||
461 | * tx_block_size. We assume the _append() code has left enough space | ||
462 | * in the FIFO for that. If there are no payloads, just pass, as it | ||
463 | * won't be transferred. | ||
464 | * | ||
465 | * The amount of padding bytes depends on how many payloads are in the | ||
466 | * TX message, as the "msg header and payload descriptors" will be | ||
467 | * shifted up in the buffer. | ||
468 | */ | ||
469 | static | ||
470 | void i2400m_tx_close(struct i2400m *i2400m) | ||
471 | { | ||
472 | struct device *dev = i2400m_dev(i2400m); | ||
473 | struct i2400m_msg_hdr *tx_msg = i2400m->tx_msg; | ||
474 | struct i2400m_msg_hdr *tx_msg_moved; | ||
475 | size_t aligned_size, padding, hdr_size; | ||
476 | void *pad_buf; | ||
477 | |||
478 | if (tx_msg->size & I2400M_TX_SKIP) /* a skipper? nothing to do */ | ||
479 | goto out; | ||
480 | |||
481 | /* Relocate the message header | ||
482 | * | ||
483 | * Find the current header size, align it to 16 and if we need | ||
484 | * to move it so the tail is next to the payloads, move it and | ||
485 | * set the offset. | ||
486 | * | ||
487 | * If it moved, this header is good only for transmission; the | ||
488 | * original one (it is kept if we moved) is still used to | ||
489 | * figure out where the next TX message starts (and where the | ||
490 | * offset to the moved header is). | ||
491 | */ | ||
492 | hdr_size = sizeof(*tx_msg) | ||
493 | + le16_to_cpu(tx_msg->num_pls) * sizeof(tx_msg->pld[0]); | ||
494 | hdr_size = ALIGN(hdr_size, I2400M_PL_PAD); | ||
495 | tx_msg->offset = I2400M_TX_PLD_SIZE - hdr_size; | ||
496 | tx_msg_moved = (void *) tx_msg + tx_msg->offset; | ||
497 | memmove(tx_msg_moved, tx_msg, hdr_size); | ||
498 | tx_msg_moved->size -= tx_msg->offset; | ||
499 | /* | ||
500 | * Now figure out how much we have to add to the (moved!) | ||
501 | * message so the size is a multiple of i2400m->bus_tx_block_size. | ||
502 | */ | ||
503 | aligned_size = ALIGN(tx_msg_moved->size, i2400m->bus_tx_block_size); | ||
504 | padding = aligned_size - tx_msg_moved->size; | ||
505 | if (padding > 0) { | ||
506 | pad_buf = i2400m_tx_fifo_push(i2400m, padding, 0); | ||
507 | if (unlikely(WARN_ON(pad_buf == NULL | ||
508 | || pad_buf == TAIL_FULL))) { | ||
509 | /* This should not happen -- append should verify | ||
510 | * there is always space left at least to append | ||
511 | * tx_block_size */ | ||
512 | dev_err(dev, | ||
513 | "SW BUG! Possible data leakage from memory the " | ||
514 | "device should not read for padding - " | ||
515 | "size %lu aligned_size %zu tx_buf %p in " | ||
516 | "%zu out %zu\n", | ||
517 | (unsigned long) tx_msg_moved->size, | ||
518 | aligned_size, i2400m->tx_buf, i2400m->tx_in, | ||
519 | i2400m->tx_out); | ||
520 | } else | ||
521 | memset(pad_buf, 0xad, padding); | ||
522 | } | ||
523 | tx_msg_moved->padding = cpu_to_le16(padding); | ||
524 | tx_msg_moved->size += padding; | ||
525 | if (tx_msg != tx_msg_moved) | ||
526 | tx_msg->size += padding; | ||
527 | out: | ||
528 | i2400m->tx_msg = NULL; | ||
529 | } | ||
530 | |||
531 | |||
532 | /** | ||
533 | * i2400m_tx - send the data in a buffer to the device | ||
534 | * | ||
535 | * @buf: pointer to the buffer to transmit | ||
536 | * | ||
537 | * @buf_len: buffer size | ||
538 | * | ||
539 | * @pl_type: type of the payload we are sending. | ||
540 | * | ||
541 | * Returns: | ||
542 | * 0 if ok, < 0 errno code on error (-ENOSPC, if there is no more | ||
543 | * room for the message in the queue). | ||
544 | * | ||
545 | * Appends the buffer to the TX FIFO and notifies the bus-specific | ||
546 | * part of the driver that there is new data ready to transmit. | ||
547 | * Once this function returns, the buffer has been copied, so it can | ||
548 | * be reused. | ||
549 | * | ||
550 | * The steps followed to append are explained in detail in the file | ||
551 | * header. | ||
552 | * | ||
553 | * Whenever we write to a message, we increase msg->size, so it | ||
554 | * reflects exactly how big the message is. This is needed so that if | ||
555 | * we concatenate two messages before they can be sent, the code that | ||
556 | * sends the messages can find the boundaries (and it will replace the | ||
557 | * size with the real barker before sending). | ||
558 | * | ||
559 | * Note: | ||
560 | * | ||
561 | * Cold and warm reset payloads need to be sent as a single | ||
562 | * payload, so we handle that. | ||
563 | */ | ||
564 | int i2400m_tx(struct i2400m *i2400m, const void *buf, size_t buf_len, | ||
565 | enum i2400m_pt pl_type) | ||
566 | { | ||
567 | int result = -ENOSPC; | ||
568 | struct device *dev = i2400m_dev(i2400m); | ||
569 | unsigned long flags; | ||
570 | size_t padded_len; | ||
571 | void *ptr; | ||
572 | unsigned is_singleton = pl_type == I2400M_PT_RESET_WARM | ||
573 | || pl_type == I2400M_PT_RESET_COLD; | ||
574 | |||
575 | d_fnstart(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u)\n", | ||
576 | i2400m, buf, buf_len, pl_type); | ||
577 | padded_len = ALIGN(buf_len, I2400M_PL_PAD); | ||
578 | d_printf(5, dev, "padded_len %zd buf_len %zd\n", padded_len, buf_len); | ||
579 | /* If there is no current TX message, create one; if the | ||
580 | * current one is out of payload slots or we have a singleton, | ||
581 | * close it and start a new one */ | ||
582 | spin_lock_irqsave(&i2400m->tx_lock, flags); | ||
583 | try_new: | ||
584 | if (unlikely(i2400m->tx_msg == NULL)) | ||
585 | i2400m_tx_new(i2400m); | ||
586 | else if (unlikely(!i2400m_tx_fits(i2400m) | ||
587 | || (is_singleton && i2400m->tx_msg->num_pls != 0))) { | ||
588 | d_printf(2, dev, "closing TX message (fits %u singleton " | ||
589 | "%u num_pls %u)\n", i2400m_tx_fits(i2400m), | ||
590 | is_singleton, i2400m->tx_msg->num_pls); | ||
591 | i2400m_tx_close(i2400m); | ||
592 | i2400m_tx_new(i2400m); | ||
593 | } | ||
594 | if (i2400m->tx_msg->size + padded_len > I2400M_TX_BUF_SIZE / 2) { | ||
595 | d_printf(2, dev, "TX: message too big, going new\n"); | ||
596 | i2400m_tx_close(i2400m); | ||
597 | i2400m_tx_new(i2400m); | ||
598 | } | ||
599 | if (i2400m->tx_msg == NULL) | ||
600 | goto error_tx_new; | ||
601 | /* So we have a current message header; now append space for | ||
602 | * the message -- if there is not enough, try the head */ | ||
603 | ptr = i2400m_tx_fifo_push(i2400m, padded_len, | ||
604 | i2400m->bus_tx_block_size); | ||
605 | if (ptr == TAIL_FULL) { /* Tail is full, try head */ | ||
606 | d_printf(2, dev, "pl append: tail full\n"); | ||
607 | i2400m_tx_close(i2400m); | ||
608 | i2400m_tx_skip_tail(i2400m); | ||
609 | goto try_new; | ||
610 | } else if (ptr == NULL) { /* All full */ | ||
611 | result = -ENOSPC; | ||
612 | d_printf(2, dev, "pl append: all full\n"); | ||
613 | } else { /* Got space, copy it, set padding */ | ||
614 | struct i2400m_msg_hdr *tx_msg = i2400m->tx_msg; | ||
615 | unsigned num_pls = le16_to_cpu(tx_msg->num_pls); | ||
616 | memcpy(ptr, buf, buf_len); | ||
617 | memset(ptr + buf_len, 0xad, padded_len - buf_len); | ||
618 | i2400m_pld_set(&tx_msg->pld[num_pls], buf_len, pl_type); | ||
619 | d_printf(3, dev, "pld 0x%08x (type 0x%1x len 0x%04zx\n", | ||
620 | le32_to_cpu(tx_msg->pld[num_pls].val), | ||
621 | pl_type, buf_len); | ||
622 | tx_msg->num_pls = le16_to_cpu(num_pls+1); | ||
623 | tx_msg->size += padded_len; | ||
624 | d_printf(2, dev, "TX: appended %zu b (up to %u b) pl #%u \n", | ||
625 | padded_len, tx_msg->size, num_pls+1); | ||
626 | d_printf(2, dev, | ||
627 | "TX: appended hdr @%zu %zu b pl #%u @%zu %zu/%zu b\n", | ||
628 | (void *)tx_msg - i2400m->tx_buf, (size_t)tx_msg->size, | ||
629 | num_pls+1, ptr - i2400m->tx_buf, buf_len, padded_len); | ||
630 | result = 0; | ||
631 | if (is_singleton) | ||
632 | i2400m_tx_close(i2400m); | ||
633 | } | ||
634 | error_tx_new: | ||
635 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | ||
636 | i2400m->bus_tx_kick(i2400m); /* always kick, might free up space */ | ||
637 | d_fnend(3, dev, "(i2400m %p skb %p [%zu bytes] pt %u) = %d\n", | ||
638 | i2400m, buf, buf_len, pl_type, result); | ||
639 | return result; | ||
640 | } | ||
641 | EXPORT_SYMBOL_GPL(i2400m_tx); | ||
642 | |||
643 | |||
644 | /** | ||
645 | * i2400m_tx_msg_get - Get the first TX message in the FIFO to start sending it | ||
646 | * | ||
647 | * @i2400m: device descriptors | ||
648 | * @bus_size: where to place the size of the TX message | ||
649 | * | ||
650 | * Called by the bus-specific driver to get the first TX message at | ||
651 | * the FIF that is ready for transmission. | ||
652 | * | ||
653 | * It sets the state in @i2400m to indicate the bus-specific driver is | ||
654 | * transfering that message (i2400m->tx_msg_size). | ||
655 | * | ||
656 | * Once the transfer is completed, call i2400m_tx_msg_sent(). | ||
657 | * | ||
658 | * Notes: | ||
659 | * | ||
660 | * The size of the TX message to be transmitted might be smaller than | ||
661 | * that of the TX message in the FIFO (in case the header was | ||
662 | * shorter). Hence, we copy it in @bus_size, for the bus layer to | ||
663 | * use. We keep the message's size in i2400m->tx_msg_size so that | ||
664 | * when the bus later is done transferring we know how much to | ||
665 | * advance the fifo. | ||
666 | * | ||
667 | * We collect statistics here as all the data is available and we | ||
668 | * assume it is going to work [see i2400m_tx_msg_sent()]. | ||
669 | */ | ||
670 | struct i2400m_msg_hdr *i2400m_tx_msg_get(struct i2400m *i2400m, | ||
671 | size_t *bus_size) | ||
672 | { | ||
673 | struct device *dev = i2400m_dev(i2400m); | ||
674 | struct i2400m_msg_hdr *tx_msg, *tx_msg_moved; | ||
675 | unsigned long flags, pls; | ||
676 | |||
677 | d_fnstart(3, dev, "(i2400m %p bus_size %p)\n", i2400m, bus_size); | ||
678 | spin_lock_irqsave(&i2400m->tx_lock, flags); | ||
679 | skip: | ||
680 | tx_msg_moved = NULL; | ||
681 | if (i2400m->tx_in == i2400m->tx_out) { /* Empty FIFO? */ | ||
682 | i2400m->tx_in = 0; | ||
683 | i2400m->tx_out = 0; | ||
684 | d_printf(2, dev, "TX: FIFO empty: resetting\n"); | ||
685 | goto out_unlock; | ||
686 | } | ||
687 | tx_msg = i2400m->tx_buf + i2400m->tx_out % I2400M_TX_BUF_SIZE; | ||
688 | if (tx_msg->size & I2400M_TX_SKIP) { /* skip? */ | ||
689 | d_printf(2, dev, "TX: skip: msg @%zu (%zu b)\n", | ||
690 | i2400m->tx_out % I2400M_TX_BUF_SIZE, | ||
691 | (size_t) tx_msg->size & ~I2400M_TX_SKIP); | ||
692 | i2400m->tx_out += tx_msg->size & ~I2400M_TX_SKIP; | ||
693 | goto skip; | ||
694 | } | ||
695 | |||
696 | if (tx_msg->num_pls == 0) { /* No payloads? */ | ||
697 | if (tx_msg == i2400m->tx_msg) { /* open, we are done */ | ||
698 | d_printf(2, dev, | ||
699 | "TX: FIFO empty: open msg w/o payloads @%zu\n", | ||
700 | (void *) tx_msg - i2400m->tx_buf); | ||
701 | tx_msg = NULL; | ||
702 | goto out_unlock; | ||
703 | } else { /* closed, skip it */ | ||
704 | d_printf(2, dev, | ||
705 | "TX: skip msg w/o payloads @%zu (%zu b)\n", | ||
706 | (void *) tx_msg - i2400m->tx_buf, | ||
707 | (size_t) tx_msg->size); | ||
708 | i2400m->tx_out += tx_msg->size & ~I2400M_TX_SKIP; | ||
709 | goto skip; | ||
710 | } | ||
711 | } | ||
712 | if (tx_msg == i2400m->tx_msg) /* open msg? */ | ||
713 | i2400m_tx_close(i2400m); | ||
714 | |||
715 | /* Now we have a valid TX message (with payloads) to TX */ | ||
716 | tx_msg_moved = (void *) tx_msg + tx_msg->offset; | ||
717 | i2400m->tx_msg_size = tx_msg->size; | ||
718 | *bus_size = tx_msg_moved->size; | ||
719 | d_printf(2, dev, "TX: pid %d msg hdr at @%zu offset +@%zu " | ||
720 | "size %zu bus_size %zu\n", | ||
721 | current->pid, (void *) tx_msg - i2400m->tx_buf, | ||
722 | (size_t) tx_msg->offset, (size_t) tx_msg->size, | ||
723 | (size_t) tx_msg_moved->size); | ||
724 | tx_msg_moved->barker = le32_to_cpu(I2400M_H2D_PREVIEW_BARKER); | ||
725 | tx_msg_moved->sequence = le32_to_cpu(i2400m->tx_sequence++); | ||
726 | |||
727 | pls = le32_to_cpu(tx_msg_moved->num_pls); | ||
728 | i2400m->tx_pl_num += pls; /* Update stats */ | ||
729 | if (pls > i2400m->tx_pl_max) | ||
730 | i2400m->tx_pl_max = pls; | ||
731 | if (pls < i2400m->tx_pl_min) | ||
732 | i2400m->tx_pl_min = pls; | ||
733 | i2400m->tx_num++; | ||
734 | i2400m->tx_size_acc += *bus_size; | ||
735 | if (*bus_size < i2400m->tx_size_min) | ||
736 | i2400m->tx_size_min = *bus_size; | ||
737 | if (*bus_size > i2400m->tx_size_max) | ||
738 | i2400m->tx_size_max = *bus_size; | ||
739 | out_unlock: | ||
740 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | ||
741 | d_fnstart(3, dev, "(i2400m %p bus_size %p [%zu]) = %p\n", | ||
742 | i2400m, bus_size, *bus_size, tx_msg_moved); | ||
743 | return tx_msg_moved; | ||
744 | } | ||
745 | EXPORT_SYMBOL_GPL(i2400m_tx_msg_get); | ||
746 | |||
747 | |||
748 | /** | ||
749 | * i2400m_tx_msg_sent - indicate the transmission of a TX message | ||
750 | * | ||
751 | * @i2400m: device descriptor | ||
752 | * | ||
753 | * Called by the bus-specific driver when a message has been sent; | ||
754 | * this pops it from the FIFO; and as there is space, start the queue | ||
755 | * in case it was stopped. | ||
756 | * | ||
757 | * Should be called even if the message send failed and we are | ||
758 | * dropping this TX message. | ||
759 | */ | ||
760 | void i2400m_tx_msg_sent(struct i2400m *i2400m) | ||
761 | { | ||
762 | unsigned n; | ||
763 | unsigned long flags; | ||
764 | struct device *dev = i2400m_dev(i2400m); | ||
765 | |||
766 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
767 | spin_lock_irqsave(&i2400m->tx_lock, flags); | ||
768 | i2400m->tx_out += i2400m->tx_msg_size; | ||
769 | d_printf(2, dev, "TX: sent %zu b\n", (size_t) i2400m->tx_msg_size); | ||
770 | i2400m->tx_msg_size = 0; | ||
771 | BUG_ON(i2400m->tx_out > i2400m->tx_in); | ||
772 | /* level them FIFO markers off */ | ||
773 | n = i2400m->tx_out / I2400M_TX_BUF_SIZE; | ||
774 | i2400m->tx_out %= I2400M_TX_BUF_SIZE; | ||
775 | i2400m->tx_in -= n * I2400M_TX_BUF_SIZE; | ||
776 | netif_start_queue(i2400m->wimax_dev.net_dev); | ||
777 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | ||
778 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | ||
779 | } | ||
780 | EXPORT_SYMBOL_GPL(i2400m_tx_msg_sent); | ||
781 | |||
782 | |||
783 | /** | ||
784 | * i2400m_tx_setup - Initialize the TX queue and infrastructure | ||
785 | * | ||
786 | * Make sure we reset the TX sequence to zero, as when this function | ||
787 | * is called, the firmware has been just restarted. | ||
788 | */ | ||
789 | int i2400m_tx_setup(struct i2400m *i2400m) | ||
790 | { | ||
791 | int result; | ||
792 | |||
793 | /* Do this here only once -- can't do on | ||
794 | * i2400m_hard_start_xmit() as we'll cause race conditions if | ||
795 | * the WS was scheduled on another CPU */ | ||
796 | INIT_WORK(&i2400m->wake_tx_ws, i2400m_wake_tx_work); | ||
797 | |||
798 | i2400m->tx_sequence = 0; | ||
799 | i2400m->tx_buf = kmalloc(I2400M_TX_BUF_SIZE, GFP_KERNEL); | ||
800 | if (i2400m->tx_buf == NULL) | ||
801 | result = -ENOMEM; | ||
802 | else | ||
803 | result = 0; | ||
804 | /* Huh? the bus layer has to define this... */ | ||
805 | BUG_ON(i2400m->bus_tx_block_size == 0); | ||
806 | return result; | ||
807 | |||
808 | } | ||
809 | |||
810 | |||
811 | /** | ||
812 | * i2400m_tx_release - Tear down the TX queue and infrastructure | ||
813 | */ | ||
814 | void i2400m_tx_release(struct i2400m *i2400m) | ||
815 | { | ||
816 | kfree(i2400m->tx_buf); | ||
817 | } | ||
diff --git a/drivers/net/wimax/i2400m/usb-debug-levels.h b/drivers/net/wimax/i2400m/usb-debug-levels.h new file mode 100644 index 000000000000..e4358bd880be --- /dev/null +++ b/drivers/net/wimax/i2400m/usb-debug-levels.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Debug levels control file for the i2400m-usb module | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com> | ||
7 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License version | ||
11 | * 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
21 | * 02110-1301, USA. | ||
22 | */ | ||
23 | #ifndef __debug_levels__h__ | ||
24 | #define __debug_levels__h__ | ||
25 | |||
26 | /* Maximum compile and run time debug level for all submodules */ | ||
27 | #define D_MODULENAME i2400m_usb | ||
28 | #define D_MASTER CONFIG_WIMAX_I2400M_DEBUG_LEVEL | ||
29 | |||
30 | #include <linux/wimax/debug.h> | ||
31 | |||
32 | /* List of all the enabled modules */ | ||
33 | enum d_module { | ||
34 | D_SUBMODULE_DECLARE(usb), | ||
35 | D_SUBMODULE_DECLARE(fw), | ||
36 | D_SUBMODULE_DECLARE(notif), | ||
37 | D_SUBMODULE_DECLARE(rx), | ||
38 | D_SUBMODULE_DECLARE(tx), | ||
39 | }; | ||
40 | |||
41 | |||
42 | #endif /* #ifndef __debug_levels__h__ */ | ||
diff --git a/drivers/net/wimax/i2400m/usb-fw.c b/drivers/net/wimax/i2400m/usb-fw.c new file mode 100644 index 000000000000..5ad287c228b8 --- /dev/null +++ b/drivers/net/wimax/i2400m/usb-fw.c | |||
@@ -0,0 +1,340 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Firmware uploader's USB specifics | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
37 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
38 | * - Initial implementation | ||
39 | * | ||
40 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
41 | * - bus generic/specific split | ||
42 | * | ||
43 | * THE PROCEDURE | ||
44 | * | ||
45 | * See fw.c for the generic description of this procedure. | ||
46 | * | ||
47 | * This file implements only the USB specifics. It boils down to how | ||
48 | * to send a command and waiting for an acknowledgement from the | ||
49 | * device. | ||
50 | * | ||
51 | * This code (and process) is single threaded. It assumes it is the | ||
52 | * only thread poking around (guaranteed by fw.c). | ||
53 | * | ||
54 | * COMMAND EXECUTION | ||
55 | * | ||
56 | * A write URB is posted with the buffer to the bulk output endpoint. | ||
57 | * | ||
58 | * ACK RECEPTION | ||
59 | * | ||
60 | * We just post a URB to the notification endpoint and wait for | ||
61 | * data. We repeat until we get all the data we expect (as indicated | ||
62 | * by the call from the bus generic code). | ||
63 | * | ||
64 | * The data is not read from the bulk in endpoint for boot mode. | ||
65 | * | ||
66 | * ROADMAP | ||
67 | * | ||
68 | * i2400mu_bus_bm_cmd_send | ||
69 | * i2400m_bm_cmd_prepare... | ||
70 | * i2400mu_tx_bulk_out | ||
71 | * | ||
72 | * i2400mu_bus_bm_wait_for_ack | ||
73 | * i2400m_notif_submit | ||
74 | */ | ||
75 | #include <linux/usb.h> | ||
76 | #include "i2400m-usb.h" | ||
77 | |||
78 | |||
79 | #define D_SUBMODULE fw | ||
80 | #include "usb-debug-levels.h" | ||
81 | |||
82 | |||
83 | /* | ||
84 | * Synchronous write to the device | ||
85 | * | ||
86 | * Takes care of updating EDC counts and thus, handle device errors. | ||
87 | */ | ||
88 | static | ||
89 | ssize_t i2400mu_tx_bulk_out(struct i2400mu *i2400mu, void *buf, size_t buf_size) | ||
90 | { | ||
91 | int result; | ||
92 | struct device *dev = &i2400mu->usb_iface->dev; | ||
93 | int len; | ||
94 | struct usb_endpoint_descriptor *epd; | ||
95 | int pipe, do_autopm = 1; | ||
96 | |||
97 | result = usb_autopm_get_interface(i2400mu->usb_iface); | ||
98 | if (result < 0) { | ||
99 | dev_err(dev, "BM-CMD: can't get autopm: %d\n", result); | ||
100 | do_autopm = 0; | ||
101 | } | ||
102 | epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_OUT); | ||
103 | pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); | ||
104 | retry: | ||
105 | result = usb_bulk_msg(i2400mu->usb_dev, pipe, buf, buf_size, &len, HZ); | ||
106 | switch (result) { | ||
107 | case 0: | ||
108 | if (len != buf_size) { | ||
109 | dev_err(dev, "BM-CMD: short write (%u B vs %zu " | ||
110 | "expected)\n", len, buf_size); | ||
111 | result = -EIO; | ||
112 | break; | ||
113 | } | ||
114 | result = len; | ||
115 | break; | ||
116 | case -EINVAL: /* while removing driver */ | ||
117 | case -ENODEV: /* dev disconnect ... */ | ||
118 | case -ENOENT: /* just ignore it */ | ||
119 | case -ESHUTDOWN: /* and exit */ | ||
120 | case -ECONNRESET: | ||
121 | result = -ESHUTDOWN; | ||
122 | break; | ||
123 | case -ETIMEDOUT: /* bah... */ | ||
124 | break; | ||
125 | default: /* any other? */ | ||
126 | if (edc_inc(&i2400mu->urb_edc, | ||
127 | EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { | ||
128 | dev_err(dev, "BM-CMD: maximum errors in " | ||
129 | "URB exceeded; resetting device\n"); | ||
130 | usb_queue_reset_device(i2400mu->usb_iface); | ||
131 | result = -ENODEV; | ||
132 | break; | ||
133 | } | ||
134 | dev_err(dev, "BM-CMD: URB error %d, retrying\n", | ||
135 | result); | ||
136 | goto retry; | ||
137 | } | ||
138 | result = len; | ||
139 | if (do_autopm) | ||
140 | usb_autopm_put_interface(i2400mu->usb_iface); | ||
141 | return result; | ||
142 | } | ||
143 | |||
144 | |||
145 | /* | ||
146 | * Send a boot-mode command over the bulk-out pipe | ||
147 | * | ||
148 | * Command can be a raw command, which requires no preparation (and | ||
149 | * which might not even be following the command format). Checks that | ||
150 | * the right amount of data was transfered. | ||
151 | * | ||
152 | * To satisfy USB requirements (no onstack, vmalloc or in data segment | ||
153 | * buffers), we copy the command to i2400m->bm_cmd_buf and send it from | ||
154 | * there. | ||
155 | * | ||
156 | * @flags: pass thru from i2400m_bm_cmd() | ||
157 | * @return: cmd_size if ok, < 0 errno code on error. | ||
158 | */ | ||
159 | ssize_t i2400mu_bus_bm_cmd_send(struct i2400m *i2400m, | ||
160 | const struct i2400m_bootrom_header *_cmd, | ||
161 | size_t cmd_size, int flags) | ||
162 | { | ||
163 | ssize_t result; | ||
164 | struct device *dev = i2400m_dev(i2400m); | ||
165 | struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); | ||
166 | int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd); | ||
167 | struct i2400m_bootrom_header *cmd; | ||
168 | size_t cmd_size_a = ALIGN(cmd_size, 16); /* USB restriction */ | ||
169 | |||
170 | d_fnstart(8, dev, "(i2400m %p cmd %p size %zu)\n", | ||
171 | i2400m, _cmd, cmd_size); | ||
172 | result = -E2BIG; | ||
173 | if (cmd_size > I2400M_BM_CMD_BUF_SIZE) | ||
174 | goto error_too_big; | ||
175 | memcpy(i2400m->bm_cmd_buf, _cmd, cmd_size); | ||
176 | cmd = i2400m->bm_cmd_buf; | ||
177 | if (cmd_size_a > cmd_size) /* Zero pad space */ | ||
178 | memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size); | ||
179 | if ((flags & I2400M_BM_CMD_RAW) == 0) { | ||
180 | if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0)) | ||
181 | dev_warn(dev, "SW BUG: response_required == 0\n"); | ||
182 | i2400m_bm_cmd_prepare(cmd); | ||
183 | } | ||
184 | result = i2400mu_tx_bulk_out(i2400mu, i2400m->bm_cmd_buf, cmd_size); | ||
185 | if (result < 0) { | ||
186 | dev_err(dev, "boot-mode cmd %d: cannot send: %zd\n", | ||
187 | opcode, result); | ||
188 | goto error_cmd_send; | ||
189 | } | ||
190 | if (result != cmd_size) { /* all was transferred? */ | ||
191 | dev_err(dev, "boot-mode cmd %d: incomplete transfer " | ||
192 | "(%zu vs %zu submitted)\n", opcode, result, cmd_size); | ||
193 | result = -EIO; | ||
194 | goto error_cmd_size; | ||
195 | } | ||
196 | error_cmd_size: | ||
197 | error_cmd_send: | ||
198 | error_too_big: | ||
199 | d_fnend(8, dev, "(i2400m %p cmd %p size %zu) = %zd\n", | ||
200 | i2400m, _cmd, cmd_size, result); | ||
201 | return result; | ||
202 | } | ||
203 | |||
204 | |||
205 | static | ||
206 | void __i2400mu_bm_notif_cb(struct urb *urb) | ||
207 | { | ||
208 | complete(urb->context); | ||
209 | } | ||
210 | |||
211 | |||
212 | /* | ||
213 | * submit a read to the notification endpoint | ||
214 | * | ||
215 | * @i2400m: device descriptor | ||
216 | * @urb: urb to use | ||
217 | * @completion: completion varible to complete when done | ||
218 | * | ||
219 | * Data is always read to i2400m->bm_ack_buf | ||
220 | */ | ||
221 | static | ||
222 | int i2400mu_notif_submit(struct i2400mu *i2400mu, struct urb *urb, | ||
223 | struct completion *completion) | ||
224 | { | ||
225 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
226 | struct usb_endpoint_descriptor *epd; | ||
227 | int pipe; | ||
228 | |||
229 | epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_NOTIFICATION); | ||
230 | pipe = usb_rcvintpipe(i2400mu->usb_dev, epd->bEndpointAddress); | ||
231 | usb_fill_int_urb(urb, i2400mu->usb_dev, pipe, | ||
232 | i2400m->bm_ack_buf, I2400M_BM_ACK_BUF_SIZE, | ||
233 | __i2400mu_bm_notif_cb, completion, | ||
234 | epd->bInterval); | ||
235 | return usb_submit_urb(urb, GFP_KERNEL); | ||
236 | } | ||
237 | |||
238 | |||
239 | /* | ||
240 | * Read an ack from the notification endpoint | ||
241 | * | ||
242 | * @i2400m: | ||
243 | * @_ack: pointer to where to store the read data | ||
244 | * @ack_size: how many bytes we should read | ||
245 | * | ||
246 | * Returns: < 0 errno code on error; otherwise, amount of received bytes. | ||
247 | * | ||
248 | * Submits a notification read, appends the read data to the given ack | ||
249 | * buffer and then repeats (until @ack_size bytes have been | ||
250 | * received). | ||
251 | */ | ||
252 | ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *i2400m, | ||
253 | struct i2400m_bootrom_header *_ack, | ||
254 | size_t ack_size) | ||
255 | { | ||
256 | ssize_t result = -ENOMEM; | ||
257 | struct device *dev = i2400m_dev(i2400m); | ||
258 | struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); | ||
259 | struct urb notif_urb; | ||
260 | void *ack = _ack; | ||
261 | size_t offset, len; | ||
262 | long val; | ||
263 | int do_autopm = 1; | ||
264 | DECLARE_COMPLETION_ONSTACK(notif_completion); | ||
265 | |||
266 | d_fnstart(8, dev, "(i2400m %p ack %p size %zu)\n", | ||
267 | i2400m, ack, ack_size); | ||
268 | BUG_ON(_ack == i2400m->bm_ack_buf); | ||
269 | result = usb_autopm_get_interface(i2400mu->usb_iface); | ||
270 | if (result < 0) { | ||
271 | dev_err(dev, "BM-ACK: can't get autopm: %d\n", (int) result); | ||
272 | do_autopm = 0; | ||
273 | } | ||
274 | usb_init_urb(¬if_urb); /* ready notifications */ | ||
275 | usb_get_urb(¬if_urb); | ||
276 | offset = 0; | ||
277 | while (offset < ack_size) { | ||
278 | init_completion(¬if_completion); | ||
279 | result = i2400mu_notif_submit(i2400mu, ¬if_urb, | ||
280 | ¬if_completion); | ||
281 | if (result < 0) | ||
282 | goto error_notif_urb_submit; | ||
283 | val = wait_for_completion_interruptible_timeout( | ||
284 | ¬if_completion, HZ); | ||
285 | if (val == 0) { | ||
286 | result = -ETIMEDOUT; | ||
287 | usb_kill_urb(¬if_urb); /* Timedout */ | ||
288 | goto error_notif_wait; | ||
289 | } | ||
290 | if (val == -ERESTARTSYS) { | ||
291 | result = -EINTR; /* Interrupted */ | ||
292 | usb_kill_urb(¬if_urb); | ||
293 | goto error_notif_wait; | ||
294 | } | ||
295 | result = notif_urb.status; /* How was the ack? */ | ||
296 | switch (result) { | ||
297 | case 0: | ||
298 | break; | ||
299 | case -EINVAL: /* while removing driver */ | ||
300 | case -ENODEV: /* dev disconnect ... */ | ||
301 | case -ENOENT: /* just ignore it */ | ||
302 | case -ESHUTDOWN: /* and exit */ | ||
303 | case -ECONNRESET: | ||
304 | result = -ESHUTDOWN; | ||
305 | goto error_dev_gone; | ||
306 | default: /* any other? */ | ||
307 | usb_kill_urb(¬if_urb); /* Timedout */ | ||
308 | if (edc_inc(&i2400mu->urb_edc, | ||
309 | EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) | ||
310 | goto error_exceeded; | ||
311 | dev_err(dev, "BM-ACK: URB error %d, " | ||
312 | "retrying\n", notif_urb.status); | ||
313 | continue; /* retry */ | ||
314 | } | ||
315 | if (notif_urb.actual_length == 0) { | ||
316 | d_printf(6, dev, "ZLP received, retrying\n"); | ||
317 | continue; | ||
318 | } | ||
319 | /* Got data, append it to the buffer */ | ||
320 | len = min(ack_size - offset, (size_t) notif_urb.actual_length); | ||
321 | memcpy(ack + offset, i2400m->bm_ack_buf, len); | ||
322 | offset += len; | ||
323 | } | ||
324 | result = offset; | ||
325 | error_notif_urb_submit: | ||
326 | error_notif_wait: | ||
327 | error_dev_gone: | ||
328 | out: | ||
329 | if (do_autopm) | ||
330 | usb_autopm_put_interface(i2400mu->usb_iface); | ||
331 | d_fnend(8, dev, "(i2400m %p ack %p size %zu) = %zd\n", | ||
332 | i2400m, ack, ack_size, result); | ||
333 | return result; | ||
334 | |||
335 | error_exceeded: | ||
336 | dev_err(dev, "bm: maximum errors in notification URB exceeded; " | ||
337 | "resetting device\n"); | ||
338 | usb_queue_reset_device(i2400mu->usb_iface); | ||
339 | goto out; | ||
340 | } | ||
diff --git a/drivers/net/wimax/i2400m/usb-notif.c b/drivers/net/wimax/i2400m/usb-notif.c new file mode 100644 index 000000000000..9702c22b2497 --- /dev/null +++ b/drivers/net/wimax/i2400m/usb-notif.c | |||
@@ -0,0 +1,269 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m over USB | ||
3 | * Notification handling | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
37 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
38 | * - Initial implementation | ||
39 | * | ||
40 | * | ||
41 | * The notification endpoint is active when the device is not in boot | ||
42 | * mode; in here we just read and get notifications; based on those, | ||
43 | * we act to either reinitialize the device after a reboot or to | ||
44 | * submit a RX request. | ||
45 | * | ||
46 | * ROADMAP | ||
47 | * | ||
48 | * i2400mu_usb_notification_setup() | ||
49 | * | ||
50 | * i2400mu_usb_notification_release() | ||
51 | * | ||
52 | * i2400mu_usb_notification_cb() Called when a URB is ready | ||
53 | * i2400mu_notif_grok() | ||
54 | * i2400m_dev_reset_handle() | ||
55 | * i2400mu_rx_kick() | ||
56 | */ | ||
57 | #include <linux/usb.h> | ||
58 | #include "i2400m-usb.h" | ||
59 | |||
60 | |||
61 | #define D_SUBMODULE notif | ||
62 | #include "usb-debug-levels.h" | ||
63 | |||
64 | |||
65 | static const | ||
66 | __le32 i2400m_ZERO_BARKER[4] = { 0, 0, 0, 0 }; | ||
67 | |||
68 | |||
69 | /* | ||
70 | * Process a received notification | ||
71 | * | ||
72 | * In normal operation mode, we can only receive two types of payloads | ||
73 | * on the notification endpoint: | ||
74 | * | ||
75 | * - a reboot barker, we do a bootstrap (the device has reseted). | ||
76 | * | ||
77 | * - a block of zeroes: there is pending data in the IN endpoint | ||
78 | */ | ||
79 | static | ||
80 | int i2400mu_notification_grok(struct i2400mu *i2400mu, const void *buf, | ||
81 | size_t buf_len) | ||
82 | { | ||
83 | int ret; | ||
84 | struct device *dev = &i2400mu->usb_iface->dev; | ||
85 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
86 | |||
87 | d_fnstart(4, dev, "(i2400m %p buf %p buf_len %zu)\n", | ||
88 | i2400mu, buf, buf_len); | ||
89 | ret = -EIO; | ||
90 | if (buf_len < sizeof(i2400m_NBOOT_BARKER)) | ||
91 | /* Not a bug, just ignore */ | ||
92 | goto error_bad_size; | ||
93 | if (!memcmp(i2400m_NBOOT_BARKER, buf, sizeof(i2400m_NBOOT_BARKER)) | ||
94 | || !memcmp(i2400m_SBOOT_BARKER, buf, sizeof(i2400m_SBOOT_BARKER))) | ||
95 | ret = i2400m_dev_reset_handle(i2400m); | ||
96 | else if (!memcmp(i2400m_ZERO_BARKER, buf, sizeof(i2400m_ZERO_BARKER))) { | ||
97 | i2400mu_rx_kick(i2400mu); | ||
98 | ret = 0; | ||
99 | } else { /* Unknown or unexpected data in the notif message */ | ||
100 | char prefix[64]; | ||
101 | ret = -EIO; | ||
102 | dev_err(dev, "HW BUG? Unknown/unexpected data in notification " | ||
103 | "message (%zu bytes)\n", buf_len); | ||
104 | snprintf(prefix, sizeof(prefix), "%s %s: ", | ||
105 | dev_driver_string(dev) , dev->bus_id); | ||
106 | if (buf_len > 64) { | ||
107 | print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, | ||
108 | 8, 4, buf, 64, 0); | ||
109 | printk(KERN_ERR "%s... (only first 64 bytes " | ||
110 | "dumped)\n", prefix); | ||
111 | } else | ||
112 | print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, | ||
113 | 8, 4, buf, buf_len, 0); | ||
114 | } | ||
115 | error_bad_size: | ||
116 | d_fnend(4, dev, "(i2400m %p buf %p buf_len %zu) = %d\n", | ||
117 | i2400mu, buf, buf_len, ret); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | |||
122 | /* | ||
123 | * URB callback for the notification endpoint | ||
124 | * | ||
125 | * @urb: the urb received from the notification endpoint | ||
126 | * | ||
127 | * This function will just process the USB side of the transaction, | ||
128 | * checking everything is fine, pass the processing to | ||
129 | * i2400m_notification_grok() and resubmit the URB. | ||
130 | */ | ||
131 | static | ||
132 | void i2400mu_notification_cb(struct urb *urb) | ||
133 | { | ||
134 | int ret; | ||
135 | struct i2400mu *i2400mu = urb->context; | ||
136 | struct device *dev = &i2400mu->usb_iface->dev; | ||
137 | |||
138 | d_fnstart(4, dev, "(urb %p status %d actual_length %d)\n", | ||
139 | urb, urb->status, urb->actual_length); | ||
140 | ret = urb->status; | ||
141 | switch (ret) { | ||
142 | case 0: | ||
143 | ret = i2400mu_notification_grok(i2400mu, urb->transfer_buffer, | ||
144 | urb->actual_length); | ||
145 | if (ret == -EIO && edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS, | ||
146 | EDC_ERROR_TIMEFRAME)) | ||
147 | goto error_exceeded; | ||
148 | if (ret == -ENOMEM) /* uff...power cycle? shutdown? */ | ||
149 | goto error_exceeded; | ||
150 | break; | ||
151 | case -EINVAL: /* while removing driver */ | ||
152 | case -ENODEV: /* dev disconnect ... */ | ||
153 | case -ENOENT: /* ditto */ | ||
154 | case -ESHUTDOWN: /* URB killed */ | ||
155 | case -ECONNRESET: /* disconnection */ | ||
156 | goto out; /* Notify around */ | ||
157 | default: /* Some error? */ | ||
158 | if (edc_inc(&i2400mu->urb_edc, | ||
159 | EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) | ||
160 | goto error_exceeded; | ||
161 | dev_err(dev, "notification: URB error %d, retrying\n", | ||
162 | urb->status); | ||
163 | } | ||
164 | usb_mark_last_busy(i2400mu->usb_dev); | ||
165 | ret = usb_submit_urb(i2400mu->notif_urb, GFP_ATOMIC); | ||
166 | switch (ret) { | ||
167 | case 0: | ||
168 | case -EINVAL: /* while removing driver */ | ||
169 | case -ENODEV: /* dev disconnect ... */ | ||
170 | case -ENOENT: /* ditto */ | ||
171 | case -ESHUTDOWN: /* URB killed */ | ||
172 | case -ECONNRESET: /* disconnection */ | ||
173 | break; /* just ignore */ | ||
174 | default: /* Some error? */ | ||
175 | dev_err(dev, "notification: cannot submit URB: %d\n", ret); | ||
176 | goto error_submit; | ||
177 | } | ||
178 | d_fnend(4, dev, "(urb %p status %d actual_length %d) = void\n", | ||
179 | urb, urb->status, urb->actual_length); | ||
180 | return; | ||
181 | |||
182 | error_exceeded: | ||
183 | dev_err(dev, "maximum errors in notification URB exceeded; " | ||
184 | "resetting device\n"); | ||
185 | error_submit: | ||
186 | usb_queue_reset_device(i2400mu->usb_iface); | ||
187 | out: | ||
188 | d_fnend(4, dev, "(urb %p status %d actual_length %d) = void\n", | ||
189 | urb, urb->status, urb->actual_length); | ||
190 | return; | ||
191 | } | ||
192 | |||
193 | |||
194 | /* | ||
195 | * setup the notification endpoint | ||
196 | * | ||
197 | * @i2400m: device descriptor | ||
198 | * | ||
199 | * This procedure prepares the notification urb and handler for receiving | ||
200 | * unsolicited barkers from the device. | ||
201 | */ | ||
202 | int i2400mu_notification_setup(struct i2400mu *i2400mu) | ||
203 | { | ||
204 | struct device *dev = &i2400mu->usb_iface->dev; | ||
205 | int usb_pipe, ret = 0; | ||
206 | struct usb_endpoint_descriptor *epd; | ||
207 | char *buf; | ||
208 | |||
209 | d_fnstart(4, dev, "(i2400m %p)\n", i2400mu); | ||
210 | buf = kmalloc(I2400MU_MAX_NOTIFICATION_LEN, GFP_KERNEL | GFP_DMA); | ||
211 | if (buf == NULL) { | ||
212 | dev_err(dev, "notification: buffer allocation failed\n"); | ||
213 | ret = -ENOMEM; | ||
214 | goto error_buf_alloc; | ||
215 | } | ||
216 | |||
217 | i2400mu->notif_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
218 | if (!i2400mu->notif_urb) { | ||
219 | ret = -ENOMEM; | ||
220 | dev_err(dev, "notification: cannot allocate URB\n"); | ||
221 | goto error_alloc_urb; | ||
222 | } | ||
223 | epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_NOTIFICATION); | ||
224 | usb_pipe = usb_rcvintpipe(i2400mu->usb_dev, epd->bEndpointAddress); | ||
225 | usb_fill_int_urb(i2400mu->notif_urb, i2400mu->usb_dev, usb_pipe, | ||
226 | buf, I2400MU_MAX_NOTIFICATION_LEN, | ||
227 | i2400mu_notification_cb, i2400mu, epd->bInterval); | ||
228 | ret = usb_submit_urb(i2400mu->notif_urb, GFP_KERNEL); | ||
229 | if (ret != 0) { | ||
230 | dev_err(dev, "notification: cannot submit URB: %d\n", ret); | ||
231 | goto error_submit; | ||
232 | } | ||
233 | d_fnend(4, dev, "(i2400m %p) = %d\n", i2400mu, ret); | ||
234 | return ret; | ||
235 | |||
236 | error_submit: | ||
237 | usb_free_urb(i2400mu->notif_urb); | ||
238 | error_alloc_urb: | ||
239 | kfree(buf); | ||
240 | error_buf_alloc: | ||
241 | d_fnend(4, dev, "(i2400m %p) = %d\n", i2400mu, ret); | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | |||
246 | /* | ||
247 | * Tear down of the notification mechanism | ||
248 | * | ||
249 | * @i2400m: device descriptor | ||
250 | * | ||
251 | * Kill the interrupt endpoint urb, free any allocated resources. | ||
252 | * | ||
253 | * We need to check if we have done it before as for example, | ||
254 | * _suspend() call this; if after a suspend() we get a _disconnect() | ||
255 | * (as the case is when hibernating), nothing bad happens. | ||
256 | */ | ||
257 | void i2400mu_notification_release(struct i2400mu *i2400mu) | ||
258 | { | ||
259 | struct device *dev = &i2400mu->usb_iface->dev; | ||
260 | |||
261 | d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); | ||
262 | if (i2400mu->notif_urb != NULL) { | ||
263 | usb_kill_urb(i2400mu->notif_urb); | ||
264 | kfree(i2400mu->notif_urb->transfer_buffer); | ||
265 | usb_free_urb(i2400mu->notif_urb); | ||
266 | i2400mu->notif_urb = NULL; | ||
267 | } | ||
268 | d_fnend(4, dev, "(i2400mu %p)\n", i2400mu); | ||
269 | } | ||
diff --git a/drivers/net/wimax/i2400m/usb-rx.c b/drivers/net/wimax/i2400m/usb-rx.c new file mode 100644 index 000000000000..074cc1f89853 --- /dev/null +++ b/drivers/net/wimax/i2400m/usb-rx.c | |||
@@ -0,0 +1,417 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * USB RX handling | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
37 | * - Initial implementation | ||
38 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
39 | * - Use skb_clone(), break up processing in chunks | ||
40 | * - Split transport/device specific | ||
41 | * - Make buffer size dynamic to exert less memory pressure | ||
42 | * | ||
43 | * | ||
44 | * This handles the RX path on USB. | ||
45 | * | ||
46 | * When a notification is received that says 'there is RX data ready', | ||
47 | * we call i2400mu_rx_kick(); that wakes up the RX kthread, which | ||
48 | * reads a buffer from USB and passes it to i2400m_rx() in the generic | ||
49 | * handling code. The RX buffer has an specific format that is | ||
50 | * described in rx.c. | ||
51 | * | ||
52 | * We use a kernel thread in a loop because: | ||
53 | * | ||
54 | * - we want to be able to call the USB power management get/put | ||
55 | * functions (blocking) before each transaction. | ||
56 | * | ||
57 | * - We might get a lot of notifications and we don't want to submit | ||
58 | * a zillion reads; by serializing, we are throttling. | ||
59 | * | ||
60 | * - RX data processing can get heavy enough so that it is not | ||
61 | * appropiate for doing it in the USB callback; thus we run it in a | ||
62 | * process context. | ||
63 | * | ||
64 | * We provide a read buffer of an arbitrary size (short of a page); if | ||
65 | * the callback reports -EOVERFLOW, it means it was too small, so we | ||
66 | * just double the size and retry (being careful to append, as | ||
67 | * sometimes the device provided some data). Every now and then we | ||
68 | * check if the average packet size is smaller than the current packet | ||
69 | * size and if so, we halve it. At the end, the size of the | ||
70 | * preallocated buffer should be following the average received | ||
71 | * transaction size, adapting dynamically to it. | ||
72 | * | ||
73 | * ROADMAP | ||
74 | * | ||
75 | * i2400mu_rx_kick() Called from notif.c when we get a | ||
76 | * 'data ready' notification | ||
77 | * i2400mu_rxd() Kernel RX daemon | ||
78 | * i2400mu_rx() Receive USB data | ||
79 | * i2400m_rx() Send data to generic i2400m RX handling | ||
80 | * | ||
81 | * i2400mu_rx_setup() called from i2400mu_bus_dev_start() | ||
82 | * | ||
83 | * i2400mu_rx_release() called from i2400mu_bus_dev_stop() | ||
84 | */ | ||
85 | #include <linux/workqueue.h> | ||
86 | #include <linux/usb.h> | ||
87 | #include "i2400m-usb.h" | ||
88 | |||
89 | |||
90 | #define D_SUBMODULE rx | ||
91 | #include "usb-debug-levels.h" | ||
92 | |||
93 | /* | ||
94 | * Dynamic RX size | ||
95 | * | ||
96 | * We can't let the rx_size be a multiple of 512 bytes (the RX | ||
97 | * endpoint's max packet size). On some USB host controllers (we | ||
98 | * haven't been able to fully characterize which), if the device is | ||
99 | * about to send (for example) X bytes and we only post a buffer to | ||
100 | * receive n*512, it will fail to mark that as babble (so that | ||
101 | * i2400mu_rx() [case -EOVERFLOW] can resize the buffer and get the | ||
102 | * rest). | ||
103 | * | ||
104 | * So on growing or shrinking, if it is a multiple of the | ||
105 | * maxpacketsize, we remove some (instead of incresing some, so in a | ||
106 | * buddy allocator we try to waste less space). | ||
107 | * | ||
108 | * Note we also need a hook for this on i2400mu_rx() -- when we do the | ||
109 | * first read, we are sure we won't hit this spot because | ||
110 | * i240mm->rx_size has been set properly. However, if we have to | ||
111 | * double because of -EOVERFLOW, when we launch the read to get the | ||
112 | * rest of the data, we *have* to make sure that also is not a | ||
113 | * multiple of the max_pkt_size. | ||
114 | */ | ||
115 | |||
116 | static | ||
117 | size_t i2400mu_rx_size_grow(struct i2400mu *i2400mu) | ||
118 | { | ||
119 | struct device *dev = &i2400mu->usb_iface->dev; | ||
120 | size_t rx_size; | ||
121 | const size_t max_pkt_size = 512; | ||
122 | |||
123 | rx_size = 2 * i2400mu->rx_size; | ||
124 | if (rx_size % max_pkt_size == 0) { | ||
125 | rx_size -= 8; | ||
126 | d_printf(1, dev, | ||
127 | "RX: expected size grew to %zu [adjusted -8] " | ||
128 | "from %zu\n", | ||
129 | rx_size, i2400mu->rx_size); | ||
130 | } else | ||
131 | d_printf(1, dev, | ||
132 | "RX: expected size grew to %zu from %zu\n", | ||
133 | rx_size, i2400mu->rx_size); | ||
134 | return rx_size; | ||
135 | } | ||
136 | |||
137 | |||
138 | static | ||
139 | void i2400mu_rx_size_maybe_shrink(struct i2400mu *i2400mu) | ||
140 | { | ||
141 | const size_t max_pkt_size = 512; | ||
142 | struct device *dev = &i2400mu->usb_iface->dev; | ||
143 | |||
144 | if (unlikely(i2400mu->rx_size_cnt >= 100 | ||
145 | && i2400mu->rx_size_auto_shrink)) { | ||
146 | size_t avg_rx_size = | ||
147 | i2400mu->rx_size_acc / i2400mu->rx_size_cnt; | ||
148 | size_t new_rx_size = i2400mu->rx_size / 2; | ||
149 | if (avg_rx_size < new_rx_size) { | ||
150 | if (new_rx_size % max_pkt_size == 0) { | ||
151 | new_rx_size -= 8; | ||
152 | d_printf(1, dev, | ||
153 | "RX: expected size shrank to %zu " | ||
154 | "[adjusted -8] from %zu\n", | ||
155 | new_rx_size, i2400mu->rx_size); | ||
156 | } else | ||
157 | d_printf(1, dev, | ||
158 | "RX: expected size shrank to %zu " | ||
159 | "from %zu\n", | ||
160 | new_rx_size, i2400mu->rx_size); | ||
161 | i2400mu->rx_size = new_rx_size; | ||
162 | i2400mu->rx_size_cnt = 0; | ||
163 | i2400mu->rx_size_acc = i2400mu->rx_size; | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * Receive a message with payloads from the USB bus into an skb | ||
170 | * | ||
171 | * @i2400mu: USB device descriptor | ||
172 | * @rx_skb: skb where to place the received message | ||
173 | * | ||
174 | * Deals with all the USB-specifics of receiving, dynamically | ||
175 | * increasing the buffer size if so needed. Returns the payload in the | ||
176 | * skb, ready to process. On a zero-length packet, we retry. | ||
177 | * | ||
178 | * On soft USB errors, we retry (until they become too frequent and | ||
179 | * then are promoted to hard); on hard USB errors, we reset the | ||
180 | * device. On other errors (skb realloacation, we just drop it and | ||
181 | * hope for the next invocation to solve it). | ||
182 | * | ||
183 | * Returns: pointer to the skb if ok, ERR_PTR on error. | ||
184 | * NOTE: this function might realloc the skb (if it is too small), | ||
185 | * so always update with the one returned. | ||
186 | * ERR_PTR() is < 0 on error. | ||
187 | */ | ||
188 | static | ||
189 | struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb) | ||
190 | { | ||
191 | int result = 0; | ||
192 | struct device *dev = &i2400mu->usb_iface->dev; | ||
193 | int usb_pipe, read_size, rx_size, do_autopm; | ||
194 | struct usb_endpoint_descriptor *epd; | ||
195 | const size_t max_pkt_size = 512; | ||
196 | |||
197 | d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); | ||
198 | do_autopm = atomic_read(&i2400mu->do_autopm); | ||
199 | result = do_autopm ? | ||
200 | usb_autopm_get_interface(i2400mu->usb_iface) : 0; | ||
201 | if (result < 0) { | ||
202 | dev_err(dev, "RX: can't get autopm: %d\n", result); | ||
203 | do_autopm = 0; | ||
204 | } | ||
205 | epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_IN); | ||
206 | usb_pipe = usb_rcvbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); | ||
207 | retry: | ||
208 | rx_size = skb_end_pointer(rx_skb) - rx_skb->data - rx_skb->len; | ||
209 | if (unlikely(rx_size % max_pkt_size == 0)) { | ||
210 | rx_size -= 8; | ||
211 | d_printf(1, dev, "RX: rx_size adapted to %d [-8]\n", rx_size); | ||
212 | } | ||
213 | result = usb_bulk_msg( | ||
214 | i2400mu->usb_dev, usb_pipe, rx_skb->data + rx_skb->len, | ||
215 | rx_size, &read_size, HZ); | ||
216 | usb_mark_last_busy(i2400mu->usb_dev); | ||
217 | switch (result) { | ||
218 | case 0: | ||
219 | if (read_size == 0) | ||
220 | goto retry; /* ZLP, just resubmit */ | ||
221 | skb_put(rx_skb, read_size); | ||
222 | break; | ||
223 | case -EINVAL: /* while removing driver */ | ||
224 | case -ENODEV: /* dev disconnect ... */ | ||
225 | case -ENOENT: /* just ignore it */ | ||
226 | case -ESHUTDOWN: | ||
227 | case -ECONNRESET: | ||
228 | break; | ||
229 | case -EOVERFLOW: { /* too small, reallocate */ | ||
230 | struct sk_buff *new_skb; | ||
231 | rx_size = i2400mu_rx_size_grow(i2400mu); | ||
232 | if (rx_size <= (1 << 16)) /* cap it */ | ||
233 | i2400mu->rx_size = rx_size; | ||
234 | else if (printk_ratelimit()) { | ||
235 | dev_err(dev, "BUG? rx_size up to %d\n", rx_size); | ||
236 | result = -EINVAL; | ||
237 | goto out; | ||
238 | } | ||
239 | skb_put(rx_skb, read_size); | ||
240 | new_skb = skb_copy_expand(rx_skb, 0, rx_size - rx_skb->len, | ||
241 | GFP_KERNEL); | ||
242 | if (new_skb == NULL) { | ||
243 | if (printk_ratelimit()) | ||
244 | dev_err(dev, "RX: Can't reallocate skb to %d; " | ||
245 | "RX dropped\n", rx_size); | ||
246 | kfree(rx_skb); | ||
247 | result = 0; | ||
248 | goto out; /* drop it...*/ | ||
249 | } | ||
250 | kfree_skb(rx_skb); | ||
251 | rx_skb = new_skb; | ||
252 | i2400mu->rx_size_cnt = 0; | ||
253 | i2400mu->rx_size_acc = i2400mu->rx_size; | ||
254 | d_printf(1, dev, "RX: size changed to %d, received %d, " | ||
255 | "copied %d, capacity %ld\n", | ||
256 | rx_size, read_size, rx_skb->len, | ||
257 | (long) (skb_end_pointer(new_skb) - new_skb->head)); | ||
258 | goto retry; | ||
259 | } | ||
260 | /* In most cases, it happens due to the hardware scheduling a | ||
261 | * read when there was no data - unfortunately, we have no way | ||
262 | * to tell this timeout from a USB timeout. So we just ignore | ||
263 | * it. */ | ||
264 | case -ETIMEDOUT: | ||
265 | dev_err(dev, "RX: timeout: %d\n", result); | ||
266 | result = 0; | ||
267 | break; | ||
268 | default: /* Any error */ | ||
269 | if (edc_inc(&i2400mu->urb_edc, | ||
270 | EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) | ||
271 | goto error_reset; | ||
272 | dev_err(dev, "RX: error receiving URB: %d, retrying\n", result); | ||
273 | goto retry; | ||
274 | } | ||
275 | out: | ||
276 | if (do_autopm) | ||
277 | usb_autopm_put_interface(i2400mu->usb_iface); | ||
278 | d_fnend(4, dev, "(i2400mu %p) = %p\n", i2400mu, rx_skb); | ||
279 | return rx_skb; | ||
280 | |||
281 | error_reset: | ||
282 | dev_err(dev, "RX: maximum errors in URB exceeded; " | ||
283 | "resetting device\n"); | ||
284 | usb_queue_reset_device(i2400mu->usb_iface); | ||
285 | rx_skb = ERR_PTR(result); | ||
286 | goto out; | ||
287 | } | ||
288 | |||
289 | |||
290 | /* | ||
291 | * Kernel thread for USB reception of data | ||
292 | * | ||
293 | * This thread waits for a kick; once kicked, it will allocate an skb | ||
294 | * and receive a single message to it from USB (using | ||
295 | * i2400mu_rx()). Once received, it is passed to the generic i2400m RX | ||
296 | * code for processing. | ||
297 | * | ||
298 | * When done processing, it runs some dirty statistics to verify if | ||
299 | * the last 100 messages received were smaller than half of the | ||
300 | * current RX buffer size. In that case, the RX buffer size is | ||
301 | * halved. This will helps lowering the pressure on the memory | ||
302 | * allocator. | ||
303 | * | ||
304 | * Hard errors force the thread to exit. | ||
305 | */ | ||
306 | static | ||
307 | int i2400mu_rxd(void *_i2400mu) | ||
308 | { | ||
309 | int result = 0; | ||
310 | struct i2400mu *i2400mu = _i2400mu; | ||
311 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
312 | struct device *dev = &i2400mu->usb_iface->dev; | ||
313 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; | ||
314 | size_t pending; | ||
315 | int rx_size; | ||
316 | struct sk_buff *rx_skb; | ||
317 | |||
318 | d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); | ||
319 | while (1) { | ||
320 | d_printf(2, dev, "TX: waiting for messages\n"); | ||
321 | pending = 0; | ||
322 | wait_event_interruptible( | ||
323 | i2400mu->rx_wq, | ||
324 | (kthread_should_stop() /* check this first! */ | ||
325 | || (pending = atomic_read(&i2400mu->rx_pending_count))) | ||
326 | ); | ||
327 | if (kthread_should_stop()) | ||
328 | break; | ||
329 | if (pending == 0) | ||
330 | continue; | ||
331 | rx_size = i2400mu->rx_size; | ||
332 | d_printf(2, dev, "RX: reading up to %d bytes\n", rx_size); | ||
333 | rx_skb = __netdev_alloc_skb(net_dev, rx_size, GFP_KERNEL); | ||
334 | if (rx_skb == NULL) { | ||
335 | dev_err(dev, "RX: can't allocate skb [%d bytes]\n", | ||
336 | rx_size); | ||
337 | msleep(50); /* give it some time? */ | ||
338 | continue; | ||
339 | } | ||
340 | |||
341 | /* Receive the message with the payloads */ | ||
342 | rx_skb = i2400mu_rx(i2400mu, rx_skb); | ||
343 | result = PTR_ERR(rx_skb); | ||
344 | if (IS_ERR(rx_skb)) | ||
345 | goto out; | ||
346 | atomic_dec(&i2400mu->rx_pending_count); | ||
347 | if (rx_skb->len == 0) { /* some ignorable condition */ | ||
348 | kfree_skb(rx_skb); | ||
349 | continue; | ||
350 | } | ||
351 | |||
352 | /* Deliver the message to the generic i2400m code */ | ||
353 | i2400mu->rx_size_cnt++; | ||
354 | i2400mu->rx_size_acc += rx_skb->len; | ||
355 | result = i2400m_rx(i2400m, rx_skb); | ||
356 | if (result == -EIO | ||
357 | && edc_inc(&i2400mu->urb_edc, | ||
358 | EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { | ||
359 | goto error_reset; | ||
360 | } | ||
361 | |||
362 | /* Maybe adjust RX buffer size */ | ||
363 | i2400mu_rx_size_maybe_shrink(i2400mu); | ||
364 | } | ||
365 | result = 0; | ||
366 | out: | ||
367 | d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result); | ||
368 | return result; | ||
369 | |||
370 | error_reset: | ||
371 | dev_err(dev, "RX: maximum errors in received buffer exceeded; " | ||
372 | "resetting device\n"); | ||
373 | usb_queue_reset_device(i2400mu->usb_iface); | ||
374 | goto out; | ||
375 | } | ||
376 | |||
377 | |||
378 | /* | ||
379 | * Start reading from the device | ||
380 | * | ||
381 | * @i2400m: device instance | ||
382 | * | ||
383 | * Notify the RX thread that there is data pending. | ||
384 | */ | ||
385 | void i2400mu_rx_kick(struct i2400mu *i2400mu) | ||
386 | { | ||
387 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
388 | struct device *dev = &i2400mu->usb_iface->dev; | ||
389 | |||
390 | d_fnstart(3, dev, "(i2400mu %p)\n", i2400m); | ||
391 | atomic_inc(&i2400mu->rx_pending_count); | ||
392 | wake_up_all(&i2400mu->rx_wq); | ||
393 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | ||
394 | } | ||
395 | |||
396 | |||
397 | int i2400mu_rx_setup(struct i2400mu *i2400mu) | ||
398 | { | ||
399 | int result = 0; | ||
400 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
401 | struct device *dev = &i2400mu->usb_iface->dev; | ||
402 | struct wimax_dev *wimax_dev = &i2400m->wimax_dev; | ||
403 | |||
404 | i2400mu->rx_kthread = kthread_run(i2400mu_rxd, i2400mu, "%s-rx", | ||
405 | wimax_dev->name); | ||
406 | if (IS_ERR(i2400mu->rx_kthread)) { | ||
407 | result = PTR_ERR(i2400mu->rx_kthread); | ||
408 | dev_err(dev, "RX: cannot start thread: %d\n", result); | ||
409 | } | ||
410 | return result; | ||
411 | } | ||
412 | |||
413 | void i2400mu_rx_release(struct i2400mu *i2400mu) | ||
414 | { | ||
415 | kthread_stop(i2400mu->rx_kthread); | ||
416 | } | ||
417 | |||
diff --git a/drivers/net/wimax/i2400m/usb-tx.c b/drivers/net/wimax/i2400m/usb-tx.c new file mode 100644 index 000000000000..dfd893356f49 --- /dev/null +++ b/drivers/net/wimax/i2400m/usb-tx.c | |||
@@ -0,0 +1,229 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * USB specific TX handling | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name of Intel Corporation nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | * | ||
34 | * | ||
35 | * Intel Corporation <linux-wimax@intel.com> | ||
36 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
37 | * - Initial implementation | ||
38 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
39 | * - Split transport/device specific | ||
40 | * | ||
41 | * | ||
42 | * Takes the TX messages in the i2400m's driver TX FIFO and sends them | ||
43 | * to the device until there are no more. | ||
44 | * | ||
45 | * If we fail sending the message, we just drop it. There isn't much | ||
46 | * we can do at this point. We could also retry, but the USB stack has | ||
47 | * already retried and still failed, so there is not much of a | ||
48 | * point. As well, most of the traffic is network, which has recovery | ||
49 | * methods for dropped packets. | ||
50 | * | ||
51 | * For sending we just obtain a FIFO buffer to send, send it to the | ||
52 | * USB bulk out, tell the TX FIFO code we have sent it; query for | ||
53 | * another one, etc... until done. | ||
54 | * | ||
55 | * We use a thread so we can call usb_autopm_enable() and | ||
56 | * usb_autopm_disable() for each transaction; this way when the device | ||
57 | * goes idle, it will suspend. It also has less overhead than a | ||
58 | * dedicated workqueue, as it is being used for a single task. | ||
59 | * | ||
60 | * ROADMAP | ||
61 | * | ||
62 | * i2400mu_tx_setup() | ||
63 | * i2400mu_tx_release() | ||
64 | * | ||
65 | * i2400mu_bus_tx_kick() - Called by the tx.c code when there | ||
66 | * is new data in the FIFO. | ||
67 | * i2400mu_txd() | ||
68 | * i2400m_tx_msg_get() | ||
69 | * i2400m_tx_msg_sent() | ||
70 | */ | ||
71 | #include "i2400m-usb.h" | ||
72 | |||
73 | |||
74 | #define D_SUBMODULE tx | ||
75 | #include "usb-debug-levels.h" | ||
76 | |||
77 | |||
78 | /* | ||
79 | * Get the next TX message in the TX FIFO and send it to the device | ||
80 | * | ||
81 | * Note that any iteration consumes a message to be sent, no matter if | ||
82 | * it succeeds or fails (we have no real way to retry or complain). | ||
83 | * | ||
84 | * Return: 0 if ok, < 0 errno code on hard error. | ||
85 | */ | ||
86 | static | ||
87 | int i2400mu_tx(struct i2400mu *i2400mu, struct i2400m_msg_hdr *tx_msg, | ||
88 | size_t tx_msg_size) | ||
89 | { | ||
90 | int result = 0; | ||
91 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
92 | struct device *dev = &i2400mu->usb_iface->dev; | ||
93 | int usb_pipe, sent_size, do_autopm; | ||
94 | struct usb_endpoint_descriptor *epd; | ||
95 | |||
96 | d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); | ||
97 | do_autopm = atomic_read(&i2400mu->do_autopm); | ||
98 | result = do_autopm ? | ||
99 | usb_autopm_get_interface(i2400mu->usb_iface) : 0; | ||
100 | if (result < 0) { | ||
101 | dev_err(dev, "TX: can't get autopm: %d\n", result); | ||
102 | do_autopm = 0; | ||
103 | } | ||
104 | epd = usb_get_epd(i2400mu->usb_iface, I2400MU_EP_BULK_OUT); | ||
105 | usb_pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); | ||
106 | retry: | ||
107 | result = usb_bulk_msg(i2400mu->usb_dev, usb_pipe, | ||
108 | tx_msg, tx_msg_size, &sent_size, HZ); | ||
109 | usb_mark_last_busy(i2400mu->usb_dev); | ||
110 | switch (result) { | ||
111 | case 0: | ||
112 | if (sent_size != tx_msg_size) { /* Too short? drop it */ | ||
113 | dev_err(dev, "TX: short write (%d B vs %zu " | ||
114 | "expected)\n", sent_size, tx_msg_size); | ||
115 | result = -EIO; | ||
116 | } | ||
117 | break; | ||
118 | case -EINVAL: /* while removing driver */ | ||
119 | case -ENODEV: /* dev disconnect ... */ | ||
120 | case -ENOENT: /* just ignore it */ | ||
121 | case -ESHUTDOWN: /* and exit */ | ||
122 | case -ECONNRESET: | ||
123 | result = -ESHUTDOWN; | ||
124 | break; | ||
125 | default: /* Some error? */ | ||
126 | if (edc_inc(&i2400mu->urb_edc, | ||
127 | EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { | ||
128 | dev_err(dev, "TX: maximum errors in URB " | ||
129 | "exceeded; resetting device\n"); | ||
130 | usb_queue_reset_device(i2400mu->usb_iface); | ||
131 | } else { | ||
132 | dev_err(dev, "TX: cannot send URB; retrying. " | ||
133 | "tx_msg @%zu %zu B [%d sent]: %d\n", | ||
134 | (void *) tx_msg - i2400m->tx_buf, | ||
135 | tx_msg_size, sent_size, result); | ||
136 | goto retry; | ||
137 | } | ||
138 | } | ||
139 | if (do_autopm) | ||
140 | usb_autopm_put_interface(i2400mu->usb_iface); | ||
141 | d_fnend(4, dev, "(i2400mu %p) = result\n", i2400mu); | ||
142 | return result; | ||
143 | } | ||
144 | |||
145 | |||
146 | /* | ||
147 | * Get the next TX message in the TX FIFO and send it to the device | ||
148 | * | ||
149 | * Note we exit the loop if i2400mu_tx() fails; that funtion only | ||
150 | * fails on hard error (failing to tx a buffer not being one of them, | ||
151 | * see its doc). | ||
152 | * | ||
153 | * Return: 0 | ||
154 | */ | ||
155 | static | ||
156 | int i2400mu_txd(void *_i2400mu) | ||
157 | { | ||
158 | int result = 0; | ||
159 | struct i2400mu *i2400mu = _i2400mu; | ||
160 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
161 | struct device *dev = &i2400mu->usb_iface->dev; | ||
162 | struct i2400m_msg_hdr *tx_msg; | ||
163 | size_t tx_msg_size; | ||
164 | |||
165 | d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); | ||
166 | |||
167 | while (1) { | ||
168 | d_printf(2, dev, "TX: waiting for messages\n"); | ||
169 | tx_msg = NULL; | ||
170 | wait_event_interruptible( | ||
171 | i2400mu->tx_wq, | ||
172 | (kthread_should_stop() /* check this first! */ | ||
173 | || (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size))) | ||
174 | ); | ||
175 | if (kthread_should_stop()) | ||
176 | break; | ||
177 | WARN_ON(tx_msg == NULL); /* should not happen...*/ | ||
178 | d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size); | ||
179 | d_dump(5, dev, tx_msg, tx_msg_size); | ||
180 | /* Yeah, we ignore errors ... not much we can do */ | ||
181 | i2400mu_tx(i2400mu, tx_msg, tx_msg_size); | ||
182 | i2400m_tx_msg_sent(i2400m); /* ack it, advance the FIFO */ | ||
183 | if (result < 0) | ||
184 | break; | ||
185 | } | ||
186 | d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result); | ||
187 | return result; | ||
188 | } | ||
189 | |||
190 | |||
191 | /* | ||
192 | * i2400m TX engine notifies us that there is data in the FIFO ready | ||
193 | * for TX | ||
194 | * | ||
195 | * If there is a URB in flight, don't do anything; when it finishes, | ||
196 | * it will see there is data in the FIFO and send it. Else, just | ||
197 | * submit a write. | ||
198 | */ | ||
199 | void i2400mu_bus_tx_kick(struct i2400m *i2400m) | ||
200 | { | ||
201 | struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); | ||
202 | struct device *dev = &i2400mu->usb_iface->dev; | ||
203 | |||
204 | d_fnstart(3, dev, "(i2400m %p) = void\n", i2400m); | ||
205 | wake_up_all(&i2400mu->tx_wq); | ||
206 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | ||
207 | } | ||
208 | |||
209 | |||
210 | int i2400mu_tx_setup(struct i2400mu *i2400mu) | ||
211 | { | ||
212 | int result = 0; | ||
213 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
214 | struct device *dev = &i2400mu->usb_iface->dev; | ||
215 | struct wimax_dev *wimax_dev = &i2400m->wimax_dev; | ||
216 | |||
217 | i2400mu->tx_kthread = kthread_run(i2400mu_txd, i2400mu, "%s-tx", | ||
218 | wimax_dev->name); | ||
219 | if (IS_ERR(i2400mu->tx_kthread)) { | ||
220 | result = PTR_ERR(i2400mu->tx_kthread); | ||
221 | dev_err(dev, "TX: cannot start thread: %d\n", result); | ||
222 | } | ||
223 | return result; | ||
224 | } | ||
225 | |||
226 | void i2400mu_tx_release(struct i2400mu *i2400mu) | ||
227 | { | ||
228 | kthread_stop(i2400mu->tx_kthread); | ||
229 | } | ||
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c new file mode 100644 index 000000000000..6d4b65fd9c17 --- /dev/null +++ b/drivers/net/wimax/i2400m/usb.c | |||
@@ -0,0 +1,591 @@ | |||
1 | /* | ||
2 | * Intel Wireless WiMAX Connection 2400m | ||
3 | * Linux driver model glue for USB device, reset & fw upload | ||
4 | * | ||
5 | * | ||
6 | * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com> | ||
7 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | ||
8 | * Yanir Lubetkin <yanirx.lubetkin@intel.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License version | ||
12 | * 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
22 | * 02110-1301, USA. | ||
23 | * | ||
24 | * | ||
25 | * See i2400m-usb.h for a general description of this driver. | ||
26 | * | ||
27 | * This file implements driver model glue, and hook ups for the | ||
28 | * generic driver to implement the bus-specific functions (device | ||
29 | * communication setup/tear down, firmware upload and resetting). | ||
30 | * | ||
31 | * ROADMAP | ||
32 | * | ||
33 | * i2400mu_probe() | ||
34 | * alloc_netdev()... | ||
35 | * i2400mu_netdev_setup() | ||
36 | * i2400mu_init() | ||
37 | * i2400m_netdev_setup() | ||
38 | * i2400m_setup()... | ||
39 | * | ||
40 | * i2400mu_disconnect | ||
41 | * i2400m_release() | ||
42 | * free_netdev() | ||
43 | * | ||
44 | * i2400mu_suspend() | ||
45 | * i2400m_cmd_enter_powersave() | ||
46 | * i2400mu_notification_release() | ||
47 | * | ||
48 | * i2400mu_resume() | ||
49 | * i2400mu_notification_setup() | ||
50 | * | ||
51 | * i2400mu_bus_dev_start() Called by i2400m_dev_start() [who is | ||
52 | * i2400mu_tx_setup() called by i2400m_setup()] | ||
53 | * i2400mu_rx_setup() | ||
54 | * i2400mu_notification_setup() | ||
55 | * | ||
56 | * i2400mu_bus_dev_stop() Called by i2400m_dev_stop() [who is | ||
57 | * i2400mu_notification_release() called by i2400m_release()] | ||
58 | * i2400mu_rx_release() | ||
59 | * i2400mu_tx_release() | ||
60 | * | ||
61 | * i2400mu_bus_reset() Called by i2400m->bus_reset | ||
62 | * __i2400mu_reset() | ||
63 | * __i2400mu_send_barker() | ||
64 | * usb_reset_device() | ||
65 | */ | ||
66 | #include "i2400m-usb.h" | ||
67 | #include <linux/wimax/i2400m.h> | ||
68 | #include <linux/debugfs.h> | ||
69 | |||
70 | |||
71 | #define D_SUBMODULE usb | ||
72 | #include "usb-debug-levels.h" | ||
73 | |||
74 | |||
75 | /* Our firmware file name */ | ||
76 | #define I2400MU_FW_FILE_NAME "i2400m-fw-usb-" I2400M_FW_VERSION ".sbcf" | ||
77 | |||
78 | static | ||
79 | int i2400mu_bus_dev_start(struct i2400m *i2400m) | ||
80 | { | ||
81 | int result; | ||
82 | struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); | ||
83 | struct device *dev = &i2400mu->usb_iface->dev; | ||
84 | |||
85 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
86 | result = i2400mu_tx_setup(i2400mu); | ||
87 | if (result < 0) | ||
88 | goto error_usb_tx_setup; | ||
89 | result = i2400mu_rx_setup(i2400mu); | ||
90 | if (result < 0) | ||
91 | goto error_usb_rx_setup; | ||
92 | result = i2400mu_notification_setup(i2400mu); | ||
93 | if (result < 0) | ||
94 | goto error_notif_setup; | ||
95 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); | ||
96 | return result; | ||
97 | |||
98 | error_notif_setup: | ||
99 | i2400mu_rx_release(i2400mu); | ||
100 | error_usb_rx_setup: | ||
101 | i2400mu_tx_release(i2400mu); | ||
102 | error_usb_tx_setup: | ||
103 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | ||
104 | return result; | ||
105 | } | ||
106 | |||
107 | |||
108 | static | ||
109 | void i2400mu_bus_dev_stop(struct i2400m *i2400m) | ||
110 | { | ||
111 | struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); | ||
112 | struct device *dev = &i2400mu->usb_iface->dev; | ||
113 | |||
114 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | ||
115 | i2400mu_notification_release(i2400mu); | ||
116 | i2400mu_rx_release(i2400mu); | ||
117 | i2400mu_tx_release(i2400mu); | ||
118 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | ||
119 | } | ||
120 | |||
121 | |||
122 | /* | ||
123 | * Sends a barker buffer to the device | ||
124 | * | ||
125 | * This helper will allocate a kmalloced buffer and use it to transmit | ||
126 | * (then free it). Reason for this is that other arches cannot use | ||
127 | * stack/vmalloc/text areas for DMA transfers. | ||
128 | * | ||
129 | * Error recovery here is simpler: anything is considered a hard error | ||
130 | * and will move the reset code to use a last-resort bus-based reset. | ||
131 | */ | ||
132 | static | ||
133 | int __i2400mu_send_barker(struct i2400mu *i2400mu, | ||
134 | const __le32 *barker, | ||
135 | size_t barker_size, | ||
136 | unsigned endpoint) | ||
137 | { | ||
138 | struct usb_endpoint_descriptor *epd = NULL; | ||
139 | int pipe, actual_len, ret; | ||
140 | struct device *dev = &i2400mu->usb_iface->dev; | ||
141 | void *buffer; | ||
142 | int do_autopm = 1; | ||
143 | |||
144 | ret = usb_autopm_get_interface(i2400mu->usb_iface); | ||
145 | if (ret < 0) { | ||
146 | dev_err(dev, "RESET: can't get autopm: %d\n", ret); | ||
147 | do_autopm = 0; | ||
148 | } | ||
149 | ret = -ENOMEM; | ||
150 | buffer = kmalloc(barker_size, GFP_KERNEL); | ||
151 | if (buffer == NULL) | ||
152 | goto error_kzalloc; | ||
153 | epd = usb_get_epd(i2400mu->usb_iface, endpoint); | ||
154 | pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); | ||
155 | memcpy(buffer, barker, barker_size); | ||
156 | ret = usb_bulk_msg(i2400mu->usb_dev, pipe, buffer, barker_size, | ||
157 | &actual_len, HZ); | ||
158 | if (ret < 0) { | ||
159 | if (ret != -EINVAL) | ||
160 | dev_err(dev, "E: barker error: %d\n", ret); | ||
161 | } else if (actual_len != barker_size) { | ||
162 | dev_err(dev, "E: only %d bytes transmitted\n", actual_len); | ||
163 | ret = -EIO; | ||
164 | } | ||
165 | kfree(buffer); | ||
166 | error_kzalloc: | ||
167 | if (do_autopm) | ||
168 | usb_autopm_put_interface(i2400mu->usb_iface); | ||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | |||
173 | /* | ||
174 | * Reset a device at different levels (warm, cold or bus) | ||
175 | * | ||
176 | * @i2400m: device descriptor | ||
177 | * @reset_type: soft, warm or bus reset (I2400M_RT_WARM/SOFT/BUS) | ||
178 | * | ||
179 | * Warm and cold resets get a USB reset if they fail. | ||
180 | * | ||
181 | * Warm reset: | ||
182 | * | ||
183 | * The device will be fully reset internally, but won't be | ||
184 | * disconnected from the USB bus (so no reenumeration will | ||
185 | * happen). Firmware upload will be neccessary. | ||
186 | * | ||
187 | * The device will send a reboot barker in the notification endpoint | ||
188 | * that will trigger the driver to reinitialize the state | ||
189 | * automatically from notif.c:i2400m_notification_grok() into | ||
190 | * i2400m_dev_bootstrap_delayed(). | ||
191 | * | ||
192 | * Cold and bus (USB) reset: | ||
193 | * | ||
194 | * The device will be fully reset internally, disconnected from the | ||
195 | * USB bus an a reenumeration will happen. Firmware upload will be | ||
196 | * neccessary. Thus, we don't do any locking or struct | ||
197 | * reinitialization, as we are going to be fully disconnected and | ||
198 | * reenumerated. | ||
199 | * | ||
200 | * Note we need to return -ENODEV if a warm reset was requested and we | ||
201 | * had to resort to a bus reset. See i2400m_op_reset(), wimax_reset() | ||
202 | * and wimax_dev->op_reset. | ||
203 | * | ||
204 | * WARNING: no driver state saved/fixed | ||
205 | */ | ||
206 | static | ||
207 | int i2400mu_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) | ||
208 | { | ||
209 | int result; | ||
210 | struct i2400mu *i2400mu = | ||
211 | container_of(i2400m, struct i2400mu, i2400m); | ||
212 | struct device *dev = i2400m_dev(i2400m); | ||
213 | static const __le32 i2400m_WARM_BOOT_BARKER[4] = { | ||
214 | __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), | ||
215 | __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), | ||
216 | __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), | ||
217 | __constant_cpu_to_le32(I2400M_WARM_RESET_BARKER), | ||
218 | }; | ||
219 | static const __le32 i2400m_COLD_BOOT_BARKER[4] = { | ||
220 | __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), | ||
221 | __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), | ||
222 | __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), | ||
223 | __constant_cpu_to_le32(I2400M_COLD_RESET_BARKER), | ||
224 | }; | ||
225 | |||
226 | d_fnstart(3, dev, "(i2400m %p rt %u)\n", i2400m, rt); | ||
227 | if (rt == I2400M_RT_WARM) | ||
228 | result = __i2400mu_send_barker(i2400mu, i2400m_WARM_BOOT_BARKER, | ||
229 | sizeof(i2400m_WARM_BOOT_BARKER), | ||
230 | I2400MU_EP_BULK_OUT); | ||
231 | else if (rt == I2400M_RT_COLD) | ||
232 | result = __i2400mu_send_barker(i2400mu, i2400m_COLD_BOOT_BARKER, | ||
233 | sizeof(i2400m_COLD_BOOT_BARKER), | ||
234 | I2400MU_EP_RESET_COLD); | ||
235 | else if (rt == I2400M_RT_BUS) { | ||
236 | do_bus_reset: | ||
237 | result = usb_reset_device(i2400mu->usb_dev); | ||
238 | switch (result) { | ||
239 | case 0: | ||
240 | case -EINVAL: /* device is gone */ | ||
241 | case -ENODEV: | ||
242 | case -ENOENT: | ||
243 | case -ESHUTDOWN: | ||
244 | result = rt == I2400M_RT_WARM ? -ENODEV : 0; | ||
245 | break; /* We assume the device is disconnected */ | ||
246 | default: | ||
247 | dev_err(dev, "USB reset failed (%d), giving up!\n", | ||
248 | result); | ||
249 | } | ||
250 | } else | ||
251 | BUG(); | ||
252 | if (result < 0 | ||
253 | && result != -EINVAL /* device is gone */ | ||
254 | && rt != I2400M_RT_BUS) { | ||
255 | dev_err(dev, "%s reset failed (%d); trying USB reset\n", | ||
256 | rt == I2400M_RT_WARM ? "warm" : "cold", result); | ||
257 | rt = I2400M_RT_BUS; | ||
258 | goto do_bus_reset; | ||
259 | } | ||
260 | d_fnend(3, dev, "(i2400m %p rt %u) = %d\n", i2400m, rt, result); | ||
261 | return result; | ||
262 | } | ||
263 | |||
264 | |||
265 | static | ||
266 | void i2400mu_netdev_setup(struct net_device *net_dev) | ||
267 | { | ||
268 | struct i2400m *i2400m = net_dev_to_i2400m(net_dev); | ||
269 | struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); | ||
270 | i2400mu_init(i2400mu); | ||
271 | i2400m_netdev_setup(net_dev); | ||
272 | } | ||
273 | |||
274 | |||
275 | /* | ||
276 | * Debug levels control; see debug.h | ||
277 | */ | ||
278 | struct d_level D_LEVEL[] = { | ||
279 | D_SUBMODULE_DEFINE(usb), | ||
280 | D_SUBMODULE_DEFINE(fw), | ||
281 | D_SUBMODULE_DEFINE(notif), | ||
282 | D_SUBMODULE_DEFINE(rx), | ||
283 | D_SUBMODULE_DEFINE(tx), | ||
284 | }; | ||
285 | size_t D_LEVEL_SIZE = ARRAY_SIZE(D_LEVEL); | ||
286 | |||
287 | |||
288 | #define __debugfs_register(prefix, name, parent) \ | ||
289 | do { \ | ||
290 | result = d_level_register_debugfs(prefix, name, parent); \ | ||
291 | if (result < 0) \ | ||
292 | goto error; \ | ||
293 | } while (0) | ||
294 | |||
295 | |||
296 | static | ||
297 | int i2400mu_debugfs_add(struct i2400mu *i2400mu) | ||
298 | { | ||
299 | int result; | ||
300 | struct device *dev = &i2400mu->usb_iface->dev; | ||
301 | struct dentry *dentry = i2400mu->i2400m.wimax_dev.debugfs_dentry; | ||
302 | struct dentry *fd; | ||
303 | |||
304 | dentry = debugfs_create_dir("i2400m-usb", dentry); | ||
305 | result = PTR_ERR(dentry); | ||
306 | if (IS_ERR(dentry)) { | ||
307 | if (result == -ENODEV) | ||
308 | result = 0; /* No debugfs support */ | ||
309 | goto error; | ||
310 | } | ||
311 | i2400mu->debugfs_dentry = dentry; | ||
312 | __debugfs_register("dl_", usb, dentry); | ||
313 | __debugfs_register("dl_", fw, dentry); | ||
314 | __debugfs_register("dl_", notif, dentry); | ||
315 | __debugfs_register("dl_", rx, dentry); | ||
316 | __debugfs_register("dl_", tx, dentry); | ||
317 | |||
318 | /* Don't touch these if you don't know what you are doing */ | ||
319 | fd = debugfs_create_u8("rx_size_auto_shrink", 0600, dentry, | ||
320 | &i2400mu->rx_size_auto_shrink); | ||
321 | result = PTR_ERR(fd); | ||
322 | if (IS_ERR(fd) && result != -ENODEV) { | ||
323 | dev_err(dev, "Can't create debugfs entry " | ||
324 | "rx_size_auto_shrink: %d\n", result); | ||
325 | goto error; | ||
326 | } | ||
327 | |||
328 | fd = debugfs_create_size_t("rx_size", 0600, dentry, | ||
329 | &i2400mu->rx_size); | ||
330 | result = PTR_ERR(fd); | ||
331 | if (IS_ERR(fd) && result != -ENODEV) { | ||
332 | dev_err(dev, "Can't create debugfs entry " | ||
333 | "rx_size: %d\n", result); | ||
334 | goto error; | ||
335 | } | ||
336 | |||
337 | return 0; | ||
338 | |||
339 | error: | ||
340 | debugfs_remove_recursive(i2400mu->debugfs_dentry); | ||
341 | return result; | ||
342 | } | ||
343 | |||
344 | |||
345 | /* | ||
346 | * Probe a i2400m interface and register it | ||
347 | * | ||
348 | * @iface: USB interface to link to | ||
349 | * @id: USB class/subclass/protocol id | ||
350 | * @returns: 0 if ok, < 0 errno code on error. | ||
351 | * | ||
352 | * Alloc a net device, initialize the bus-specific details and then | ||
353 | * calls the bus-generic initialization routine. That will register | ||
354 | * the wimax and netdev devices, upload the firmware [using | ||
355 | * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the | ||
356 | * communication with the device and then will start to talk to it to | ||
357 | * finnish setting it up. | ||
358 | */ | ||
359 | static | ||
360 | int i2400mu_probe(struct usb_interface *iface, | ||
361 | const struct usb_device_id *id) | ||
362 | { | ||
363 | int result; | ||
364 | struct net_device *net_dev; | ||
365 | struct device *dev = &iface->dev; | ||
366 | struct i2400m *i2400m; | ||
367 | struct i2400mu *i2400mu; | ||
368 | struct usb_device *usb_dev = interface_to_usbdev(iface); | ||
369 | |||
370 | if (usb_dev->speed != USB_SPEED_HIGH) | ||
371 | dev_err(dev, "device not connected as high speed\n"); | ||
372 | |||
373 | /* Allocate instance [calls i2400m_netdev_setup() on it]. */ | ||
374 | result = -ENOMEM; | ||
375 | net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d", | ||
376 | i2400mu_netdev_setup); | ||
377 | if (net_dev == NULL) { | ||
378 | dev_err(dev, "no memory for network device instance\n"); | ||
379 | goto error_alloc_netdev; | ||
380 | } | ||
381 | SET_NETDEV_DEV(net_dev, dev); | ||
382 | i2400m = net_dev_to_i2400m(net_dev); | ||
383 | i2400mu = container_of(i2400m, struct i2400mu, i2400m); | ||
384 | i2400m->wimax_dev.net_dev = net_dev; | ||
385 | i2400mu->usb_dev = usb_get_dev(usb_dev); | ||
386 | i2400mu->usb_iface = iface; | ||
387 | usb_set_intfdata(iface, i2400mu); | ||
388 | |||
389 | i2400m->bus_tx_block_size = I2400MU_BLK_SIZE; | ||
390 | i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX; | ||
391 | i2400m->bus_dev_start = i2400mu_bus_dev_start; | ||
392 | i2400m->bus_dev_stop = i2400mu_bus_dev_stop; | ||
393 | i2400m->bus_tx_kick = i2400mu_bus_tx_kick; | ||
394 | i2400m->bus_reset = i2400mu_bus_reset; | ||
395 | i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send; | ||
396 | i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack; | ||
397 | i2400m->bus_fw_name = I2400MU_FW_FILE_NAME; | ||
398 | i2400m->bus_bm_mac_addr_impaired = 0; | ||
399 | |||
400 | iface->needs_remote_wakeup = 1; /* autosuspend (15s delay) */ | ||
401 | device_init_wakeup(dev, 1); | ||
402 | usb_autopm_enable(i2400mu->usb_iface); | ||
403 | usb_dev->autosuspend_delay = 15 * HZ; | ||
404 | usb_dev->autosuspend_disabled = 0; | ||
405 | |||
406 | result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT); | ||
407 | if (result < 0) { | ||
408 | dev_err(dev, "cannot setup device: %d\n", result); | ||
409 | goto error_setup; | ||
410 | } | ||
411 | result = i2400mu_debugfs_add(i2400mu); | ||
412 | if (result < 0) { | ||
413 | dev_err(dev, "Can't register i2400mu's debugfs: %d\n", result); | ||
414 | goto error_debugfs_add; | ||
415 | } | ||
416 | return 0; | ||
417 | |||
418 | error_debugfs_add: | ||
419 | i2400m_release(i2400m); | ||
420 | error_setup: | ||
421 | usb_set_intfdata(iface, NULL); | ||
422 | usb_put_dev(i2400mu->usb_dev); | ||
423 | free_netdev(net_dev); | ||
424 | error_alloc_netdev: | ||
425 | return result; | ||
426 | } | ||
427 | |||
428 | |||
429 | /* | ||
430 | * Disconect a i2400m from the system. | ||
431 | * | ||
432 | * i2400m_stop() has been called before, so al the rx and tx contexts | ||
433 | * have been taken down already. Make sure the queue is stopped, | ||
434 | * unregister netdev and i2400m, free and kill. | ||
435 | */ | ||
436 | static | ||
437 | void i2400mu_disconnect(struct usb_interface *iface) | ||
438 | { | ||
439 | struct i2400mu *i2400mu = usb_get_intfdata(iface); | ||
440 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
441 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; | ||
442 | struct device *dev = &iface->dev; | ||
443 | |||
444 | d_fnstart(3, dev, "(iface %p i2400m %p)\n", iface, i2400m); | ||
445 | |||
446 | debugfs_remove_recursive(i2400mu->debugfs_dentry); | ||
447 | i2400m_release(i2400m); | ||
448 | usb_set_intfdata(iface, NULL); | ||
449 | usb_put_dev(i2400mu->usb_dev); | ||
450 | free_netdev(net_dev); | ||
451 | d_fnend(3, dev, "(iface %p i2400m %p) = void\n", iface, i2400m); | ||
452 | } | ||
453 | |||
454 | |||
455 | /* | ||
456 | * Get the device ready for USB port or system standby and hibernation | ||
457 | * | ||
458 | * USB port and system standby are handled the same. | ||
459 | * | ||
460 | * When the system hibernates, the USB device is powered down and then | ||
461 | * up, so we don't really have to do much here, as it will be seen as | ||
462 | * a reconnect. Still for simplicity we consider this case the same as | ||
463 | * suspend, so that the device has a chance to do notify the base | ||
464 | * station (if connected). | ||
465 | * | ||
466 | * So at the end, the three cases require common handling. | ||
467 | * | ||
468 | * If at the time of this call the device's firmware is not loaded, | ||
469 | * nothing has to be done. | ||
470 | * | ||
471 | * If the firmware is loaded, we need to: | ||
472 | * | ||
473 | * - tell the device to go into host interface power save mode, wait | ||
474 | * for it to ack | ||
475 | * | ||
476 | * This is quite more interesting than it is; we need to execute a | ||
477 | * command, but this time, we don't want the code in usb-{tx,rx}.c | ||
478 | * to call the usb_autopm_get/put_interface() barriers as it'd | ||
479 | * deadlock, so we need to decrement i2400mu->do_autopm, that acts | ||
480 | * as a poor man's semaphore. Ugly, but it works. | ||
481 | * | ||
482 | * As well, the device might refuse going to sleep for whichever | ||
483 | * reason. In this case we just fail. For system suspend/hibernate, | ||
484 | * we *can't* fail. We look at usb_dev->auto_pm to see if the | ||
485 | * suspend call comes from the USB stack or from the system and act | ||
486 | * in consequence. | ||
487 | * | ||
488 | * - stop the notification endpoint polling | ||
489 | */ | ||
490 | static | ||
491 | int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg) | ||
492 | { | ||
493 | int result = 0; | ||
494 | struct device *dev = &iface->dev; | ||
495 | struct i2400mu *i2400mu = usb_get_intfdata(iface); | ||
496 | struct usb_device *usb_dev = i2400mu->usb_dev; | ||
497 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
498 | |||
499 | d_fnstart(3, dev, "(iface %p pm_msg %u)\n", iface, pm_msg.event); | ||
500 | if (i2400m->updown == 0) | ||
501 | goto no_firmware; | ||
502 | d_printf(1, dev, "fw up, requesting standby\n"); | ||
503 | atomic_dec(&i2400mu->do_autopm); | ||
504 | result = i2400m_cmd_enter_powersave(i2400m); | ||
505 | atomic_inc(&i2400mu->do_autopm); | ||
506 | if (result < 0 && usb_dev->auto_pm == 0) { | ||
507 | /* System suspend, can't fail */ | ||
508 | dev_err(dev, "failed to suspend, will reset on resume\n"); | ||
509 | result = 0; | ||
510 | } | ||
511 | if (result < 0) | ||
512 | goto error_enter_powersave; | ||
513 | i2400mu_notification_release(i2400mu); | ||
514 | d_printf(1, dev, "fw up, got standby\n"); | ||
515 | error_enter_powersave: | ||
516 | no_firmware: | ||
517 | d_fnend(3, dev, "(iface %p pm_msg %u) = %d\n", | ||
518 | iface, pm_msg.event, result); | ||
519 | return result; | ||
520 | } | ||
521 | |||
522 | |||
523 | static | ||
524 | int i2400mu_resume(struct usb_interface *iface) | ||
525 | { | ||
526 | int ret = 0; | ||
527 | struct device *dev = &iface->dev; | ||
528 | struct i2400mu *i2400mu = usb_get_intfdata(iface); | ||
529 | struct i2400m *i2400m = &i2400mu->i2400m; | ||
530 | |||
531 | d_fnstart(3, dev, "(iface %p)\n", iface); | ||
532 | if (i2400m->updown == 0) { | ||
533 | d_printf(1, dev, "fw was down, no resume neeed\n"); | ||
534 | goto out; | ||
535 | } | ||
536 | d_printf(1, dev, "fw was up, resuming\n"); | ||
537 | i2400mu_notification_setup(i2400mu); | ||
538 | /* USB has flow control, so we don't need to give it time to | ||
539 | * come back; otherwise, we'd use something like a get-state | ||
540 | * command... */ | ||
541 | out: | ||
542 | d_fnend(3, dev, "(iface %p) = %d\n", iface, ret); | ||
543 | return ret; | ||
544 | } | ||
545 | |||
546 | |||
547 | static | ||
548 | struct usb_device_id i2400mu_id_table[] = { | ||
549 | { USB_DEVICE(0x8086, 0x0181) }, | ||
550 | { USB_DEVICE(0x8086, 0x1403) }, | ||
551 | { USB_DEVICE(0x8086, 0x1405) }, | ||
552 | { USB_DEVICE(0x8086, 0x0180) }, | ||
553 | { USB_DEVICE(0x8086, 0x0182) }, | ||
554 | { USB_DEVICE(0x8086, 0x1406) }, | ||
555 | { USB_DEVICE(0x8086, 0x1403) }, | ||
556 | { }, | ||
557 | }; | ||
558 | MODULE_DEVICE_TABLE(usb, i2400mu_id_table); | ||
559 | |||
560 | |||
561 | static | ||
562 | struct usb_driver i2400mu_driver = { | ||
563 | .name = KBUILD_MODNAME, | ||
564 | .suspend = i2400mu_suspend, | ||
565 | .resume = i2400mu_resume, | ||
566 | .probe = i2400mu_probe, | ||
567 | .disconnect = i2400mu_disconnect, | ||
568 | .id_table = i2400mu_id_table, | ||
569 | .supports_autosuspend = 1, | ||
570 | }; | ||
571 | |||
572 | static | ||
573 | int __init i2400mu_driver_init(void) | ||
574 | { | ||
575 | return usb_register(&i2400mu_driver); | ||
576 | } | ||
577 | module_init(i2400mu_driver_init); | ||
578 | |||
579 | |||
580 | static | ||
581 | void __exit i2400mu_driver_exit(void) | ||
582 | { | ||
583 | flush_scheduled_work(); /* for the stuff we schedule from sysfs.c */ | ||
584 | usb_deregister(&i2400mu_driver); | ||
585 | } | ||
586 | module_exit(i2400mu_driver_exit); | ||
587 | |||
588 | MODULE_AUTHOR("Intel Corporation <linux-wimax@intel.com>"); | ||
589 | MODULE_DESCRIPTION("Intel 2400M WiMAX networking for USB"); | ||
590 | MODULE_LICENSE("GPL"); | ||
591 | MODULE_FIRMWARE(I2400MU_FW_FILE_NAME); | ||
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 350157fcd080..4223672c4432 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
@@ -3836,7 +3836,7 @@ static int reset_atmel_card(struct net_device *dev) | |||
3836 | This routine is also responsible for initialising some | 3836 | This routine is also responsible for initialising some |
3837 | hardware-specific fields in the atmel_private structure, | 3837 | hardware-specific fields in the atmel_private structure, |
3838 | including a copy of the firmware's hostinfo stucture | 3838 | including a copy of the firmware's hostinfo stucture |
3839 | which is the route into the rest of the firmare datastructures. */ | 3839 | which is the route into the rest of the firmware datastructures. */ |
3840 | 3840 | ||
3841 | struct atmel_private *priv = netdev_priv(dev); | 3841 | struct atmel_private *priv = netdev_priv(dev); |
3842 | u8 configuration; | 3842 | u8 configuration; |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 1667065b86a7..823c2bf5e31e 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -1332,7 +1332,7 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv) | |||
1332 | IPW_AUX_HOST_RESET_REG_STOP_MASTER); | 1332 | IPW_AUX_HOST_RESET_REG_STOP_MASTER); |
1333 | 1333 | ||
1334 | /* Step 2. Wait for stop Master Assert | 1334 | /* Step 2. Wait for stop Master Assert |
1335 | * (not more then 50us, otherwise ret error */ | 1335 | * (not more than 50us, otherwise ret error */ |
1336 | i = 5; | 1336 | i = 5; |
1337 | do { | 1337 | do { |
1338 | udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY); | 1338 | udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY); |
@@ -1830,7 +1830,7 @@ static void ipw2100_down(struct ipw2100_priv *priv) | |||
1830 | cancel_delayed_work(&priv->rf_kill); | 1830 | cancel_delayed_work(&priv->rf_kill); |
1831 | } | 1831 | } |
1832 | 1832 | ||
1833 | /* Kill the firmare hang check timer */ | 1833 | /* Kill the firmware hang check timer */ |
1834 | if (!priv->stop_hang_check) { | 1834 | if (!priv->stop_hang_check) { |
1835 | priv->stop_hang_check = 1; | 1835 | priv->stop_hang_check = 1; |
1836 | cancel_delayed_work(&priv->hang_check); | 1836 | cancel_delayed_work(&priv->hang_check); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 37ad0d2fb64c..aee9cba13eb3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c | |||
@@ -184,8 +184,8 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align, | |||
184 | * Make room for new data, note that we increase both | 184 | * Make room for new data, note that we increase both |
185 | * headsize and tailsize when required. The tailsize is | 185 | * headsize and tailsize when required. The tailsize is |
186 | * only needed when ICV data needs to be inserted and | 186 | * only needed when ICV data needs to be inserted and |
187 | * the padding is smaller then the ICV data. | 187 | * the padding is smaller than the ICV data. |
188 | * When alignment requirements is greater then the | 188 | * When alignment requirements is greater than the |
189 | * ICV data we must trim the skb to the correct size | 189 | * ICV data we must trim the skb to the correct size |
190 | * because we need to remove the extra bytes. | 190 | * because we need to remove the extra bytes. |
191 | */ | 191 | */ |
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index dd0de3a9ed4e..7015f2480550 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c | |||
@@ -236,7 +236,7 @@ struct strip { | |||
236 | unsigned long tx_errors; /* Planned stuff */ | 236 | unsigned long tx_errors; /* Planned stuff */ |
237 | unsigned long rx_dropped; /* No memory for skb */ | 237 | unsigned long rx_dropped; /* No memory for skb */ |
238 | unsigned long tx_dropped; /* When MTU change */ | 238 | unsigned long tx_dropped; /* When MTU change */ |
239 | unsigned long rx_over_errors; /* Frame bigger then STRIP buf. */ | 239 | unsigned long rx_over_errors; /* Frame bigger than STRIP buf. */ |
240 | 240 | ||
241 | unsigned long pps_timer; /* Timer to determine pps */ | 241 | unsigned long pps_timer; /* Timer to determine pps */ |
242 | unsigned long rx_pps_count; /* Counter to determine pps */ | 242 | unsigned long rx_pps_count; /* Counter to determine pps */ |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c index 23a07fe15a2c..0b6b7730c716 100644 --- a/drivers/rtc/rtc-ds1511.c +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -630,7 +630,7 @@ ds1511_rtc_init(void) | |||
630 | static void __exit | 630 | static void __exit |
631 | ds1511_rtc_exit(void) | 631 | ds1511_rtc_exit(void) |
632 | { | 632 | { |
633 | return platform_driver_unregister(&ds1511_rtc_driver); | 633 | platform_driver_unregister(&ds1511_rtc_driver); |
634 | } | 634 | } |
635 | 635 | ||
636 | module_init(ds1511_rtc_init); | 636 | module_init(ds1511_rtc_init); |
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c index dc0b6224ad9b..7d1547b0070e 100644 --- a/drivers/rtc/rtc-stk17ta8.c +++ b/drivers/rtc/rtc-stk17ta8.c | |||
@@ -399,7 +399,7 @@ static __init int stk17ta8_init(void) | |||
399 | 399 | ||
400 | static __exit void stk17ta8_exit(void) | 400 | static __exit void stk17ta8_exit(void) |
401 | { | 401 | { |
402 | return platform_driver_unregister(&stk17ta8_rtc_driver); | 402 | platform_driver_unregister(&stk17ta8_rtc_driver); |
403 | } | 403 | } |
404 | 404 | ||
405 | module_init(stk17ta8_init); | 405 | module_init(stk17ta8_init); |
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 892e2878d61b..f8e05ce98621 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c | |||
@@ -535,8 +535,8 @@ static int dasd_eer_open(struct inode *inp, struct file *filp) | |||
535 | eerb->buffer_page_count > INT_MAX / PAGE_SIZE) { | 535 | eerb->buffer_page_count > INT_MAX / PAGE_SIZE) { |
536 | kfree(eerb); | 536 | kfree(eerb); |
537 | MESSAGE(KERN_WARNING, "can't open device since module " | 537 | MESSAGE(KERN_WARNING, "can't open device since module " |
538 | "parameter eer_pages is smaller then 1 or" | 538 | "parameter eer_pages is smaller than 1 or" |
539 | " bigger then %d", (int)(INT_MAX / PAGE_SIZE)); | 539 | " bigger than %d", (int)(INT_MAX / PAGE_SIZE)); |
540 | unlock_kernel(); | 540 | unlock_kernel(); |
541 | return -EINVAL; | 541 | return -EINVAL; |
542 | } | 542 | } |
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index aabbeb909cc6..d8a2289fcb69 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c | |||
@@ -427,7 +427,7 @@ static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) | |||
427 | buffer = priv->buffer + sizeof(int); | 427 | buffer = priv->buffer + sizeof(int); |
428 | } | 428 | } |
429 | /* | 429 | /* |
430 | * If the record is bigger then our buffer, we receive only | 430 | * If the record is bigger than our buffer, we receive only |
431 | * a part of it. We can get the rest later. | 431 | * a part of it. We can get the rest later. |
432 | */ | 432 | */ |
433 | if (iucv_data_count > NET_BUFFER_SIZE) | 433 | if (iucv_data_count > NET_BUFFER_SIZE) |
@@ -437,7 +437,7 @@ static int vmlogrdr_receive_data(struct vmlogrdr_priv_t *priv) | |||
437 | 0, buffer, iucv_data_count, | 437 | 0, buffer, iucv_data_count, |
438 | &priv->residual_length); | 438 | &priv->residual_length); |
439 | spin_unlock_bh(&priv->priv_lock); | 439 | spin_unlock_bh(&priv->priv_lock); |
440 | /* An rc of 5 indicates that the record was bigger then | 440 | /* An rc of 5 indicates that the record was bigger than |
441 | * the buffer, which is OK for us. A 9 indicates that the | 441 | * the buffer, which is OK for us. A 9 indicates that the |
442 | * record was purged befor we could receive it. | 442 | * record was purged befor we could receive it. |
443 | */ | 443 | */ |
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 3c298c7253ee..964769f66eac 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c | |||
@@ -633,7 +633,7 @@ static int orc_device_reset(struct orc_host * host, struct scsi_cmnd *cmd, unsig | |||
633 | return FAILED; | 633 | return FAILED; |
634 | } | 634 | } |
635 | 635 | ||
636 | /* Reset device is handled by the firmare, we fill in an SCB and | 636 | /* Reset device is handled by the firmware, we fill in an SCB and |
637 | fire it at the controller, it does the rest */ | 637 | fire it at the controller, it does the rest */ |
638 | scb->opcode = ORC_BUSDEVRST; | 638 | scb->opcode = ORC_BUSDEVRST; |
639 | scb->target = target; | 639 | scb->target = target; |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 8c64494444bf..311ed6dea726 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -1964,10 +1964,10 @@ lpfc_set_disctmo(struct lpfc_vport *vport) | |||
1964 | uint32_t tmo; | 1964 | uint32_t tmo; |
1965 | 1965 | ||
1966 | if (vport->port_state == LPFC_LOCAL_CFG_LINK) { | 1966 | if (vport->port_state == LPFC_LOCAL_CFG_LINK) { |
1967 | /* For FAN, timeout should be greater then edtov */ | 1967 | /* For FAN, timeout should be greater than edtov */ |
1968 | tmo = (((phba->fc_edtov + 999) / 1000) + 1); | 1968 | tmo = (((phba->fc_edtov + 999) / 1000) + 1); |
1969 | } else { | 1969 | } else { |
1970 | /* Normal discovery timeout should be > then ELS/CT timeout | 1970 | /* Normal discovery timeout should be > than ELS/CT timeout |
1971 | * FC spec states we need 3 * ratov for CT requests | 1971 | * FC spec states we need 3 * ratov for CT requests |
1972 | */ | 1972 | */ |
1973 | tmo = ((phba->fc_ratov * 3) + 3); | 1973 | tmo = ((phba->fc_ratov * 3) + 3); |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 01dfdc8696f8..a36a120561e2 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -420,7 +420,7 @@ lpfc_sli_next_iocb_slot (struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
420 | if (unlikely(pring->local_getidx >= max_cmd_idx)) { | 420 | if (unlikely(pring->local_getidx >= max_cmd_idx)) { |
421 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 421 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
422 | "0315 Ring %d issue: portCmdGet %d " | 422 | "0315 Ring %d issue: portCmdGet %d " |
423 | "is bigger then cmd ring %d\n", | 423 | "is bigger than cmd ring %d\n", |
424 | pring->ringno, | 424 | pring->ringno, |
425 | pring->local_getidx, max_cmd_idx); | 425 | pring->local_getidx, max_cmd_idx); |
426 | 426 | ||
@@ -1628,12 +1628,12 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
1628 | { | 1628 | { |
1629 | struct lpfc_pgp *pgp = &phba->port_gp[pring->ringno]; | 1629 | struct lpfc_pgp *pgp = &phba->port_gp[pring->ringno]; |
1630 | /* | 1630 | /* |
1631 | * Ring <ringno> handler: portRspPut <portRspPut> is bigger then | 1631 | * Ring <ringno> handler: portRspPut <portRspPut> is bigger than |
1632 | * rsp ring <portRspMax> | 1632 | * rsp ring <portRspMax> |
1633 | */ | 1633 | */ |
1634 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 1634 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
1635 | "0312 Ring %d handler: portRspPut %d " | 1635 | "0312 Ring %d handler: portRspPut %d " |
1636 | "is bigger then rsp ring %d\n", | 1636 | "is bigger than rsp ring %d\n", |
1637 | pring->ringno, le32_to_cpu(pgp->rspPutInx), | 1637 | pring->ringno, le32_to_cpu(pgp->rspPutInx), |
1638 | pring->numRiocb); | 1638 | pring->numRiocb); |
1639 | 1639 | ||
@@ -2083,12 +2083,12 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, | |||
2083 | portRspPut = le32_to_cpu(pgp->rspPutInx); | 2083 | portRspPut = le32_to_cpu(pgp->rspPutInx); |
2084 | if (portRspPut >= portRspMax) { | 2084 | if (portRspPut >= portRspMax) { |
2085 | /* | 2085 | /* |
2086 | * Ring <ringno> handler: portRspPut <portRspPut> is bigger then | 2086 | * Ring <ringno> handler: portRspPut <portRspPut> is bigger than |
2087 | * rsp ring <portRspMax> | 2087 | * rsp ring <portRspMax> |
2088 | */ | 2088 | */ |
2089 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | 2089 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, |
2090 | "0303 Ring %d handler: portRspPut %d " | 2090 | "0303 Ring %d handler: portRspPut %d " |
2091 | "is bigger then rsp ring %d\n", | 2091 | "is bigger than rsp ring %d\n", |
2092 | pring->ringno, portRspPut, portRspMax); | 2092 | pring->ringno, portRspPut, portRspMax); |
2093 | 2093 | ||
2094 | phba->link_state = LPFC_HBA_ERROR; | 2094 | phba->link_state = LPFC_HBA_ERROR; |
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 7dc62deb4087..9fdcd60c5493 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c | |||
@@ -1967,8 +1967,8 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) | |||
1967 | scb->state |= aor; | 1967 | scb->state |= aor; |
1968 | 1968 | ||
1969 | /* | 1969 | /* |
1970 | * Check if this command has firmare owenership. If | 1970 | * Check if this command has firmware ownership. If |
1971 | * yes, we cannot reset this command. Whenever, f/w | 1971 | * yes, we cannot reset this command. Whenever f/w |
1972 | * completes this command, we will return appropriate | 1972 | * completes this command, we will return appropriate |
1973 | * status from ISR. | 1973 | * status from ISR. |
1974 | */ | 1974 | */ |
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 8cb9240596ab..df09820e8916 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c | |||
@@ -128,7 +128,7 @@ | |||
128 | - Integrate ql12160_set_target_parameters() with 1280 version | 128 | - Integrate ql12160_set_target_parameters() with 1280 version |
129 | - Make qla1280_setup() non static | 129 | - Make qla1280_setup() non static |
130 | - Do not call qla1280_check_for_dead_scsi_bus() on every I/O request | 130 | - Do not call qla1280_check_for_dead_scsi_bus() on every I/O request |
131 | sent to the card - this command pauses the firmare!!! | 131 | sent to the card - this command pauses the firmware!!! |
132 | Rev 3.23.15 Beta March 19, 2002, Jes Sorensen | 132 | Rev 3.23.15 Beta March 19, 2002, Jes Sorensen |
133 | - Clean up qla1280.h - remove obsolete QL_DEBUG_LEVEL_x definitions | 133 | - Clean up qla1280.h - remove obsolete QL_DEBUG_LEVEL_x definitions |
134 | - Remove a pile of pointless and confusing (srb_t **) and | 134 | - Remove a pile of pointless and confusing (srb_t **) and |
@@ -659,7 +659,7 @@ static int qla1280_read_nvram(struct scsi_qla_host *ha) | |||
659 | /* The firmware interface is, um, interesting, in that the | 659 | /* The firmware interface is, um, interesting, in that the |
660 | * actual firmware image on the chip is little endian, thus, | 660 | * actual firmware image on the chip is little endian, thus, |
661 | * the process of taking that image to the CPU would end up | 661 | * the process of taking that image to the CPU would end up |
662 | * little endian. However, the firmare interface requires it | 662 | * little endian. However, the firmware interface requires it |
663 | * to be read a word (two bytes) at a time. | 663 | * to be read a word (two bytes) at a time. |
664 | * | 664 | * |
665 | * The net result of this would be that the word (and | 665 | * The net result of this would be that the word (and |
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index c577d79bd7e8..051b0f5e8c8e 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -392,7 +392,7 @@ int qla4xxx_get_firmware_status(struct scsi_qla_host * ha) | |||
392 | ha->iocb_hiwat -= IOCB_HIWAT_CUSHION; | 392 | ha->iocb_hiwat -= IOCB_HIWAT_CUSHION; |
393 | else | 393 | else |
394 | dev_info(&ha->pdev->dev, "WARNING!!! You have less than %d " | 394 | dev_info(&ha->pdev->dev, "WARNING!!! You have less than %d " |
395 | "firmare IOCBs available (%d).\n", | 395 | "firmware IOCBs available (%d).\n", |
396 | IOCB_HIWAT_CUSHION, ha->iocb_hiwat); | 396 | IOCB_HIWAT_CUSHION, ha->iocb_hiwat); |
397 | 397 | ||
398 | return QLA_SUCCESS; | 398 | return QLA_SUCCESS; |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 381838ebd460..d86ebea9350a 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -1650,7 +1650,7 @@ int scsi_error_handler(void *data) | |||
1650 | * We use TASK_INTERRUPTIBLE so that the thread is not | 1650 | * We use TASK_INTERRUPTIBLE so that the thread is not |
1651 | * counted against the load average as a running process. | 1651 | * counted against the load average as a running process. |
1652 | * We never actually get interrupted because kthread_run | 1652 | * We never actually get interrupted because kthread_run |
1653 | * disables singal delivery for the created thread. | 1653 | * disables signal delivery for the created thread. |
1654 | */ | 1654 | */ |
1655 | set_current_state(TASK_INTERRUPTIBLE); | 1655 | set_current_state(TASK_INTERRUPTIBLE); |
1656 | while (!kthread_should_stop()) { | 1656 | while (!kthread_should_stop()) { |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 18486b51668d..17914a346f71 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/kthread.h> | 33 | #include <linux/kthread.h> |
34 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
35 | #include <linux/async.h> | ||
35 | 36 | ||
36 | #include <scsi/scsi.h> | 37 | #include <scsi/scsi.h> |
37 | #include <scsi/scsi_cmnd.h> | 38 | #include <scsi/scsi_cmnd.h> |
@@ -179,6 +180,8 @@ int scsi_complete_async_scans(void) | |||
179 | spin_unlock(&async_scan_lock); | 180 | spin_unlock(&async_scan_lock); |
180 | 181 | ||
181 | kfree(data); | 182 | kfree(data); |
183 | /* Synchronize async operations globally */ | ||
184 | async_synchronize_full(); | ||
182 | return 0; | 185 | return 0; |
183 | } | 186 | } |
184 | 187 | ||
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 62b28d58e65e..e035c1114010 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
50 | #include <linux/string_helpers.h> | 50 | #include <linux/string_helpers.h> |
51 | #include <linux/async.h> | ||
51 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
52 | 53 | ||
53 | #include <scsi/scsi.h> | 54 | #include <scsi/scsi.h> |
@@ -1802,6 +1803,71 @@ static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen) | |||
1802 | return 0; | 1803 | return 0; |
1803 | } | 1804 | } |
1804 | 1805 | ||
1806 | /* | ||
1807 | * The asynchronous part of sd_probe | ||
1808 | */ | ||
1809 | static void sd_probe_async(void *data, async_cookie_t cookie) | ||
1810 | { | ||
1811 | struct scsi_disk *sdkp = data; | ||
1812 | struct scsi_device *sdp; | ||
1813 | struct gendisk *gd; | ||
1814 | u32 index; | ||
1815 | struct device *dev; | ||
1816 | |||
1817 | sdp = sdkp->device; | ||
1818 | gd = sdkp->disk; | ||
1819 | index = sdkp->index; | ||
1820 | dev = &sdp->sdev_gendev; | ||
1821 | |||
1822 | if (!sdp->request_queue->rq_timeout) { | ||
1823 | if (sdp->type != TYPE_MOD) | ||
1824 | blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); | ||
1825 | else | ||
1826 | blk_queue_rq_timeout(sdp->request_queue, | ||
1827 | SD_MOD_TIMEOUT); | ||
1828 | } | ||
1829 | |||
1830 | device_initialize(&sdkp->dev); | ||
1831 | sdkp->dev.parent = &sdp->sdev_gendev; | ||
1832 | sdkp->dev.class = &sd_disk_class; | ||
1833 | strncpy(sdkp->dev.bus_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE); | ||
1834 | |||
1835 | if (device_add(&sdkp->dev)) | ||
1836 | goto out_free_index; | ||
1837 | |||
1838 | get_device(&sdp->sdev_gendev); | ||
1839 | |||
1840 | if (index < SD_MAX_DISKS) { | ||
1841 | gd->major = sd_major((index & 0xf0) >> 4); | ||
1842 | gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); | ||
1843 | gd->minors = SD_MINORS; | ||
1844 | } | ||
1845 | gd->fops = &sd_fops; | ||
1846 | gd->private_data = &sdkp->driver; | ||
1847 | gd->queue = sdkp->device->request_queue; | ||
1848 | |||
1849 | sd_revalidate_disk(gd); | ||
1850 | |||
1851 | blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); | ||
1852 | |||
1853 | gd->driverfs_dev = &sdp->sdev_gendev; | ||
1854 | gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS; | ||
1855 | if (sdp->removable) | ||
1856 | gd->flags |= GENHD_FL_REMOVABLE; | ||
1857 | |||
1858 | dev_set_drvdata(dev, sdkp); | ||
1859 | add_disk(gd); | ||
1860 | sd_dif_config_host(sdkp); | ||
1861 | |||
1862 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", | ||
1863 | sdp->removable ? "removable " : ""); | ||
1864 | |||
1865 | return; | ||
1866 | |||
1867 | out_free_index: | ||
1868 | ida_remove(&sd_index_ida, index); | ||
1869 | } | ||
1870 | |||
1805 | /** | 1871 | /** |
1806 | * sd_probe - called during driver initialization and whenever a | 1872 | * sd_probe - called during driver initialization and whenever a |
1807 | * new scsi device is attached to the system. It is called once | 1873 | * new scsi device is attached to the system. It is called once |
@@ -1865,48 +1931,7 @@ static int sd_probe(struct device *dev) | |||
1865 | sdkp->openers = 0; | 1931 | sdkp->openers = 0; |
1866 | sdkp->previous_state = 1; | 1932 | sdkp->previous_state = 1; |
1867 | 1933 | ||
1868 | if (!sdp->request_queue->rq_timeout) { | 1934 | async_schedule(sd_probe_async, sdkp); |
1869 | if (sdp->type != TYPE_MOD) | ||
1870 | blk_queue_rq_timeout(sdp->request_queue, SD_TIMEOUT); | ||
1871 | else | ||
1872 | blk_queue_rq_timeout(sdp->request_queue, | ||
1873 | SD_MOD_TIMEOUT); | ||
1874 | } | ||
1875 | |||
1876 | device_initialize(&sdkp->dev); | ||
1877 | sdkp->dev.parent = &sdp->sdev_gendev; | ||
1878 | sdkp->dev.class = &sd_disk_class; | ||
1879 | strncpy(sdkp->dev.bus_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE); | ||
1880 | |||
1881 | if (device_add(&sdkp->dev)) | ||
1882 | goto out_free_index; | ||
1883 | |||
1884 | get_device(&sdp->sdev_gendev); | ||
1885 | |||
1886 | if (index < SD_MAX_DISKS) { | ||
1887 | gd->major = sd_major((index & 0xf0) >> 4); | ||
1888 | gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00); | ||
1889 | gd->minors = SD_MINORS; | ||
1890 | } | ||
1891 | gd->fops = &sd_fops; | ||
1892 | gd->private_data = &sdkp->driver; | ||
1893 | gd->queue = sdkp->device->request_queue; | ||
1894 | |||
1895 | sd_revalidate_disk(gd); | ||
1896 | |||
1897 | blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); | ||
1898 | |||
1899 | gd->driverfs_dev = &sdp->sdev_gendev; | ||
1900 | gd->flags = GENHD_FL_EXT_DEVT | GENHD_FL_DRIVERFS; | ||
1901 | if (sdp->removable) | ||
1902 | gd->flags |= GENHD_FL_REMOVABLE; | ||
1903 | |||
1904 | dev_set_drvdata(dev, sdkp); | ||
1905 | add_disk(gd); | ||
1906 | sd_dif_config_host(sdkp); | ||
1907 | |||
1908 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", | ||
1909 | sdp->removable ? "removable " : ""); | ||
1910 | 1935 | ||
1911 | return 0; | 1936 | return 0; |
1912 | 1937 | ||
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index daa00567bc44..1889a63ebc22 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -3123,7 +3123,7 @@ static int __init serial8250_init(void) | |||
3123 | if (nr_uarts > UART_NR) | 3123 | if (nr_uarts > UART_NR) |
3124 | nr_uarts = UART_NR; | 3124 | nr_uarts = UART_NR; |
3125 | 3125 | ||
3126 | printk(KERN_INFO "Serial: 8250/16550 driver" | 3126 | printk(KERN_INFO "Serial: 8250/16550 driver, " |
3127 | "%d ports, IRQ sharing %sabled\n", nr_uarts, | 3127 | "%d ports, IRQ sharing %sabled\n", nr_uarts, |
3128 | share_irqs ? "en" : "dis"); | 3128 | share_irqs ? "en" : "dis"); |
3129 | 3129 | ||
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 8b2c619a09f2..e642c22c80e2 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c | |||
@@ -1203,7 +1203,7 @@ static void e100_disable_txdma_channel(struct e100_serial *info) | |||
1203 | unsigned long flags; | 1203 | unsigned long flags; |
1204 | 1204 | ||
1205 | /* Disable output DMA channel for the serial port in question | 1205 | /* Disable output DMA channel for the serial port in question |
1206 | * ( set to something other then serialX) | 1206 | * ( set to something other than serialX) |
1207 | */ | 1207 | */ |
1208 | local_irq_save(flags); | 1208 | local_irq_save(flags); |
1209 | DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line)); | 1209 | DFLOW(DEBUG_LOG(info->line, "disable_txdma_channel %i\n", info->line)); |
@@ -1266,7 +1266,7 @@ static void e100_disable_rxdma_channel(struct e100_serial *info) | |||
1266 | unsigned long flags; | 1266 | unsigned long flags; |
1267 | 1267 | ||
1268 | /* Disable input DMA channel for the serial port in question | 1268 | /* Disable input DMA channel for the serial port in question |
1269 | * ( set to something other then serialX) | 1269 | * ( set to something other than serialX) |
1270 | */ | 1270 | */ |
1271 | local_irq_save(flags); | 1271 | local_irq_save(flags); |
1272 | if (info->line == 0) { | 1272 | if (info->line == 0) { |
diff --git a/drivers/spi/spi_lm70llp.c b/drivers/spi/spi_lm70llp.c index af6526767e2a..568c781ad91c 100644 --- a/drivers/spi/spi_lm70llp.c +++ b/drivers/spi/spi_lm70llp.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * spi_lm70llp.c - driver for lm70llp eval board for the LM70 sensor | 2 | * spi_lm70llp.c - driver for LM70EVAL-LLP board for the LM70 sensor |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com> | 4 | * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com> |
5 | * | 5 | * |
@@ -40,8 +40,12 @@ | |||
40 | * master controller driver. The hwmon/lm70 driver is a "SPI protocol | 40 | * master controller driver. The hwmon/lm70 driver is a "SPI protocol |
41 | * driver", layered on top of this one and usable without the lm70llp. | 41 | * driver", layered on top of this one and usable without the lm70llp. |
42 | * | 42 | * |
43 | * Datasheet and Schematic: | ||
43 | * The LM70 is a temperature sensor chip from National Semiconductor; its | 44 | * The LM70 is a temperature sensor chip from National Semiconductor; its |
44 | * datasheet is available at http://www.national.com/pf/LM/LM70.html | 45 | * datasheet is available at http://www.national.com/pf/LM/LM70.html |
46 | * The schematic for this particular board (the LM70EVAL-LLP) is | ||
47 | * available (on page 4) here: | ||
48 | * http://www.national.com/appinfo/tempsensors/files/LM70LLPEVALmanual.pdf | ||
45 | * | 49 | * |
46 | * Also see Documentation/spi/spi-lm70llp. The SPI<->parport code here is | 50 | * Also see Documentation/spi/spi-lm70llp. The SPI<->parport code here is |
47 | * (heavily) based on spi-butterfly by David Brownell. | 51 | * (heavily) based on spi-butterfly by David Brownell. |
@@ -64,7 +68,7 @@ | |||
64 | * | 68 | * |
65 | * Note that parport pin 13 actually gets inverted by the transistor | 69 | * Note that parport pin 13 actually gets inverted by the transistor |
66 | * arrangement which lets either the parport or the LM70 drive the | 70 | * arrangement which lets either the parport or the LM70 drive the |
67 | * SI/SO signal. | 71 | * SI/SO signal (see the schematic for details). |
68 | */ | 72 | */ |
69 | 73 | ||
70 | #define DRVNAME "spi-lm70llp" | 74 | #define DRVNAME "spi-lm70llp" |
@@ -106,12 +110,16 @@ static inline struct spi_lm70llp *spidev_to_pp(struct spi_device *spi) | |||
106 | static inline void deassertCS(struct spi_lm70llp *pp) | 110 | static inline void deassertCS(struct spi_lm70llp *pp) |
107 | { | 111 | { |
108 | u8 data = parport_read_data(pp->port); | 112 | u8 data = parport_read_data(pp->port); |
113 | |||
114 | data &= ~0x80; /* pull D7/SI-out low while de-asserted */ | ||
109 | parport_write_data(pp->port, data | nCS); | 115 | parport_write_data(pp->port, data | nCS); |
110 | } | 116 | } |
111 | 117 | ||
112 | static inline void assertCS(struct spi_lm70llp *pp) | 118 | static inline void assertCS(struct spi_lm70llp *pp) |
113 | { | 119 | { |
114 | u8 data = parport_read_data(pp->port); | 120 | u8 data = parport_read_data(pp->port); |
121 | |||
122 | data |= 0x80; /* pull D7/SI-out high so lm70 drives SO-in */ | ||
115 | parport_write_data(pp->port, data & ~nCS); | 123 | parport_write_data(pp->port, data & ~nCS); |
116 | } | 124 | } |
117 | 125 | ||
@@ -184,22 +192,7 @@ static void lm70_chipselect(struct spi_device *spi, int value) | |||
184 | */ | 192 | */ |
185 | static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits) | 193 | static u32 lm70_txrx(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits) |
186 | { | 194 | { |
187 | static u32 sio=0; | 195 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); |
188 | static int first_time=1; | ||
189 | |||
190 | /* First time: perform SPI bitbang and return the LSB of | ||
191 | * the result of the SPI call. | ||
192 | */ | ||
193 | if (first_time) { | ||
194 | sio = bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | ||
195 | first_time=0; | ||
196 | return (sio & 0x00ff); | ||
197 | } | ||
198 | /* Return the MSB of the result of the SPI call */ | ||
199 | else { | ||
200 | first_time=1; | ||
201 | return (sio >> 8); | ||
202 | } | ||
203 | } | 196 | } |
204 | 197 | ||
205 | static void spi_lm70llp_attach(struct parport *p) | 198 | static void spi_lm70llp_attach(struct parport *p) |
@@ -293,10 +286,9 @@ static void spi_lm70llp_attach(struct parport *p) | |||
293 | status = -ENODEV; | 286 | status = -ENODEV; |
294 | goto out_bitbang_stop; | 287 | goto out_bitbang_stop; |
295 | } | 288 | } |
296 | pp->spidev_lm70->bits_per_word = 16; | 289 | pp->spidev_lm70->bits_per_word = 8; |
297 | 290 | ||
298 | lm70llp = pp; | 291 | lm70llp = pp; |
299 | |||
300 | return; | 292 | return; |
301 | 293 | ||
302 | out_bitbang_stop: | 294 | out_bitbang_stop: |
@@ -326,7 +318,6 @@ static void spi_lm70llp_detach(struct parport *p) | |||
326 | 318 | ||
327 | /* power down */ | 319 | /* power down */ |
328 | parport_write_data(pp->port, 0); | 320 | parport_write_data(pp->port, 0); |
329 | msleep(10); | ||
330 | 321 | ||
331 | parport_release(pp->pd); | 322 | parport_release(pp->pd); |
332 | parport_unregister_device(pp->pd); | 323 | parport_unregister_device(pp->pd); |
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 289d81adfb9c..83babb0a1df7 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig | |||
@@ -150,4 +150,6 @@ source "drivers/usb/atm/Kconfig" | |||
150 | 150 | ||
151 | source "drivers/usb/gadget/Kconfig" | 151 | source "drivers/usb/gadget/Kconfig" |
152 | 152 | ||
153 | source "drivers/usb/otg/Kconfig" | ||
154 | |||
153 | endif # USB_SUPPORT | 155 | endif # USB_SUPPORT |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d50a99f70aee..00b47ea24f86 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -1275,7 +1275,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
1275 | struct acm *acm = usb_get_intfdata(intf); | 1275 | struct acm *acm = usb_get_intfdata(intf); |
1276 | int cnt; | 1276 | int cnt; |
1277 | 1277 | ||
1278 | if (acm->dev->auto_pm) { | 1278 | if (message.event & PM_EVENT_AUTO) { |
1279 | int b; | 1279 | int b; |
1280 | 1280 | ||
1281 | spin_lock_irq(&acm->read_lock); | 1281 | spin_lock_irq(&acm->read_lock); |
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 5a8ecc045e3f..3771d6e6d0cc 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -764,7 +764,8 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | |||
764 | 764 | ||
765 | mutex_lock(&desc->plock); | 765 | mutex_lock(&desc->plock); |
766 | #ifdef CONFIG_PM | 766 | #ifdef CONFIG_PM |
767 | if (interface_to_usbdev(desc->intf)->auto_pm && test_bit(WDM_IN_USE, &desc->flags)) { | 767 | if ((message.event & PM_EVENT_AUTO) && |
768 | test_bit(WDM_IN_USE, &desc->flags)) { | ||
768 | rv = -EBUSY; | 769 | rv = -EBUSY; |
769 | } else { | 770 | } else { |
770 | #endif | 771 | #endif |
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 43a863c5cc43..0f5c05f6f9df 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/kernel.h> | ||
24 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
25 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
26 | #include <linux/kref.h> | 27 | #include <linux/kref.h> |
@@ -482,7 +483,6 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, | |||
482 | int retval; | 483 | int retval; |
483 | int actual; | 484 | int actual; |
484 | unsigned long int n_bytes; | 485 | unsigned long int n_bytes; |
485 | int n; | ||
486 | int remaining; | 486 | int remaining; |
487 | int done; | 487 | int done; |
488 | int this_part; | 488 | int this_part; |
@@ -526,11 +526,8 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, | |||
526 | goto exit; | 526 | goto exit; |
527 | } | 527 | } |
528 | 528 | ||
529 | n_bytes = 12 + this_part; | 529 | n_bytes = roundup(12 + this_part, 4); |
530 | if (this_part % 4) | 530 | memset(buffer + 12 + this_part, 0, n_bytes - (12 + this_part)); |
531 | n_bytes += 4 - this_part % 4; | ||
532 | for (n = 12 + this_part; n < n_bytes; n++) | ||
533 | buffer[n] = 0; | ||
534 | 531 | ||
535 | retval = usb_bulk_msg(data->usb_dev, | 532 | retval = usb_bulk_msg(data->usb_dev, |
536 | usb_sndbulkpipe(data->usb_dev, | 533 | usb_sndbulkpipe(data->usb_dev, |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index aa79280df15d..26fece124e0e 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -981,9 +981,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
981 | return -EINVAL; | 981 | return -EINVAL; |
982 | if (!uurb->buffer) | 982 | if (!uurb->buffer) |
983 | return -EINVAL; | 983 | return -EINVAL; |
984 | if (uurb->signr != 0 && (uurb->signr < SIGRTMIN || | ||
985 | uurb->signr > SIGRTMAX)) | ||
986 | return -EINVAL; | ||
987 | if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && | 984 | if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && |
988 | (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { | 985 | (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) { |
989 | ifnum = findintfep(ps->dev, uurb->endpoint); | 986 | ifnum = findintfep(ps->dev, uurb->endpoint); |
@@ -1320,7 +1317,7 @@ static int get_urb32(struct usbdevfs_urb *kurb, | |||
1320 | if (__get_user(uptr, &uurb->buffer)) | 1317 | if (__get_user(uptr, &uurb->buffer)) |
1321 | return -EFAULT; | 1318 | return -EFAULT; |
1322 | kurb->buffer = compat_ptr(uptr); | 1319 | kurb->buffer = compat_ptr(uptr); |
1323 | if (__get_user(uptr, &uurb->buffer)) | 1320 | if (__get_user(uptr, &uurb->usercontext)) |
1324 | return -EFAULT; | 1321 | return -EFAULT; |
1325 | kurb->usercontext = compat_ptr(uptr); | 1322 | kurb->usercontext = compat_ptr(uptr); |
1326 | 1323 | ||
@@ -1401,8 +1398,6 @@ static int proc_disconnectsignal(struct dev_state *ps, void __user *arg) | |||
1401 | 1398 | ||
1402 | if (copy_from_user(&ds, arg, sizeof(ds))) | 1399 | if (copy_from_user(&ds, arg, sizeof(ds))) |
1403 | return -EFAULT; | 1400 | return -EFAULT; |
1404 | if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX)) | ||
1405 | return -EINVAL; | ||
1406 | ps->discsignr = ds.signr; | 1401 | ps->discsignr = ds.signr; |
1407 | ps->disccontext = ds.context; | 1402 | ps->disccontext = ds.context; |
1408 | return 0; | 1403 | return 0; |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 8c081308b0e2..98760553bc95 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -184,6 +184,20 @@ static int usb_unbind_device(struct device *dev) | |||
184 | return 0; | 184 | return 0; |
185 | } | 185 | } |
186 | 186 | ||
187 | /* | ||
188 | * Cancel any pending scheduled resets | ||
189 | * | ||
190 | * [see usb_queue_reset_device()] | ||
191 | * | ||
192 | * Called after unconfiguring / when releasing interfaces. See | ||
193 | * comments in __usb_queue_reset_device() regarding | ||
194 | * udev->reset_running. | ||
195 | */ | ||
196 | static void usb_cancel_queued_reset(struct usb_interface *iface) | ||
197 | { | ||
198 | if (iface->reset_running == 0) | ||
199 | cancel_work_sync(&iface->reset_ws); | ||
200 | } | ||
187 | 201 | ||
188 | /* called from driver core with dev locked */ | 202 | /* called from driver core with dev locked */ |
189 | static int usb_probe_interface(struct device *dev) | 203 | static int usb_probe_interface(struct device *dev) |
@@ -242,6 +256,7 @@ static int usb_probe_interface(struct device *dev) | |||
242 | mark_quiesced(intf); | 256 | mark_quiesced(intf); |
243 | intf->needs_remote_wakeup = 0; | 257 | intf->needs_remote_wakeup = 0; |
244 | intf->condition = USB_INTERFACE_UNBOUND; | 258 | intf->condition = USB_INTERFACE_UNBOUND; |
259 | usb_cancel_queued_reset(intf); | ||
245 | } else | 260 | } else |
246 | intf->condition = USB_INTERFACE_BOUND; | 261 | intf->condition = USB_INTERFACE_BOUND; |
247 | 262 | ||
@@ -272,6 +287,7 @@ static int usb_unbind_interface(struct device *dev) | |||
272 | usb_disable_interface(udev, intf); | 287 | usb_disable_interface(udev, intf); |
273 | 288 | ||
274 | driver->disconnect(intf); | 289 | driver->disconnect(intf); |
290 | usb_cancel_queued_reset(intf); | ||
275 | 291 | ||
276 | /* Reset other interface state. | 292 | /* Reset other interface state. |
277 | * We cannot do a Set-Interface if the device is suspended or | 293 | * We cannot do a Set-Interface if the device is suspended or |
@@ -279,9 +295,12 @@ static int usb_unbind_interface(struct device *dev) | |||
279 | * altsetting means creating new endpoint device entries). | 295 | * altsetting means creating new endpoint device entries). |
280 | * When either of these happens, defer the Set-Interface. | 296 | * When either of these happens, defer the Set-Interface. |
281 | */ | 297 | */ |
282 | if (intf->cur_altsetting->desc.bAlternateSetting == 0) | 298 | if (intf->cur_altsetting->desc.bAlternateSetting == 0) { |
283 | ; /* Already in altsetting 0 so skip Set-Interface */ | 299 | /* Already in altsetting 0 so skip Set-Interface. |
284 | else if (!error && intf->dev.power.status == DPM_ON) | 300 | * Just re-enable it without affecting the endpoint toggles. |
301 | */ | ||
302 | usb_enable_interface(udev, intf, false); | ||
303 | } else if (!error && intf->dev.power.status == DPM_ON) | ||
285 | usb_set_interface(udev, intf->altsetting[0]. | 304 | usb_set_interface(udev, intf->altsetting[0]. |
286 | desc.bInterfaceNumber, 0); | 305 | desc.bInterfaceNumber, 0); |
287 | else | 306 | else |
@@ -380,8 +399,10 @@ void usb_driver_release_interface(struct usb_driver *driver, | |||
380 | if (device_is_registered(dev)) { | 399 | if (device_is_registered(dev)) { |
381 | iface->condition = USB_INTERFACE_UNBINDING; | 400 | iface->condition = USB_INTERFACE_UNBINDING; |
382 | device_release_driver(dev); | 401 | device_release_driver(dev); |
402 | } else { | ||
403 | iface->condition = USB_INTERFACE_UNBOUND; | ||
404 | usb_cancel_queued_reset(iface); | ||
383 | } | 405 | } |
384 | |||
385 | dev->driver = NULL; | 406 | dev->driver = NULL; |
386 | usb_set_intfdata(iface, NULL); | 407 | usb_set_intfdata(iface, NULL); |
387 | 408 | ||
@@ -904,7 +925,7 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg) | |||
904 | } | 925 | } |
905 | 926 | ||
906 | /* Caller has locked udev's pm_mutex */ | 927 | /* Caller has locked udev's pm_mutex */ |
907 | static int usb_resume_device(struct usb_device *udev) | 928 | static int usb_resume_device(struct usb_device *udev, pm_message_t msg) |
908 | { | 929 | { |
909 | struct usb_device_driver *udriver; | 930 | struct usb_device_driver *udriver; |
910 | int status = 0; | 931 | int status = 0; |
@@ -922,7 +943,7 @@ static int usb_resume_device(struct usb_device *udev) | |||
922 | udev->reset_resume = 1; | 943 | udev->reset_resume = 1; |
923 | 944 | ||
924 | udriver = to_usb_device_driver(udev->dev.driver); | 945 | udriver = to_usb_device_driver(udev->dev.driver); |
925 | status = udriver->resume(udev); | 946 | status = udriver->resume(udev, msg); |
926 | 947 | ||
927 | done: | 948 | done: |
928 | dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status); | 949 | dev_vdbg(&udev->dev, "%s: status %d\n", __func__, status); |
@@ -942,7 +963,8 @@ static int usb_suspend_interface(struct usb_device *udev, | |||
942 | if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf)) | 963 | if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf)) |
943 | goto done; | 964 | goto done; |
944 | 965 | ||
945 | if (intf->condition == USB_INTERFACE_UNBOUND) /* This can't happen */ | 966 | /* This can happen; see usb_driver_release_interface() */ |
967 | if (intf->condition == USB_INTERFACE_UNBOUND) | ||
946 | goto done; | 968 | goto done; |
947 | driver = to_usb_driver(intf->dev.driver); | 969 | driver = to_usb_driver(intf->dev.driver); |
948 | 970 | ||
@@ -950,7 +972,7 @@ static int usb_suspend_interface(struct usb_device *udev, | |||
950 | status = driver->suspend(intf, msg); | 972 | status = driver->suspend(intf, msg); |
951 | if (status == 0) | 973 | if (status == 0) |
952 | mark_quiesced(intf); | 974 | mark_quiesced(intf); |
953 | else if (!udev->auto_pm) | 975 | else if (!(msg.event & PM_EVENT_AUTO)) |
954 | dev_err(&intf->dev, "%s error %d\n", | 976 | dev_err(&intf->dev, "%s error %d\n", |
955 | "suspend", status); | 977 | "suspend", status); |
956 | } else { | 978 | } else { |
@@ -968,7 +990,7 @@ static int usb_suspend_interface(struct usb_device *udev, | |||
968 | 990 | ||
969 | /* Caller has locked intf's usb_device's pm_mutex */ | 991 | /* Caller has locked intf's usb_device's pm_mutex */ |
970 | static int usb_resume_interface(struct usb_device *udev, | 992 | static int usb_resume_interface(struct usb_device *udev, |
971 | struct usb_interface *intf, int reset_resume) | 993 | struct usb_interface *intf, pm_message_t msg, int reset_resume) |
972 | { | 994 | { |
973 | struct usb_driver *driver; | 995 | struct usb_driver *driver; |
974 | int status = 0; | 996 | int status = 0; |
@@ -1092,7 +1114,7 @@ static int autosuspend_check(struct usb_device *udev, int reschedule) | |||
1092 | if (reschedule) { | 1114 | if (reschedule) { |
1093 | if (!timer_pending(&udev->autosuspend.timer)) { | 1115 | if (!timer_pending(&udev->autosuspend.timer)) { |
1094 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, | 1116 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, |
1095 | round_jiffies_relative(suspend_time - j)); | 1117 | round_jiffies_up_relative(suspend_time - j)); |
1096 | } | 1118 | } |
1097 | return -EAGAIN; | 1119 | return -EAGAIN; |
1098 | } | 1120 | } |
@@ -1119,10 +1141,9 @@ static inline int autosuspend_check(struct usb_device *udev, int reschedule) | |||
1119 | * all the interfaces which were suspended are resumed so that they remain | 1141 | * all the interfaces which were suspended are resumed so that they remain |
1120 | * in the same state as the device. | 1142 | * in the same state as the device. |
1121 | * | 1143 | * |
1122 | * If an autosuspend is in progress (@udev->auto_pm is set), the routine | 1144 | * If an autosuspend is in progress the routine checks first to make sure |
1123 | * checks first to make sure that neither the device itself or any of its | 1145 | * that neither the device itself or any of its active interfaces is in use |
1124 | * active interfaces is in use (pm_usage_cnt is greater than 0). If they | 1146 | * (pm_usage_cnt is greater than 0). If they are, the autosuspend fails. |
1125 | * are, the autosuspend fails. | ||
1126 | * | 1147 | * |
1127 | * If the suspend succeeds, the routine recursively queues an autosuspend | 1148 | * If the suspend succeeds, the routine recursively queues an autosuspend |
1128 | * request for @udev's parent device, thereby propagating the change up | 1149 | * request for @udev's parent device, thereby propagating the change up |
@@ -1157,7 +1178,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1157 | 1178 | ||
1158 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); | 1179 | udev->do_remote_wakeup = device_may_wakeup(&udev->dev); |
1159 | 1180 | ||
1160 | if (udev->auto_pm) { | 1181 | if (msg.event & PM_EVENT_AUTO) { |
1161 | status = autosuspend_check(udev, 0); | 1182 | status = autosuspend_check(udev, 0); |
1162 | if (status < 0) | 1183 | if (status < 0) |
1163 | goto done; | 1184 | goto done; |
@@ -1177,13 +1198,16 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1177 | 1198 | ||
1178 | /* If the suspend failed, resume interfaces that did get suspended */ | 1199 | /* If the suspend failed, resume interfaces that did get suspended */ |
1179 | if (status != 0) { | 1200 | if (status != 0) { |
1201 | pm_message_t msg2; | ||
1202 | |||
1203 | msg2.event = msg.event ^ (PM_EVENT_SUSPEND | PM_EVENT_RESUME); | ||
1180 | while (--i >= 0) { | 1204 | while (--i >= 0) { |
1181 | intf = udev->actconfig->interface[i]; | 1205 | intf = udev->actconfig->interface[i]; |
1182 | usb_resume_interface(udev, intf, 0); | 1206 | usb_resume_interface(udev, intf, msg2, 0); |
1183 | } | 1207 | } |
1184 | 1208 | ||
1185 | /* Try another autosuspend when the interfaces aren't busy */ | 1209 | /* Try another autosuspend when the interfaces aren't busy */ |
1186 | if (udev->auto_pm) | 1210 | if (msg.event & PM_EVENT_AUTO) |
1187 | autosuspend_check(udev, status == -EBUSY); | 1211 | autosuspend_check(udev, status == -EBUSY); |
1188 | 1212 | ||
1189 | /* If the suspend succeeded then prevent any more URB submissions, | 1213 | /* If the suspend succeeded then prevent any more URB submissions, |
@@ -1213,6 +1237,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1213 | /** | 1237 | /** |
1214 | * usb_resume_both - resume a USB device and its interfaces | 1238 | * usb_resume_both - resume a USB device and its interfaces |
1215 | * @udev: the usb_device to resume | 1239 | * @udev: the usb_device to resume |
1240 | * @msg: Power Management message describing this state transition | ||
1216 | * | 1241 | * |
1217 | * This is the central routine for resuming USB devices. It calls the | 1242 | * This is the central routine for resuming USB devices. It calls the |
1218 | * the resume method for @udev and then calls the resume methods for all | 1243 | * the resume method for @udev and then calls the resume methods for all |
@@ -1238,7 +1263,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1238 | * | 1263 | * |
1239 | * This routine can run only in process context. | 1264 | * This routine can run only in process context. |
1240 | */ | 1265 | */ |
1241 | static int usb_resume_both(struct usb_device *udev) | 1266 | static int usb_resume_both(struct usb_device *udev, pm_message_t msg) |
1242 | { | 1267 | { |
1243 | int status = 0; | 1268 | int status = 0; |
1244 | int i; | 1269 | int i; |
@@ -1254,14 +1279,15 @@ static int usb_resume_both(struct usb_device *udev) | |||
1254 | 1279 | ||
1255 | /* Propagate the resume up the tree, if necessary */ | 1280 | /* Propagate the resume up the tree, if necessary */ |
1256 | if (udev->state == USB_STATE_SUSPENDED) { | 1281 | if (udev->state == USB_STATE_SUSPENDED) { |
1257 | if (udev->auto_pm && udev->autoresume_disabled) { | 1282 | if ((msg.event & PM_EVENT_AUTO) && |
1283 | udev->autoresume_disabled) { | ||
1258 | status = -EPERM; | 1284 | status = -EPERM; |
1259 | goto done; | 1285 | goto done; |
1260 | } | 1286 | } |
1261 | if (parent) { | 1287 | if (parent) { |
1262 | status = usb_autoresume_device(parent); | 1288 | status = usb_autoresume_device(parent); |
1263 | if (status == 0) { | 1289 | if (status == 0) { |
1264 | status = usb_resume_device(udev); | 1290 | status = usb_resume_device(udev, msg); |
1265 | if (status || udev->state == | 1291 | if (status || udev->state == |
1266 | USB_STATE_NOTATTACHED) { | 1292 | USB_STATE_NOTATTACHED) { |
1267 | usb_autosuspend_device(parent); | 1293 | usb_autosuspend_device(parent); |
@@ -1284,15 +1310,16 @@ static int usb_resume_both(struct usb_device *udev) | |||
1284 | /* We can't progagate beyond the USB subsystem, | 1310 | /* We can't progagate beyond the USB subsystem, |
1285 | * so if a root hub's controller is suspended | 1311 | * so if a root hub's controller is suspended |
1286 | * then we're stuck. */ | 1312 | * then we're stuck. */ |
1287 | status = usb_resume_device(udev); | 1313 | status = usb_resume_device(udev, msg); |
1288 | } | 1314 | } |
1289 | } else if (udev->reset_resume) | 1315 | } else if (udev->reset_resume) |
1290 | status = usb_resume_device(udev); | 1316 | status = usb_resume_device(udev, msg); |
1291 | 1317 | ||
1292 | if (status == 0 && udev->actconfig) { | 1318 | if (status == 0 && udev->actconfig) { |
1293 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | 1319 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { |
1294 | intf = udev->actconfig->interface[i]; | 1320 | intf = udev->actconfig->interface[i]; |
1295 | usb_resume_interface(udev, intf, udev->reset_resume); | 1321 | usb_resume_interface(udev, intf, msg, |
1322 | udev->reset_resume); | ||
1296 | } | 1323 | } |
1297 | } | 1324 | } |
1298 | 1325 | ||
@@ -1320,13 +1347,13 @@ static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt) | |||
1320 | udev->last_busy = jiffies; | 1347 | udev->last_busy = jiffies; |
1321 | if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) { | 1348 | if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) { |
1322 | if (udev->state == USB_STATE_SUSPENDED) | 1349 | if (udev->state == USB_STATE_SUSPENDED) |
1323 | status = usb_resume_both(udev); | 1350 | status = usb_resume_both(udev, PMSG_AUTO_RESUME); |
1324 | if (status != 0) | 1351 | if (status != 0) |
1325 | udev->pm_usage_cnt -= inc_usage_cnt; | 1352 | udev->pm_usage_cnt -= inc_usage_cnt; |
1326 | else if (inc_usage_cnt) | 1353 | else if (inc_usage_cnt) |
1327 | udev->last_busy = jiffies; | 1354 | udev->last_busy = jiffies; |
1328 | } else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) { | 1355 | } else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) { |
1329 | status = usb_suspend_both(udev, PMSG_SUSPEND); | 1356 | status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); |
1330 | } | 1357 | } |
1331 | usb_pm_unlock(udev); | 1358 | usb_pm_unlock(udev); |
1332 | return status; | 1359 | return status; |
@@ -1341,6 +1368,19 @@ void usb_autosuspend_work(struct work_struct *work) | |||
1341 | usb_autopm_do_device(udev, 0); | 1368 | usb_autopm_do_device(udev, 0); |
1342 | } | 1369 | } |
1343 | 1370 | ||
1371 | /* usb_autoresume_work - callback routine to autoresume a USB device */ | ||
1372 | void usb_autoresume_work(struct work_struct *work) | ||
1373 | { | ||
1374 | struct usb_device *udev = | ||
1375 | container_of(work, struct usb_device, autoresume); | ||
1376 | |||
1377 | /* Wake it up, let the drivers do their thing, and then put it | ||
1378 | * back to sleep. | ||
1379 | */ | ||
1380 | if (usb_autopm_do_device(udev, 1) == 0) | ||
1381 | usb_autopm_do_device(udev, -1); | ||
1382 | } | ||
1383 | |||
1344 | /** | 1384 | /** |
1345 | * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces | 1385 | * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces |
1346 | * @udev: the usb_device to autosuspend | 1386 | * @udev: the usb_device to autosuspend |
@@ -1437,13 +1477,14 @@ static int usb_autopm_do_interface(struct usb_interface *intf, | |||
1437 | udev->last_busy = jiffies; | 1477 | udev->last_busy = jiffies; |
1438 | if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) { | 1478 | if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) { |
1439 | if (udev->state == USB_STATE_SUSPENDED) | 1479 | if (udev->state == USB_STATE_SUSPENDED) |
1440 | status = usb_resume_both(udev); | 1480 | status = usb_resume_both(udev, |
1481 | PMSG_AUTO_RESUME); | ||
1441 | if (status != 0) | 1482 | if (status != 0) |
1442 | intf->pm_usage_cnt -= inc_usage_cnt; | 1483 | intf->pm_usage_cnt -= inc_usage_cnt; |
1443 | else | 1484 | else |
1444 | udev->last_busy = jiffies; | 1485 | udev->last_busy = jiffies; |
1445 | } else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) { | 1486 | } else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) { |
1446 | status = usb_suspend_both(udev, PMSG_SUSPEND); | 1487 | status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); |
1447 | } | 1488 | } |
1448 | } | 1489 | } |
1449 | usb_pm_unlock(udev); | 1490 | usb_pm_unlock(udev); |
@@ -1492,6 +1533,45 @@ void usb_autopm_put_interface(struct usb_interface *intf) | |||
1492 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface); | 1533 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface); |
1493 | 1534 | ||
1494 | /** | 1535 | /** |
1536 | * usb_autopm_put_interface_async - decrement a USB interface's PM-usage counter | ||
1537 | * @intf: the usb_interface whose counter should be decremented | ||
1538 | * | ||
1539 | * This routine does essentially the same thing as | ||
1540 | * usb_autopm_put_interface(): it decrements @intf's usage counter and | ||
1541 | * queues a delayed autosuspend request if the counter is <= 0. The | ||
1542 | * difference is that it does not acquire the device's pm_mutex; | ||
1543 | * callers must handle all synchronization issues themselves. | ||
1544 | * | ||
1545 | * Typically a driver would call this routine during an URB's completion | ||
1546 | * handler, if no more URBs were pending. | ||
1547 | * | ||
1548 | * This routine can run in atomic context. | ||
1549 | */ | ||
1550 | void usb_autopm_put_interface_async(struct usb_interface *intf) | ||
1551 | { | ||
1552 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1553 | int status = 0; | ||
1554 | |||
1555 | if (intf->condition == USB_INTERFACE_UNBOUND) { | ||
1556 | status = -ENODEV; | ||
1557 | } else { | ||
1558 | udev->last_busy = jiffies; | ||
1559 | --intf->pm_usage_cnt; | ||
1560 | if (udev->autosuspend_disabled || udev->autosuspend_delay < 0) | ||
1561 | status = -EPERM; | ||
1562 | else if (intf->pm_usage_cnt <= 0 && | ||
1563 | !timer_pending(&udev->autosuspend.timer)) { | ||
1564 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, | ||
1565 | round_jiffies_up_relative( | ||
1566 | udev->autosuspend_delay)); | ||
1567 | } | ||
1568 | } | ||
1569 | dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", | ||
1570 | __func__, status, intf->pm_usage_cnt); | ||
1571 | } | ||
1572 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async); | ||
1573 | |||
1574 | /** | ||
1495 | * usb_autopm_get_interface - increment a USB interface's PM-usage counter | 1575 | * usb_autopm_get_interface - increment a USB interface's PM-usage counter |
1496 | * @intf: the usb_interface whose counter should be incremented | 1576 | * @intf: the usb_interface whose counter should be incremented |
1497 | * | 1577 | * |
@@ -1537,6 +1617,37 @@ int usb_autopm_get_interface(struct usb_interface *intf) | |||
1537 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface); | 1617 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface); |
1538 | 1618 | ||
1539 | /** | 1619 | /** |
1620 | * usb_autopm_get_interface_async - increment a USB interface's PM-usage counter | ||
1621 | * @intf: the usb_interface whose counter should be incremented | ||
1622 | * | ||
1623 | * This routine does much the same thing as | ||
1624 | * usb_autopm_get_interface(): it increments @intf's usage counter and | ||
1625 | * queues an autoresume request if the result is > 0. The differences | ||
1626 | * are that it does not acquire the device's pm_mutex (callers must | ||
1627 | * handle all synchronization issues themselves), and it does not | ||
1628 | * autoresume the device directly (it only queues a request). After a | ||
1629 | * successful call, the device will generally not yet be resumed. | ||
1630 | * | ||
1631 | * This routine can run in atomic context. | ||
1632 | */ | ||
1633 | int usb_autopm_get_interface_async(struct usb_interface *intf) | ||
1634 | { | ||
1635 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1636 | int status = 0; | ||
1637 | |||
1638 | if (intf->condition == USB_INTERFACE_UNBOUND) | ||
1639 | status = -ENODEV; | ||
1640 | else if (udev->autoresume_disabled) | ||
1641 | status = -EPERM; | ||
1642 | else if (++intf->pm_usage_cnt > 0 && udev->state == USB_STATE_SUSPENDED) | ||
1643 | queue_work(ksuspend_usb_wq, &udev->autoresume); | ||
1644 | dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", | ||
1645 | __func__, status, intf->pm_usage_cnt); | ||
1646 | return status; | ||
1647 | } | ||
1648 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async); | ||
1649 | |||
1650 | /** | ||
1540 | * usb_autopm_set_interface - set a USB interface's autosuspend state | 1651 | * usb_autopm_set_interface - set a USB interface's autosuspend state |
1541 | * @intf: the usb_interface whose state should be set | 1652 | * @intf: the usb_interface whose state should be set |
1542 | * | 1653 | * |
@@ -1563,6 +1674,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_set_interface); | |||
1563 | void usb_autosuspend_work(struct work_struct *work) | 1674 | void usb_autosuspend_work(struct work_struct *work) |
1564 | {} | 1675 | {} |
1565 | 1676 | ||
1677 | void usb_autoresume_work(struct work_struct *work) | ||
1678 | {} | ||
1679 | |||
1566 | #endif /* CONFIG_USB_SUSPEND */ | 1680 | #endif /* CONFIG_USB_SUSPEND */ |
1567 | 1681 | ||
1568 | /** | 1682 | /** |
@@ -1595,6 +1709,7 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg) | |||
1595 | /** | 1709 | /** |
1596 | * usb_external_resume_device - external resume of a USB device and its interfaces | 1710 | * usb_external_resume_device - external resume of a USB device and its interfaces |
1597 | * @udev: the usb_device to resume | 1711 | * @udev: the usb_device to resume |
1712 | * @msg: Power Management message describing this state transition | ||
1598 | * | 1713 | * |
1599 | * This routine handles external resume requests: ones not generated | 1714 | * This routine handles external resume requests: ones not generated |
1600 | * internally by a USB driver (autoresume) but rather coming from the user | 1715 | * internally by a USB driver (autoresume) but rather coming from the user |
@@ -1603,13 +1718,13 @@ int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg) | |||
1603 | * | 1718 | * |
1604 | * The caller must hold @udev's device lock. | 1719 | * The caller must hold @udev's device lock. |
1605 | */ | 1720 | */ |
1606 | int usb_external_resume_device(struct usb_device *udev) | 1721 | int usb_external_resume_device(struct usb_device *udev, pm_message_t msg) |
1607 | { | 1722 | { |
1608 | int status; | 1723 | int status; |
1609 | 1724 | ||
1610 | usb_pm_lock(udev); | 1725 | usb_pm_lock(udev); |
1611 | udev->auto_pm = 0; | 1726 | udev->auto_pm = 0; |
1612 | status = usb_resume_both(udev); | 1727 | status = usb_resume_both(udev, msg); |
1613 | udev->last_busy = jiffies; | 1728 | udev->last_busy = jiffies; |
1614 | usb_pm_unlock(udev); | 1729 | usb_pm_unlock(udev); |
1615 | if (status == 0) | 1730 | if (status == 0) |
@@ -1622,7 +1737,7 @@ int usb_external_resume_device(struct usb_device *udev) | |||
1622 | return status; | 1737 | return status; |
1623 | } | 1738 | } |
1624 | 1739 | ||
1625 | int usb_suspend(struct device *dev, pm_message_t message) | 1740 | int usb_suspend(struct device *dev, pm_message_t msg) |
1626 | { | 1741 | { |
1627 | struct usb_device *udev; | 1742 | struct usb_device *udev; |
1628 | 1743 | ||
@@ -1641,10 +1756,10 @@ int usb_suspend(struct device *dev, pm_message_t message) | |||
1641 | } | 1756 | } |
1642 | 1757 | ||
1643 | udev->skip_sys_resume = 0; | 1758 | udev->skip_sys_resume = 0; |
1644 | return usb_external_suspend_device(udev, message); | 1759 | return usb_external_suspend_device(udev, msg); |
1645 | } | 1760 | } |
1646 | 1761 | ||
1647 | int usb_resume(struct device *dev) | 1762 | int usb_resume(struct device *dev, pm_message_t msg) |
1648 | { | 1763 | { |
1649 | struct usb_device *udev; | 1764 | struct usb_device *udev; |
1650 | 1765 | ||
@@ -1656,7 +1771,7 @@ int usb_resume(struct device *dev) | |||
1656 | */ | 1771 | */ |
1657 | if (udev->skip_sys_resume) | 1772 | if (udev->skip_sys_resume) |
1658 | return 0; | 1773 | return 0; |
1659 | return usb_external_resume_device(udev); | 1774 | return usb_external_resume_device(udev, msg); |
1660 | } | 1775 | } |
1661 | 1776 | ||
1662 | #endif /* CONFIG_PM */ | 1777 | #endif /* CONFIG_PM */ |
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 946fae43d622..e1710f260b4f 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c | |||
@@ -276,7 +276,7 @@ static void ep_device_release(struct device *dev) | |||
276 | kfree(ep_dev); | 276 | kfree(ep_dev); |
277 | } | 277 | } |
278 | 278 | ||
279 | int usb_create_ep_files(struct device *parent, | 279 | int usb_create_ep_devs(struct device *parent, |
280 | struct usb_host_endpoint *endpoint, | 280 | struct usb_host_endpoint *endpoint, |
281 | struct usb_device *udev) | 281 | struct usb_device *udev) |
282 | { | 282 | { |
@@ -340,7 +340,7 @@ exit: | |||
340 | return retval; | 340 | return retval; |
341 | } | 341 | } |
342 | 342 | ||
343 | void usb_remove_ep_files(struct usb_host_endpoint *endpoint) | 343 | void usb_remove_ep_devs(struct usb_host_endpoint *endpoint) |
344 | { | 344 | { |
345 | struct ep_device *ep_dev = endpoint->ep_dev; | 345 | struct ep_device *ep_dev = endpoint->ep_dev; |
346 | 346 | ||
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 7e912f21fd36..30ecac3af15a 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c | |||
@@ -200,18 +200,18 @@ static int generic_suspend(struct usb_device *udev, pm_message_t msg) | |||
200 | * interfaces manually by doing a bus (or "global") suspend. | 200 | * interfaces manually by doing a bus (or "global") suspend. |
201 | */ | 201 | */ |
202 | if (!udev->parent) | 202 | if (!udev->parent) |
203 | rc = hcd_bus_suspend(udev); | 203 | rc = hcd_bus_suspend(udev, msg); |
204 | 204 | ||
205 | /* Non-root devices don't need to do anything for FREEZE or PRETHAW */ | 205 | /* Non-root devices don't need to do anything for FREEZE or PRETHAW */ |
206 | else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW) | 206 | else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW) |
207 | rc = 0; | 207 | rc = 0; |
208 | else | 208 | else |
209 | rc = usb_port_suspend(udev); | 209 | rc = usb_port_suspend(udev, msg); |
210 | 210 | ||
211 | return rc; | 211 | return rc; |
212 | } | 212 | } |
213 | 213 | ||
214 | static int generic_resume(struct usb_device *udev) | 214 | static int generic_resume(struct usb_device *udev, pm_message_t msg) |
215 | { | 215 | { |
216 | int rc; | 216 | int rc; |
217 | 217 | ||
@@ -221,9 +221,9 @@ static int generic_resume(struct usb_device *udev) | |||
221 | * interfaces manually by doing a bus (or "global") resume. | 221 | * interfaces manually by doing a bus (or "global") resume. |
222 | */ | 222 | */ |
223 | if (!udev->parent) | 223 | if (!udev->parent) |
224 | rc = hcd_bus_resume(udev); | 224 | rc = hcd_bus_resume(udev, msg); |
225 | else | 225 | else |
226 | rc = usb_port_resume(udev); | 226 | rc = usb_port_resume(udev, msg); |
227 | return rc; | 227 | return rc; |
228 | } | 228 | } |
229 | 229 | ||
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 5b87ae7f0a6a..507741ed4482 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -128,6 +128,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
128 | } | 128 | } |
129 | 129 | ||
130 | pci_set_master(dev); | 130 | pci_set_master(dev); |
131 | device_set_wakeup_enable(&dev->dev, 1); | ||
131 | 132 | ||
132 | retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); | 133 | retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); |
133 | if (retval != 0) | 134 | if (retval != 0) |
@@ -191,17 +192,15 @@ EXPORT_SYMBOL_GPL(usb_hcd_pci_remove); | |||
191 | /** | 192 | /** |
192 | * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD | 193 | * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD |
193 | * @dev: USB Host Controller being suspended | 194 | * @dev: USB Host Controller being suspended |
194 | * @message: semantics in flux | 195 | * @message: Power Management message describing this state transition |
195 | * | 196 | * |
196 | * Store this function in the HCD's struct pci_driver as suspend(). | 197 | * Store this function in the HCD's struct pci_driver as .suspend. |
197 | */ | 198 | */ |
198 | int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | 199 | int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) |
199 | { | 200 | { |
200 | struct usb_hcd *hcd; | 201 | struct usb_hcd *hcd = pci_get_drvdata(dev); |
201 | int retval = 0; | 202 | int retval = 0; |
202 | int has_pci_pm; | 203 | int wake, w; |
203 | |||
204 | hcd = pci_get_drvdata(dev); | ||
205 | 204 | ||
206 | /* Root hub suspend should have stopped all downstream traffic, | 205 | /* Root hub suspend should have stopped all downstream traffic, |
207 | * and all bus master traffic. And done so for both the interface | 206 | * and all bus master traffic. And done so for both the interface |
@@ -212,8 +211,15 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
212 | * otherwise the swsusp will save (and restore) garbage state. | 211 | * otherwise the swsusp will save (and restore) garbage state. |
213 | */ | 212 | */ |
214 | if (!(hcd->state == HC_STATE_SUSPENDED || | 213 | if (!(hcd->state == HC_STATE_SUSPENDED || |
215 | hcd->state == HC_STATE_HALT)) | 214 | hcd->state == HC_STATE_HALT)) { |
216 | return -EBUSY; | 215 | dev_warn(&dev->dev, "Root hub is not suspended\n"); |
216 | retval = -EBUSY; | ||
217 | goto done; | ||
218 | } | ||
219 | |||
220 | /* We might already be suspended (runtime PM -- not yet written) */ | ||
221 | if (dev->current_state != PCI_D0) | ||
222 | goto done; | ||
217 | 223 | ||
218 | if (hcd->driver->pci_suspend) { | 224 | if (hcd->driver->pci_suspend) { |
219 | retval = hcd->driver->pci_suspend(hcd, message); | 225 | retval = hcd->driver->pci_suspend(hcd, message); |
@@ -221,49 +227,60 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
221 | if (retval) | 227 | if (retval) |
222 | goto done; | 228 | goto done; |
223 | } | 229 | } |
224 | synchronize_irq(dev->irq); | ||
225 | 230 | ||
226 | /* FIXME until the generic PM interfaces change a lot more, this | 231 | synchronize_irq(dev->irq); |
227 | * can't use PCI D1 and D2 states. For example, the confusion | ||
228 | * between messages and states will need to vanish, and messages | ||
229 | * will need to provide a target system state again. | ||
230 | * | ||
231 | * It'll be important to learn characteristics of the target state, | ||
232 | * especially on embedded hardware where the HCD will often be in | ||
233 | * charge of an external VBUS power supply and one or more clocks. | ||
234 | * Some target system states will leave them active; others won't. | ||
235 | * (With PCI, that's often handled by platform BIOS code.) | ||
236 | */ | ||
237 | 232 | ||
238 | /* even when the PCI layer rejects some of the PCI calls | 233 | /* Don't fail on error to enable wakeup. We rely on pci code |
239 | * below, HCs can try global suspend and reduce DMA traffic. | 234 | * to reject requests the hardware can't implement, rather |
240 | * PM-sensitive HCDs may already have done this. | 235 | * than coding the same thing. |
241 | */ | 236 | */ |
242 | has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); | 237 | wake = (hcd->state == HC_STATE_SUSPENDED && |
238 | device_may_wakeup(&dev->dev)); | ||
239 | w = pci_wake_from_d3(dev, wake); | ||
240 | if (w < 0) | ||
241 | wake = w; | ||
242 | dev_dbg(&dev->dev, "wakeup: %d\n", wake); | ||
243 | 243 | ||
244 | /* Downstream ports from this root hub should already be quiesced, so | 244 | /* Downstream ports from this root hub should already be quiesced, so |
245 | * there will be no DMA activity. Now we can shut down the upstream | 245 | * there will be no DMA activity. Now we can shut down the upstream |
246 | * link (except maybe for PME# resume signaling) and enter some PCI | 246 | * link (except maybe for PME# resume signaling) and enter some PCI |
247 | * low power state, if the hardware allows. | 247 | * low power state, if the hardware allows. |
248 | */ | 248 | */ |
249 | if (hcd->state == HC_STATE_SUSPENDED) { | 249 | pci_disable_device(dev); |
250 | done: | ||
251 | return retval; | ||
252 | } | ||
253 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend); | ||
250 | 254 | ||
251 | /* no DMA or IRQs except when HC is active */ | 255 | /** |
252 | if (dev->current_state == PCI_D0) { | 256 | * usb_hcd_pci_suspend_late - suspend a PCI-based HCD after IRQs are disabled |
253 | pci_save_state(dev); | 257 | * @dev: USB Host Controller being suspended |
254 | pci_disable_device(dev); | 258 | * @message: Power Management message describing this state transition |
255 | } | 259 | * |
260 | * Store this function in the HCD's struct pci_driver as .suspend_late. | ||
261 | */ | ||
262 | int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t message) | ||
263 | { | ||
264 | int retval = 0; | ||
265 | int has_pci_pm; | ||
256 | 266 | ||
257 | if (message.event == PM_EVENT_FREEZE || | 267 | /* We might already be suspended (runtime PM -- not yet written) */ |
258 | message.event == PM_EVENT_PRETHAW) { | 268 | if (dev->current_state != PCI_D0) |
259 | dev_dbg(hcd->self.controller, "--> no state change\n"); | 269 | goto done; |
260 | goto done; | ||
261 | } | ||
262 | 270 | ||
263 | if (!has_pci_pm) { | 271 | pci_save_state(dev); |
264 | dev_dbg(hcd->self.controller, "--> PCI D0/legacy\n"); | 272 | |
265 | goto done; | 273 | /* Don't change state if we don't need to */ |
266 | } | 274 | if (message.event == PM_EVENT_FREEZE || |
275 | message.event == PM_EVENT_PRETHAW) { | ||
276 | dev_dbg(&dev->dev, "--> no state change\n"); | ||
277 | goto done; | ||
278 | } | ||
279 | |||
280 | has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); | ||
281 | if (!has_pci_pm) { | ||
282 | dev_dbg(&dev->dev, "--> PCI D0 legacy\n"); | ||
283 | } else { | ||
267 | 284 | ||
268 | /* NOTE: dev->current_state becomes nonzero only here, and | 285 | /* NOTE: dev->current_state becomes nonzero only here, and |
269 | * only for devices that support PCI PM. Also, exiting | 286 | * only for devices that support PCI PM. Also, exiting |
@@ -273,35 +290,16 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
273 | retval = pci_set_power_state(dev, PCI_D3hot); | 290 | retval = pci_set_power_state(dev, PCI_D3hot); |
274 | suspend_report_result(pci_set_power_state, retval); | 291 | suspend_report_result(pci_set_power_state, retval); |
275 | if (retval == 0) { | 292 | if (retval == 0) { |
276 | int wake = device_can_wakeup(&hcd->self.root_hub->dev); | 293 | dev_dbg(&dev->dev, "--> PCI D3\n"); |
277 | |||
278 | wake = wake && device_may_wakeup(hcd->self.controller); | ||
279 | |||
280 | dev_dbg(hcd->self.controller, "--> PCI D3%s\n", | ||
281 | wake ? "/wakeup" : ""); | ||
282 | |||
283 | /* Ignore these return values. We rely on pci code to | ||
284 | * reject requests the hardware can't implement, rather | ||
285 | * than coding the same thing. | ||
286 | */ | ||
287 | (void) pci_enable_wake(dev, PCI_D3hot, wake); | ||
288 | (void) pci_enable_wake(dev, PCI_D3cold, wake); | ||
289 | } else { | 294 | } else { |
290 | dev_dbg(&dev->dev, "PCI D3 suspend fail, %d\n", | 295 | dev_dbg(&dev->dev, "PCI D3 suspend fail, %d\n", |
291 | retval); | 296 | retval); |
292 | (void) usb_hcd_pci_resume(dev); | 297 | pci_restore_state(dev); |
293 | } | 298 | } |
294 | |||
295 | } else if (hcd->state != HC_STATE_HALT) { | ||
296 | dev_dbg(hcd->self.controller, "hcd state %d; not suspended\n", | ||
297 | hcd->state); | ||
298 | WARN_ON(1); | ||
299 | retval = -EINVAL; | ||
300 | } | 299 | } |
301 | 300 | ||
302 | done: | ||
303 | if (retval == 0) { | ||
304 | #ifdef CONFIG_PPC_PMAC | 301 | #ifdef CONFIG_PPC_PMAC |
302 | if (retval == 0) { | ||
305 | /* Disable ASIC clocks for USB */ | 303 | /* Disable ASIC clocks for USB */ |
306 | if (machine_is(powermac)) { | 304 | if (machine_is(powermac)) { |
307 | struct device_node *of_node; | 305 | struct device_node *of_node; |
@@ -311,30 +309,24 @@ done: | |||
311 | pmac_call_feature(PMAC_FTR_USB_ENABLE, | 309 | pmac_call_feature(PMAC_FTR_USB_ENABLE, |
312 | of_node, 0, 0); | 310 | of_node, 0, 0); |
313 | } | 311 | } |
314 | #endif | ||
315 | } | 312 | } |
313 | #endif | ||
316 | 314 | ||
315 | done: | ||
317 | return retval; | 316 | return retval; |
318 | } | 317 | } |
319 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend); | 318 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend_late); |
320 | 319 | ||
321 | /** | 320 | /** |
322 | * usb_hcd_pci_resume - power management resume of a PCI-based HCD | 321 | * usb_hcd_pci_resume_early - resume a PCI-based HCD before IRQs are enabled |
323 | * @dev: USB Host Controller being resumed | 322 | * @dev: USB Host Controller being resumed |
324 | * | 323 | * |
325 | * Store this function in the HCD's struct pci_driver as resume(). | 324 | * Store this function in the HCD's struct pci_driver as .resume_early. |
326 | */ | 325 | */ |
327 | int usb_hcd_pci_resume(struct pci_dev *dev) | 326 | int usb_hcd_pci_resume_early(struct pci_dev *dev) |
328 | { | 327 | { |
329 | struct usb_hcd *hcd; | 328 | int retval = 0; |
330 | int retval; | 329 | pci_power_t state = dev->current_state; |
331 | |||
332 | hcd = pci_get_drvdata(dev); | ||
333 | if (hcd->state != HC_STATE_SUSPENDED) { | ||
334 | dev_dbg(hcd->self.controller, | ||
335 | "can't resume, not suspended!\n"); | ||
336 | return 0; | ||
337 | } | ||
338 | 330 | ||
339 | #ifdef CONFIG_PPC_PMAC | 331 | #ifdef CONFIG_PPC_PMAC |
340 | /* Reenable ASIC clocks for USB */ | 332 | /* Reenable ASIC clocks for USB */ |
@@ -352,7 +344,7 @@ int usb_hcd_pci_resume(struct pci_dev *dev) | |||
352 | * calls "standby", "suspend to RAM", and so on). There are also | 344 | * calls "standby", "suspend to RAM", and so on). There are also |
353 | * dirty cases when swsusp fakes a suspend in "shutdown" mode. | 345 | * dirty cases when swsusp fakes a suspend in "shutdown" mode. |
354 | */ | 346 | */ |
355 | if (dev->current_state != PCI_D0) { | 347 | if (state != PCI_D0) { |
356 | #ifdef DEBUG | 348 | #ifdef DEBUG |
357 | int pci_pm; | 349 | int pci_pm; |
358 | u16 pmcr; | 350 | u16 pmcr; |
@@ -364,8 +356,7 @@ int usb_hcd_pci_resume(struct pci_dev *dev) | |||
364 | /* Clean case: power to USB and to HC registers was | 356 | /* Clean case: power to USB and to HC registers was |
365 | * maintained; remote wakeup is easy. | 357 | * maintained; remote wakeup is easy. |
366 | */ | 358 | */ |
367 | dev_dbg(hcd->self.controller, "resume from PCI D%d\n", | 359 | dev_dbg(&dev->dev, "resume from PCI D%d\n", pmcr); |
368 | pmcr); | ||
369 | } else { | 360 | } else { |
370 | /* Clean: HC lost Vcc power, D0 uninitialized | 361 | /* Clean: HC lost Vcc power, D0 uninitialized |
371 | * + Vaux may have preserved port and transceiver | 362 | * + Vaux may have preserved port and transceiver |
@@ -376,32 +367,55 @@ int usb_hcd_pci_resume(struct pci_dev *dev) | |||
376 | * + after BIOS init | 367 | * + after BIOS init |
377 | * + after Linux init (HCD statically linked) | 368 | * + after Linux init (HCD statically linked) |
378 | */ | 369 | */ |
379 | dev_dbg(hcd->self.controller, | 370 | dev_dbg(&dev->dev, "resume from previous PCI D%d\n", |
380 | "PCI D0, from previous PCI D%d\n", | 371 | state); |
381 | dev->current_state); | ||
382 | } | 372 | } |
383 | #endif | 373 | #endif |
384 | /* yes, ignore these results too... */ | 374 | |
385 | (void) pci_enable_wake(dev, dev->current_state, 0); | 375 | retval = pci_set_power_state(dev, PCI_D0); |
386 | (void) pci_enable_wake(dev, PCI_D3cold, 0); | ||
387 | } else { | 376 | } else { |
388 | /* Same basic cases: clean (powered/not), dirty */ | 377 | /* Same basic cases: clean (powered/not), dirty */ |
389 | dev_dbg(hcd->self.controller, "PCI legacy resume\n"); | 378 | dev_dbg(&dev->dev, "PCI legacy resume\n"); |
379 | } | ||
380 | |||
381 | if (retval < 0) | ||
382 | dev_err(&dev->dev, "can't resume: %d\n", retval); | ||
383 | else | ||
384 | pci_restore_state(dev); | ||
385 | |||
386 | return retval; | ||
387 | } | ||
388 | EXPORT_SYMBOL_GPL(usb_hcd_pci_resume_early); | ||
389 | |||
390 | /** | ||
391 | * usb_hcd_pci_resume - power management resume of a PCI-based HCD | ||
392 | * @dev: USB Host Controller being resumed | ||
393 | * | ||
394 | * Store this function in the HCD's struct pci_driver as .resume. | ||
395 | */ | ||
396 | int usb_hcd_pci_resume(struct pci_dev *dev) | ||
397 | { | ||
398 | struct usb_hcd *hcd; | ||
399 | int retval; | ||
400 | |||
401 | hcd = pci_get_drvdata(dev); | ||
402 | if (hcd->state != HC_STATE_SUSPENDED) { | ||
403 | dev_dbg(hcd->self.controller, | ||
404 | "can't resume, not suspended!\n"); | ||
405 | return 0; | ||
390 | } | 406 | } |
391 | 407 | ||
392 | /* NOTE: the PCI API itself is asymmetric here. We don't need to | ||
393 | * pci_set_power_state(PCI_D0) since that's part of re-enabling; | ||
394 | * but that won't re-enable bus mastering. Yet pci_disable_device() | ||
395 | * explicitly disables bus mastering... | ||
396 | */ | ||
397 | retval = pci_enable_device(dev); | 408 | retval = pci_enable_device(dev); |
398 | if (retval < 0) { | 409 | if (retval < 0) { |
399 | dev_err(hcd->self.controller, | 410 | dev_err(&dev->dev, "can't re-enable after resume, %d!\n", |
400 | "can't re-enable after resume, %d!\n", retval); | 411 | retval); |
401 | return retval; | 412 | return retval; |
402 | } | 413 | } |
414 | |||
403 | pci_set_master(dev); | 415 | pci_set_master(dev); |
404 | pci_restore_state(dev); | 416 | |
417 | /* yes, ignore this result too... */ | ||
418 | (void) pci_wake_from_d3(dev, 0); | ||
405 | 419 | ||
406 | clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); | 420 | clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); |
407 | 421 | ||
@@ -413,7 +427,6 @@ int usb_hcd_pci_resume(struct pci_dev *dev) | |||
413 | usb_hc_died(hcd); | 427 | usb_hc_died(hcd); |
414 | } | 428 | } |
415 | } | 429 | } |
416 | |||
417 | return retval; | 430 | return retval; |
418 | } | 431 | } |
419 | EXPORT_SYMBOL_GPL(usb_hcd_pci_resume); | 432 | EXPORT_SYMBOL_GPL(usb_hcd_pci_resume); |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index e1b42626d04d..3c711db55d86 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1010,7 +1010,7 @@ int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb) | |||
1010 | spin_lock(&hcd_urb_list_lock); | 1010 | spin_lock(&hcd_urb_list_lock); |
1011 | 1011 | ||
1012 | /* Check that the URB isn't being killed */ | 1012 | /* Check that the URB isn't being killed */ |
1013 | if (unlikely(urb->reject)) { | 1013 | if (unlikely(atomic_read(&urb->reject))) { |
1014 | rc = -EPERM; | 1014 | rc = -EPERM; |
1015 | goto done; | 1015 | goto done; |
1016 | } | 1016 | } |
@@ -1340,7 +1340,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | |||
1340 | INIT_LIST_HEAD(&urb->urb_list); | 1340 | INIT_LIST_HEAD(&urb->urb_list); |
1341 | atomic_dec(&urb->use_count); | 1341 | atomic_dec(&urb->use_count); |
1342 | atomic_dec(&urb->dev->urbnum); | 1342 | atomic_dec(&urb->dev->urbnum); |
1343 | if (urb->reject) | 1343 | if (atomic_read(&urb->reject)) |
1344 | wake_up(&usb_kill_urb_queue); | 1344 | wake_up(&usb_kill_urb_queue); |
1345 | usb_put_urb(urb); | 1345 | usb_put_urb(urb); |
1346 | } | 1346 | } |
@@ -1444,7 +1444,7 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status) | |||
1444 | urb->status = status; | 1444 | urb->status = status; |
1445 | urb->complete (urb); | 1445 | urb->complete (urb); |
1446 | atomic_dec (&urb->use_count); | 1446 | atomic_dec (&urb->use_count); |
1447 | if (unlikely (urb->reject)) | 1447 | if (unlikely(atomic_read(&urb->reject))) |
1448 | wake_up (&usb_kill_urb_queue); | 1448 | wake_up (&usb_kill_urb_queue); |
1449 | usb_put_urb (urb); | 1449 | usb_put_urb (urb); |
1450 | } | 1450 | } |
@@ -1573,14 +1573,14 @@ int usb_hcd_get_frame_number (struct usb_device *udev) | |||
1573 | 1573 | ||
1574 | #ifdef CONFIG_PM | 1574 | #ifdef CONFIG_PM |
1575 | 1575 | ||
1576 | int hcd_bus_suspend(struct usb_device *rhdev) | 1576 | int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) |
1577 | { | 1577 | { |
1578 | struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); | 1578 | struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); |
1579 | int status; | 1579 | int status; |
1580 | int old_state = hcd->state; | 1580 | int old_state = hcd->state; |
1581 | 1581 | ||
1582 | dev_dbg(&rhdev->dev, "bus %s%s\n", | 1582 | dev_dbg(&rhdev->dev, "bus %s%s\n", |
1583 | rhdev->auto_pm ? "auto-" : "", "suspend"); | 1583 | (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend"); |
1584 | if (!hcd->driver->bus_suspend) { | 1584 | if (!hcd->driver->bus_suspend) { |
1585 | status = -ENOENT; | 1585 | status = -ENOENT; |
1586 | } else { | 1586 | } else { |
@@ -1598,14 +1598,14 @@ int hcd_bus_suspend(struct usb_device *rhdev) | |||
1598 | return status; | 1598 | return status; |
1599 | } | 1599 | } |
1600 | 1600 | ||
1601 | int hcd_bus_resume(struct usb_device *rhdev) | 1601 | int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) |
1602 | { | 1602 | { |
1603 | struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); | 1603 | struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); |
1604 | int status; | 1604 | int status; |
1605 | int old_state = hcd->state; | 1605 | int old_state = hcd->state; |
1606 | 1606 | ||
1607 | dev_dbg(&rhdev->dev, "usb %s%s\n", | 1607 | dev_dbg(&rhdev->dev, "usb %s%s\n", |
1608 | rhdev->auto_pm ? "auto-" : "", "resume"); | 1608 | (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume"); |
1609 | if (!hcd->driver->bus_resume) | 1609 | if (!hcd->driver->bus_resume) |
1610 | return -ENOENT; | 1610 | return -ENOENT; |
1611 | if (hcd->state == HC_STATE_RUNNING) | 1611 | if (hcd->state == HC_STATE_RUNNING) |
@@ -1638,7 +1638,7 @@ static void hcd_resume_work(struct work_struct *work) | |||
1638 | 1638 | ||
1639 | usb_lock_device(udev); | 1639 | usb_lock_device(udev); |
1640 | usb_mark_last_busy(udev); | 1640 | usb_mark_last_busy(udev); |
1641 | usb_external_resume_device(udev); | 1641 | usb_external_resume_device(udev, PMSG_REMOTE_RESUME); |
1642 | usb_unlock_device(udev); | 1642 | usb_unlock_device(udev); |
1643 | } | 1643 | } |
1644 | 1644 | ||
@@ -2028,7 +2028,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_platform_shutdown); | |||
2028 | 2028 | ||
2029 | /*-------------------------------------------------------------------------*/ | 2029 | /*-------------------------------------------------------------------------*/ |
2030 | 2030 | ||
2031 | #if defined(CONFIG_USB_MON) | 2031 | #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) |
2032 | 2032 | ||
2033 | struct usb_mon_operations *mon_ops; | 2033 | struct usb_mon_operations *mon_ops; |
2034 | 2034 | ||
@@ -2064,4 +2064,4 @@ void usb_mon_deregister (void) | |||
2064 | } | 2064 | } |
2065 | EXPORT_SYMBOL_GPL (usb_mon_deregister); | 2065 | EXPORT_SYMBOL_GPL (usb_mon_deregister); |
2066 | 2066 | ||
2067 | #endif /* CONFIG_USB_MON */ | 2067 | #endif /* CONFIG_USB_MON || CONFIG_USB_MON_MODULE */ |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 9465e70f4dd0..572d2cf46e8d 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -16,6 +16,8 @@ | |||
16 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 16 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #ifndef __USB_CORE_HCD_H | ||
20 | #define __USB_CORE_HCD_H | ||
19 | 21 | ||
20 | #ifdef __KERNEL__ | 22 | #ifdef __KERNEL__ |
21 | 23 | ||
@@ -254,7 +256,9 @@ extern int usb_hcd_pci_probe(struct pci_dev *dev, | |||
254 | extern void usb_hcd_pci_remove(struct pci_dev *dev); | 256 | extern void usb_hcd_pci_remove(struct pci_dev *dev); |
255 | 257 | ||
256 | #ifdef CONFIG_PM | 258 | #ifdef CONFIG_PM |
257 | extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t state); | 259 | extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t msg); |
260 | extern int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t msg); | ||
261 | extern int usb_hcd_pci_resume_early(struct pci_dev *dev); | ||
258 | extern int usb_hcd_pci_resume(struct pci_dev *dev); | 262 | extern int usb_hcd_pci_resume(struct pci_dev *dev); |
259 | #endif /* CONFIG_PM */ | 263 | #endif /* CONFIG_PM */ |
260 | 264 | ||
@@ -386,8 +390,8 @@ extern int usb_find_interface_driver(struct usb_device *dev, | |||
386 | #ifdef CONFIG_PM | 390 | #ifdef CONFIG_PM |
387 | extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd); | 391 | extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd); |
388 | extern void usb_root_hub_lost_power(struct usb_device *rhdev); | 392 | extern void usb_root_hub_lost_power(struct usb_device *rhdev); |
389 | extern int hcd_bus_suspend(struct usb_device *rhdev); | 393 | extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg); |
390 | extern int hcd_bus_resume(struct usb_device *rhdev); | 394 | extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg); |
391 | #else | 395 | #else |
392 | static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) | 396 | static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) |
393 | { | 397 | { |
@@ -419,7 +423,7 @@ static inline void usbfs_cleanup(void) { } | |||
419 | 423 | ||
420 | /*-------------------------------------------------------------------------*/ | 424 | /*-------------------------------------------------------------------------*/ |
421 | 425 | ||
422 | #if defined(CONFIG_USB_MON) | 426 | #if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) |
423 | 427 | ||
424 | struct usb_mon_operations { | 428 | struct usb_mon_operations { |
425 | void (*urb_submit)(struct usb_bus *bus, struct urb *urb); | 429 | void (*urb_submit)(struct usb_bus *bus, struct urb *urb); |
@@ -461,7 +465,7 @@ static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, | |||
461 | static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, | 465 | static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, |
462 | int status) {} | 466 | int status) {} |
463 | 467 | ||
464 | #endif /* CONFIG_USB_MON */ | 468 | #endif /* CONFIG_USB_MON || CONFIG_USB_MON_MODULE */ |
465 | 469 | ||
466 | /*-------------------------------------------------------------------------*/ | 470 | /*-------------------------------------------------------------------------*/ |
467 | 471 | ||
@@ -490,3 +494,5 @@ extern struct rw_semaphore ehci_cf_port_reset_rwsem; | |||
490 | extern unsigned long usb_hcds_loaded; | 494 | extern unsigned long usb_hcds_loaded; |
491 | 495 | ||
492 | #endif /* __KERNEL__ */ | 496 | #endif /* __KERNEL__ */ |
497 | |||
498 | #endif /* __USB_CORE_HCD_H */ | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b19cbfcd51da..d5d0e40b1e2d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -107,7 +107,9 @@ MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs"); | |||
107 | /* define initial 64-byte descriptor request timeout in milliseconds */ | 107 | /* define initial 64-byte descriptor request timeout in milliseconds */ |
108 | static int initial_descriptor_timeout = USB_CTRL_GET_TIMEOUT; | 108 | static int initial_descriptor_timeout = USB_CTRL_GET_TIMEOUT; |
109 | module_param(initial_descriptor_timeout, int, S_IRUGO|S_IWUSR); | 109 | module_param(initial_descriptor_timeout, int, S_IRUGO|S_IWUSR); |
110 | MODULE_PARM_DESC(initial_descriptor_timeout, "initial 64-byte descriptor request timeout in milliseconds (default 5000 - 5.0 seconds)"); | 110 | MODULE_PARM_DESC(initial_descriptor_timeout, |
111 | "initial 64-byte descriptor request timeout in milliseconds " | ||
112 | "(default 5000 - 5.0 seconds)"); | ||
111 | 113 | ||
112 | /* | 114 | /* |
113 | * As of 2.6.10 we introduce a new USB device initialization scheme which | 115 | * As of 2.6.10 we introduce a new USB device initialization scheme which |
@@ -1136,8 +1138,8 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1136 | hdev = interface_to_usbdev(intf); | 1138 | hdev = interface_to_usbdev(intf); |
1137 | 1139 | ||
1138 | if (hdev->level == MAX_TOPO_LEVEL) { | 1140 | if (hdev->level == MAX_TOPO_LEVEL) { |
1139 | dev_err(&intf->dev, "Unsupported bus topology: " | 1141 | dev_err(&intf->dev, |
1140 | "hub nested too deep\n"); | 1142 | "Unsupported bus topology: hub nested too deep\n"); |
1141 | return -E2BIG; | 1143 | return -E2BIG; |
1142 | } | 1144 | } |
1143 | 1145 | ||
@@ -1374,8 +1376,9 @@ static void usb_stop_pm(struct usb_device *udev) | |||
1374 | usb_autosuspend_device(udev->parent); | 1376 | usb_autosuspend_device(udev->parent); |
1375 | usb_pm_unlock(udev); | 1377 | usb_pm_unlock(udev); |
1376 | 1378 | ||
1377 | /* Stop any autosuspend requests already submitted */ | 1379 | /* Stop any autosuspend or autoresume requests already submitted */ |
1378 | cancel_rearming_delayed_work(&udev->autosuspend); | 1380 | cancel_delayed_work_sync(&udev->autosuspend); |
1381 | cancel_work_sync(&udev->autoresume); | ||
1379 | } | 1382 | } |
1380 | 1383 | ||
1381 | #else | 1384 | #else |
@@ -1434,17 +1437,12 @@ void usb_disconnect(struct usb_device **pdev) | |||
1434 | usb_disable_device(udev, 0); | 1437 | usb_disable_device(udev, 0); |
1435 | usb_hcd_synchronize_unlinks(udev); | 1438 | usb_hcd_synchronize_unlinks(udev); |
1436 | 1439 | ||
1440 | usb_remove_ep_devs(&udev->ep0); | ||
1437 | usb_unlock_device(udev); | 1441 | usb_unlock_device(udev); |
1438 | 1442 | ||
1439 | /* Remove the device-specific files from sysfs. This must be | ||
1440 | * done with udev unlocked, because some of the attribute | ||
1441 | * routines try to acquire the device lock. | ||
1442 | */ | ||
1443 | usb_remove_sysfs_dev_files(udev); | ||
1444 | |||
1445 | /* Unregister the device. The device driver is responsible | 1443 | /* Unregister the device. The device driver is responsible |
1446 | * for removing the device files from usbfs and sysfs and for | 1444 | * for de-configuring the device and invoking the remove-device |
1447 | * de-configuring the device. | 1445 | * notifier chain (used by usbfs and possibly others). |
1448 | */ | 1446 | */ |
1449 | device_del(&udev->dev); | 1447 | device_del(&udev->dev); |
1450 | 1448 | ||
@@ -1476,8 +1474,8 @@ static void announce_device(struct usb_device *udev) | |||
1476 | dev_info(&udev->dev, "New USB device found, idVendor=%04x, idProduct=%04x\n", | 1474 | dev_info(&udev->dev, "New USB device found, idVendor=%04x, idProduct=%04x\n", |
1477 | le16_to_cpu(udev->descriptor.idVendor), | 1475 | le16_to_cpu(udev->descriptor.idVendor), |
1478 | le16_to_cpu(udev->descriptor.idProduct)); | 1476 | le16_to_cpu(udev->descriptor.idProduct)); |
1479 | dev_info(&udev->dev, "New USB device strings: Mfr=%d, Product=%d, " | 1477 | dev_info(&udev->dev, |
1480 | "SerialNumber=%d\n", | 1478 | "New USB device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", |
1481 | udev->descriptor.iManufacturer, | 1479 | udev->descriptor.iManufacturer, |
1482 | udev->descriptor.iProduct, | 1480 | udev->descriptor.iProduct, |
1483 | udev->descriptor.iSerialNumber); | 1481 | udev->descriptor.iSerialNumber); |
@@ -1542,7 +1540,7 @@ static int usb_configure_device_otg(struct usb_device *udev) | |||
1542 | * customize to match your product. | 1540 | * customize to match your product. |
1543 | */ | 1541 | */ |
1544 | dev_info(&udev->dev, | 1542 | dev_info(&udev->dev, |
1545 | "can't set HNP mode; %d\n", | 1543 | "can't set HNP mode: %d\n", |
1546 | err); | 1544 | err); |
1547 | bus->b_hnp_enable = 0; | 1545 | bus->b_hnp_enable = 0; |
1548 | } | 1546 | } |
@@ -1635,6 +1633,10 @@ int usb_new_device(struct usb_device *udev) | |||
1635 | { | 1633 | { |
1636 | int err; | 1634 | int err; |
1637 | 1635 | ||
1636 | /* Increment the parent's count of unsuspended children */ | ||
1637 | if (udev->parent) | ||
1638 | usb_autoresume_device(udev->parent); | ||
1639 | |||
1638 | usb_detect_quirks(udev); /* Determine quirks */ | 1640 | usb_detect_quirks(udev); /* Determine quirks */ |
1639 | err = usb_configure_device(udev); /* detect & probe dev/intfs */ | 1641 | err = usb_configure_device(udev); /* detect & probe dev/intfs */ |
1640 | if (err < 0) | 1642 | if (err < 0) |
@@ -1643,13 +1645,12 @@ int usb_new_device(struct usb_device *udev) | |||
1643 | udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, | 1645 | udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, |
1644 | (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); | 1646 | (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); |
1645 | 1647 | ||
1646 | /* Increment the parent's count of unsuspended children */ | 1648 | /* Tell the world! */ |
1647 | if (udev->parent) | 1649 | announce_device(udev); |
1648 | usb_autoresume_device(udev->parent); | ||
1649 | 1650 | ||
1650 | /* Register the device. The device driver is responsible | 1651 | /* Register the device. The device driver is responsible |
1651 | * for adding the device files to sysfs and for configuring | 1652 | * for configuring the device and invoking the add-device |
1652 | * the device. | 1653 | * notifier chain (used by usbfs and possibly others). |
1653 | */ | 1654 | */ |
1654 | err = device_add(&udev->dev); | 1655 | err = device_add(&udev->dev); |
1655 | if (err) { | 1656 | if (err) { |
@@ -1657,15 +1658,12 @@ int usb_new_device(struct usb_device *udev) | |||
1657 | goto fail; | 1658 | goto fail; |
1658 | } | 1659 | } |
1659 | 1660 | ||
1660 | /* put device-specific files into sysfs */ | 1661 | (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); |
1661 | usb_create_sysfs_dev_files(udev); | ||
1662 | |||
1663 | /* Tell the world! */ | ||
1664 | announce_device(udev); | ||
1665 | return err; | 1662 | return err; |
1666 | 1663 | ||
1667 | fail: | 1664 | fail: |
1668 | usb_set_device_state(udev, USB_STATE_NOTATTACHED); | 1665 | usb_set_device_state(udev, USB_STATE_NOTATTACHED); |
1666 | usb_stop_pm(udev); | ||
1669 | return err; | 1667 | return err; |
1670 | } | 1668 | } |
1671 | 1669 | ||
@@ -1982,7 +1980,7 @@ static int check_port_resume_type(struct usb_device *udev, | |||
1982 | * | 1980 | * |
1983 | * Returns 0 on success, else negative errno. | 1981 | * Returns 0 on success, else negative errno. |
1984 | */ | 1982 | */ |
1985 | int usb_port_suspend(struct usb_device *udev) | 1983 | int usb_port_suspend(struct usb_device *udev, pm_message_t msg) |
1986 | { | 1984 | { |
1987 | struct usb_hub *hub = hdev_to_hub(udev->parent); | 1985 | struct usb_hub *hub = hdev_to_hub(udev->parent); |
1988 | int port1 = udev->portnum; | 1986 | int port1 = udev->portnum; |
@@ -2021,7 +2019,7 @@ int usb_port_suspend(struct usb_device *udev) | |||
2021 | } else { | 2019 | } else { |
2022 | /* device has up to 10 msec to fully suspend */ | 2020 | /* device has up to 10 msec to fully suspend */ |
2023 | dev_dbg(&udev->dev, "usb %ssuspend\n", | 2021 | dev_dbg(&udev->dev, "usb %ssuspend\n", |
2024 | udev->auto_pm ? "auto-" : ""); | 2022 | (msg.event & PM_EVENT_AUTO ? "auto-" : "")); |
2025 | usb_set_device_state(udev, USB_STATE_SUSPENDED); | 2023 | usb_set_device_state(udev, USB_STATE_SUSPENDED); |
2026 | msleep(10); | 2024 | msleep(10); |
2027 | } | 2025 | } |
@@ -2045,8 +2043,8 @@ static int finish_port_resume(struct usb_device *udev) | |||
2045 | u16 devstatus; | 2043 | u16 devstatus; |
2046 | 2044 | ||
2047 | /* caller owns the udev device lock */ | 2045 | /* caller owns the udev device lock */ |
2048 | dev_dbg(&udev->dev, "finish %sresume\n", | 2046 | dev_dbg(&udev->dev, "%s\n", |
2049 | udev->reset_resume ? "reset-" : ""); | 2047 | udev->reset_resume ? "finish reset-resume" : "finish resume"); |
2050 | 2048 | ||
2051 | /* usb ch9 identifies four variants of SUSPENDED, based on what | 2049 | /* usb ch9 identifies four variants of SUSPENDED, based on what |
2052 | * state the device resumes to. Linux currently won't see the | 2050 | * state the device resumes to. Linux currently won't see the |
@@ -2098,8 +2096,9 @@ static int finish_port_resume(struct usb_device *udev) | |||
2098 | NULL, 0, | 2096 | NULL, 0, |
2099 | USB_CTRL_SET_TIMEOUT); | 2097 | USB_CTRL_SET_TIMEOUT); |
2100 | if (status) | 2098 | if (status) |
2101 | dev_dbg(&udev->dev, "disable remote " | 2099 | dev_dbg(&udev->dev, |
2102 | "wakeup, status %d\n", status); | 2100 | "disable remote wakeup, status %d\n", |
2101 | status); | ||
2103 | } | 2102 | } |
2104 | status = 0; | 2103 | status = 0; |
2105 | } | 2104 | } |
@@ -2140,7 +2139,7 @@ static int finish_port_resume(struct usb_device *udev) | |||
2140 | * | 2139 | * |
2141 | * Returns 0 on success, else negative errno. | 2140 | * Returns 0 on success, else negative errno. |
2142 | */ | 2141 | */ |
2143 | int usb_port_resume(struct usb_device *udev) | 2142 | int usb_port_resume(struct usb_device *udev, pm_message_t msg) |
2144 | { | 2143 | { |
2145 | struct usb_hub *hub = hdev_to_hub(udev->parent); | 2144 | struct usb_hub *hub = hdev_to_hub(udev->parent); |
2146 | int port1 = udev->portnum; | 2145 | int port1 = udev->portnum; |
@@ -2165,7 +2164,7 @@ int usb_port_resume(struct usb_device *udev) | |||
2165 | } else { | 2164 | } else { |
2166 | /* drive resume for at least 20 msec */ | 2165 | /* drive resume for at least 20 msec */ |
2167 | dev_dbg(&udev->dev, "usb %sresume\n", | 2166 | dev_dbg(&udev->dev, "usb %sresume\n", |
2168 | udev->auto_pm ? "auto-" : ""); | 2167 | (msg.event & PM_EVENT_AUTO ? "auto-" : "")); |
2169 | msleep(25); | 2168 | msleep(25); |
2170 | 2169 | ||
2171 | /* Virtual root hubs can trigger on GET_PORT_STATUS to | 2170 | /* Virtual root hubs can trigger on GET_PORT_STATUS to |
@@ -2206,7 +2205,7 @@ static int remote_wakeup(struct usb_device *udev) | |||
2206 | if (udev->state == USB_STATE_SUSPENDED) { | 2205 | if (udev->state == USB_STATE_SUSPENDED) { |
2207 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); | 2206 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); |
2208 | usb_mark_last_busy(udev); | 2207 | usb_mark_last_busy(udev); |
2209 | status = usb_external_resume_device(udev); | 2208 | status = usb_external_resume_device(udev, PMSG_REMOTE_RESUME); |
2210 | } | 2209 | } |
2211 | return status; | 2210 | return status; |
2212 | } | 2211 | } |
@@ -2215,14 +2214,14 @@ static int remote_wakeup(struct usb_device *udev) | |||
2215 | 2214 | ||
2216 | /* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */ | 2215 | /* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */ |
2217 | 2216 | ||
2218 | int usb_port_suspend(struct usb_device *udev) | 2217 | int usb_port_suspend(struct usb_device *udev, pm_message_t msg) |
2219 | { | 2218 | { |
2220 | return 0; | 2219 | return 0; |
2221 | } | 2220 | } |
2222 | 2221 | ||
2223 | /* However we may need to do a reset-resume */ | 2222 | /* However we may need to do a reset-resume */ |
2224 | 2223 | ||
2225 | int usb_port_resume(struct usb_device *udev) | 2224 | int usb_port_resume(struct usb_device *udev, pm_message_t msg) |
2226 | { | 2225 | { |
2227 | struct usb_hub *hub = hdev_to_hub(udev->parent); | 2226 | struct usb_hub *hub = hdev_to_hub(udev->parent); |
2228 | int port1 = udev->portnum; | 2227 | int port1 = udev->portnum; |
@@ -2262,7 +2261,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
2262 | 2261 | ||
2263 | udev = hdev->children [port1-1]; | 2262 | udev = hdev->children [port1-1]; |
2264 | if (udev && udev->can_submit) { | 2263 | if (udev && udev->can_submit) { |
2265 | if (!hdev->auto_pm) | 2264 | if (!(msg.event & PM_EVENT_AUTO)) |
2266 | dev_dbg(&intf->dev, "port %d nyet suspended\n", | 2265 | dev_dbg(&intf->dev, "port %d nyet suspended\n", |
2267 | port1); | 2266 | port1); |
2268 | return -EBUSY; | 2267 | return -EBUSY; |
@@ -2385,7 +2384,7 @@ void usb_ep0_reinit(struct usb_device *udev) | |||
2385 | { | 2384 | { |
2386 | usb_disable_endpoint(udev, 0 + USB_DIR_IN); | 2385 | usb_disable_endpoint(udev, 0 + USB_DIR_IN); |
2387 | usb_disable_endpoint(udev, 0 + USB_DIR_OUT); | 2386 | usb_disable_endpoint(udev, 0 + USB_DIR_OUT); |
2388 | usb_enable_endpoint(udev, &udev->ep0); | 2387 | usb_enable_endpoint(udev, &udev->ep0, true); |
2389 | } | 2388 | } |
2390 | EXPORT_SYMBOL_GPL(usb_ep0_reinit); | 2389 | EXPORT_SYMBOL_GPL(usb_ep0_reinit); |
2391 | 2390 | ||
@@ -2582,9 +2581,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2582 | goto fail; | 2581 | goto fail; |
2583 | } | 2582 | } |
2584 | if (r) { | 2583 | if (r) { |
2585 | dev_err(&udev->dev, "device descriptor " | 2584 | dev_err(&udev->dev, |
2586 | "read/%s, error %d\n", | 2585 | "device descriptor read/64, error %d\n", |
2587 | "64", r); | 2586 | r); |
2588 | retval = -EMSGSIZE; | 2587 | retval = -EMSGSIZE; |
2589 | continue; | 2588 | continue; |
2590 | } | 2589 | } |
@@ -2621,9 +2620,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2621 | 2620 | ||
2622 | retval = usb_get_device_descriptor(udev, 8); | 2621 | retval = usb_get_device_descriptor(udev, 8); |
2623 | if (retval < 8) { | 2622 | if (retval < 8) { |
2624 | dev_err(&udev->dev, "device descriptor " | 2623 | dev_err(&udev->dev, |
2625 | "read/%s, error %d\n", | 2624 | "device descriptor read/8, error %d\n", |
2626 | "8", retval); | 2625 | retval); |
2627 | if (retval >= 0) | 2626 | if (retval >= 0) |
2628 | retval = -EMSGSIZE; | 2627 | retval = -EMSGSIZE; |
2629 | } else { | 2628 | } else { |
@@ -2650,8 +2649,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2650 | 2649 | ||
2651 | retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); | 2650 | retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); |
2652 | if (retval < (signed)sizeof(udev->descriptor)) { | 2651 | if (retval < (signed)sizeof(udev->descriptor)) { |
2653 | dev_err(&udev->dev, "device descriptor read/%s, error %d\n", | 2652 | dev_err(&udev->dev, "device descriptor read/all, error %d\n", |
2654 | "all", retval); | 2653 | retval); |
2655 | if (retval >= 0) | 2654 | if (retval >= 0) |
2656 | retval = -ENOMSG; | 2655 | retval = -ENOMSG; |
2657 | goto fail; | 2656 | goto fail; |
@@ -2719,9 +2718,9 @@ hub_power_remaining (struct usb_hub *hub) | |||
2719 | else | 2718 | else |
2720 | delta = 8; | 2719 | delta = 8; |
2721 | if (delta > hub->mA_per_port) | 2720 | if (delta > hub->mA_per_port) |
2722 | dev_warn(&udev->dev, "%dmA is over %umA budget " | 2721 | dev_warn(&udev->dev, |
2723 | "for port %d!\n", | 2722 | "%dmA is over %umA budget for port %d!\n", |
2724 | delta, hub->mA_per_port, port1); | 2723 | delta, hub->mA_per_port, port1); |
2725 | remaining -= delta; | 2724 | remaining -= delta; |
2726 | } | 2725 | } |
2727 | if (remaining < 0) { | 2726 | if (remaining < 0) { |
@@ -3517,3 +3516,46 @@ int usb_reset_device(struct usb_device *udev) | |||
3517 | return ret; | 3516 | return ret; |
3518 | } | 3517 | } |
3519 | EXPORT_SYMBOL_GPL(usb_reset_device); | 3518 | EXPORT_SYMBOL_GPL(usb_reset_device); |
3519 | |||
3520 | |||
3521 | /** | ||
3522 | * usb_queue_reset_device - Reset a USB device from an atomic context | ||
3523 | * @iface: USB interface belonging to the device to reset | ||
3524 | * | ||
3525 | * This function can be used to reset a USB device from an atomic | ||
3526 | * context, where usb_reset_device() won't work (as it blocks). | ||
3527 | * | ||
3528 | * Doing a reset via this method is functionally equivalent to calling | ||
3529 | * usb_reset_device(), except for the fact that it is delayed to a | ||
3530 | * workqueue. This means that any drivers bound to other interfaces | ||
3531 | * might be unbound, as well as users from usbfs in user space. | ||
3532 | * | ||
3533 | * Corner cases: | ||
3534 | * | ||
3535 | * - Scheduling two resets at the same time from two different drivers | ||
3536 | * attached to two different interfaces of the same device is | ||
3537 | * possible; depending on how the driver attached to each interface | ||
3538 | * handles ->pre_reset(), the second reset might happen or not. | ||
3539 | * | ||
3540 | * - If a driver is unbound and it had a pending reset, the reset will | ||
3541 | * be cancelled. | ||
3542 | * | ||
3543 | * - This function can be called during .probe() or .disconnect() | ||
3544 | * times. On return from .disconnect(), any pending resets will be | ||
3545 | * cancelled. | ||
3546 | * | ||
3547 | * There is no no need to lock/unlock the @reset_ws as schedule_work() | ||
3548 | * does its own. | ||
3549 | * | ||
3550 | * NOTE: We don't do any reference count tracking because it is not | ||
3551 | * needed. The lifecycle of the work_struct is tied to the | ||
3552 | * usb_interface. Before destroying the interface we cancel the | ||
3553 | * work_struct, so the fact that work_struct is queued and or | ||
3554 | * running means the interface (and thus, the device) exist and | ||
3555 | * are referenced. | ||
3556 | */ | ||
3557 | void usb_queue_reset_device(struct usb_interface *iface) | ||
3558 | { | ||
3559 | schedule_work(&iface->reset_ws); | ||
3560 | } | ||
3561 | EXPORT_SYMBOL_GPL(usb_queue_reset_device); | ||
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 6d1048faf08e..de51667dd64d 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include "hcd.h" /* for usbcore internals */ | 18 | #include "hcd.h" /* for usbcore internals */ |
19 | #include "usb.h" | 19 | #include "usb.h" |
20 | 20 | ||
21 | static void cancel_async_set_config(struct usb_device *udev); | ||
22 | |||
21 | struct api_context { | 23 | struct api_context { |
22 | struct completion done; | 24 | struct completion done; |
23 | int status; | 25 | int status; |
@@ -139,9 +141,9 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, | |||
139 | 141 | ||
140 | dr->bRequestType = requesttype; | 142 | dr->bRequestType = requesttype; |
141 | dr->bRequest = request; | 143 | dr->bRequest = request; |
142 | dr->wValue = cpu_to_le16p(&value); | 144 | dr->wValue = cpu_to_le16(value); |
143 | dr->wIndex = cpu_to_le16p(&index); | 145 | dr->wIndex = cpu_to_le16(index); |
144 | dr->wLength = cpu_to_le16p(&size); | 146 | dr->wLength = cpu_to_le16(size); |
145 | 147 | ||
146 | /* dbg("usb_control_msg"); */ | 148 | /* dbg("usb_control_msg"); */ |
147 | 149 | ||
@@ -1004,6 +1006,34 @@ int usb_clear_halt(struct usb_device *dev, int pipe) | |||
1004 | } | 1006 | } |
1005 | EXPORT_SYMBOL_GPL(usb_clear_halt); | 1007 | EXPORT_SYMBOL_GPL(usb_clear_halt); |
1006 | 1008 | ||
1009 | static int create_intf_ep_devs(struct usb_interface *intf) | ||
1010 | { | ||
1011 | struct usb_device *udev = interface_to_usbdev(intf); | ||
1012 | struct usb_host_interface *alt = intf->cur_altsetting; | ||
1013 | int i; | ||
1014 | |||
1015 | if (intf->ep_devs_created || intf->unregistering) | ||
1016 | return 0; | ||
1017 | |||
1018 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) | ||
1019 | (void) usb_create_ep_devs(&intf->dev, &alt->endpoint[i], udev); | ||
1020 | intf->ep_devs_created = 1; | ||
1021 | return 0; | ||
1022 | } | ||
1023 | |||
1024 | static void remove_intf_ep_devs(struct usb_interface *intf) | ||
1025 | { | ||
1026 | struct usb_host_interface *alt = intf->cur_altsetting; | ||
1027 | int i; | ||
1028 | |||
1029 | if (!intf->ep_devs_created) | ||
1030 | return; | ||
1031 | |||
1032 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) | ||
1033 | usb_remove_ep_devs(&alt->endpoint[i]); | ||
1034 | intf->ep_devs_created = 0; | ||
1035 | } | ||
1036 | |||
1007 | /** | 1037 | /** |
1008 | * usb_disable_endpoint -- Disable an endpoint by address | 1038 | * usb_disable_endpoint -- Disable an endpoint by address |
1009 | * @dev: the device whose endpoint is being disabled | 1039 | * @dev: the device whose endpoint is being disabled |
@@ -1092,7 +1122,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
1092 | dev_dbg(&dev->dev, "unregistering interface %s\n", | 1122 | dev_dbg(&dev->dev, "unregistering interface %s\n", |
1093 | dev_name(&interface->dev)); | 1123 | dev_name(&interface->dev)); |
1094 | interface->unregistering = 1; | 1124 | interface->unregistering = 1; |
1095 | usb_remove_sysfs_intf_files(interface); | 1125 | remove_intf_ep_devs(interface); |
1096 | device_del(&interface->dev); | 1126 | device_del(&interface->dev); |
1097 | } | 1127 | } |
1098 | 1128 | ||
@@ -1113,22 +1143,26 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) | |||
1113 | * usb_enable_endpoint - Enable an endpoint for USB communications | 1143 | * usb_enable_endpoint - Enable an endpoint for USB communications |
1114 | * @dev: the device whose interface is being enabled | 1144 | * @dev: the device whose interface is being enabled |
1115 | * @ep: the endpoint | 1145 | * @ep: the endpoint |
1146 | * @reset_toggle: flag to set the endpoint's toggle back to 0 | ||
1116 | * | 1147 | * |
1117 | * Resets the endpoint toggle, and sets dev->ep_{in,out} pointers. | 1148 | * Resets the endpoint toggle if asked, and sets dev->ep_{in,out} pointers. |
1118 | * For control endpoints, both the input and output sides are handled. | 1149 | * For control endpoints, both the input and output sides are handled. |
1119 | */ | 1150 | */ |
1120 | void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep) | 1151 | void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep, |
1152 | bool reset_toggle) | ||
1121 | { | 1153 | { |
1122 | int epnum = usb_endpoint_num(&ep->desc); | 1154 | int epnum = usb_endpoint_num(&ep->desc); |
1123 | int is_out = usb_endpoint_dir_out(&ep->desc); | 1155 | int is_out = usb_endpoint_dir_out(&ep->desc); |
1124 | int is_control = usb_endpoint_xfer_control(&ep->desc); | 1156 | int is_control = usb_endpoint_xfer_control(&ep->desc); |
1125 | 1157 | ||
1126 | if (is_out || is_control) { | 1158 | if (is_out || is_control) { |
1127 | usb_settoggle(dev, epnum, 1, 0); | 1159 | if (reset_toggle) |
1160 | usb_settoggle(dev, epnum, 1, 0); | ||
1128 | dev->ep_out[epnum] = ep; | 1161 | dev->ep_out[epnum] = ep; |
1129 | } | 1162 | } |
1130 | if (!is_out || is_control) { | 1163 | if (!is_out || is_control) { |
1131 | usb_settoggle(dev, epnum, 0, 0); | 1164 | if (reset_toggle) |
1165 | usb_settoggle(dev, epnum, 0, 0); | ||
1132 | dev->ep_in[epnum] = ep; | 1166 | dev->ep_in[epnum] = ep; |
1133 | } | 1167 | } |
1134 | ep->enabled = 1; | 1168 | ep->enabled = 1; |
@@ -1138,17 +1172,18 @@ void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep) | |||
1138 | * usb_enable_interface - Enable all the endpoints for an interface | 1172 | * usb_enable_interface - Enable all the endpoints for an interface |
1139 | * @dev: the device whose interface is being enabled | 1173 | * @dev: the device whose interface is being enabled |
1140 | * @intf: pointer to the interface descriptor | 1174 | * @intf: pointer to the interface descriptor |
1175 | * @reset_toggles: flag to set the endpoints' toggles back to 0 | ||
1141 | * | 1176 | * |
1142 | * Enables all the endpoints for the interface's current altsetting. | 1177 | * Enables all the endpoints for the interface's current altsetting. |
1143 | */ | 1178 | */ |
1144 | static void usb_enable_interface(struct usb_device *dev, | 1179 | void usb_enable_interface(struct usb_device *dev, |
1145 | struct usb_interface *intf) | 1180 | struct usb_interface *intf, bool reset_toggles) |
1146 | { | 1181 | { |
1147 | struct usb_host_interface *alt = intf->cur_altsetting; | 1182 | struct usb_host_interface *alt = intf->cur_altsetting; |
1148 | int i; | 1183 | int i; |
1149 | 1184 | ||
1150 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) | 1185 | for (i = 0; i < alt->desc.bNumEndpoints; ++i) |
1151 | usb_enable_endpoint(dev, &alt->endpoint[i]); | 1186 | usb_enable_endpoint(dev, &alt->endpoint[i], reset_toggles); |
1152 | } | 1187 | } |
1153 | 1188 | ||
1154 | /** | 1189 | /** |
@@ -1235,8 +1270,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
1235 | */ | 1270 | */ |
1236 | 1271 | ||
1237 | /* prevent submissions using previous endpoint settings */ | 1272 | /* prevent submissions using previous endpoint settings */ |
1238 | if (iface->cur_altsetting != alt) | 1273 | if (iface->cur_altsetting != alt) { |
1274 | remove_intf_ep_devs(iface); | ||
1239 | usb_remove_sysfs_intf_files(iface); | 1275 | usb_remove_sysfs_intf_files(iface); |
1276 | } | ||
1240 | usb_disable_interface(dev, iface); | 1277 | usb_disable_interface(dev, iface); |
1241 | 1278 | ||
1242 | iface->cur_altsetting = alt; | 1279 | iface->cur_altsetting = alt; |
@@ -1271,10 +1308,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) | |||
1271 | * during the SETUP stage - hence EP0 toggles are "don't care" here. | 1308 | * during the SETUP stage - hence EP0 toggles are "don't care" here. |
1272 | * (Likewise, EP0 never "halts" on well designed devices.) | 1309 | * (Likewise, EP0 never "halts" on well designed devices.) |
1273 | */ | 1310 | */ |
1274 | usb_enable_interface(dev, iface); | 1311 | usb_enable_interface(dev, iface, true); |
1275 | if (device_is_registered(&iface->dev)) | 1312 | if (device_is_registered(&iface->dev)) { |
1276 | usb_create_sysfs_intf_files(iface); | 1313 | usb_create_sysfs_intf_files(iface); |
1277 | 1314 | create_intf_ep_devs(iface); | |
1315 | } | ||
1278 | return 0; | 1316 | return 0; |
1279 | } | 1317 | } |
1280 | EXPORT_SYMBOL_GPL(usb_set_interface); | 1318 | EXPORT_SYMBOL_GPL(usb_set_interface); |
@@ -1334,7 +1372,6 @@ int usb_reset_configuration(struct usb_device *dev) | |||
1334 | struct usb_interface *intf = config->interface[i]; | 1372 | struct usb_interface *intf = config->interface[i]; |
1335 | struct usb_host_interface *alt; | 1373 | struct usb_host_interface *alt; |
1336 | 1374 | ||
1337 | usb_remove_sysfs_intf_files(intf); | ||
1338 | alt = usb_altnum_to_altsetting(intf, 0); | 1375 | alt = usb_altnum_to_altsetting(intf, 0); |
1339 | 1376 | ||
1340 | /* No altsetting 0? We'll assume the first altsetting. | 1377 | /* No altsetting 0? We'll assume the first altsetting. |
@@ -1345,10 +1382,16 @@ int usb_reset_configuration(struct usb_device *dev) | |||
1345 | if (!alt) | 1382 | if (!alt) |
1346 | alt = &intf->altsetting[0]; | 1383 | alt = &intf->altsetting[0]; |
1347 | 1384 | ||
1385 | if (alt != intf->cur_altsetting) { | ||
1386 | remove_intf_ep_devs(intf); | ||
1387 | usb_remove_sysfs_intf_files(intf); | ||
1388 | } | ||
1348 | intf->cur_altsetting = alt; | 1389 | intf->cur_altsetting = alt; |
1349 | usb_enable_interface(dev, intf); | 1390 | usb_enable_interface(dev, intf, true); |
1350 | if (device_is_registered(&intf->dev)) | 1391 | if (device_is_registered(&intf->dev)) { |
1351 | usb_create_sysfs_intf_files(intf); | 1392 | usb_create_sysfs_intf_files(intf); |
1393 | create_intf_ep_devs(intf); | ||
1394 | } | ||
1352 | } | 1395 | } |
1353 | return 0; | 1396 | return 0; |
1354 | } | 1397 | } |
@@ -1441,6 +1484,46 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev, | |||
1441 | return retval; | 1484 | return retval; |
1442 | } | 1485 | } |
1443 | 1486 | ||
1487 | |||
1488 | /* | ||
1489 | * Internal function to queue a device reset | ||
1490 | * | ||
1491 | * This is initialized into the workstruct in 'struct | ||
1492 | * usb_device->reset_ws' that is launched by | ||
1493 | * message.c:usb_set_configuration() when initializing each 'struct | ||
1494 | * usb_interface'. | ||
1495 | * | ||
1496 | * It is safe to get the USB device without reference counts because | ||
1497 | * the life cycle of @iface is bound to the life cycle of @udev. Then, | ||
1498 | * this function will be ran only if @iface is alive (and before | ||
1499 | * freeing it any scheduled instances of it will have been cancelled). | ||
1500 | * | ||
1501 | * We need to set a flag (usb_dev->reset_running) because when we call | ||
1502 | * the reset, the interfaces might be unbound. The current interface | ||
1503 | * cannot try to remove the queued work as it would cause a deadlock | ||
1504 | * (you cannot remove your work from within your executing | ||
1505 | * workqueue). This flag lets it know, so that | ||
1506 | * usb_cancel_queued_reset() doesn't try to do it. | ||
1507 | * | ||
1508 | * See usb_queue_reset_device() for more details | ||
1509 | */ | ||
1510 | void __usb_queue_reset_device(struct work_struct *ws) | ||
1511 | { | ||
1512 | int rc; | ||
1513 | struct usb_interface *iface = | ||
1514 | container_of(ws, struct usb_interface, reset_ws); | ||
1515 | struct usb_device *udev = interface_to_usbdev(iface); | ||
1516 | |||
1517 | rc = usb_lock_device_for_reset(udev, iface); | ||
1518 | if (rc >= 0) { | ||
1519 | iface->reset_running = 1; | ||
1520 | usb_reset_device(udev); | ||
1521 | iface->reset_running = 0; | ||
1522 | usb_unlock_device(udev); | ||
1523 | } | ||
1524 | } | ||
1525 | |||
1526 | |||
1444 | /* | 1527 | /* |
1445 | * usb_set_configuration - Makes a particular device setting be current | 1528 | * usb_set_configuration - Makes a particular device setting be current |
1446 | * @dev: the device whose configuration is being updated | 1529 | * @dev: the device whose configuration is being updated |
@@ -1560,6 +1643,9 @@ free_interfaces: | |||
1560 | if (dev->state != USB_STATE_ADDRESS) | 1643 | if (dev->state != USB_STATE_ADDRESS) |
1561 | usb_disable_device(dev, 1); /* Skip ep0 */ | 1644 | usb_disable_device(dev, 1); /* Skip ep0 */ |
1562 | 1645 | ||
1646 | /* Get rid of pending async Set-Config requests for this device */ | ||
1647 | cancel_async_set_config(dev); | ||
1648 | |||
1563 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1649 | ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
1564 | USB_REQ_SET_CONFIGURATION, 0, configuration, 0, | 1650 | USB_REQ_SET_CONFIGURATION, 0, configuration, 0, |
1565 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 1651 | NULL, 0, USB_CTRL_SET_TIMEOUT); |
@@ -1604,13 +1690,14 @@ free_interfaces: | |||
1604 | alt = &intf->altsetting[0]; | 1690 | alt = &intf->altsetting[0]; |
1605 | 1691 | ||
1606 | intf->cur_altsetting = alt; | 1692 | intf->cur_altsetting = alt; |
1607 | usb_enable_interface(dev, intf); | 1693 | usb_enable_interface(dev, intf, true); |
1608 | intf->dev.parent = &dev->dev; | 1694 | intf->dev.parent = &dev->dev; |
1609 | intf->dev.driver = NULL; | 1695 | intf->dev.driver = NULL; |
1610 | intf->dev.bus = &usb_bus_type; | 1696 | intf->dev.bus = &usb_bus_type; |
1611 | intf->dev.type = &usb_if_device_type; | 1697 | intf->dev.type = &usb_if_device_type; |
1612 | intf->dev.groups = usb_interface_groups; | 1698 | intf->dev.groups = usb_interface_groups; |
1613 | intf->dev.dma_mask = dev->dev.dma_mask; | 1699 | intf->dev.dma_mask = dev->dev.dma_mask; |
1700 | INIT_WORK(&intf->reset_ws, __usb_queue_reset_device); | ||
1614 | device_initialize(&intf->dev); | 1701 | device_initialize(&intf->dev); |
1615 | mark_quiesced(intf); | 1702 | mark_quiesced(intf); |
1616 | dev_set_name(&intf->dev, "%d-%s:%d.%d", | 1703 | dev_set_name(&intf->dev, "%d-%s:%d.%d", |
@@ -1641,17 +1728,21 @@ free_interfaces: | |||
1641 | dev_name(&intf->dev), ret); | 1728 | dev_name(&intf->dev), ret); |
1642 | continue; | 1729 | continue; |
1643 | } | 1730 | } |
1644 | usb_create_sysfs_intf_files(intf); | 1731 | create_intf_ep_devs(intf); |
1645 | } | 1732 | } |
1646 | 1733 | ||
1647 | usb_autosuspend_device(dev); | 1734 | usb_autosuspend_device(dev); |
1648 | return 0; | 1735 | return 0; |
1649 | } | 1736 | } |
1650 | 1737 | ||
1738 | static LIST_HEAD(set_config_list); | ||
1739 | static DEFINE_SPINLOCK(set_config_lock); | ||
1740 | |||
1651 | struct set_config_request { | 1741 | struct set_config_request { |
1652 | struct usb_device *udev; | 1742 | struct usb_device *udev; |
1653 | int config; | 1743 | int config; |
1654 | struct work_struct work; | 1744 | struct work_struct work; |
1745 | struct list_head node; | ||
1655 | }; | 1746 | }; |
1656 | 1747 | ||
1657 | /* Worker routine for usb_driver_set_configuration() */ | 1748 | /* Worker routine for usb_driver_set_configuration() */ |
@@ -1659,14 +1750,35 @@ static void driver_set_config_work(struct work_struct *work) | |||
1659 | { | 1750 | { |
1660 | struct set_config_request *req = | 1751 | struct set_config_request *req = |
1661 | container_of(work, struct set_config_request, work); | 1752 | container_of(work, struct set_config_request, work); |
1753 | struct usb_device *udev = req->udev; | ||
1754 | |||
1755 | usb_lock_device(udev); | ||
1756 | spin_lock(&set_config_lock); | ||
1757 | list_del(&req->node); | ||
1758 | spin_unlock(&set_config_lock); | ||
1662 | 1759 | ||
1663 | usb_lock_device(req->udev); | 1760 | if (req->config >= -1) /* Is req still valid? */ |
1664 | usb_set_configuration(req->udev, req->config); | 1761 | usb_set_configuration(udev, req->config); |
1665 | usb_unlock_device(req->udev); | 1762 | usb_unlock_device(udev); |
1666 | usb_put_dev(req->udev); | 1763 | usb_put_dev(udev); |
1667 | kfree(req); | 1764 | kfree(req); |
1668 | } | 1765 | } |
1669 | 1766 | ||
1767 | /* Cancel pending Set-Config requests for a device whose configuration | ||
1768 | * was just changed | ||
1769 | */ | ||
1770 | static void cancel_async_set_config(struct usb_device *udev) | ||
1771 | { | ||
1772 | struct set_config_request *req; | ||
1773 | |||
1774 | spin_lock(&set_config_lock); | ||
1775 | list_for_each_entry(req, &set_config_list, node) { | ||
1776 | if (req->udev == udev) | ||
1777 | req->config = -999; /* Mark as cancelled */ | ||
1778 | } | ||
1779 | spin_unlock(&set_config_lock); | ||
1780 | } | ||
1781 | |||
1670 | /** | 1782 | /** |
1671 | * usb_driver_set_configuration - Provide a way for drivers to change device configurations | 1783 | * usb_driver_set_configuration - Provide a way for drivers to change device configurations |
1672 | * @udev: the device whose configuration is being updated | 1784 | * @udev: the device whose configuration is being updated |
@@ -1698,6 +1810,10 @@ int usb_driver_set_configuration(struct usb_device *udev, int config) | |||
1698 | req->config = config; | 1810 | req->config = config; |
1699 | INIT_WORK(&req->work, driver_set_config_work); | 1811 | INIT_WORK(&req->work, driver_set_config_work); |
1700 | 1812 | ||
1813 | spin_lock(&set_config_lock); | ||
1814 | list_add(&req->node, &set_config_list); | ||
1815 | spin_unlock(&set_config_lock); | ||
1816 | |||
1701 | usb_get_dev(udev); | 1817 | usb_get_dev(udev); |
1702 | schedule_work(&req->work); | 1818 | schedule_work(&req->work); |
1703 | return 0; | 1819 | return 0; |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 4fb65fdc9dc3..4cc2456ef3be 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -359,19 +359,19 @@ set_level(struct device *dev, struct device_attribute *attr, | |||
359 | strncmp(buf, on_string, len) == 0) { | 359 | strncmp(buf, on_string, len) == 0) { |
360 | udev->autosuspend_disabled = 1; | 360 | udev->autosuspend_disabled = 1; |
361 | udev->autoresume_disabled = 0; | 361 | udev->autoresume_disabled = 0; |
362 | rc = usb_external_resume_device(udev); | 362 | rc = usb_external_resume_device(udev, PMSG_USER_RESUME); |
363 | 363 | ||
364 | } else if (len == sizeof auto_string - 1 && | 364 | } else if (len == sizeof auto_string - 1 && |
365 | strncmp(buf, auto_string, len) == 0) { | 365 | strncmp(buf, auto_string, len) == 0) { |
366 | udev->autosuspend_disabled = 0; | 366 | udev->autosuspend_disabled = 0; |
367 | udev->autoresume_disabled = 0; | 367 | udev->autoresume_disabled = 0; |
368 | rc = usb_external_resume_device(udev); | 368 | rc = usb_external_resume_device(udev, PMSG_USER_RESUME); |
369 | 369 | ||
370 | } else if (len == sizeof suspend_string - 1 && | 370 | } else if (len == sizeof suspend_string - 1 && |
371 | strncmp(buf, suspend_string, len) == 0) { | 371 | strncmp(buf, suspend_string, len) == 0) { |
372 | udev->autosuspend_disabled = 0; | 372 | udev->autosuspend_disabled = 0; |
373 | udev->autoresume_disabled = 1; | 373 | udev->autoresume_disabled = 1; |
374 | rc = usb_external_suspend_device(udev, PMSG_SUSPEND); | 374 | rc = usb_external_suspend_device(udev, PMSG_USER_SUSPEND); |
375 | 375 | ||
376 | } else | 376 | } else |
377 | rc = -EINVAL; | 377 | rc = -EINVAL; |
@@ -629,9 +629,6 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) | |||
629 | struct device *dev = &udev->dev; | 629 | struct device *dev = &udev->dev; |
630 | int retval; | 630 | int retval; |
631 | 631 | ||
632 | /* Unforunately these attributes cannot be created before | ||
633 | * the uevent is broadcast. | ||
634 | */ | ||
635 | retval = device_create_bin_file(dev, &dev_bin_attr_descriptors); | 632 | retval = device_create_bin_file(dev, &dev_bin_attr_descriptors); |
636 | if (retval) | 633 | if (retval) |
637 | goto error; | 634 | goto error; |
@@ -643,11 +640,7 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) | |||
643 | retval = add_power_attributes(dev); | 640 | retval = add_power_attributes(dev); |
644 | if (retval) | 641 | if (retval) |
645 | goto error; | 642 | goto error; |
646 | 643 | return retval; | |
647 | retval = usb_create_ep_files(dev, &udev->ep0, udev); | ||
648 | if (retval) | ||
649 | goto error; | ||
650 | return 0; | ||
651 | error: | 644 | error: |
652 | usb_remove_sysfs_dev_files(udev); | 645 | usb_remove_sysfs_dev_files(udev); |
653 | return retval; | 646 | return retval; |
@@ -657,7 +650,6 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) | |||
657 | { | 650 | { |
658 | struct device *dev = &udev->dev; | 651 | struct device *dev = &udev->dev; |
659 | 652 | ||
660 | usb_remove_ep_files(&udev->ep0); | ||
661 | remove_power_attributes(dev); | 653 | remove_power_attributes(dev); |
662 | remove_persist_attributes(dev); | 654 | remove_persist_attributes(dev); |
663 | device_remove_bin_file(dev, &dev_bin_attr_descriptors); | 655 | device_remove_bin_file(dev, &dev_bin_attr_descriptors); |
@@ -812,28 +804,6 @@ struct attribute_group *usb_interface_groups[] = { | |||
812 | NULL | 804 | NULL |
813 | }; | 805 | }; |
814 | 806 | ||
815 | static inline void usb_create_intf_ep_files(struct usb_interface *intf, | ||
816 | struct usb_device *udev) | ||
817 | { | ||
818 | struct usb_host_interface *iface_desc; | ||
819 | int i; | ||
820 | |||
821 | iface_desc = intf->cur_altsetting; | ||
822 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) | ||
823 | usb_create_ep_files(&intf->dev, &iface_desc->endpoint[i], | ||
824 | udev); | ||
825 | } | ||
826 | |||
827 | static inline void usb_remove_intf_ep_files(struct usb_interface *intf) | ||
828 | { | ||
829 | struct usb_host_interface *iface_desc; | ||
830 | int i; | ||
831 | |||
832 | iface_desc = intf->cur_altsetting; | ||
833 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) | ||
834 | usb_remove_ep_files(&iface_desc->endpoint[i]); | ||
835 | } | ||
836 | |||
837 | int usb_create_sysfs_intf_files(struct usb_interface *intf) | 807 | int usb_create_sysfs_intf_files(struct usb_interface *intf) |
838 | { | 808 | { |
839 | struct usb_device *udev = interface_to_usbdev(intf); | 809 | struct usb_device *udev = interface_to_usbdev(intf); |
@@ -843,26 +813,19 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) | |||
843 | if (intf->sysfs_files_created || intf->unregistering) | 813 | if (intf->sysfs_files_created || intf->unregistering) |
844 | return 0; | 814 | return 0; |
845 | 815 | ||
846 | /* The interface string may be present in some altsettings | ||
847 | * and missing in others. Hence its attribute cannot be created | ||
848 | * before the uevent is broadcast. | ||
849 | */ | ||
850 | if (alt->string == NULL) | 816 | if (alt->string == NULL) |
851 | alt->string = usb_cache_string(udev, alt->desc.iInterface); | 817 | alt->string = usb_cache_string(udev, alt->desc.iInterface); |
852 | if (alt->string) | 818 | if (alt->string) |
853 | retval = device_create_file(&intf->dev, &dev_attr_interface); | 819 | retval = device_create_file(&intf->dev, &dev_attr_interface); |
854 | usb_create_intf_ep_files(intf, udev); | ||
855 | intf->sysfs_files_created = 1; | 820 | intf->sysfs_files_created = 1; |
856 | return 0; | 821 | return 0; |
857 | } | 822 | } |
858 | 823 | ||
859 | void usb_remove_sysfs_intf_files(struct usb_interface *intf) | 824 | void usb_remove_sysfs_intf_files(struct usb_interface *intf) |
860 | { | 825 | { |
861 | struct device *dev = &intf->dev; | ||
862 | |||
863 | if (!intf->sysfs_files_created) | 826 | if (!intf->sysfs_files_created) |
864 | return; | 827 | return; |
865 | usb_remove_intf_ep_files(intf); | 828 | |
866 | device_remove_file(dev, &dev_attr_interface); | 829 | device_remove_file(&intf->dev, &dev_attr_interface); |
867 | intf->sysfs_files_created = 0; | 830 | intf->sysfs_files_created = 0; |
868 | } | 831 | } |
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 1f68af9db3f7..58bc5e3c2560 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
@@ -10,7 +10,6 @@ | |||
10 | 10 | ||
11 | #define to_urb(d) container_of(d, struct urb, kref) | 11 | #define to_urb(d) container_of(d, struct urb, kref) |
12 | 12 | ||
13 | static DEFINE_SPINLOCK(usb_reject_lock); | ||
14 | 13 | ||
15 | static void urb_destroy(struct kref *kref) | 14 | static void urb_destroy(struct kref *kref) |
16 | { | 15 | { |
@@ -131,9 +130,7 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor) | |||
131 | urb->anchor = anchor; | 130 | urb->anchor = anchor; |
132 | 131 | ||
133 | if (unlikely(anchor->poisoned)) { | 132 | if (unlikely(anchor->poisoned)) { |
134 | spin_lock(&usb_reject_lock); | 133 | atomic_inc(&urb->reject); |
135 | urb->reject++; | ||
136 | spin_unlock(&usb_reject_lock); | ||
137 | } | 134 | } |
138 | 135 | ||
139 | spin_unlock_irqrestore(&anchor->lock, flags); | 136 | spin_unlock_irqrestore(&anchor->lock, flags); |
@@ -565,16 +562,12 @@ void usb_kill_urb(struct urb *urb) | |||
565 | might_sleep(); | 562 | might_sleep(); |
566 | if (!(urb && urb->dev && urb->ep)) | 563 | if (!(urb && urb->dev && urb->ep)) |
567 | return; | 564 | return; |
568 | spin_lock_irq(&usb_reject_lock); | 565 | atomic_inc(&urb->reject); |
569 | ++urb->reject; | ||
570 | spin_unlock_irq(&usb_reject_lock); | ||
571 | 566 | ||
572 | usb_hcd_unlink_urb(urb, -ENOENT); | 567 | usb_hcd_unlink_urb(urb, -ENOENT); |
573 | wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); | 568 | wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); |
574 | 569 | ||
575 | spin_lock_irq(&usb_reject_lock); | 570 | atomic_dec(&urb->reject); |
576 | --urb->reject; | ||
577 | spin_unlock_irq(&usb_reject_lock); | ||
578 | } | 571 | } |
579 | EXPORT_SYMBOL_GPL(usb_kill_urb); | 572 | EXPORT_SYMBOL_GPL(usb_kill_urb); |
580 | 573 | ||
@@ -606,9 +599,7 @@ void usb_poison_urb(struct urb *urb) | |||
606 | might_sleep(); | 599 | might_sleep(); |
607 | if (!(urb && urb->dev && urb->ep)) | 600 | if (!(urb && urb->dev && urb->ep)) |
608 | return; | 601 | return; |
609 | spin_lock_irq(&usb_reject_lock); | 602 | atomic_inc(&urb->reject); |
610 | ++urb->reject; | ||
611 | spin_unlock_irq(&usb_reject_lock); | ||
612 | 603 | ||
613 | usb_hcd_unlink_urb(urb, -ENOENT); | 604 | usb_hcd_unlink_urb(urb, -ENOENT); |
614 | wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); | 605 | wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); |
@@ -617,14 +608,10 @@ EXPORT_SYMBOL_GPL(usb_poison_urb); | |||
617 | 608 | ||
618 | void usb_unpoison_urb(struct urb *urb) | 609 | void usb_unpoison_urb(struct urb *urb) |
619 | { | 610 | { |
620 | unsigned long flags; | ||
621 | |||
622 | if (!urb) | 611 | if (!urb) |
623 | return; | 612 | return; |
624 | 613 | ||
625 | spin_lock_irqsave(&usb_reject_lock, flags); | 614 | atomic_dec(&urb->reject); |
626 | --urb->reject; | ||
627 | spin_unlock_irqrestore(&usb_reject_lock, flags); | ||
628 | } | 615 | } |
629 | EXPORT_SYMBOL_GPL(usb_unpoison_urb); | 616 | EXPORT_SYMBOL_GPL(usb_unpoison_urb); |
630 | 617 | ||
@@ -692,6 +679,26 @@ void usb_poison_anchored_urbs(struct usb_anchor *anchor) | |||
692 | EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); | 679 | EXPORT_SYMBOL_GPL(usb_poison_anchored_urbs); |
693 | 680 | ||
694 | /** | 681 | /** |
682 | * usb_unpoison_anchored_urbs - let an anchor be used successfully again | ||
683 | * @anchor: anchor the requests are bound to | ||
684 | * | ||
685 | * Reverses the effect of usb_poison_anchored_urbs | ||
686 | * the anchor can be used normally after it returns | ||
687 | */ | ||
688 | void usb_unpoison_anchored_urbs(struct usb_anchor *anchor) | ||
689 | { | ||
690 | unsigned long flags; | ||
691 | struct urb *lazarus; | ||
692 | |||
693 | spin_lock_irqsave(&anchor->lock, flags); | ||
694 | list_for_each_entry(lazarus, &anchor->urb_list, anchor_list) { | ||
695 | usb_unpoison_urb(lazarus); | ||
696 | } | ||
697 | anchor->poisoned = 0; | ||
698 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
699 | } | ||
700 | EXPORT_SYMBOL_GPL(usb_unpoison_anchored_urbs); | ||
701 | /** | ||
695 | * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse | 702 | * usb_unlink_anchored_urbs - asynchronously cancel transfer requests en masse |
696 | * @anchor: anchor the requests are bound to | 703 | * @anchor: anchor the requests are bound to |
697 | * | 704 | * |
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 399e15fc5052..dcfc072630c1 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -253,7 +253,7 @@ static int usb_dev_prepare(struct device *dev) | |||
253 | static void usb_dev_complete(struct device *dev) | 253 | static void usb_dev_complete(struct device *dev) |
254 | { | 254 | { |
255 | /* Currently used only for rebinding interfaces */ | 255 | /* Currently used only for rebinding interfaces */ |
256 | usb_resume(dev); /* Implement eventually? */ | 256 | usb_resume(dev, PMSG_RESUME); /* Message event is meaningless */ |
257 | } | 257 | } |
258 | 258 | ||
259 | static int usb_dev_suspend(struct device *dev) | 259 | static int usb_dev_suspend(struct device *dev) |
@@ -263,7 +263,7 @@ static int usb_dev_suspend(struct device *dev) | |||
263 | 263 | ||
264 | static int usb_dev_resume(struct device *dev) | 264 | static int usb_dev_resume(struct device *dev) |
265 | { | 265 | { |
266 | return usb_resume(dev); | 266 | return usb_resume(dev, PMSG_RESUME); |
267 | } | 267 | } |
268 | 268 | ||
269 | static int usb_dev_freeze(struct device *dev) | 269 | static int usb_dev_freeze(struct device *dev) |
@@ -273,7 +273,7 @@ static int usb_dev_freeze(struct device *dev) | |||
273 | 273 | ||
274 | static int usb_dev_thaw(struct device *dev) | 274 | static int usb_dev_thaw(struct device *dev) |
275 | { | 275 | { |
276 | return usb_resume(dev); | 276 | return usb_resume(dev, PMSG_THAW); |
277 | } | 277 | } |
278 | 278 | ||
279 | static int usb_dev_poweroff(struct device *dev) | 279 | static int usb_dev_poweroff(struct device *dev) |
@@ -283,7 +283,7 @@ static int usb_dev_poweroff(struct device *dev) | |||
283 | 283 | ||
284 | static int usb_dev_restore(struct device *dev) | 284 | static int usb_dev_restore(struct device *dev) |
285 | { | 285 | { |
286 | return usb_resume(dev); | 286 | return usb_resume(dev, PMSG_RESTORE); |
287 | } | 287 | } |
288 | 288 | ||
289 | static struct dev_pm_ops usb_device_pm_ops = { | 289 | static struct dev_pm_ops usb_device_pm_ops = { |
@@ -362,7 +362,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, | |||
362 | dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; | 362 | dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; |
363 | dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; | 363 | dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT; |
364 | /* ep0 maxpacket comes later, from device descriptor */ | 364 | /* ep0 maxpacket comes later, from device descriptor */ |
365 | usb_enable_endpoint(dev, &dev->ep0); | 365 | usb_enable_endpoint(dev, &dev->ep0, true); |
366 | dev->can_submit = 1; | 366 | dev->can_submit = 1; |
367 | 367 | ||
368 | /* Save readable and stable topology id, distinguishing devices | 368 | /* Save readable and stable topology id, distinguishing devices |
@@ -402,6 +402,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, | |||
402 | #ifdef CONFIG_PM | 402 | #ifdef CONFIG_PM |
403 | mutex_init(&dev->pm_mutex); | 403 | mutex_init(&dev->pm_mutex); |
404 | INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); | 404 | INIT_DELAYED_WORK(&dev->autosuspend, usb_autosuspend_work); |
405 | INIT_WORK(&dev->autoresume, usb_autoresume_work); | ||
405 | dev->autosuspend_delay = usb_autosuspend_delay * HZ; | 406 | dev->autosuspend_delay = usb_autosuspend_delay * HZ; |
406 | dev->connect_time = jiffies; | 407 | dev->connect_time = jiffies; |
407 | dev->active_duration = -jiffies; | 408 | dev->active_duration = -jiffies; |
@@ -513,10 +514,7 @@ EXPORT_SYMBOL_GPL(usb_put_intf); | |||
513 | * disconnect; in some drivers (such as usb-storage) the disconnect() | 514 | * disconnect; in some drivers (such as usb-storage) the disconnect() |
514 | * or suspend() method will block waiting for a device reset to complete. | 515 | * or suspend() method will block waiting for a device reset to complete. |
515 | * | 516 | * |
516 | * Returns a negative error code for failure, otherwise 1 or 0 to indicate | 517 | * Returns a negative error code for failure, otherwise 0. |
517 | * that the device will or will not have to be unlocked. (0 can be | ||
518 | * returned when an interface is given and is BINDING, because in that | ||
519 | * case the driver already owns the device lock.) | ||
520 | */ | 518 | */ |
521 | int usb_lock_device_for_reset(struct usb_device *udev, | 519 | int usb_lock_device_for_reset(struct usb_device *udev, |
522 | const struct usb_interface *iface) | 520 | const struct usb_interface *iface) |
@@ -527,16 +525,9 @@ int usb_lock_device_for_reset(struct usb_device *udev, | |||
527 | return -ENODEV; | 525 | return -ENODEV; |
528 | if (udev->state == USB_STATE_SUSPENDED) | 526 | if (udev->state == USB_STATE_SUSPENDED) |
529 | return -EHOSTUNREACH; | 527 | return -EHOSTUNREACH; |
530 | if (iface) { | 528 | if (iface && (iface->condition == USB_INTERFACE_UNBINDING || |
531 | switch (iface->condition) { | 529 | iface->condition == USB_INTERFACE_UNBOUND)) |
532 | case USB_INTERFACE_BINDING: | 530 | return -EINTR; |
533 | return 0; | ||
534 | case USB_INTERFACE_BOUND: | ||
535 | break; | ||
536 | default: | ||
537 | return -EINTR; | ||
538 | } | ||
539 | } | ||
540 | 531 | ||
541 | while (usb_trylock_device(udev) != 0) { | 532 | while (usb_trylock_device(udev) != 0) { |
542 | 533 | ||
@@ -550,10 +541,11 @@ int usb_lock_device_for_reset(struct usb_device *udev, | |||
550 | return -ENODEV; | 541 | return -ENODEV; |
551 | if (udev->state == USB_STATE_SUSPENDED) | 542 | if (udev->state == USB_STATE_SUSPENDED) |
552 | return -EHOSTUNREACH; | 543 | return -EHOSTUNREACH; |
553 | if (iface && iface->condition != USB_INTERFACE_BOUND) | 544 | if (iface && (iface->condition == USB_INTERFACE_UNBINDING || |
545 | iface->condition == USB_INTERFACE_UNBOUND)) | ||
554 | return -EINTR; | 546 | return -EINTR; |
555 | } | 547 | } |
556 | return 1; | 548 | return 0; |
557 | } | 549 | } |
558 | EXPORT_SYMBOL_GPL(usb_lock_device_for_reset); | 550 | EXPORT_SYMBOL_GPL(usb_lock_device_for_reset); |
559 | 551 | ||
@@ -962,8 +954,12 @@ void usb_buffer_unmap_sg(const struct usb_device *dev, int is_in, | |||
962 | } | 954 | } |
963 | EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg); | 955 | EXPORT_SYMBOL_GPL(usb_buffer_unmap_sg); |
964 | 956 | ||
965 | /* format to disable USB on kernel command line is: nousb */ | 957 | /* To disable USB, kernel command line is 'nousb' not 'usbcore.nousb' */ |
966 | __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444); | 958 | #ifdef MODULE |
959 | module_param(nousb, bool, 0444); | ||
960 | #else | ||
961 | core_param(nousb, nousb, bool, 0444); | ||
962 | #endif | ||
967 | 963 | ||
968 | /* | 964 | /* |
969 | * for external read access to <nousb> | 965 | * for external read access to <nousb> |
@@ -975,6 +971,37 @@ int usb_disabled(void) | |||
975 | EXPORT_SYMBOL_GPL(usb_disabled); | 971 | EXPORT_SYMBOL_GPL(usb_disabled); |
976 | 972 | ||
977 | /* | 973 | /* |
974 | * Notifications of device and interface registration | ||
975 | */ | ||
976 | static int usb_bus_notify(struct notifier_block *nb, unsigned long action, | ||
977 | void *data) | ||
978 | { | ||
979 | struct device *dev = data; | ||
980 | |||
981 | switch (action) { | ||
982 | case BUS_NOTIFY_ADD_DEVICE: | ||
983 | if (dev->type == &usb_device_type) | ||
984 | (void) usb_create_sysfs_dev_files(to_usb_device(dev)); | ||
985 | else if (dev->type == &usb_if_device_type) | ||
986 | (void) usb_create_sysfs_intf_files( | ||
987 | to_usb_interface(dev)); | ||
988 | break; | ||
989 | |||
990 | case BUS_NOTIFY_DEL_DEVICE: | ||
991 | if (dev->type == &usb_device_type) | ||
992 | usb_remove_sysfs_dev_files(to_usb_device(dev)); | ||
993 | else if (dev->type == &usb_if_device_type) | ||
994 | usb_remove_sysfs_intf_files(to_usb_interface(dev)); | ||
995 | break; | ||
996 | } | ||
997 | return 0; | ||
998 | } | ||
999 | |||
1000 | static struct notifier_block usb_bus_nb = { | ||
1001 | .notifier_call = usb_bus_notify, | ||
1002 | }; | ||
1003 | |||
1004 | /* | ||
978 | * Init | 1005 | * Init |
979 | */ | 1006 | */ |
980 | static int __init usb_init(void) | 1007 | static int __init usb_init(void) |
@@ -991,6 +1018,9 @@ static int __init usb_init(void) | |||
991 | retval = bus_register(&usb_bus_type); | 1018 | retval = bus_register(&usb_bus_type); |
992 | if (retval) | 1019 | if (retval) |
993 | goto bus_register_failed; | 1020 | goto bus_register_failed; |
1021 | retval = bus_register_notifier(&usb_bus_type, &usb_bus_nb); | ||
1022 | if (retval) | ||
1023 | goto bus_notifier_failed; | ||
994 | retval = usb_host_init(); | 1024 | retval = usb_host_init(); |
995 | if (retval) | 1025 | if (retval) |
996 | goto host_init_failed; | 1026 | goto host_init_failed; |
@@ -1025,6 +1055,8 @@ driver_register_failed: | |||
1025 | major_init_failed: | 1055 | major_init_failed: |
1026 | usb_host_cleanup(); | 1056 | usb_host_cleanup(); |
1027 | host_init_failed: | 1057 | host_init_failed: |
1058 | bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); | ||
1059 | bus_notifier_failed: | ||
1028 | bus_unregister(&usb_bus_type); | 1060 | bus_unregister(&usb_bus_type); |
1029 | bus_register_failed: | 1061 | bus_register_failed: |
1030 | ksuspend_usb_cleanup(); | 1062 | ksuspend_usb_cleanup(); |
@@ -1048,6 +1080,7 @@ static void __exit usb_exit(void) | |||
1048 | usb_devio_cleanup(); | 1080 | usb_devio_cleanup(); |
1049 | usb_hub_cleanup(); | 1081 | usb_hub_cleanup(); |
1050 | usb_host_cleanup(); | 1082 | usb_host_cleanup(); |
1083 | bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); | ||
1051 | bus_unregister(&usb_bus_type); | 1084 | bus_unregister(&usb_bus_type); |
1052 | ksuspend_usb_cleanup(); | 1085 | ksuspend_usb_cleanup(); |
1053 | } | 1086 | } |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 9a1a45ac3add..386177867a8a 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -1,16 +1,20 @@ | |||
1 | #include <linux/pm.h> | ||
2 | |||
1 | /* Functions local to drivers/usb/core/ */ | 3 | /* Functions local to drivers/usb/core/ */ |
2 | 4 | ||
3 | extern int usb_create_sysfs_dev_files(struct usb_device *dev); | 5 | extern int usb_create_sysfs_dev_files(struct usb_device *dev); |
4 | extern void usb_remove_sysfs_dev_files(struct usb_device *dev); | 6 | extern void usb_remove_sysfs_dev_files(struct usb_device *dev); |
5 | extern int usb_create_sysfs_intf_files(struct usb_interface *intf); | 7 | extern int usb_create_sysfs_intf_files(struct usb_interface *intf); |
6 | extern void usb_remove_sysfs_intf_files(struct usb_interface *intf); | 8 | extern void usb_remove_sysfs_intf_files(struct usb_interface *intf); |
7 | extern int usb_create_ep_files(struct device *parent, | 9 | extern int usb_create_ep_devs(struct device *parent, |
8 | struct usb_host_endpoint *endpoint, | 10 | struct usb_host_endpoint *endpoint, |
9 | struct usb_device *udev); | 11 | struct usb_device *udev); |
10 | extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint); | 12 | extern void usb_remove_ep_devs(struct usb_host_endpoint *endpoint); |
11 | 13 | ||
12 | extern void usb_enable_endpoint(struct usb_device *dev, | 14 | extern void usb_enable_endpoint(struct usb_device *dev, |
13 | struct usb_host_endpoint *ep); | 15 | struct usb_host_endpoint *ep, bool reset_toggle); |
16 | extern void usb_enable_interface(struct usb_device *dev, | ||
17 | struct usb_interface *intf, bool reset_toggles); | ||
14 | extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr); | 18 | extern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr); |
15 | extern void usb_disable_interface(struct usb_device *dev, | 19 | extern void usb_disable_interface(struct usb_device *dev, |
16 | struct usb_interface *intf); | 20 | struct usb_interface *intf); |
@@ -42,14 +46,16 @@ extern void usb_host_cleanup(void); | |||
42 | #ifdef CONFIG_PM | 46 | #ifdef CONFIG_PM |
43 | 47 | ||
44 | extern int usb_suspend(struct device *dev, pm_message_t msg); | 48 | extern int usb_suspend(struct device *dev, pm_message_t msg); |
45 | extern int usb_resume(struct device *dev); | 49 | extern int usb_resume(struct device *dev, pm_message_t msg); |
46 | 50 | ||
47 | extern void usb_autosuspend_work(struct work_struct *work); | 51 | extern void usb_autosuspend_work(struct work_struct *work); |
48 | extern int usb_port_suspend(struct usb_device *dev); | 52 | extern void usb_autoresume_work(struct work_struct *work); |
49 | extern int usb_port_resume(struct usb_device *dev); | 53 | extern int usb_port_suspend(struct usb_device *dev, pm_message_t msg); |
54 | extern int usb_port_resume(struct usb_device *dev, pm_message_t msg); | ||
50 | extern int usb_external_suspend_device(struct usb_device *udev, | 55 | extern int usb_external_suspend_device(struct usb_device *udev, |
51 | pm_message_t msg); | 56 | pm_message_t msg); |
52 | extern int usb_external_resume_device(struct usb_device *udev); | 57 | extern int usb_external_resume_device(struct usb_device *udev, |
58 | pm_message_t msg); | ||
53 | 59 | ||
54 | static inline void usb_pm_lock(struct usb_device *udev) | 60 | static inline void usb_pm_lock(struct usb_device *udev) |
55 | { | 61 | { |
@@ -63,12 +69,12 @@ static inline void usb_pm_unlock(struct usb_device *udev) | |||
63 | 69 | ||
64 | #else | 70 | #else |
65 | 71 | ||
66 | static inline int usb_port_suspend(struct usb_device *udev) | 72 | static inline int usb_port_suspend(struct usb_device *udev, pm_message_t msg) |
67 | { | 73 | { |
68 | return 0; | 74 | return 0; |
69 | } | 75 | } |
70 | 76 | ||
71 | static inline int usb_port_resume(struct usb_device *udev) | 77 | static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg) |
72 | { | 78 | { |
73 | return 0; | 79 | return 0; |
74 | } | 80 | } |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index dd4cd5a51370..3219d137340a 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -297,13 +297,34 @@ config USB_S3C2410_DEBUG | |||
297 | 297 | ||
298 | # musb builds in ../musb along with host support | 298 | # musb builds in ../musb along with host support |
299 | config USB_GADGET_MUSB_HDRC | 299 | config USB_GADGET_MUSB_HDRC |
300 | boolean "Inventra HDRC USB Peripheral (TI, ...)" | 300 | boolean "Inventra HDRC USB Peripheral (TI, ADI, ...)" |
301 | depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG) | 301 | depends on USB_MUSB_HDRC && (USB_MUSB_PERIPHERAL || USB_MUSB_OTG) |
302 | select USB_GADGET_DUALSPEED | 302 | select USB_GADGET_DUALSPEED |
303 | select USB_GADGET_SELECTED | 303 | select USB_GADGET_SELECTED |
304 | help | 304 | help |
305 | This OTG-capable silicon IP is used in dual designs including | 305 | This OTG-capable silicon IP is used in dual designs including |
306 | the TI DaVinci, OMAP 243x, OMAP 343x, and TUSB 6010. | 306 | the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin |
307 | |||
308 | config USB_GADGET_IMX | ||
309 | boolean "Freescale IMX USB Peripheral Controller" | ||
310 | depends on ARCH_MX1 | ||
311 | help | ||
312 | Freescale's IMX series include an integrated full speed | ||
313 | USB 1.1 device controller. The controller in the IMX series | ||
314 | is register-compatible. | ||
315 | |||
316 | It has Six fixed-function endpoints, as well as endpoint | ||
317 | zero (for control transfers). | ||
318 | |||
319 | Say "y" to link the driver statically, or "m" to build a | ||
320 | dynamically linked module called "imx_udc" and force all | ||
321 | gadget drivers to also be dynamically linked. | ||
322 | |||
323 | config USB_IMX | ||
324 | tristate | ||
325 | depends on USB_GADGET_IMX | ||
326 | default USB_GADGET | ||
327 | select USB_GADGET_SELECTED | ||
307 | 328 | ||
308 | config USB_GADGET_M66592 | 329 | config USB_GADGET_M66592 |
309 | boolean "Renesas M66592 USB Peripheral Controller" | 330 | boolean "Renesas M66592 USB Peripheral Controller" |
@@ -377,6 +398,24 @@ config USB_FSL_QE | |||
377 | default USB_GADGET | 398 | default USB_GADGET |
378 | select USB_GADGET_SELECTED | 399 | select USB_GADGET_SELECTED |
379 | 400 | ||
401 | config USB_GADGET_CI13XXX | ||
402 | boolean "MIPS USB CI13xxx" | ||
403 | depends on PCI | ||
404 | select USB_GADGET_DUALSPEED | ||
405 | help | ||
406 | MIPS USB IP core family device controller | ||
407 | Currently it only supports IP part number CI13412 | ||
408 | |||
409 | Say "y" to link the driver statically, or "m" to build a | ||
410 | dynamically linked module called "ci13xxx_udc" and force all | ||
411 | gadget drivers to also be dynamically linked. | ||
412 | |||
413 | config USB_CI13XXX | ||
414 | tristate | ||
415 | depends on USB_GADGET_CI13XXX | ||
416 | default USB_GADGET | ||
417 | select USB_GADGET_SELECTED | ||
418 | |||
380 | config USB_GADGET_NET2280 | 419 | config USB_GADGET_NET2280 |
381 | boolean "NetChip 228x" | 420 | boolean "NetChip 228x" |
382 | depends on PCI | 421 | depends on PCI |
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index bd4041b47dce..39a51d746cb7 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_NET2280) += net2280.o | |||
10 | obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o | 10 | obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o |
11 | obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o | 11 | obj-$(CONFIG_USB_PXA25X) += pxa25x_udc.o |
12 | obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o | 12 | obj-$(CONFIG_USB_PXA27X) += pxa27x_udc.o |
13 | obj-$(CONFIG_USB_IMX) += imx_udc.o | ||
13 | obj-$(CONFIG_USB_GOKU) += goku_udc.o | 14 | obj-$(CONFIG_USB_GOKU) += goku_udc.o |
14 | obj-$(CONFIG_USB_OMAP) += omap_udc.o | 15 | obj-$(CONFIG_USB_OMAP) += omap_udc.o |
15 | obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o | 16 | obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o |
@@ -19,6 +20,7 @@ obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o | |||
19 | obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o | 20 | obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o |
20 | obj-$(CONFIG_USB_M66592) += m66592-udc.o | 21 | obj-$(CONFIG_USB_M66592) += m66592-udc.o |
21 | obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o | 22 | obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o |
23 | obj-$(CONFIG_USB_CI13XXX) += ci13xxx_udc.o | ||
22 | 24 | ||
23 | # | 25 | # |
24 | # USB gadget drivers | 26 | # USB gadget drivers |
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c new file mode 100644 index 000000000000..bebf911c7e5f --- /dev/null +++ b/drivers/usb/gadget/ci13xxx_udc.c | |||
@@ -0,0 +1,2830 @@ | |||
1 | /* | ||
2 | * ci13xxx_udc.c - MIPS USB IP core family device controller | ||
3 | * | ||
4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | ||
5 | * | ||
6 | * Author: David Lopo | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * Description: MIPS USB IP core family device controller | ||
15 | * Currently it only supports IP part number CI13412 | ||
16 | * | ||
17 | * This driver is composed of several blocks: | ||
18 | * - HW: hardware interface | ||
19 | * - DBG: debug facilities (optional) | ||
20 | * - UTIL: utilities | ||
21 | * - ISR: interrupts handling | ||
22 | * - ENDPT: endpoint operations (Gadget API) | ||
23 | * - GADGET: gadget operations (Gadget API) | ||
24 | * - BUS: bus glue code, bus abstraction layer | ||
25 | * - PCI: PCI core interface and PCI resources (interrupts, memory...) | ||
26 | * | ||
27 | * Compile Options | ||
28 | * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities | ||
29 | * - STALL_IN: non-empty bulk-in pipes cannot be halted | ||
30 | * if defined mass storage compliance succeeds but with warnings | ||
31 | * => case 4: Hi > Dn | ||
32 | * => case 5: Hi > Di | ||
33 | * => case 8: Hi <> Do | ||
34 | * if undefined usbtest 13 fails | ||
35 | * - TRACE: enable function tracing (depends on DEBUG) | ||
36 | * | ||
37 | * Main Features | ||
38 | * - Chapter 9 & Mass Storage Compliance with Gadget File Storage | ||
39 | * - Chapter 9 Compliance with Gadget Zero (STALL_IN undefined) | ||
40 | * - Normal & LPM support | ||
41 | * | ||
42 | * USBTEST Report | ||
43 | * - OK: 0-12, 13 (STALL_IN defined) & 14 | ||
44 | * - Not Supported: 15 & 16 (ISO) | ||
45 | * | ||
46 | * TODO List | ||
47 | * - OTG | ||
48 | * - Isochronous & Interrupt Traffic | ||
49 | * - Handle requests which spawns into several TDs | ||
50 | * - GET_STATUS(device) - always reports 0 | ||
51 | * - Gadget API (majority of optional features) | ||
52 | * - Suspend & Remote Wakeup | ||
53 | */ | ||
54 | #include <linux/device.h> | ||
55 | #include <linux/dmapool.h> | ||
56 | #include <linux/dma-mapping.h> | ||
57 | #include <linux/init.h> | ||
58 | #include <linux/interrupt.h> | ||
59 | #include <linux/interrupt.h> | ||
60 | #include <linux/io.h> | ||
61 | #include <linux/irq.h> | ||
62 | #include <linux/kernel.h> | ||
63 | #include <linux/module.h> | ||
64 | #include <linux/pci.h> | ||
65 | #include <linux/usb/ch9.h> | ||
66 | #include <linux/usb/gadget.h> | ||
67 | |||
68 | #include "ci13xxx_udc.h" | ||
69 | |||
70 | |||
71 | /****************************************************************************** | ||
72 | * DEFINE | ||
73 | *****************************************************************************/ | ||
74 | /* ctrl register bank access */ | ||
75 | static DEFINE_SPINLOCK(udc_lock); | ||
76 | |||
77 | /* driver name */ | ||
78 | #define UDC_DRIVER_NAME "ci13xxx_udc" | ||
79 | |||
80 | /* control endpoint description */ | ||
81 | static const struct usb_endpoint_descriptor | ||
82 | ctrl_endpt_desc = { | ||
83 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
84 | .bDescriptorType = USB_DT_ENDPOINT, | ||
85 | |||
86 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | ||
87 | .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), | ||
88 | }; | ||
89 | |||
90 | /* UDC descriptor */ | ||
91 | static struct ci13xxx *_udc; | ||
92 | |||
93 | /* Interrupt statistics */ | ||
94 | #define ISR_MASK 0x1F | ||
95 | static struct { | ||
96 | u32 test; | ||
97 | u32 ui; | ||
98 | u32 uei; | ||
99 | u32 pci; | ||
100 | u32 uri; | ||
101 | u32 sli; | ||
102 | u32 none; | ||
103 | struct { | ||
104 | u32 cnt; | ||
105 | u32 buf[ISR_MASK+1]; | ||
106 | u32 idx; | ||
107 | } hndl; | ||
108 | } isr_statistics; | ||
109 | |||
110 | /** | ||
111 | * ffs_nr: find first (least significant) bit set | ||
112 | * @x: the word to search | ||
113 | * | ||
114 | * This function returns bit number (instead of position) | ||
115 | */ | ||
116 | static int ffs_nr(u32 x) | ||
117 | { | ||
118 | int n = ffs(x); | ||
119 | |||
120 | return n ? n-1 : 32; | ||
121 | } | ||
122 | |||
123 | /****************************************************************************** | ||
124 | * HW block | ||
125 | *****************************************************************************/ | ||
126 | /* register bank descriptor */ | ||
127 | static struct { | ||
128 | unsigned lpm; /* is LPM? */ | ||
129 | void __iomem *abs; /* bus map offset */ | ||
130 | void __iomem *cap; /* bus map offset + CAP offset + CAP data */ | ||
131 | size_t size; /* bank size */ | ||
132 | } hw_bank; | ||
133 | |||
134 | /* UDC register map */ | ||
135 | #define ABS_CAPLENGTH (0x100UL) | ||
136 | #define ABS_HCCPARAMS (0x108UL) | ||
137 | #define ABS_DCCPARAMS (0x124UL) | ||
138 | #define ABS_TESTMODE (hw_bank.lpm ? 0x0FCUL : 0x138UL) | ||
139 | /* offset to CAPLENTGH (addr + data) */ | ||
140 | #define CAP_USBCMD (0x000UL) | ||
141 | #define CAP_USBSTS (0x004UL) | ||
142 | #define CAP_USBINTR (0x008UL) | ||
143 | #define CAP_DEVICEADDR (0x014UL) | ||
144 | #define CAP_ENDPTLISTADDR (0x018UL) | ||
145 | #define CAP_PORTSC (0x044UL) | ||
146 | #define CAP_DEVLC (0x0B4UL) | ||
147 | #define CAP_USBMODE (hw_bank.lpm ? 0x0C8UL : 0x068UL) | ||
148 | #define CAP_ENDPTSETUPSTAT (hw_bank.lpm ? 0x0D8UL : 0x06CUL) | ||
149 | #define CAP_ENDPTPRIME (hw_bank.lpm ? 0x0DCUL : 0x070UL) | ||
150 | #define CAP_ENDPTFLUSH (hw_bank.lpm ? 0x0E0UL : 0x074UL) | ||
151 | #define CAP_ENDPTSTAT (hw_bank.lpm ? 0x0E4UL : 0x078UL) | ||
152 | #define CAP_ENDPTCOMPLETE (hw_bank.lpm ? 0x0E8UL : 0x07CUL) | ||
153 | #define CAP_ENDPTCTRL (hw_bank.lpm ? 0x0ECUL : 0x080UL) | ||
154 | #define CAP_LAST (hw_bank.lpm ? 0x12CUL : 0x0C0UL) | ||
155 | |||
156 | /* maximum number of enpoints: valid only after hw_device_reset() */ | ||
157 | static unsigned hw_ep_max; | ||
158 | |||
159 | /** | ||
160 | * hw_ep_bit: calculates the bit number | ||
161 | * @num: endpoint number | ||
162 | * @dir: endpoint direction | ||
163 | * | ||
164 | * This function returns bit number | ||
165 | */ | ||
166 | static inline int hw_ep_bit(int num, int dir) | ||
167 | { | ||
168 | return num + (dir ? 16 : 0); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * hw_aread: reads from register bitfield | ||
173 | * @addr: address relative to bus map | ||
174 | * @mask: bitfield mask | ||
175 | * | ||
176 | * This function returns register bitfield data | ||
177 | */ | ||
178 | static u32 hw_aread(u32 addr, u32 mask) | ||
179 | { | ||
180 | return ioread32(addr + hw_bank.abs) & mask; | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * hw_awrite: writes to register bitfield | ||
185 | * @addr: address relative to bus map | ||
186 | * @mask: bitfield mask | ||
187 | * @data: new data | ||
188 | */ | ||
189 | static void hw_awrite(u32 addr, u32 mask, u32 data) | ||
190 | { | ||
191 | iowrite32(hw_aread(addr, ~mask) | (data & mask), | ||
192 | addr + hw_bank.abs); | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * hw_cread: reads from register bitfield | ||
197 | * @addr: address relative to CAP offset plus content | ||
198 | * @mask: bitfield mask | ||
199 | * | ||
200 | * This function returns register bitfield data | ||
201 | */ | ||
202 | static u32 hw_cread(u32 addr, u32 mask) | ||
203 | { | ||
204 | return ioread32(addr + hw_bank.cap) & mask; | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * hw_cwrite: writes to register bitfield | ||
209 | * @addr: address relative to CAP offset plus content | ||
210 | * @mask: bitfield mask | ||
211 | * @data: new data | ||
212 | */ | ||
213 | static void hw_cwrite(u32 addr, u32 mask, u32 data) | ||
214 | { | ||
215 | iowrite32(hw_cread(addr, ~mask) | (data & mask), | ||
216 | addr + hw_bank.cap); | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * hw_ctest_and_clear: tests & clears register bitfield | ||
221 | * @addr: address relative to CAP offset plus content | ||
222 | * @mask: bitfield mask | ||
223 | * | ||
224 | * This function returns register bitfield data | ||
225 | */ | ||
226 | static u32 hw_ctest_and_clear(u32 addr, u32 mask) | ||
227 | { | ||
228 | u32 reg = hw_cread(addr, mask); | ||
229 | |||
230 | iowrite32(reg, addr + hw_bank.cap); | ||
231 | return reg; | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * hw_ctest_and_write: tests & writes register bitfield | ||
236 | * @addr: address relative to CAP offset plus content | ||
237 | * @mask: bitfield mask | ||
238 | * @data: new data | ||
239 | * | ||
240 | * This function returns register bitfield data | ||
241 | */ | ||
242 | static u32 hw_ctest_and_write(u32 addr, u32 mask, u32 data) | ||
243 | { | ||
244 | u32 reg = hw_cread(addr, ~0); | ||
245 | |||
246 | iowrite32((reg & ~mask) | (data & mask), addr + hw_bank.cap); | ||
247 | return (reg & mask) >> ffs_nr(mask); | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * hw_device_reset: resets chip (execute without interruption) | ||
252 | * @base: register base address | ||
253 | * | ||
254 | * This function returns an error code | ||
255 | */ | ||
256 | static int hw_device_reset(void __iomem *base) | ||
257 | { | ||
258 | u32 reg; | ||
259 | |||
260 | /* bank is a module variable */ | ||
261 | hw_bank.abs = base; | ||
262 | |||
263 | hw_bank.cap = hw_bank.abs; | ||
264 | hw_bank.cap += ABS_CAPLENGTH; | ||
265 | hw_bank.cap += ioread8(hw_bank.cap); | ||
266 | |||
267 | reg = hw_aread(ABS_HCCPARAMS, HCCPARAMS_LEN) >> ffs_nr(HCCPARAMS_LEN); | ||
268 | hw_bank.lpm = reg; | ||
269 | hw_bank.size = hw_bank.cap - hw_bank.abs; | ||
270 | hw_bank.size += CAP_LAST; | ||
271 | hw_bank.size /= sizeof(u32); | ||
272 | |||
273 | /* should flush & stop before reset */ | ||
274 | hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); | ||
275 | hw_cwrite(CAP_USBCMD, USBCMD_RS, 0); | ||
276 | |||
277 | hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST); | ||
278 | while (hw_cread(CAP_USBCMD, USBCMD_RST)) | ||
279 | udelay(10); /* not RTOS friendly */ | ||
280 | |||
281 | /* USBMODE should be configured step by step */ | ||
282 | hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE); | ||
283 | hw_cwrite(CAP_USBMODE, USBMODE_CM, USBMODE_CM_DEVICE); | ||
284 | hw_cwrite(CAP_USBMODE, USBMODE_SLOM, USBMODE_SLOM); /* HW >= 2.3 */ | ||
285 | |||
286 | if (hw_cread(CAP_USBMODE, USBMODE_CM) != USBMODE_CM_DEVICE) { | ||
287 | pr_err("cannot enter in device mode"); | ||
288 | pr_err("lpm = %i", hw_bank.lpm); | ||
289 | return -ENODEV; | ||
290 | } | ||
291 | |||
292 | reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN); | ||
293 | if (reg == 0 || reg > ENDPT_MAX) | ||
294 | return -ENODEV; | ||
295 | |||
296 | hw_ep_max = reg; /* cache hw ENDPT_MAX */ | ||
297 | |||
298 | /* setup lock mode ? */ | ||
299 | |||
300 | /* ENDPTSETUPSTAT is '0' by default */ | ||
301 | |||
302 | /* HCSPARAMS.bf.ppc SHOULD BE zero for device */ | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | /** | ||
308 | * hw_device_state: enables/disables interrupts & starts/stops device (execute | ||
309 | * without interruption) | ||
310 | * @dma: 0 => disable, !0 => enable and set dma engine | ||
311 | * | ||
312 | * This function returns an error code | ||
313 | */ | ||
314 | static int hw_device_state(u32 dma) | ||
315 | { | ||
316 | if (dma) { | ||
317 | hw_cwrite(CAP_ENDPTLISTADDR, ~0, dma); | ||
318 | /* interrupt, error, port change, reset, sleep/suspend */ | ||
319 | hw_cwrite(CAP_USBINTR, ~0, | ||
320 | USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI); | ||
321 | hw_cwrite(CAP_USBCMD, USBCMD_RS, USBCMD_RS); | ||
322 | } else { | ||
323 | hw_cwrite(CAP_USBCMD, USBCMD_RS, 0); | ||
324 | hw_cwrite(CAP_USBINTR, ~0, 0); | ||
325 | } | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | /** | ||
330 | * hw_ep_flush: flush endpoint fifo (execute without interruption) | ||
331 | * @num: endpoint number | ||
332 | * @dir: endpoint direction | ||
333 | * | ||
334 | * This function returns an error code | ||
335 | */ | ||
336 | static int hw_ep_flush(int num, int dir) | ||
337 | { | ||
338 | int n = hw_ep_bit(num, dir); | ||
339 | |||
340 | do { | ||
341 | /* flush any pending transfer */ | ||
342 | hw_cwrite(CAP_ENDPTFLUSH, BIT(n), BIT(n)); | ||
343 | while (hw_cread(CAP_ENDPTFLUSH, BIT(n))) | ||
344 | cpu_relax(); | ||
345 | } while (hw_cread(CAP_ENDPTSTAT, BIT(n))); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | /** | ||
351 | * hw_ep_disable: disables endpoint (execute without interruption) | ||
352 | * @num: endpoint number | ||
353 | * @dir: endpoint direction | ||
354 | * | ||
355 | * This function returns an error code | ||
356 | */ | ||
357 | static int hw_ep_disable(int num, int dir) | ||
358 | { | ||
359 | hw_ep_flush(num, dir); | ||
360 | hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32), | ||
361 | dir ? ENDPTCTRL_TXE : ENDPTCTRL_RXE, 0); | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | /** | ||
366 | * hw_ep_enable: enables endpoint (execute without interruption) | ||
367 | * @num: endpoint number | ||
368 | * @dir: endpoint direction | ||
369 | * @type: endpoint type | ||
370 | * | ||
371 | * This function returns an error code | ||
372 | */ | ||
373 | static int hw_ep_enable(int num, int dir, int type) | ||
374 | { | ||
375 | u32 mask, data; | ||
376 | |||
377 | if (dir) { | ||
378 | mask = ENDPTCTRL_TXT; /* type */ | ||
379 | data = type << ffs_nr(mask); | ||
380 | |||
381 | mask |= ENDPTCTRL_TXS; /* unstall */ | ||
382 | mask |= ENDPTCTRL_TXR; /* reset data toggle */ | ||
383 | data |= ENDPTCTRL_TXR; | ||
384 | mask |= ENDPTCTRL_TXE; /* enable */ | ||
385 | data |= ENDPTCTRL_TXE; | ||
386 | } else { | ||
387 | mask = ENDPTCTRL_RXT; /* type */ | ||
388 | data = type << ffs_nr(mask); | ||
389 | |||
390 | mask |= ENDPTCTRL_RXS; /* unstall */ | ||
391 | mask |= ENDPTCTRL_RXR; /* reset data toggle */ | ||
392 | data |= ENDPTCTRL_RXR; | ||
393 | mask |= ENDPTCTRL_RXE; /* enable */ | ||
394 | data |= ENDPTCTRL_RXE; | ||
395 | } | ||
396 | hw_cwrite(CAP_ENDPTCTRL + num * sizeof(u32), mask, data); | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | /** | ||
401 | * hw_ep_get_halt: return endpoint halt status | ||
402 | * @num: endpoint number | ||
403 | * @dir: endpoint direction | ||
404 | * | ||
405 | * This function returns 1 if endpoint halted | ||
406 | */ | ||
407 | static int hw_ep_get_halt(int num, int dir) | ||
408 | { | ||
409 | u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; | ||
410 | |||
411 | return hw_cread(CAP_ENDPTCTRL + num * sizeof(u32), mask) ? 1 : 0; | ||
412 | } | ||
413 | |||
414 | /** | ||
415 | * hw_ep_is_primed: test if endpoint is primed (execute without interruption) | ||
416 | * @num: endpoint number | ||
417 | * @dir: endpoint direction | ||
418 | * | ||
419 | * This function returns true if endpoint primed | ||
420 | */ | ||
421 | static int hw_ep_is_primed(int num, int dir) | ||
422 | { | ||
423 | u32 reg = hw_cread(CAP_ENDPTPRIME, ~0) | hw_cread(CAP_ENDPTSTAT, ~0); | ||
424 | |||
425 | return test_bit(hw_ep_bit(num, dir), (void *)®); | ||
426 | } | ||
427 | |||
428 | /** | ||
429 | * hw_test_and_clear_setup_status: test & clear setup status (execute without | ||
430 | * interruption) | ||
431 | * @n: bit number (endpoint) | ||
432 | * | ||
433 | * This function returns setup status | ||
434 | */ | ||
435 | static int hw_test_and_clear_setup_status(int n) | ||
436 | { | ||
437 | return hw_ctest_and_clear(CAP_ENDPTSETUPSTAT, BIT(n)); | ||
438 | } | ||
439 | |||
440 | /** | ||
441 | * hw_ep_prime: primes endpoint (execute without interruption) | ||
442 | * @num: endpoint number | ||
443 | * @dir: endpoint direction | ||
444 | * @is_ctrl: true if control endpoint | ||
445 | * | ||
446 | * This function returns an error code | ||
447 | */ | ||
448 | static int hw_ep_prime(int num, int dir, int is_ctrl) | ||
449 | { | ||
450 | int n = hw_ep_bit(num, dir); | ||
451 | |||
452 | /* the caller should flush first */ | ||
453 | if (hw_ep_is_primed(num, dir)) | ||
454 | return -EBUSY; | ||
455 | |||
456 | if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num))) | ||
457 | return -EAGAIN; | ||
458 | |||
459 | hw_cwrite(CAP_ENDPTPRIME, BIT(n), BIT(n)); | ||
460 | |||
461 | while (hw_cread(CAP_ENDPTPRIME, BIT(n))) | ||
462 | cpu_relax(); | ||
463 | if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num))) | ||
464 | return -EAGAIN; | ||
465 | |||
466 | /* status shoult be tested according with manual but it doesn't work */ | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | /** | ||
471 | * hw_ep_set_halt: configures ep halt & resets data toggle after clear (execute | ||
472 | * without interruption) | ||
473 | * @num: endpoint number | ||
474 | * @dir: endpoint direction | ||
475 | * @value: true => stall, false => unstall | ||
476 | * | ||
477 | * This function returns an error code | ||
478 | */ | ||
479 | static int hw_ep_set_halt(int num, int dir, int value) | ||
480 | { | ||
481 | if (value != 0 && value != 1) | ||
482 | return -EINVAL; | ||
483 | |||
484 | do { | ||
485 | u32 addr = CAP_ENDPTCTRL + num * sizeof(u32); | ||
486 | u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; | ||
487 | u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; | ||
488 | |||
489 | /* data toggle - reserved for EP0 but it's in ESS */ | ||
490 | hw_cwrite(addr, mask_xs|mask_xr, value ? mask_xs : mask_xr); | ||
491 | |||
492 | } while (value != hw_ep_get_halt(num, dir)); | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | /** | ||
498 | * hw_intr_clear: disables interrupt & clears interrupt status (execute without | ||
499 | * interruption) | ||
500 | * @n: interrupt bit | ||
501 | * | ||
502 | * This function returns an error code | ||
503 | */ | ||
504 | static int hw_intr_clear(int n) | ||
505 | { | ||
506 | if (n >= REG_BITS) | ||
507 | return -EINVAL; | ||
508 | |||
509 | hw_cwrite(CAP_USBINTR, BIT(n), 0); | ||
510 | hw_cwrite(CAP_USBSTS, BIT(n), BIT(n)); | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | /** | ||
515 | * hw_intr_force: enables interrupt & forces interrupt status (execute without | ||
516 | * interruption) | ||
517 | * @n: interrupt bit | ||
518 | * | ||
519 | * This function returns an error code | ||
520 | */ | ||
521 | static int hw_intr_force(int n) | ||
522 | { | ||
523 | if (n >= REG_BITS) | ||
524 | return -EINVAL; | ||
525 | |||
526 | hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE); | ||
527 | hw_cwrite(CAP_USBINTR, BIT(n), BIT(n)); | ||
528 | hw_cwrite(CAP_USBSTS, BIT(n), BIT(n)); | ||
529 | hw_awrite(ABS_TESTMODE, TESTMODE_FORCE, 0); | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | /** | ||
534 | * hw_is_port_high_speed: test if port is high speed | ||
535 | * | ||
536 | * This function returns true if high speed port | ||
537 | */ | ||
538 | static int hw_port_is_high_speed(void) | ||
539 | { | ||
540 | return hw_bank.lpm ? hw_cread(CAP_DEVLC, DEVLC_PSPD) : | ||
541 | hw_cread(CAP_PORTSC, PORTSC_HSP); | ||
542 | } | ||
543 | |||
544 | /** | ||
545 | * hw_port_test_get: reads port test mode value | ||
546 | * | ||
547 | * This function returns port test mode value | ||
548 | */ | ||
549 | static u8 hw_port_test_get(void) | ||
550 | { | ||
551 | return hw_cread(CAP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC); | ||
552 | } | ||
553 | |||
554 | /** | ||
555 | * hw_port_test_set: writes port test mode (execute without interruption) | ||
556 | * @mode: new value | ||
557 | * | ||
558 | * This function returns an error code | ||
559 | */ | ||
560 | static int hw_port_test_set(u8 mode) | ||
561 | { | ||
562 | const u8 TEST_MODE_MAX = 7; | ||
563 | |||
564 | if (mode > TEST_MODE_MAX) | ||
565 | return -EINVAL; | ||
566 | |||
567 | hw_cwrite(CAP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC)); | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | /** | ||
572 | * hw_read_intr_enable: returns interrupt enable register | ||
573 | * | ||
574 | * This function returns register data | ||
575 | */ | ||
576 | static u32 hw_read_intr_enable(void) | ||
577 | { | ||
578 | return hw_cread(CAP_USBINTR, ~0); | ||
579 | } | ||
580 | |||
581 | /** | ||
582 | * hw_read_intr_status: returns interrupt status register | ||
583 | * | ||
584 | * This function returns register data | ||
585 | */ | ||
586 | static u32 hw_read_intr_status(void) | ||
587 | { | ||
588 | return hw_cread(CAP_USBSTS, ~0); | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * hw_register_read: reads all device registers (execute without interruption) | ||
593 | * @buf: destination buffer | ||
594 | * @size: buffer size | ||
595 | * | ||
596 | * This function returns number of registers read | ||
597 | */ | ||
598 | static size_t hw_register_read(u32 *buf, size_t size) | ||
599 | { | ||
600 | unsigned i; | ||
601 | |||
602 | if (size > hw_bank.size) | ||
603 | size = hw_bank.size; | ||
604 | |||
605 | for (i = 0; i < size; i++) | ||
606 | buf[i] = hw_aread(i * sizeof(u32), ~0); | ||
607 | |||
608 | return size; | ||
609 | } | ||
610 | |||
611 | /** | ||
612 | * hw_register_write: writes to register | ||
613 | * @addr: register address | ||
614 | * @data: register value | ||
615 | * | ||
616 | * This function returns an error code | ||
617 | */ | ||
618 | static int hw_register_write(u16 addr, u32 data) | ||
619 | { | ||
620 | /* align */ | ||
621 | addr /= sizeof(u32); | ||
622 | |||
623 | if (addr >= hw_bank.size) | ||
624 | return -EINVAL; | ||
625 | |||
626 | /* align */ | ||
627 | addr *= sizeof(u32); | ||
628 | |||
629 | hw_awrite(addr, ~0, data); | ||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | /** | ||
634 | * hw_test_and_clear_complete: test & clear complete status (execute without | ||
635 | * interruption) | ||
636 | * @n: bit number (endpoint) | ||
637 | * | ||
638 | * This function returns complete status | ||
639 | */ | ||
640 | static int hw_test_and_clear_complete(int n) | ||
641 | { | ||
642 | return hw_ctest_and_clear(CAP_ENDPTCOMPLETE, BIT(n)); | ||
643 | } | ||
644 | |||
645 | /** | ||
646 | * hw_test_and_clear_intr_active: test & clear active interrupts (execute | ||
647 | * without interruption) | ||
648 | * | ||
649 | * This function returns active interrutps | ||
650 | */ | ||
651 | static u32 hw_test_and_clear_intr_active(void) | ||
652 | { | ||
653 | u32 reg = hw_read_intr_status() & hw_read_intr_enable(); | ||
654 | |||
655 | hw_cwrite(CAP_USBSTS, ~0, reg); | ||
656 | return reg; | ||
657 | } | ||
658 | |||
659 | /** | ||
660 | * hw_test_and_clear_setup_guard: test & clear setup guard (execute without | ||
661 | * interruption) | ||
662 | * | ||
663 | * This function returns guard value | ||
664 | */ | ||
665 | static int hw_test_and_clear_setup_guard(void) | ||
666 | { | ||
667 | return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, 0); | ||
668 | } | ||
669 | |||
670 | /** | ||
671 | * hw_test_and_set_setup_guard: test & set setup guard (execute without | ||
672 | * interruption) | ||
673 | * | ||
674 | * This function returns guard value | ||
675 | */ | ||
676 | static int hw_test_and_set_setup_guard(void) | ||
677 | { | ||
678 | return hw_ctest_and_write(CAP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); | ||
679 | } | ||
680 | |||
681 | /** | ||
682 | * hw_usb_set_address: configures USB address (execute without interruption) | ||
683 | * @value: new USB address | ||
684 | * | ||
685 | * This function returns an error code | ||
686 | */ | ||
687 | static int hw_usb_set_address(u8 value) | ||
688 | { | ||
689 | /* advance */ | ||
690 | hw_cwrite(CAP_DEVICEADDR, DEVICEADDR_USBADR | DEVICEADDR_USBADRA, | ||
691 | value << ffs_nr(DEVICEADDR_USBADR) | DEVICEADDR_USBADRA); | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | /** | ||
696 | * hw_usb_reset: restart device after a bus reset (execute without | ||
697 | * interruption) | ||
698 | * | ||
699 | * This function returns an error code | ||
700 | */ | ||
701 | static int hw_usb_reset(void) | ||
702 | { | ||
703 | hw_usb_set_address(0); | ||
704 | |||
705 | /* ESS flushes only at end?!? */ | ||
706 | hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0); /* flush all EPs */ | ||
707 | |||
708 | /* clear setup token semaphores */ | ||
709 | hw_cwrite(CAP_ENDPTSETUPSTAT, 0, 0); /* writes its content */ | ||
710 | |||
711 | /* clear complete status */ | ||
712 | hw_cwrite(CAP_ENDPTCOMPLETE, 0, 0); /* writes its content */ | ||
713 | |||
714 | /* wait until all bits cleared */ | ||
715 | while (hw_cread(CAP_ENDPTPRIME, ~0)) | ||
716 | udelay(10); /* not RTOS friendly */ | ||
717 | |||
718 | /* reset all endpoints ? */ | ||
719 | |||
720 | /* reset internal status and wait for further instructions | ||
721 | no need to verify the port reset status (ESS does it) */ | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | /****************************************************************************** | ||
727 | * DBG block | ||
728 | *****************************************************************************/ | ||
729 | /** | ||
730 | * show_device: prints information about device capabilities and status | ||
731 | * | ||
732 | * Check "device.h" for details | ||
733 | */ | ||
734 | static ssize_t show_device(struct device *dev, struct device_attribute *attr, | ||
735 | char *buf) | ||
736 | { | ||
737 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
738 | struct usb_gadget *gadget = &udc->gadget; | ||
739 | int n = 0; | ||
740 | |||
741 | dbg_trace("[%s] %p\n", __func__, buf); | ||
742 | if (attr == NULL || buf == NULL) { | ||
743 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
744 | return 0; | ||
745 | } | ||
746 | |||
747 | n += scnprintf(buf + n, PAGE_SIZE - n, "speed = %d\n", | ||
748 | gadget->speed); | ||
749 | n += scnprintf(buf + n, PAGE_SIZE - n, "is_dualspeed = %d\n", | ||
750 | gadget->is_dualspeed); | ||
751 | n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg = %d\n", | ||
752 | gadget->is_otg); | ||
753 | n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral = %d\n", | ||
754 | gadget->is_a_peripheral); | ||
755 | n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable = %d\n", | ||
756 | gadget->b_hnp_enable); | ||
757 | n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support = %d\n", | ||
758 | gadget->a_hnp_support); | ||
759 | n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n", | ||
760 | gadget->a_alt_hnp_support); | ||
761 | n += scnprintf(buf + n, PAGE_SIZE - n, "name = %s\n", | ||
762 | (gadget->name ? gadget->name : "")); | ||
763 | |||
764 | return n; | ||
765 | } | ||
766 | static DEVICE_ATTR(device, S_IRUSR, show_device, NULL); | ||
767 | |||
768 | /** | ||
769 | * show_driver: prints information about attached gadget (if any) | ||
770 | * | ||
771 | * Check "device.h" for details | ||
772 | */ | ||
773 | static ssize_t show_driver(struct device *dev, struct device_attribute *attr, | ||
774 | char *buf) | ||
775 | { | ||
776 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
777 | struct usb_gadget_driver *driver = udc->driver; | ||
778 | int n = 0; | ||
779 | |||
780 | dbg_trace("[%s] %p\n", __func__, buf); | ||
781 | if (attr == NULL || buf == NULL) { | ||
782 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | if (driver == NULL) | ||
787 | return scnprintf(buf, PAGE_SIZE, | ||
788 | "There is no gadget attached!\n"); | ||
789 | |||
790 | n += scnprintf(buf + n, PAGE_SIZE - n, "function = %s\n", | ||
791 | (driver->function ? driver->function : "")); | ||
792 | n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n", | ||
793 | driver->speed); | ||
794 | |||
795 | return n; | ||
796 | } | ||
797 | static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL); | ||
798 | |||
799 | /* Maximum event message length */ | ||
800 | #define DBG_DATA_MSG 64UL | ||
801 | |||
802 | /* Maximum event messages */ | ||
803 | #define DBG_DATA_MAX 128UL | ||
804 | |||
805 | /* Event buffer descriptor */ | ||
806 | static struct { | ||
807 | char (buf[DBG_DATA_MAX])[DBG_DATA_MSG]; /* buffer */ | ||
808 | unsigned idx; /* index */ | ||
809 | unsigned tty; /* print to console? */ | ||
810 | rwlock_t lck; /* lock */ | ||
811 | } dbg_data = { | ||
812 | .idx = 0, | ||
813 | .tty = 0, | ||
814 | .lck = __RW_LOCK_UNLOCKED(lck) | ||
815 | }; | ||
816 | |||
817 | /** | ||
818 | * dbg_dec: decrements debug event index | ||
819 | * @idx: buffer index | ||
820 | */ | ||
821 | static void dbg_dec(unsigned *idx) | ||
822 | { | ||
823 | *idx = (*idx - 1) & (DBG_DATA_MAX-1); | ||
824 | } | ||
825 | |||
826 | /** | ||
827 | * dbg_inc: increments debug event index | ||
828 | * @idx: buffer index | ||
829 | */ | ||
830 | static void dbg_inc(unsigned *idx) | ||
831 | { | ||
832 | *idx = (*idx + 1) & (DBG_DATA_MAX-1); | ||
833 | } | ||
834 | |||
835 | /** | ||
836 | * dbg_print: prints the common part of the event | ||
837 | * @addr: endpoint address | ||
838 | * @name: event name | ||
839 | * @status: status | ||
840 | * @extra: extra information | ||
841 | */ | ||
842 | static void dbg_print(u8 addr, const char *name, int status, const char *extra) | ||
843 | { | ||
844 | struct timeval tval; | ||
845 | unsigned int stamp; | ||
846 | unsigned long flags; | ||
847 | |||
848 | write_lock_irqsave(&dbg_data.lck, flags); | ||
849 | |||
850 | do_gettimeofday(&tval); | ||
851 | stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s */ | ||
852 | stamp = stamp * 1000000 + tval.tv_usec; | ||
853 | |||
854 | scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG, | ||
855 | "%04X\t» %02X %-7.7s %4i «\t%s\n", | ||
856 | stamp, addr, name, status, extra); | ||
857 | |||
858 | dbg_inc(&dbg_data.idx); | ||
859 | |||
860 | write_unlock_irqrestore(&dbg_data.lck, flags); | ||
861 | |||
862 | if (dbg_data.tty != 0) | ||
863 | pr_notice("%04X\t» %02X %-7.7s %4i «\t%s\n", | ||
864 | stamp, addr, name, status, extra); | ||
865 | } | ||
866 | |||
867 | /** | ||
868 | * dbg_done: prints a DONE event | ||
869 | * @addr: endpoint address | ||
870 | * @td: transfer descriptor | ||
871 | * @status: status | ||
872 | */ | ||
873 | static void dbg_done(u8 addr, const u32 token, int status) | ||
874 | { | ||
875 | char msg[DBG_DATA_MSG]; | ||
876 | |||
877 | scnprintf(msg, sizeof(msg), "%d %02X", | ||
878 | (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES), | ||
879 | (int)(token & TD_STATUS) >> ffs_nr(TD_STATUS)); | ||
880 | dbg_print(addr, "DONE", status, msg); | ||
881 | } | ||
882 | |||
883 | /** | ||
884 | * dbg_event: prints a generic event | ||
885 | * @addr: endpoint address | ||
886 | * @name: event name | ||
887 | * @status: status | ||
888 | */ | ||
889 | static void dbg_event(u8 addr, const char *name, int status) | ||
890 | { | ||
891 | if (name != NULL) | ||
892 | dbg_print(addr, name, status, ""); | ||
893 | } | ||
894 | |||
895 | /* | ||
896 | * dbg_queue: prints a QUEUE event | ||
897 | * @addr: endpoint address | ||
898 | * @req: USB request | ||
899 | * @status: status | ||
900 | */ | ||
901 | static void dbg_queue(u8 addr, const struct usb_request *req, int status) | ||
902 | { | ||
903 | char msg[DBG_DATA_MSG]; | ||
904 | |||
905 | if (req != NULL) { | ||
906 | scnprintf(msg, sizeof(msg), | ||
907 | "%d %d", !req->no_interrupt, req->length); | ||
908 | dbg_print(addr, "QUEUE", status, msg); | ||
909 | } | ||
910 | } | ||
911 | |||
912 | /** | ||
913 | * dbg_setup: prints a SETUP event | ||
914 | * @addr: endpoint address | ||
915 | * @req: setup request | ||
916 | */ | ||
917 | static void dbg_setup(u8 addr, const struct usb_ctrlrequest *req) | ||
918 | { | ||
919 | char msg[DBG_DATA_MSG]; | ||
920 | |||
921 | if (req != NULL) { | ||
922 | scnprintf(msg, sizeof(msg), | ||
923 | "%02X %02X %04X %04X %d", req->bRequestType, | ||
924 | req->bRequest, le16_to_cpu(req->wValue), | ||
925 | le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength)); | ||
926 | dbg_print(addr, "SETUP", 0, msg); | ||
927 | } | ||
928 | } | ||
929 | |||
930 | /** | ||
931 | * show_events: displays the event buffer | ||
932 | * | ||
933 | * Check "device.h" for details | ||
934 | */ | ||
935 | static ssize_t show_events(struct device *dev, struct device_attribute *attr, | ||
936 | char *buf) | ||
937 | { | ||
938 | unsigned long flags; | ||
939 | unsigned i, j, n = 0; | ||
940 | |||
941 | dbg_trace("[%s] %p\n", __func__, buf); | ||
942 | if (attr == NULL || buf == NULL) { | ||
943 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
944 | return 0; | ||
945 | } | ||
946 | |||
947 | read_lock_irqsave(&dbg_data.lck, flags); | ||
948 | |||
949 | i = dbg_data.idx; | ||
950 | for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) { | ||
951 | n += strlen(dbg_data.buf[i]); | ||
952 | if (n >= PAGE_SIZE) { | ||
953 | n -= strlen(dbg_data.buf[i]); | ||
954 | break; | ||
955 | } | ||
956 | } | ||
957 | for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i)) | ||
958 | j += scnprintf(buf + j, PAGE_SIZE - j, | ||
959 | "%s", dbg_data.buf[i]); | ||
960 | |||
961 | read_unlock_irqrestore(&dbg_data.lck, flags); | ||
962 | |||
963 | return n; | ||
964 | } | ||
965 | |||
966 | /** | ||
967 | * store_events: configure if events are going to be also printed to console | ||
968 | * | ||
969 | * Check "device.h" for details | ||
970 | */ | ||
971 | static ssize_t store_events(struct device *dev, struct device_attribute *attr, | ||
972 | const char *buf, size_t count) | ||
973 | { | ||
974 | unsigned tty; | ||
975 | |||
976 | dbg_trace("[%s] %p, %d\n", __func__, buf, count); | ||
977 | if (attr == NULL || buf == NULL) { | ||
978 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
979 | goto done; | ||
980 | } | ||
981 | |||
982 | if (sscanf(buf, "%u", &tty) != 1 || tty > 1) { | ||
983 | dev_err(dev, "<1|0>: enable|disable console log\n"); | ||
984 | goto done; | ||
985 | } | ||
986 | |||
987 | dbg_data.tty = tty; | ||
988 | dev_info(dev, "tty = %u", dbg_data.tty); | ||
989 | |||
990 | done: | ||
991 | return count; | ||
992 | } | ||
993 | static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events); | ||
994 | |||
995 | /** | ||
996 | * show_inters: interrupt status, enable status and historic | ||
997 | * | ||
998 | * Check "device.h" for details | ||
999 | */ | ||
1000 | static ssize_t show_inters(struct device *dev, struct device_attribute *attr, | ||
1001 | char *buf) | ||
1002 | { | ||
1003 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
1004 | unsigned long flags; | ||
1005 | u32 intr; | ||
1006 | unsigned i, j, n = 0; | ||
1007 | |||
1008 | dbg_trace("[%s] %p\n", __func__, buf); | ||
1009 | if (attr == NULL || buf == NULL) { | ||
1010 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
1011 | return 0; | ||
1012 | } | ||
1013 | |||
1014 | spin_lock_irqsave(udc->lock, flags); | ||
1015 | |||
1016 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
1017 | "status = %08x\n", hw_read_intr_status()); | ||
1018 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
1019 | "enable = %08x\n", hw_read_intr_enable()); | ||
1020 | |||
1021 | n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n", | ||
1022 | isr_statistics.test); | ||
1023 | n += scnprintf(buf + n, PAGE_SIZE - n, "» ui = %d\n", | ||
1024 | isr_statistics.ui); | ||
1025 | n += scnprintf(buf + n, PAGE_SIZE - n, "» uei = %d\n", | ||
1026 | isr_statistics.uei); | ||
1027 | n += scnprintf(buf + n, PAGE_SIZE - n, "» pci = %d\n", | ||
1028 | isr_statistics.pci); | ||
1029 | n += scnprintf(buf + n, PAGE_SIZE - n, "» uri = %d\n", | ||
1030 | isr_statistics.uri); | ||
1031 | n += scnprintf(buf + n, PAGE_SIZE - n, "» sli = %d\n", | ||
1032 | isr_statistics.sli); | ||
1033 | n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n", | ||
1034 | isr_statistics.none); | ||
1035 | n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n", | ||
1036 | isr_statistics.hndl.cnt); | ||
1037 | |||
1038 | for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) { | ||
1039 | i &= ISR_MASK; | ||
1040 | intr = isr_statistics.hndl.buf[i]; | ||
1041 | |||
1042 | if (USBi_UI & intr) | ||
1043 | n += scnprintf(buf + n, PAGE_SIZE - n, "ui "); | ||
1044 | intr &= ~USBi_UI; | ||
1045 | if (USBi_UEI & intr) | ||
1046 | n += scnprintf(buf + n, PAGE_SIZE - n, "uei "); | ||
1047 | intr &= ~USBi_UEI; | ||
1048 | if (USBi_PCI & intr) | ||
1049 | n += scnprintf(buf + n, PAGE_SIZE - n, "pci "); | ||
1050 | intr &= ~USBi_PCI; | ||
1051 | if (USBi_URI & intr) | ||
1052 | n += scnprintf(buf + n, PAGE_SIZE - n, "uri "); | ||
1053 | intr &= ~USBi_URI; | ||
1054 | if (USBi_SLI & intr) | ||
1055 | n += scnprintf(buf + n, PAGE_SIZE - n, "sli "); | ||
1056 | intr &= ~USBi_SLI; | ||
1057 | if (intr) | ||
1058 | n += scnprintf(buf + n, PAGE_SIZE - n, "??? "); | ||
1059 | if (isr_statistics.hndl.buf[i]) | ||
1060 | n += scnprintf(buf + n, PAGE_SIZE - n, "\n"); | ||
1061 | } | ||
1062 | |||
1063 | spin_unlock_irqrestore(udc->lock, flags); | ||
1064 | |||
1065 | return n; | ||
1066 | } | ||
1067 | |||
1068 | /** | ||
1069 | * store_inters: enable & force or disable an individual interrutps | ||
1070 | * (to be used for test purposes only) | ||
1071 | * | ||
1072 | * Check "device.h" for details | ||
1073 | */ | ||
1074 | static ssize_t store_inters(struct device *dev, struct device_attribute *attr, | ||
1075 | const char *buf, size_t count) | ||
1076 | { | ||
1077 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
1078 | unsigned long flags; | ||
1079 | unsigned en, bit; | ||
1080 | |||
1081 | dbg_trace("[%s] %p, %d\n", __func__, buf, count); | ||
1082 | if (attr == NULL || buf == NULL) { | ||
1083 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
1084 | goto done; | ||
1085 | } | ||
1086 | |||
1087 | if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) { | ||
1088 | dev_err(dev, "<1|0> <bit>: enable|disable interrupt"); | ||
1089 | goto done; | ||
1090 | } | ||
1091 | |||
1092 | spin_lock_irqsave(udc->lock, flags); | ||
1093 | if (en) { | ||
1094 | if (hw_intr_force(bit)) | ||
1095 | dev_err(dev, "invalid bit number\n"); | ||
1096 | else | ||
1097 | isr_statistics.test++; | ||
1098 | } else { | ||
1099 | if (hw_intr_clear(bit)) | ||
1100 | dev_err(dev, "invalid bit number\n"); | ||
1101 | } | ||
1102 | spin_unlock_irqrestore(udc->lock, flags); | ||
1103 | |||
1104 | done: | ||
1105 | return count; | ||
1106 | } | ||
1107 | static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters); | ||
1108 | |||
1109 | /** | ||
1110 | * show_port_test: reads port test mode | ||
1111 | * | ||
1112 | * Check "device.h" for details | ||
1113 | */ | ||
1114 | static ssize_t show_port_test(struct device *dev, | ||
1115 | struct device_attribute *attr, char *buf) | ||
1116 | { | ||
1117 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
1118 | unsigned long flags; | ||
1119 | unsigned mode; | ||
1120 | |||
1121 | dbg_trace("[%s] %p\n", __func__, buf); | ||
1122 | if (attr == NULL || buf == NULL) { | ||
1123 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
1124 | return 0; | ||
1125 | } | ||
1126 | |||
1127 | spin_lock_irqsave(udc->lock, flags); | ||
1128 | mode = hw_port_test_get(); | ||
1129 | spin_unlock_irqrestore(udc->lock, flags); | ||
1130 | |||
1131 | return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode); | ||
1132 | } | ||
1133 | |||
1134 | /** | ||
1135 | * store_port_test: writes port test mode | ||
1136 | * | ||
1137 | * Check "device.h" for details | ||
1138 | */ | ||
1139 | static ssize_t store_port_test(struct device *dev, | ||
1140 | struct device_attribute *attr, | ||
1141 | const char *buf, size_t count) | ||
1142 | { | ||
1143 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
1144 | unsigned long flags; | ||
1145 | unsigned mode; | ||
1146 | |||
1147 | dbg_trace("[%s] %p, %d\n", __func__, buf, count); | ||
1148 | if (attr == NULL || buf == NULL) { | ||
1149 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
1150 | goto done; | ||
1151 | } | ||
1152 | |||
1153 | if (sscanf(buf, "%u", &mode) != 1) { | ||
1154 | dev_err(dev, "<mode>: set port test mode"); | ||
1155 | goto done; | ||
1156 | } | ||
1157 | |||
1158 | spin_lock_irqsave(udc->lock, flags); | ||
1159 | if (hw_port_test_set(mode)) | ||
1160 | dev_err(dev, "invalid mode\n"); | ||
1161 | spin_unlock_irqrestore(udc->lock, flags); | ||
1162 | |||
1163 | done: | ||
1164 | return count; | ||
1165 | } | ||
1166 | static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR, | ||
1167 | show_port_test, store_port_test); | ||
1168 | |||
1169 | /** | ||
1170 | * show_qheads: DMA contents of all queue heads | ||
1171 | * | ||
1172 | * Check "device.h" for details | ||
1173 | */ | ||
1174 | static ssize_t show_qheads(struct device *dev, struct device_attribute *attr, | ||
1175 | char *buf) | ||
1176 | { | ||
1177 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
1178 | unsigned long flags; | ||
1179 | unsigned i, j, n = 0; | ||
1180 | |||
1181 | dbg_trace("[%s] %p\n", __func__, buf); | ||
1182 | if (attr == NULL || buf == NULL) { | ||
1183 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
1184 | return 0; | ||
1185 | } | ||
1186 | |||
1187 | spin_lock_irqsave(udc->lock, flags); | ||
1188 | for (i = 0; i < hw_ep_max; i++) { | ||
1189 | struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; | ||
1190 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
1191 | "EP=%02i: RX=%08X TX=%08X\n", | ||
1192 | i, (u32)mEp->qh[RX].dma, (u32)mEp->qh[TX].dma); | ||
1193 | for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) { | ||
1194 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
1195 | " %04X: %08X %08X\n", j, | ||
1196 | *((u32 *)mEp->qh[RX].ptr + j), | ||
1197 | *((u32 *)mEp->qh[TX].ptr + j)); | ||
1198 | } | ||
1199 | } | ||
1200 | spin_unlock_irqrestore(udc->lock, flags); | ||
1201 | |||
1202 | return n; | ||
1203 | } | ||
1204 | static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL); | ||
1205 | |||
1206 | /** | ||
1207 | * show_registers: dumps all registers | ||
1208 | * | ||
1209 | * Check "device.h" for details | ||
1210 | */ | ||
1211 | static ssize_t show_registers(struct device *dev, | ||
1212 | struct device_attribute *attr, char *buf) | ||
1213 | { | ||
1214 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
1215 | unsigned long flags; | ||
1216 | u32 dump[512]; | ||
1217 | unsigned i, k, n = 0; | ||
1218 | |||
1219 | dbg_trace("[%s] %p\n", __func__, buf); | ||
1220 | if (attr == NULL || buf == NULL) { | ||
1221 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1225 | spin_lock_irqsave(udc->lock, flags); | ||
1226 | k = hw_register_read(dump, sizeof(dump)/sizeof(u32)); | ||
1227 | spin_unlock_irqrestore(udc->lock, flags); | ||
1228 | |||
1229 | for (i = 0; i < k; i++) { | ||
1230 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
1231 | "reg[0x%04X] = 0x%08X\n", | ||
1232 | i * (unsigned)sizeof(u32), dump[i]); | ||
1233 | } | ||
1234 | |||
1235 | return n; | ||
1236 | } | ||
1237 | |||
1238 | /** | ||
1239 | * store_registers: writes value to register address | ||
1240 | * | ||
1241 | * Check "device.h" for details | ||
1242 | */ | ||
1243 | static ssize_t store_registers(struct device *dev, | ||
1244 | struct device_attribute *attr, | ||
1245 | const char *buf, size_t count) | ||
1246 | { | ||
1247 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
1248 | unsigned long addr, data, flags; | ||
1249 | |||
1250 | dbg_trace("[%s] %p, %d\n", __func__, buf, count); | ||
1251 | if (attr == NULL || buf == NULL) { | ||
1252 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
1253 | goto done; | ||
1254 | } | ||
1255 | |||
1256 | if (sscanf(buf, "%li %li", &addr, &data) != 2) { | ||
1257 | dev_err(dev, "<addr> <data>: write data to register address"); | ||
1258 | goto done; | ||
1259 | } | ||
1260 | |||
1261 | spin_lock_irqsave(udc->lock, flags); | ||
1262 | if (hw_register_write(addr, data)) | ||
1263 | dev_err(dev, "invalid address range\n"); | ||
1264 | spin_unlock_irqrestore(udc->lock, flags); | ||
1265 | |||
1266 | done: | ||
1267 | return count; | ||
1268 | } | ||
1269 | static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR, | ||
1270 | show_registers, store_registers); | ||
1271 | |||
1272 | /** | ||
1273 | * show_requests: DMA contents of all requests currently queued (all endpts) | ||
1274 | * | ||
1275 | * Check "device.h" for details | ||
1276 | */ | ||
1277 | static ssize_t show_requests(struct device *dev, struct device_attribute *attr, | ||
1278 | char *buf) | ||
1279 | { | ||
1280 | struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev); | ||
1281 | unsigned long flags; | ||
1282 | struct list_head *ptr = NULL; | ||
1283 | struct ci13xxx_req *req = NULL; | ||
1284 | unsigned i, j, k, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32); | ||
1285 | |||
1286 | dbg_trace("[%s] %p\n", __func__, buf); | ||
1287 | if (attr == NULL || buf == NULL) { | ||
1288 | dev_err(dev, "[%s] EINVAL\n", __func__); | ||
1289 | return 0; | ||
1290 | } | ||
1291 | |||
1292 | spin_lock_irqsave(udc->lock, flags); | ||
1293 | for (i = 0; i < hw_ep_max; i++) | ||
1294 | for (k = RX; k <= TX; k++) | ||
1295 | list_for_each(ptr, &udc->ci13xxx_ep[i].qh[k].queue) | ||
1296 | { | ||
1297 | req = list_entry(ptr, | ||
1298 | struct ci13xxx_req, queue); | ||
1299 | |||
1300 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
1301 | "EP=%02i: TD=%08X %s\n", | ||
1302 | i, (u32)req->dma, | ||
1303 | ((k == RX) ? "RX" : "TX")); | ||
1304 | |||
1305 | for (j = 0; j < qSize; j++) | ||
1306 | n += scnprintf(buf + n, PAGE_SIZE - n, | ||
1307 | " %04X: %08X\n", j, | ||
1308 | *((u32 *)req->ptr + j)); | ||
1309 | } | ||
1310 | spin_unlock_irqrestore(udc->lock, flags); | ||
1311 | |||
1312 | return n; | ||
1313 | } | ||
1314 | static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL); | ||
1315 | |||
1316 | /** | ||
1317 | * dbg_create_files: initializes the attribute interface | ||
1318 | * @dev: device | ||
1319 | * | ||
1320 | * This function returns an error code | ||
1321 | */ | ||
1322 | __maybe_unused static int dbg_create_files(struct device *dev) | ||
1323 | { | ||
1324 | int retval = 0; | ||
1325 | |||
1326 | if (dev == NULL) | ||
1327 | return -EINVAL; | ||
1328 | retval = device_create_file(dev, &dev_attr_device); | ||
1329 | if (retval) | ||
1330 | goto done; | ||
1331 | retval = device_create_file(dev, &dev_attr_driver); | ||
1332 | if (retval) | ||
1333 | goto rm_device; | ||
1334 | retval = device_create_file(dev, &dev_attr_events); | ||
1335 | if (retval) | ||
1336 | goto rm_driver; | ||
1337 | retval = device_create_file(dev, &dev_attr_inters); | ||
1338 | if (retval) | ||
1339 | goto rm_events; | ||
1340 | retval = device_create_file(dev, &dev_attr_port_test); | ||
1341 | if (retval) | ||
1342 | goto rm_inters; | ||
1343 | retval = device_create_file(dev, &dev_attr_qheads); | ||
1344 | if (retval) | ||
1345 | goto rm_port_test; | ||
1346 | retval = device_create_file(dev, &dev_attr_registers); | ||
1347 | if (retval) | ||
1348 | goto rm_qheads; | ||
1349 | retval = device_create_file(dev, &dev_attr_requests); | ||
1350 | if (retval) | ||
1351 | goto rm_registers; | ||
1352 | return 0; | ||
1353 | |||
1354 | rm_registers: | ||
1355 | device_remove_file(dev, &dev_attr_registers); | ||
1356 | rm_qheads: | ||
1357 | device_remove_file(dev, &dev_attr_qheads); | ||
1358 | rm_port_test: | ||
1359 | device_remove_file(dev, &dev_attr_port_test); | ||
1360 | rm_inters: | ||
1361 | device_remove_file(dev, &dev_attr_inters); | ||
1362 | rm_events: | ||
1363 | device_remove_file(dev, &dev_attr_events); | ||
1364 | rm_driver: | ||
1365 | device_remove_file(dev, &dev_attr_driver); | ||
1366 | rm_device: | ||
1367 | device_remove_file(dev, &dev_attr_device); | ||
1368 | done: | ||
1369 | return retval; | ||
1370 | } | ||
1371 | |||
1372 | /** | ||
1373 | * dbg_remove_files: destroys the attribute interface | ||
1374 | * @dev: device | ||
1375 | * | ||
1376 | * This function returns an error code | ||
1377 | */ | ||
1378 | __maybe_unused static int dbg_remove_files(struct device *dev) | ||
1379 | { | ||
1380 | if (dev == NULL) | ||
1381 | return -EINVAL; | ||
1382 | device_remove_file(dev, &dev_attr_requests); | ||
1383 | device_remove_file(dev, &dev_attr_registers); | ||
1384 | device_remove_file(dev, &dev_attr_qheads); | ||
1385 | device_remove_file(dev, &dev_attr_port_test); | ||
1386 | device_remove_file(dev, &dev_attr_inters); | ||
1387 | device_remove_file(dev, &dev_attr_events); | ||
1388 | device_remove_file(dev, &dev_attr_driver); | ||
1389 | device_remove_file(dev, &dev_attr_device); | ||
1390 | return 0; | ||
1391 | } | ||
1392 | |||
1393 | /****************************************************************************** | ||
1394 | * UTIL block | ||
1395 | *****************************************************************************/ | ||
1396 | /** | ||
1397 | * _usb_addr: calculates endpoint address from direction & number | ||
1398 | * @ep: endpoint | ||
1399 | */ | ||
1400 | static inline u8 _usb_addr(struct ci13xxx_ep *ep) | ||
1401 | { | ||
1402 | return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num; | ||
1403 | } | ||
1404 | |||
1405 | /** | ||
1406 | * _hardware_queue: configures a request at hardware level | ||
1407 | * @gadget: gadget | ||
1408 | * @mEp: endpoint | ||
1409 | * | ||
1410 | * This function returns an error code | ||
1411 | */ | ||
1412 | static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) | ||
1413 | { | ||
1414 | unsigned i; | ||
1415 | |||
1416 | trace("%p, %p", mEp, mReq); | ||
1417 | |||
1418 | /* don't queue twice */ | ||
1419 | if (mReq->req.status == -EALREADY) | ||
1420 | return -EALREADY; | ||
1421 | |||
1422 | if (hw_ep_is_primed(mEp->num, mEp->dir)) | ||
1423 | return -EBUSY; | ||
1424 | |||
1425 | mReq->req.status = -EALREADY; | ||
1426 | |||
1427 | if (mReq->req.length && !mReq->req.dma) { | ||
1428 | mReq->req.dma = \ | ||
1429 | dma_map_single(mEp->device, mReq->req.buf, | ||
1430 | mReq->req.length, mEp->dir ? | ||
1431 | DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
1432 | if (mReq->req.dma == 0) | ||
1433 | return -ENOMEM; | ||
1434 | |||
1435 | mReq->map = 1; | ||
1436 | } | ||
1437 | |||
1438 | /* | ||
1439 | * TD configuration | ||
1440 | * TODO - handle requests which spawns into several TDs | ||
1441 | */ | ||
1442 | memset(mReq->ptr, 0, sizeof(*mReq->ptr)); | ||
1443 | mReq->ptr->next |= TD_TERMINATE; | ||
1444 | mReq->ptr->token = mReq->req.length << ffs_nr(TD_TOTAL_BYTES); | ||
1445 | mReq->ptr->token &= TD_TOTAL_BYTES; | ||
1446 | mReq->ptr->token |= TD_IOC; | ||
1447 | mReq->ptr->token |= TD_STATUS_ACTIVE; | ||
1448 | mReq->ptr->page[0] = mReq->req.dma; | ||
1449 | for (i = 1; i < 5; i++) | ||
1450 | mReq->ptr->page[i] = | ||
1451 | (mReq->req.dma + i * PAGE_SIZE) & ~TD_RESERVED_MASK; | ||
1452 | |||
1453 | /* | ||
1454 | * QH configuration | ||
1455 | * At this point it's guaranteed exclusive access to qhead | ||
1456 | * (endpt is not primed) so it's no need to use tripwire | ||
1457 | */ | ||
1458 | mEp->qh[mEp->dir].ptr->td.next = mReq->dma; /* TERMINATE = 0 */ | ||
1459 | mEp->qh[mEp->dir].ptr->td.token &= ~TD_STATUS; /* clear status */ | ||
1460 | if (mReq->req.zero == 0) | ||
1461 | mEp->qh[mEp->dir].ptr->cap |= QH_ZLT; | ||
1462 | else | ||
1463 | mEp->qh[mEp->dir].ptr->cap &= ~QH_ZLT; | ||
1464 | |||
1465 | wmb(); /* synchronize before ep prime */ | ||
1466 | |||
1467 | return hw_ep_prime(mEp->num, mEp->dir, | ||
1468 | mEp->type == USB_ENDPOINT_XFER_CONTROL); | ||
1469 | } | ||
1470 | |||
1471 | /** | ||
1472 | * _hardware_dequeue: handles a request at hardware level | ||
1473 | * @gadget: gadget | ||
1474 | * @mEp: endpoint | ||
1475 | * | ||
1476 | * This function returns an error code | ||
1477 | */ | ||
1478 | static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) | ||
1479 | { | ||
1480 | trace("%p, %p", mEp, mReq); | ||
1481 | |||
1482 | if (mReq->req.status != -EALREADY) | ||
1483 | return -EINVAL; | ||
1484 | |||
1485 | if (hw_ep_is_primed(mEp->num, mEp->dir)) | ||
1486 | hw_ep_flush(mEp->num, mEp->dir); | ||
1487 | |||
1488 | mReq->req.status = 0; | ||
1489 | |||
1490 | if (mReq->map) { | ||
1491 | dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length, | ||
1492 | mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
1493 | mReq->req.dma = 0; | ||
1494 | mReq->map = 0; | ||
1495 | } | ||
1496 | |||
1497 | mReq->req.status = mReq->ptr->token & TD_STATUS; | ||
1498 | if ((TD_STATUS_ACTIVE & mReq->req.status) != 0) | ||
1499 | mReq->req.status = -ECONNRESET; | ||
1500 | else if ((TD_STATUS_HALTED & mReq->req.status) != 0) | ||
1501 | mReq->req.status = -1; | ||
1502 | else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0) | ||
1503 | mReq->req.status = -1; | ||
1504 | else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0) | ||
1505 | mReq->req.status = -1; | ||
1506 | |||
1507 | mReq->req.actual = mReq->ptr->token & TD_TOTAL_BYTES; | ||
1508 | mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES); | ||
1509 | mReq->req.actual = mReq->req.length - mReq->req.actual; | ||
1510 | mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual; | ||
1511 | |||
1512 | return mReq->req.actual; | ||
1513 | } | ||
1514 | |||
1515 | /** | ||
1516 | * _ep_nuke: dequeues all endpoint requests | ||
1517 | * @mEp: endpoint | ||
1518 | * | ||
1519 | * This function returns an error code | ||
1520 | * Caller must hold lock | ||
1521 | */ | ||
1522 | static int _ep_nuke(struct ci13xxx_ep *mEp) | ||
1523 | __releases(mEp->lock) | ||
1524 | __acquires(mEp->lock) | ||
1525 | { | ||
1526 | trace("%p", mEp); | ||
1527 | |||
1528 | if (mEp == NULL) | ||
1529 | return -EINVAL; | ||
1530 | |||
1531 | hw_ep_flush(mEp->num, mEp->dir); | ||
1532 | |||
1533 | while (!list_empty(&mEp->qh[mEp->dir].queue)) { | ||
1534 | |||
1535 | /* pop oldest request */ | ||
1536 | struct ci13xxx_req *mReq = \ | ||
1537 | list_entry(mEp->qh[mEp->dir].queue.next, | ||
1538 | struct ci13xxx_req, queue); | ||
1539 | list_del_init(&mReq->queue); | ||
1540 | mReq->req.status = -ESHUTDOWN; | ||
1541 | |||
1542 | if (!mReq->req.no_interrupt && mReq->req.complete != NULL) { | ||
1543 | spin_unlock(mEp->lock); | ||
1544 | mReq->req.complete(&mEp->ep, &mReq->req); | ||
1545 | spin_lock(mEp->lock); | ||
1546 | } | ||
1547 | } | ||
1548 | return 0; | ||
1549 | } | ||
1550 | |||
1551 | /** | ||
1552 | * _gadget_stop_activity: stops all USB activity, flushes & disables all endpts | ||
1553 | * @gadget: gadget | ||
1554 | * | ||
1555 | * This function returns an error code | ||
1556 | * Caller must hold lock | ||
1557 | */ | ||
1558 | static int _gadget_stop_activity(struct usb_gadget *gadget) | ||
1559 | __releases(udc->lock) | ||
1560 | __acquires(udc->lock) | ||
1561 | { | ||
1562 | struct usb_ep *ep; | ||
1563 | struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); | ||
1564 | struct ci13xxx_ep *mEp = container_of(gadget->ep0, | ||
1565 | struct ci13xxx_ep, ep); | ||
1566 | |||
1567 | trace("%p", gadget); | ||
1568 | |||
1569 | if (gadget == NULL) | ||
1570 | return -EINVAL; | ||
1571 | |||
1572 | spin_unlock(udc->lock); | ||
1573 | |||
1574 | /* flush all endpoints */ | ||
1575 | gadget_for_each_ep(ep, gadget) { | ||
1576 | usb_ep_fifo_flush(ep); | ||
1577 | } | ||
1578 | usb_ep_fifo_flush(gadget->ep0); | ||
1579 | |||
1580 | udc->driver->disconnect(gadget); | ||
1581 | |||
1582 | /* make sure to disable all endpoints */ | ||
1583 | gadget_for_each_ep(ep, gadget) { | ||
1584 | usb_ep_disable(ep); | ||
1585 | } | ||
1586 | usb_ep_disable(gadget->ep0); | ||
1587 | |||
1588 | if (mEp->status != NULL) { | ||
1589 | usb_ep_free_request(gadget->ep0, mEp->status); | ||
1590 | mEp->status = NULL; | ||
1591 | } | ||
1592 | |||
1593 | spin_lock(udc->lock); | ||
1594 | |||
1595 | return 0; | ||
1596 | } | ||
1597 | |||
1598 | /****************************************************************************** | ||
1599 | * ISR block | ||
1600 | *****************************************************************************/ | ||
1601 | /** | ||
1602 | * isr_reset_handler: USB reset interrupt handler | ||
1603 | * @udc: UDC device | ||
1604 | * | ||
1605 | * This function resets USB engine after a bus reset occurred | ||
1606 | */ | ||
1607 | static void isr_reset_handler(struct ci13xxx *udc) | ||
1608 | __releases(udc->lock) | ||
1609 | __acquires(udc->lock) | ||
1610 | { | ||
1611 | struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[0]; | ||
1612 | int retval; | ||
1613 | |||
1614 | trace("%p", udc); | ||
1615 | |||
1616 | if (udc == NULL) { | ||
1617 | err("EINVAL"); | ||
1618 | return; | ||
1619 | } | ||
1620 | |||
1621 | dbg_event(0xFF, "BUS RST", 0); | ||
1622 | |||
1623 | retval = _gadget_stop_activity(&udc->gadget); | ||
1624 | if (retval) | ||
1625 | goto done; | ||
1626 | |||
1627 | retval = hw_usb_reset(); | ||
1628 | if (retval) | ||
1629 | goto done; | ||
1630 | |||
1631 | spin_unlock(udc->lock); | ||
1632 | retval = usb_ep_enable(&mEp->ep, &ctrl_endpt_desc); | ||
1633 | if (!retval) { | ||
1634 | mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_KERNEL); | ||
1635 | if (mEp->status == NULL) { | ||
1636 | usb_ep_disable(&mEp->ep); | ||
1637 | retval = -ENOMEM; | ||
1638 | } | ||
1639 | } | ||
1640 | spin_lock(udc->lock); | ||
1641 | |||
1642 | done: | ||
1643 | if (retval) | ||
1644 | err("error: %i", retval); | ||
1645 | } | ||
1646 | |||
1647 | /** | ||
1648 | * isr_get_status_complete: get_status request complete function | ||
1649 | * @ep: endpoint | ||
1650 | * @req: request handled | ||
1651 | * | ||
1652 | * Caller must release lock | ||
1653 | */ | ||
1654 | static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) | ||
1655 | { | ||
1656 | trace("%p, %p", ep, req); | ||
1657 | |||
1658 | if (ep == NULL || req == NULL) { | ||
1659 | err("EINVAL"); | ||
1660 | return; | ||
1661 | } | ||
1662 | |||
1663 | kfree(req->buf); | ||
1664 | usb_ep_free_request(ep, req); | ||
1665 | } | ||
1666 | |||
1667 | /** | ||
1668 | * isr_get_status_response: get_status request response | ||
1669 | * @ep: endpoint | ||
1670 | * @setup: setup request packet | ||
1671 | * | ||
1672 | * This function returns an error code | ||
1673 | */ | ||
1674 | static int isr_get_status_response(struct ci13xxx_ep *mEp, | ||
1675 | struct usb_ctrlrequest *setup) | ||
1676 | __releases(mEp->lock) | ||
1677 | __acquires(mEp->lock) | ||
1678 | { | ||
1679 | struct usb_request *req = NULL; | ||
1680 | gfp_t gfp_flags = GFP_ATOMIC; | ||
1681 | int dir, num, retval; | ||
1682 | |||
1683 | trace("%p, %p", mEp, setup); | ||
1684 | |||
1685 | if (mEp == NULL || setup == NULL) | ||
1686 | return -EINVAL; | ||
1687 | |||
1688 | spin_unlock(mEp->lock); | ||
1689 | req = usb_ep_alloc_request(&mEp->ep, gfp_flags); | ||
1690 | spin_lock(mEp->lock); | ||
1691 | if (req == NULL) | ||
1692 | return -ENOMEM; | ||
1693 | |||
1694 | req->complete = isr_get_status_complete; | ||
1695 | req->length = 2; | ||
1696 | req->buf = kzalloc(req->length, gfp_flags); | ||
1697 | if (req->buf == NULL) { | ||
1698 | retval = -ENOMEM; | ||
1699 | goto err_free_req; | ||
1700 | } | ||
1701 | |||
1702 | if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) { | ||
1703 | /* TODO: D1 - Remote Wakeup; D0 - Self Powered */ | ||
1704 | retval = 0; | ||
1705 | } else if ((setup->bRequestType & USB_RECIP_MASK) \ | ||
1706 | == USB_RECIP_ENDPOINT) { | ||
1707 | dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ? | ||
1708 | TX : RX; | ||
1709 | num = le16_to_cpu(setup->wIndex) & USB_ENDPOINT_NUMBER_MASK; | ||
1710 | *((u16 *)req->buf) = hw_ep_get_halt(num, dir); | ||
1711 | } | ||
1712 | /* else do nothing; reserved for future use */ | ||
1713 | |||
1714 | spin_unlock(mEp->lock); | ||
1715 | retval = usb_ep_queue(&mEp->ep, req, gfp_flags); | ||
1716 | spin_lock(mEp->lock); | ||
1717 | if (retval) | ||
1718 | goto err_free_buf; | ||
1719 | |||
1720 | return 0; | ||
1721 | |||
1722 | err_free_buf: | ||
1723 | kfree(req->buf); | ||
1724 | err_free_req: | ||
1725 | spin_unlock(mEp->lock); | ||
1726 | usb_ep_free_request(&mEp->ep, req); | ||
1727 | spin_lock(mEp->lock); | ||
1728 | return retval; | ||
1729 | } | ||
1730 | |||
1731 | /** | ||
1732 | * isr_setup_status_phase: queues the status phase of a setup transation | ||
1733 | * @mEp: endpoint | ||
1734 | * | ||
1735 | * This function returns an error code | ||
1736 | */ | ||
1737 | static int isr_setup_status_phase(struct ci13xxx_ep *mEp) | ||
1738 | __releases(mEp->lock) | ||
1739 | __acquires(mEp->lock) | ||
1740 | { | ||
1741 | int retval; | ||
1742 | |||
1743 | trace("%p", mEp); | ||
1744 | |||
1745 | /* mEp is always valid & configured */ | ||
1746 | |||
1747 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | ||
1748 | mEp->dir = (mEp->dir == TX) ? RX : TX; | ||
1749 | |||
1750 | mEp->status->no_interrupt = 1; | ||
1751 | |||
1752 | spin_unlock(mEp->lock); | ||
1753 | retval = usb_ep_queue(&mEp->ep, mEp->status, GFP_ATOMIC); | ||
1754 | spin_lock(mEp->lock); | ||
1755 | |||
1756 | return retval; | ||
1757 | } | ||
1758 | |||
1759 | /** | ||
1760 | * isr_tr_complete_low: transaction complete low level handler | ||
1761 | * @mEp: endpoint | ||
1762 | * | ||
1763 | * This function returns an error code | ||
1764 | * Caller must hold lock | ||
1765 | */ | ||
1766 | static int isr_tr_complete_low(struct ci13xxx_ep *mEp) | ||
1767 | __releases(mEp->lock) | ||
1768 | __acquires(mEp->lock) | ||
1769 | { | ||
1770 | struct ci13xxx_req *mReq; | ||
1771 | int retval; | ||
1772 | |||
1773 | trace("%p", mEp); | ||
1774 | |||
1775 | if (list_empty(&mEp->qh[mEp->dir].queue)) | ||
1776 | return -EINVAL; | ||
1777 | |||
1778 | /* pop oldest request */ | ||
1779 | mReq = list_entry(mEp->qh[mEp->dir].queue.next, | ||
1780 | struct ci13xxx_req, queue); | ||
1781 | list_del_init(&mReq->queue); | ||
1782 | |||
1783 | retval = _hardware_dequeue(mEp, mReq); | ||
1784 | if (retval < 0) { | ||
1785 | dbg_event(_usb_addr(mEp), "DONE", retval); | ||
1786 | goto done; | ||
1787 | } | ||
1788 | |||
1789 | dbg_done(_usb_addr(mEp), mReq->ptr->token, retval); | ||
1790 | |||
1791 | if (!mReq->req.no_interrupt && mReq->req.complete != NULL) { | ||
1792 | spin_unlock(mEp->lock); | ||
1793 | mReq->req.complete(&mEp->ep, &mReq->req); | ||
1794 | spin_lock(mEp->lock); | ||
1795 | } | ||
1796 | |||
1797 | if (!list_empty(&mEp->qh[mEp->dir].queue)) { | ||
1798 | mReq = list_entry(mEp->qh[mEp->dir].queue.next, | ||
1799 | struct ci13xxx_req, queue); | ||
1800 | _hardware_enqueue(mEp, mReq); | ||
1801 | } | ||
1802 | |||
1803 | done: | ||
1804 | return retval; | ||
1805 | } | ||
1806 | |||
1807 | /** | ||
1808 | * isr_tr_complete_handler: transaction complete interrupt handler | ||
1809 | * @udc: UDC descriptor | ||
1810 | * | ||
1811 | * This function handles traffic events | ||
1812 | */ | ||
1813 | static void isr_tr_complete_handler(struct ci13xxx *udc) | ||
1814 | __releases(udc->lock) | ||
1815 | __acquires(udc->lock) | ||
1816 | { | ||
1817 | unsigned i; | ||
1818 | |||
1819 | trace("%p", udc); | ||
1820 | |||
1821 | if (udc == NULL) { | ||
1822 | err("EINVAL"); | ||
1823 | return; | ||
1824 | } | ||
1825 | |||
1826 | for (i = 0; i < hw_ep_max; i++) { | ||
1827 | struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; | ||
1828 | int type, num, err = -EINVAL; | ||
1829 | struct usb_ctrlrequest req; | ||
1830 | |||
1831 | |||
1832 | if (mEp->desc == NULL) | ||
1833 | continue; /* not configured */ | ||
1834 | |||
1835 | if ((mEp->dir == RX && hw_test_and_clear_complete(i)) || | ||
1836 | (mEp->dir == TX && hw_test_and_clear_complete(i + 16))) { | ||
1837 | err = isr_tr_complete_low(mEp); | ||
1838 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { | ||
1839 | if (err > 0) /* needs status phase */ | ||
1840 | err = isr_setup_status_phase(mEp); | ||
1841 | if (err < 0) { | ||
1842 | dbg_event(_usb_addr(mEp), | ||
1843 | "ERROR", err); | ||
1844 | spin_unlock(udc->lock); | ||
1845 | if (usb_ep_set_halt(&mEp->ep)) | ||
1846 | err("error: ep_set_halt"); | ||
1847 | spin_lock(udc->lock); | ||
1848 | } | ||
1849 | } | ||
1850 | } | ||
1851 | |||
1852 | if (mEp->type != USB_ENDPOINT_XFER_CONTROL || | ||
1853 | !hw_test_and_clear_setup_status(i)) | ||
1854 | continue; | ||
1855 | |||
1856 | if (i != 0) { | ||
1857 | warn("ctrl traffic received at endpoint"); | ||
1858 | continue; | ||
1859 | } | ||
1860 | |||
1861 | /* read_setup_packet */ | ||
1862 | do { | ||
1863 | hw_test_and_set_setup_guard(); | ||
1864 | memcpy(&req, &mEp->qh[RX].ptr->setup, sizeof(req)); | ||
1865 | } while (!hw_test_and_clear_setup_guard()); | ||
1866 | |||
1867 | type = req.bRequestType; | ||
1868 | |||
1869 | mEp->dir = (type & USB_DIR_IN) ? TX : RX; | ||
1870 | |||
1871 | dbg_setup(_usb_addr(mEp), &req); | ||
1872 | |||
1873 | switch (req.bRequest) { | ||
1874 | case USB_REQ_CLEAR_FEATURE: | ||
1875 | if (type != (USB_DIR_OUT|USB_RECIP_ENDPOINT) && | ||
1876 | le16_to_cpu(req.wValue) != USB_ENDPOINT_HALT) | ||
1877 | goto delegate; | ||
1878 | if (req.wLength != 0) | ||
1879 | break; | ||
1880 | num = le16_to_cpu(req.wIndex); | ||
1881 | num &= USB_ENDPOINT_NUMBER_MASK; | ||
1882 | if (!udc->ci13xxx_ep[num].wedge) { | ||
1883 | spin_unlock(udc->lock); | ||
1884 | err = usb_ep_clear_halt( | ||
1885 | &udc->ci13xxx_ep[num].ep); | ||
1886 | spin_lock(udc->lock); | ||
1887 | if (err) | ||
1888 | break; | ||
1889 | } | ||
1890 | err = isr_setup_status_phase(mEp); | ||
1891 | break; | ||
1892 | case USB_REQ_GET_STATUS: | ||
1893 | if (type != (USB_DIR_IN|USB_RECIP_DEVICE) && | ||
1894 | type != (USB_DIR_IN|USB_RECIP_ENDPOINT) && | ||
1895 | type != (USB_DIR_IN|USB_RECIP_INTERFACE)) | ||
1896 | goto delegate; | ||
1897 | if (le16_to_cpu(req.wLength) != 2 || | ||
1898 | le16_to_cpu(req.wValue) != 0) | ||
1899 | break; | ||
1900 | err = isr_get_status_response(mEp, &req); | ||
1901 | break; | ||
1902 | case USB_REQ_SET_ADDRESS: | ||
1903 | if (type != (USB_DIR_OUT|USB_RECIP_DEVICE)) | ||
1904 | goto delegate; | ||
1905 | if (le16_to_cpu(req.wLength) != 0 || | ||
1906 | le16_to_cpu(req.wIndex) != 0) | ||
1907 | break; | ||
1908 | err = hw_usb_set_address((u8)le16_to_cpu(req.wValue)); | ||
1909 | if (err) | ||
1910 | break; | ||
1911 | err = isr_setup_status_phase(mEp); | ||
1912 | break; | ||
1913 | case USB_REQ_SET_FEATURE: | ||
1914 | if (type != (USB_DIR_OUT|USB_RECIP_ENDPOINT) && | ||
1915 | le16_to_cpu(req.wValue) != USB_ENDPOINT_HALT) | ||
1916 | goto delegate; | ||
1917 | if (req.wLength != 0) | ||
1918 | break; | ||
1919 | num = le16_to_cpu(req.wIndex); | ||
1920 | num &= USB_ENDPOINT_NUMBER_MASK; | ||
1921 | |||
1922 | spin_unlock(udc->lock); | ||
1923 | err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep); | ||
1924 | spin_lock(udc->lock); | ||
1925 | if (err) | ||
1926 | break; | ||
1927 | err = isr_setup_status_phase(mEp); | ||
1928 | break; | ||
1929 | default: | ||
1930 | delegate: | ||
1931 | if (req.wLength == 0) /* no data phase */ | ||
1932 | mEp->dir = TX; | ||
1933 | |||
1934 | spin_unlock(udc->lock); | ||
1935 | err = udc->driver->setup(&udc->gadget, &req); | ||
1936 | spin_lock(udc->lock); | ||
1937 | break; | ||
1938 | } | ||
1939 | |||
1940 | if (err < 0) { | ||
1941 | dbg_event(_usb_addr(mEp), "ERROR", err); | ||
1942 | |||
1943 | spin_unlock(udc->lock); | ||
1944 | if (usb_ep_set_halt(&mEp->ep)) | ||
1945 | err("error: ep_set_halt"); | ||
1946 | spin_lock(udc->lock); | ||
1947 | } | ||
1948 | } | ||
1949 | } | ||
1950 | |||
1951 | /****************************************************************************** | ||
1952 | * ENDPT block | ||
1953 | *****************************************************************************/ | ||
1954 | /** | ||
1955 | * ep_enable: configure endpoint, making it usable | ||
1956 | * | ||
1957 | * Check usb_ep_enable() at "usb_gadget.h" for details | ||
1958 | */ | ||
1959 | static int ep_enable(struct usb_ep *ep, | ||
1960 | const struct usb_endpoint_descriptor *desc) | ||
1961 | { | ||
1962 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
1963 | int direction, retval = 0; | ||
1964 | unsigned long flags; | ||
1965 | |||
1966 | trace("%p, %p", ep, desc); | ||
1967 | |||
1968 | if (ep == NULL || desc == NULL) | ||
1969 | return -EINVAL; | ||
1970 | |||
1971 | spin_lock_irqsave(mEp->lock, flags); | ||
1972 | |||
1973 | /* only internal SW should enable ctrl endpts */ | ||
1974 | |||
1975 | mEp->desc = desc; | ||
1976 | |||
1977 | if (!list_empty(&mEp->qh[mEp->dir].queue)) | ||
1978 | warn("enabling a non-empty endpoint!"); | ||
1979 | |||
1980 | mEp->dir = (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? TX : RX; | ||
1981 | mEp->num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | ||
1982 | mEp->type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | ||
1983 | |||
1984 | mEp->ep.maxpacket = __constant_le16_to_cpu(desc->wMaxPacketSize); | ||
1985 | |||
1986 | direction = mEp->dir; | ||
1987 | do { | ||
1988 | dbg_event(_usb_addr(mEp), "ENABLE", 0); | ||
1989 | |||
1990 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | ||
1991 | mEp->qh[mEp->dir].ptr->cap |= QH_IOS; | ||
1992 | else if (mEp->type == USB_ENDPOINT_XFER_ISOC) | ||
1993 | mEp->qh[mEp->dir].ptr->cap &= ~QH_MULT; | ||
1994 | else | ||
1995 | mEp->qh[mEp->dir].ptr->cap &= ~QH_ZLT; | ||
1996 | |||
1997 | mEp->qh[mEp->dir].ptr->cap |= | ||
1998 | (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT; | ||
1999 | mEp->qh[mEp->dir].ptr->td.next |= TD_TERMINATE; /* needed? */ | ||
2000 | |||
2001 | retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type); | ||
2002 | |||
2003 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | ||
2004 | mEp->dir = (mEp->dir == TX) ? RX : TX; | ||
2005 | |||
2006 | } while (mEp->dir != direction); | ||
2007 | |||
2008 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2009 | return retval; | ||
2010 | } | ||
2011 | |||
2012 | /** | ||
2013 | * ep_disable: endpoint is no longer usable | ||
2014 | * | ||
2015 | * Check usb_ep_disable() at "usb_gadget.h" for details | ||
2016 | */ | ||
2017 | static int ep_disable(struct usb_ep *ep) | ||
2018 | { | ||
2019 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
2020 | int direction, retval = 0; | ||
2021 | unsigned long flags; | ||
2022 | |||
2023 | trace("%p", ep); | ||
2024 | |||
2025 | if (ep == NULL) | ||
2026 | return -EINVAL; | ||
2027 | else if (mEp->desc == NULL) | ||
2028 | return -EBUSY; | ||
2029 | |||
2030 | spin_lock_irqsave(mEp->lock, flags); | ||
2031 | |||
2032 | /* only internal SW should disable ctrl endpts */ | ||
2033 | |||
2034 | direction = mEp->dir; | ||
2035 | do { | ||
2036 | dbg_event(_usb_addr(mEp), "DISABLE", 0); | ||
2037 | |||
2038 | retval |= _ep_nuke(mEp); | ||
2039 | retval |= hw_ep_disable(mEp->num, mEp->dir); | ||
2040 | |||
2041 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | ||
2042 | mEp->dir = (mEp->dir == TX) ? RX : TX; | ||
2043 | |||
2044 | } while (mEp->dir != direction); | ||
2045 | |||
2046 | mEp->desc = NULL; | ||
2047 | |||
2048 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2049 | return retval; | ||
2050 | } | ||
2051 | |||
2052 | /** | ||
2053 | * ep_alloc_request: allocate a request object to use with this endpoint | ||
2054 | * | ||
2055 | * Check usb_ep_alloc_request() at "usb_gadget.h" for details | ||
2056 | */ | ||
2057 | static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) | ||
2058 | { | ||
2059 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
2060 | struct ci13xxx_req *mReq = NULL; | ||
2061 | unsigned long flags; | ||
2062 | |||
2063 | trace("%p, %i", ep, gfp_flags); | ||
2064 | |||
2065 | if (ep == NULL) { | ||
2066 | err("EINVAL"); | ||
2067 | return NULL; | ||
2068 | } | ||
2069 | |||
2070 | spin_lock_irqsave(mEp->lock, flags); | ||
2071 | |||
2072 | mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags); | ||
2073 | if (mReq != NULL) { | ||
2074 | INIT_LIST_HEAD(&mReq->queue); | ||
2075 | |||
2076 | mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags, | ||
2077 | &mReq->dma); | ||
2078 | if (mReq->ptr == NULL) { | ||
2079 | kfree(mReq); | ||
2080 | mReq = NULL; | ||
2081 | } | ||
2082 | } | ||
2083 | |||
2084 | dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL); | ||
2085 | |||
2086 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2087 | |||
2088 | return (mReq == NULL) ? NULL : &mReq->req; | ||
2089 | } | ||
2090 | |||
2091 | /** | ||
2092 | * ep_free_request: frees a request object | ||
2093 | * | ||
2094 | * Check usb_ep_free_request() at "usb_gadget.h" for details | ||
2095 | */ | ||
2096 | static void ep_free_request(struct usb_ep *ep, struct usb_request *req) | ||
2097 | { | ||
2098 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
2099 | struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); | ||
2100 | unsigned long flags; | ||
2101 | |||
2102 | trace("%p, %p", ep, req); | ||
2103 | |||
2104 | if (ep == NULL || req == NULL) { | ||
2105 | err("EINVAL"); | ||
2106 | return; | ||
2107 | } else if (!list_empty(&mReq->queue)) { | ||
2108 | err("EBUSY"); | ||
2109 | return; | ||
2110 | } | ||
2111 | |||
2112 | spin_lock_irqsave(mEp->lock, flags); | ||
2113 | |||
2114 | if (mReq->ptr) | ||
2115 | dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma); | ||
2116 | kfree(mReq); | ||
2117 | |||
2118 | dbg_event(_usb_addr(mEp), "FREE", 0); | ||
2119 | |||
2120 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2121 | } | ||
2122 | |||
2123 | /** | ||
2124 | * ep_queue: queues (submits) an I/O request to an endpoint | ||
2125 | * | ||
2126 | * Check usb_ep_queue()* at usb_gadget.h" for details | ||
2127 | */ | ||
2128 | static int ep_queue(struct usb_ep *ep, struct usb_request *req, | ||
2129 | gfp_t __maybe_unused gfp_flags) | ||
2130 | { | ||
2131 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
2132 | struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); | ||
2133 | int retval = 0; | ||
2134 | unsigned long flags; | ||
2135 | |||
2136 | trace("%p, %p, %X", ep, req, gfp_flags); | ||
2137 | |||
2138 | if (ep == NULL || req == NULL || mEp->desc == NULL) | ||
2139 | return -EINVAL; | ||
2140 | |||
2141 | spin_lock_irqsave(mEp->lock, flags); | ||
2142 | |||
2143 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL && | ||
2144 | !list_empty(&mEp->qh[mEp->dir].queue)) { | ||
2145 | _ep_nuke(mEp); | ||
2146 | retval = -EOVERFLOW; | ||
2147 | warn("endpoint ctrl %X nuked", _usb_addr(mEp)); | ||
2148 | } | ||
2149 | |||
2150 | /* first nuke then test link, e.g. previous status has not sent */ | ||
2151 | if (!list_empty(&mReq->queue)) { | ||
2152 | retval = -EBUSY; | ||
2153 | err("request already in queue"); | ||
2154 | goto done; | ||
2155 | } | ||
2156 | |||
2157 | if (req->length > (4 * PAGE_SIZE)) { | ||
2158 | req->length = (4 * PAGE_SIZE); | ||
2159 | retval = -EMSGSIZE; | ||
2160 | warn("request length truncated"); | ||
2161 | } | ||
2162 | |||
2163 | dbg_queue(_usb_addr(mEp), req, retval); | ||
2164 | |||
2165 | /* push request */ | ||
2166 | mReq->req.status = -EINPROGRESS; | ||
2167 | mReq->req.actual = 0; | ||
2168 | list_add_tail(&mReq->queue, &mEp->qh[mEp->dir].queue); | ||
2169 | |||
2170 | retval = _hardware_enqueue(mEp, mReq); | ||
2171 | if (retval == -EALREADY || retval == -EBUSY) { | ||
2172 | dbg_event(_usb_addr(mEp), "QUEUE", retval); | ||
2173 | retval = 0; | ||
2174 | } | ||
2175 | |||
2176 | done: | ||
2177 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2178 | return retval; | ||
2179 | } | ||
2180 | |||
2181 | /** | ||
2182 | * ep_dequeue: dequeues (cancels, unlinks) an I/O request from an endpoint | ||
2183 | * | ||
2184 | * Check usb_ep_dequeue() at "usb_gadget.h" for details | ||
2185 | */ | ||
2186 | static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) | ||
2187 | { | ||
2188 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
2189 | struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); | ||
2190 | unsigned long flags; | ||
2191 | |||
2192 | trace("%p, %p", ep, req); | ||
2193 | |||
2194 | if (ep == NULL || req == NULL || mEp->desc == NULL || | ||
2195 | list_empty(&mReq->queue) || list_empty(&mEp->qh[mEp->dir].queue)) | ||
2196 | return -EINVAL; | ||
2197 | |||
2198 | spin_lock_irqsave(mEp->lock, flags); | ||
2199 | |||
2200 | dbg_event(_usb_addr(mEp), "DEQUEUE", 0); | ||
2201 | |||
2202 | if (mReq->req.status == -EALREADY) | ||
2203 | _hardware_dequeue(mEp, mReq); | ||
2204 | |||
2205 | /* pop request */ | ||
2206 | list_del_init(&mReq->queue); | ||
2207 | req->status = -ECONNRESET; | ||
2208 | |||
2209 | if (!mReq->req.no_interrupt && mReq->req.complete != NULL) { | ||
2210 | spin_unlock(mEp->lock); | ||
2211 | mReq->req.complete(&mEp->ep, &mReq->req); | ||
2212 | spin_lock(mEp->lock); | ||
2213 | } | ||
2214 | |||
2215 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2216 | return 0; | ||
2217 | } | ||
2218 | |||
2219 | /** | ||
2220 | * ep_set_halt: sets the endpoint halt feature | ||
2221 | * | ||
2222 | * Check usb_ep_set_halt() at "usb_gadget.h" for details | ||
2223 | */ | ||
2224 | static int ep_set_halt(struct usb_ep *ep, int value) | ||
2225 | { | ||
2226 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
2227 | int direction, retval = 0; | ||
2228 | unsigned long flags; | ||
2229 | |||
2230 | trace("%p, %i", ep, value); | ||
2231 | |||
2232 | if (ep == NULL || mEp->desc == NULL) | ||
2233 | return -EINVAL; | ||
2234 | |||
2235 | spin_lock_irqsave(mEp->lock, flags); | ||
2236 | |||
2237 | #ifndef STALL_IN | ||
2238 | /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */ | ||
2239 | if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX && | ||
2240 | !list_empty(&mEp->qh[mEp->dir].queue)) { | ||
2241 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2242 | return -EAGAIN; | ||
2243 | } | ||
2244 | #endif | ||
2245 | |||
2246 | direction = mEp->dir; | ||
2247 | do { | ||
2248 | dbg_event(_usb_addr(mEp), "HALT", value); | ||
2249 | retval |= hw_ep_set_halt(mEp->num, mEp->dir, value); | ||
2250 | |||
2251 | if (!value) | ||
2252 | mEp->wedge = 0; | ||
2253 | |||
2254 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | ||
2255 | mEp->dir = (mEp->dir == TX) ? RX : TX; | ||
2256 | |||
2257 | } while (mEp->dir != direction); | ||
2258 | |||
2259 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2260 | return retval; | ||
2261 | } | ||
2262 | |||
2263 | /** | ||
2264 | * ep_set_wedge: sets the halt feature and ignores clear requests | ||
2265 | * | ||
2266 | * Check usb_ep_set_wedge() at "usb_gadget.h" for details | ||
2267 | */ | ||
2268 | static int ep_set_wedge(struct usb_ep *ep) | ||
2269 | { | ||
2270 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
2271 | unsigned long flags; | ||
2272 | |||
2273 | trace("%p", ep); | ||
2274 | |||
2275 | if (ep == NULL || mEp->desc == NULL) | ||
2276 | return -EINVAL; | ||
2277 | |||
2278 | spin_lock_irqsave(mEp->lock, flags); | ||
2279 | |||
2280 | dbg_event(_usb_addr(mEp), "WEDGE", 0); | ||
2281 | mEp->wedge = 1; | ||
2282 | |||
2283 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2284 | |||
2285 | return usb_ep_set_halt(ep); | ||
2286 | } | ||
2287 | |||
2288 | /** | ||
2289 | * ep_fifo_flush: flushes contents of a fifo | ||
2290 | * | ||
2291 | * Check usb_ep_fifo_flush() at "usb_gadget.h" for details | ||
2292 | */ | ||
2293 | static void ep_fifo_flush(struct usb_ep *ep) | ||
2294 | { | ||
2295 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | ||
2296 | unsigned long flags; | ||
2297 | |||
2298 | trace("%p", ep); | ||
2299 | |||
2300 | if (ep == NULL) { | ||
2301 | err("%02X: -EINVAL", _usb_addr(mEp)); | ||
2302 | return; | ||
2303 | } | ||
2304 | |||
2305 | spin_lock_irqsave(mEp->lock, flags); | ||
2306 | |||
2307 | dbg_event(_usb_addr(mEp), "FFLUSH", 0); | ||
2308 | hw_ep_flush(mEp->num, mEp->dir); | ||
2309 | |||
2310 | spin_unlock_irqrestore(mEp->lock, flags); | ||
2311 | } | ||
2312 | |||
2313 | /** | ||
2314 | * Endpoint-specific part of the API to the USB controller hardware | ||
2315 | * Check "usb_gadget.h" for details | ||
2316 | */ | ||
2317 | static const struct usb_ep_ops usb_ep_ops = { | ||
2318 | .enable = ep_enable, | ||
2319 | .disable = ep_disable, | ||
2320 | .alloc_request = ep_alloc_request, | ||
2321 | .free_request = ep_free_request, | ||
2322 | .queue = ep_queue, | ||
2323 | .dequeue = ep_dequeue, | ||
2324 | .set_halt = ep_set_halt, | ||
2325 | .set_wedge = ep_set_wedge, | ||
2326 | .fifo_flush = ep_fifo_flush, | ||
2327 | }; | ||
2328 | |||
2329 | /****************************************************************************** | ||
2330 | * GADGET block | ||
2331 | *****************************************************************************/ | ||
2332 | /** | ||
2333 | * Device operations part of the API to the USB controller hardware, | ||
2334 | * which don't involve endpoints (or i/o) | ||
2335 | * Check "usb_gadget.h" for details | ||
2336 | */ | ||
2337 | static const struct usb_gadget_ops usb_gadget_ops; | ||
2338 | |||
2339 | /** | ||
2340 | * usb_gadget_register_driver: register a gadget driver | ||
2341 | * | ||
2342 | * Check usb_gadget_register_driver() at "usb_gadget.h" for details | ||
2343 | * Interrupts are enabled here | ||
2344 | */ | ||
2345 | int usb_gadget_register_driver(struct usb_gadget_driver *driver) | ||
2346 | { | ||
2347 | struct ci13xxx *udc = _udc; | ||
2348 | unsigned long i, k, flags; | ||
2349 | int retval = -ENOMEM; | ||
2350 | |||
2351 | trace("%p", driver); | ||
2352 | |||
2353 | if (driver == NULL || | ||
2354 | driver->bind == NULL || | ||
2355 | driver->unbind == NULL || | ||
2356 | driver->setup == NULL || | ||
2357 | driver->disconnect == NULL || | ||
2358 | driver->suspend == NULL || | ||
2359 | driver->resume == NULL) | ||
2360 | return -EINVAL; | ||
2361 | else if (udc == NULL) | ||
2362 | return -ENODEV; | ||
2363 | else if (udc->driver != NULL) | ||
2364 | return -EBUSY; | ||
2365 | |||
2366 | /* alloc resources */ | ||
2367 | udc->qh_pool = dma_pool_create("ci13xxx_qh", &udc->gadget.dev, | ||
2368 | sizeof(struct ci13xxx_qh), | ||
2369 | 64, PAGE_SIZE); | ||
2370 | if (udc->qh_pool == NULL) | ||
2371 | return -ENOMEM; | ||
2372 | |||
2373 | udc->td_pool = dma_pool_create("ci13xxx_td", &udc->gadget.dev, | ||
2374 | sizeof(struct ci13xxx_td), | ||
2375 | 64, PAGE_SIZE); | ||
2376 | if (udc->td_pool == NULL) { | ||
2377 | dma_pool_destroy(udc->qh_pool); | ||
2378 | udc->qh_pool = NULL; | ||
2379 | return -ENOMEM; | ||
2380 | } | ||
2381 | |||
2382 | spin_lock_irqsave(udc->lock, flags); | ||
2383 | |||
2384 | info("hw_ep_max = %d", hw_ep_max); | ||
2385 | |||
2386 | udc->driver = driver; | ||
2387 | udc->gadget.ops = NULL; | ||
2388 | udc->gadget.dev.driver = NULL; | ||
2389 | |||
2390 | retval = 0; | ||
2391 | for (i = 0; i < hw_ep_max; i++) { | ||
2392 | struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; | ||
2393 | |||
2394 | scnprintf(mEp->name, sizeof(mEp->name), "ep%i", (int)i); | ||
2395 | |||
2396 | mEp->lock = udc->lock; | ||
2397 | mEp->device = &udc->gadget.dev; | ||
2398 | mEp->td_pool = udc->td_pool; | ||
2399 | |||
2400 | mEp->ep.name = mEp->name; | ||
2401 | mEp->ep.ops = &usb_ep_ops; | ||
2402 | mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; | ||
2403 | |||
2404 | /* this allocation cannot be random */ | ||
2405 | for (k = RX; k <= TX; k++) { | ||
2406 | INIT_LIST_HEAD(&mEp->qh[k].queue); | ||
2407 | mEp->qh[k].ptr = dma_pool_alloc(udc->qh_pool, | ||
2408 | GFP_KERNEL, | ||
2409 | &mEp->qh[k].dma); | ||
2410 | if (mEp->qh[k].ptr == NULL) | ||
2411 | retval = -ENOMEM; | ||
2412 | else | ||
2413 | memset(mEp->qh[k].ptr, 0, | ||
2414 | sizeof(*mEp->qh[k].ptr)); | ||
2415 | } | ||
2416 | if (i == 0) | ||
2417 | udc->gadget.ep0 = &mEp->ep; | ||
2418 | else | ||
2419 | list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list); | ||
2420 | } | ||
2421 | if (retval) | ||
2422 | goto done; | ||
2423 | |||
2424 | /* bind gadget */ | ||
2425 | driver->driver.bus = NULL; | ||
2426 | udc->gadget.ops = &usb_gadget_ops; | ||
2427 | udc->gadget.dev.driver = &driver->driver; | ||
2428 | |||
2429 | spin_unlock_irqrestore(udc->lock, flags); | ||
2430 | retval = driver->bind(&udc->gadget); /* MAY SLEEP */ | ||
2431 | spin_lock_irqsave(udc->lock, flags); | ||
2432 | |||
2433 | if (retval) { | ||
2434 | udc->gadget.ops = NULL; | ||
2435 | udc->gadget.dev.driver = NULL; | ||
2436 | goto done; | ||
2437 | } | ||
2438 | |||
2439 | retval = hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma); | ||
2440 | |||
2441 | done: | ||
2442 | spin_unlock_irqrestore(udc->lock, flags); | ||
2443 | if (retval) | ||
2444 | usb_gadget_unregister_driver(driver); | ||
2445 | return retval; | ||
2446 | } | ||
2447 | EXPORT_SYMBOL(usb_gadget_register_driver); | ||
2448 | |||
2449 | /** | ||
2450 | * usb_gadget_unregister_driver: unregister a gadget driver | ||
2451 | * | ||
2452 | * Check usb_gadget_unregister_driver() at "usb_gadget.h" for details | ||
2453 | */ | ||
2454 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | ||
2455 | { | ||
2456 | struct ci13xxx *udc = _udc; | ||
2457 | unsigned long i, k, flags; | ||
2458 | |||
2459 | trace("%p", driver); | ||
2460 | |||
2461 | if (driver == NULL || | ||
2462 | driver->bind == NULL || | ||
2463 | driver->unbind == NULL || | ||
2464 | driver->setup == NULL || | ||
2465 | driver->disconnect == NULL || | ||
2466 | driver->suspend == NULL || | ||
2467 | driver->resume == NULL || | ||
2468 | driver != udc->driver) | ||
2469 | return -EINVAL; | ||
2470 | |||
2471 | spin_lock_irqsave(udc->lock, flags); | ||
2472 | |||
2473 | hw_device_state(0); | ||
2474 | |||
2475 | /* unbind gadget */ | ||
2476 | if (udc->gadget.ops != NULL) { | ||
2477 | _gadget_stop_activity(&udc->gadget); | ||
2478 | |||
2479 | spin_unlock_irqrestore(udc->lock, flags); | ||
2480 | driver->unbind(&udc->gadget); /* MAY SLEEP */ | ||
2481 | spin_lock_irqsave(udc->lock, flags); | ||
2482 | |||
2483 | udc->gadget.ops = NULL; | ||
2484 | udc->gadget.dev.driver = NULL; | ||
2485 | } | ||
2486 | |||
2487 | /* free resources */ | ||
2488 | for (i = 0; i < hw_ep_max; i++) { | ||
2489 | struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; | ||
2490 | |||
2491 | if (i == 0) | ||
2492 | udc->gadget.ep0 = NULL; | ||
2493 | else if (!list_empty(&mEp->ep.ep_list)) | ||
2494 | list_del_init(&mEp->ep.ep_list); | ||
2495 | |||
2496 | for (k = RX; k <= TX; k++) | ||
2497 | if (mEp->qh[k].ptr != NULL) | ||
2498 | dma_pool_free(udc->qh_pool, | ||
2499 | mEp->qh[k].ptr, mEp->qh[k].dma); | ||
2500 | } | ||
2501 | |||
2502 | udc->driver = NULL; | ||
2503 | |||
2504 | spin_unlock_irqrestore(udc->lock, flags); | ||
2505 | |||
2506 | if (udc->td_pool != NULL) { | ||
2507 | dma_pool_destroy(udc->td_pool); | ||
2508 | udc->td_pool = NULL; | ||
2509 | } | ||
2510 | if (udc->qh_pool != NULL) { | ||
2511 | dma_pool_destroy(udc->qh_pool); | ||
2512 | udc->qh_pool = NULL; | ||
2513 | } | ||
2514 | |||
2515 | return 0; | ||
2516 | } | ||
2517 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | ||
2518 | |||
2519 | /****************************************************************************** | ||
2520 | * BUS block | ||
2521 | *****************************************************************************/ | ||
2522 | /** | ||
2523 | * udc_irq: global interrupt handler | ||
2524 | * | ||
2525 | * This function returns IRQ_HANDLED if the IRQ has been handled | ||
2526 | * It locks access to registers | ||
2527 | */ | ||
2528 | static irqreturn_t udc_irq(void) | ||
2529 | { | ||
2530 | struct ci13xxx *udc = _udc; | ||
2531 | irqreturn_t retval; | ||
2532 | u32 intr; | ||
2533 | |||
2534 | trace(); | ||
2535 | |||
2536 | if (udc == NULL) { | ||
2537 | err("ENODEV"); | ||
2538 | return IRQ_HANDLED; | ||
2539 | } | ||
2540 | |||
2541 | spin_lock(udc->lock); | ||
2542 | intr = hw_test_and_clear_intr_active(); | ||
2543 | if (intr) { | ||
2544 | isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intr; | ||
2545 | isr_statistics.hndl.idx &= ISR_MASK; | ||
2546 | isr_statistics.hndl.cnt++; | ||
2547 | |||
2548 | /* order defines priority - do NOT change it */ | ||
2549 | if (USBi_URI & intr) { | ||
2550 | isr_statistics.uri++; | ||
2551 | isr_reset_handler(udc); | ||
2552 | } | ||
2553 | if (USBi_PCI & intr) { | ||
2554 | isr_statistics.pci++; | ||
2555 | udc->gadget.speed = hw_port_is_high_speed() ? | ||
2556 | USB_SPEED_HIGH : USB_SPEED_FULL; | ||
2557 | } | ||
2558 | if (USBi_UEI & intr) | ||
2559 | isr_statistics.uei++; | ||
2560 | if (USBi_UI & intr) { | ||
2561 | isr_statistics.ui++; | ||
2562 | isr_tr_complete_handler(udc); | ||
2563 | } | ||
2564 | if (USBi_SLI & intr) | ||
2565 | isr_statistics.sli++; | ||
2566 | retval = IRQ_HANDLED; | ||
2567 | } else { | ||
2568 | isr_statistics.none++; | ||
2569 | retval = IRQ_NONE; | ||
2570 | } | ||
2571 | spin_unlock(udc->lock); | ||
2572 | |||
2573 | return retval; | ||
2574 | } | ||
2575 | |||
2576 | /** | ||
2577 | * udc_release: driver release function | ||
2578 | * @dev: device | ||
2579 | * | ||
2580 | * Currently does nothing | ||
2581 | */ | ||
2582 | static void udc_release(struct device *dev) | ||
2583 | { | ||
2584 | trace("%p", dev); | ||
2585 | |||
2586 | if (dev == NULL) | ||
2587 | err("EINVAL"); | ||
2588 | } | ||
2589 | |||
2590 | /** | ||
2591 | * udc_probe: parent probe must call this to initialize UDC | ||
2592 | * @dev: parent device | ||
2593 | * @regs: registers base address | ||
2594 | * @name: driver name | ||
2595 | * | ||
2596 | * This function returns an error code | ||
2597 | * No interrupts active, the IRQ has not been requested yet | ||
2598 | * Kernel assumes 32-bit DMA operations by default, no need to dma_set_mask | ||
2599 | */ | ||
2600 | static int udc_probe(struct device *dev, void __iomem *regs, const char *name) | ||
2601 | { | ||
2602 | struct ci13xxx *udc; | ||
2603 | int retval = 0; | ||
2604 | |||
2605 | trace("%p, %p, %p", dev, regs, name); | ||
2606 | |||
2607 | if (dev == NULL || regs == NULL || name == NULL) | ||
2608 | return -EINVAL; | ||
2609 | |||
2610 | udc = kzalloc(sizeof(struct ci13xxx), GFP_KERNEL); | ||
2611 | if (udc == NULL) | ||
2612 | return -ENOMEM; | ||
2613 | |||
2614 | udc->lock = &udc_lock; | ||
2615 | |||
2616 | retval = hw_device_reset(regs); | ||
2617 | if (retval) | ||
2618 | goto done; | ||
2619 | |||
2620 | udc->gadget.ops = NULL; | ||
2621 | udc->gadget.speed = USB_SPEED_UNKNOWN; | ||
2622 | udc->gadget.is_dualspeed = 1; | ||
2623 | udc->gadget.is_otg = 0; | ||
2624 | udc->gadget.name = name; | ||
2625 | |||
2626 | INIT_LIST_HEAD(&udc->gadget.ep_list); | ||
2627 | udc->gadget.ep0 = NULL; | ||
2628 | |||
2629 | strcpy(udc->gadget.dev.bus_id, "gadget"); | ||
2630 | udc->gadget.dev.dma_mask = dev->dma_mask; | ||
2631 | udc->gadget.dev.parent = dev; | ||
2632 | udc->gadget.dev.release = udc_release; | ||
2633 | |||
2634 | retval = device_register(&udc->gadget.dev); | ||
2635 | if (retval) | ||
2636 | goto done; | ||
2637 | |||
2638 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | ||
2639 | retval = dbg_create_files(&udc->gadget.dev); | ||
2640 | #endif | ||
2641 | if (retval) { | ||
2642 | device_unregister(&udc->gadget.dev); | ||
2643 | goto done; | ||
2644 | } | ||
2645 | |||
2646 | _udc = udc; | ||
2647 | return retval; | ||
2648 | |||
2649 | done: | ||
2650 | err("error = %i", retval); | ||
2651 | kfree(udc); | ||
2652 | _udc = NULL; | ||
2653 | return retval; | ||
2654 | } | ||
2655 | |||
2656 | /** | ||
2657 | * udc_remove: parent remove must call this to remove UDC | ||
2658 | * | ||
2659 | * No interrupts active, the IRQ has been released | ||
2660 | */ | ||
2661 | static void udc_remove(void) | ||
2662 | { | ||
2663 | struct ci13xxx *udc = _udc; | ||
2664 | |||
2665 | if (udc == NULL) { | ||
2666 | err("EINVAL"); | ||
2667 | return; | ||
2668 | } | ||
2669 | |||
2670 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | ||
2671 | dbg_remove_files(&udc->gadget.dev); | ||
2672 | #endif | ||
2673 | device_unregister(&udc->gadget.dev); | ||
2674 | |||
2675 | kfree(udc); | ||
2676 | _udc = NULL; | ||
2677 | } | ||
2678 | |||
2679 | /****************************************************************************** | ||
2680 | * PCI block | ||
2681 | *****************************************************************************/ | ||
2682 | /** | ||
2683 | * ci13xxx_pci_irq: interrut handler | ||
2684 | * @irq: irq number | ||
2685 | * @pdev: USB Device Controller interrupt source | ||
2686 | * | ||
2687 | * This function returns IRQ_HANDLED if the IRQ has been handled | ||
2688 | * This is an ISR don't trace, use attribute interface instead | ||
2689 | */ | ||
2690 | static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev) | ||
2691 | { | ||
2692 | if (irq == 0) { | ||
2693 | dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!"); | ||
2694 | return IRQ_HANDLED; | ||
2695 | } | ||
2696 | return udc_irq(); | ||
2697 | } | ||
2698 | |||
2699 | /** | ||
2700 | * ci13xxx_pci_probe: PCI probe | ||
2701 | * @pdev: USB device controller being probed | ||
2702 | * @id: PCI hotplug ID connecting controller to UDC framework | ||
2703 | * | ||
2704 | * This function returns an error code | ||
2705 | * Allocates basic PCI resources for this USB device controller, and then | ||
2706 | * invokes the udc_probe() method to start the UDC associated with it | ||
2707 | */ | ||
2708 | static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, | ||
2709 | const struct pci_device_id *id) | ||
2710 | { | ||
2711 | void __iomem *regs = NULL; | ||
2712 | int retval = 0; | ||
2713 | |||
2714 | if (id == NULL) | ||
2715 | return -EINVAL; | ||
2716 | |||
2717 | retval = pci_enable_device(pdev); | ||
2718 | if (retval) | ||
2719 | goto done; | ||
2720 | |||
2721 | if (!pdev->irq) { | ||
2722 | dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); | ||
2723 | retval = -ENODEV; | ||
2724 | goto disable_device; | ||
2725 | } | ||
2726 | |||
2727 | retval = pci_request_regions(pdev, UDC_DRIVER_NAME); | ||
2728 | if (retval) | ||
2729 | goto disable_device; | ||
2730 | |||
2731 | /* BAR 0 holds all the registers */ | ||
2732 | regs = pci_iomap(pdev, 0, 0); | ||
2733 | if (!regs) { | ||
2734 | dev_err(&pdev->dev, "Error mapping memory!"); | ||
2735 | retval = -EFAULT; | ||
2736 | goto release_regions; | ||
2737 | } | ||
2738 | pci_set_drvdata(pdev, (__force void *)regs); | ||
2739 | |||
2740 | pci_set_master(pdev); | ||
2741 | pci_try_set_mwi(pdev); | ||
2742 | |||
2743 | retval = udc_probe(&pdev->dev, regs, UDC_DRIVER_NAME); | ||
2744 | if (retval) | ||
2745 | goto iounmap; | ||
2746 | |||
2747 | /* our device does not have MSI capability */ | ||
2748 | |||
2749 | retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED, | ||
2750 | UDC_DRIVER_NAME, pdev); | ||
2751 | if (retval) | ||
2752 | goto gadget_remove; | ||
2753 | |||
2754 | return 0; | ||
2755 | |||
2756 | gadget_remove: | ||
2757 | udc_remove(); | ||
2758 | iounmap: | ||
2759 | pci_iounmap(pdev, regs); | ||
2760 | release_regions: | ||
2761 | pci_release_regions(pdev); | ||
2762 | disable_device: | ||
2763 | pci_disable_device(pdev); | ||
2764 | done: | ||
2765 | return retval; | ||
2766 | } | ||
2767 | |||
2768 | /** | ||
2769 | * ci13xxx_pci_remove: PCI remove | ||
2770 | * @pdev: USB Device Controller being removed | ||
2771 | * | ||
2772 | * Reverses the effect of ci13xxx_pci_probe(), | ||
2773 | * first invoking the udc_remove() and then releases | ||
2774 | * all PCI resources allocated for this USB device controller | ||
2775 | */ | ||
2776 | static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) | ||
2777 | { | ||
2778 | free_irq(pdev->irq, pdev); | ||
2779 | udc_remove(); | ||
2780 | pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev)); | ||
2781 | pci_release_regions(pdev); | ||
2782 | pci_disable_device(pdev); | ||
2783 | } | ||
2784 | |||
2785 | /** | ||
2786 | * PCI device table | ||
2787 | * PCI device structure | ||
2788 | * | ||
2789 | * Check "pci.h" for details | ||
2790 | */ | ||
2791 | static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { | ||
2792 | { PCI_DEVICE(0x153F, 0x1004) }, | ||
2793 | { PCI_DEVICE(0x153F, 0x1006) }, | ||
2794 | { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } | ||
2795 | }; | ||
2796 | MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table); | ||
2797 | |||
2798 | static struct pci_driver ci13xxx_pci_driver = { | ||
2799 | .name = UDC_DRIVER_NAME, | ||
2800 | .id_table = ci13xxx_pci_id_table, | ||
2801 | .probe = ci13xxx_pci_probe, | ||
2802 | .remove = __devexit_p(ci13xxx_pci_remove), | ||
2803 | }; | ||
2804 | |||
2805 | /** | ||
2806 | * ci13xxx_pci_init: module init | ||
2807 | * | ||
2808 | * Driver load | ||
2809 | */ | ||
2810 | static int __init ci13xxx_pci_init(void) | ||
2811 | { | ||
2812 | return pci_register_driver(&ci13xxx_pci_driver); | ||
2813 | } | ||
2814 | module_init(ci13xxx_pci_init); | ||
2815 | |||
2816 | /** | ||
2817 | * ci13xxx_pci_exit: module exit | ||
2818 | * | ||
2819 | * Driver unload | ||
2820 | */ | ||
2821 | static void __exit ci13xxx_pci_exit(void) | ||
2822 | { | ||
2823 | pci_unregister_driver(&ci13xxx_pci_driver); | ||
2824 | } | ||
2825 | module_exit(ci13xxx_pci_exit); | ||
2826 | |||
2827 | MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); | ||
2828 | MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); | ||
2829 | MODULE_LICENSE("GPL"); | ||
2830 | MODULE_VERSION("June 2008"); | ||
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h new file mode 100644 index 000000000000..4026e9cede34 --- /dev/null +++ b/drivers/usb/gadget/ci13xxx_udc.h | |||
@@ -0,0 +1,195 @@ | |||
1 | /* | ||
2 | * ci13xxx_udc.h - structures, registers, and macros MIPS USB IP core | ||
3 | * | ||
4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | ||
5 | * | ||
6 | * Author: David Lopo | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * Description: MIPS USB IP core family device controller | ||
13 | * Structures, registers and logging macros | ||
14 | */ | ||
15 | |||
16 | #ifndef _CI13XXX_h_ | ||
17 | #define _CI13XXX_h_ | ||
18 | |||
19 | /****************************************************************************** | ||
20 | * DEFINE | ||
21 | *****************************************************************************/ | ||
22 | #define ENDPT_MAX (16) | ||
23 | #define CTRL_PAYLOAD_MAX (64) | ||
24 | #define RX (0) /* similar to USB_DIR_OUT but can be used as an index */ | ||
25 | #define TX (1) /* similar to USB_DIR_IN but can be used as an index */ | ||
26 | |||
27 | /****************************************************************************** | ||
28 | * STRUCTURES | ||
29 | *****************************************************************************/ | ||
30 | /* DMA layout of transfer descriptors */ | ||
31 | struct ci13xxx_td { | ||
32 | /* 0 */ | ||
33 | u32 next; | ||
34 | #define TD_TERMINATE BIT(0) | ||
35 | /* 1 */ | ||
36 | u32 token; | ||
37 | #define TD_STATUS (0x00FFUL << 0) | ||
38 | #define TD_STATUS_TR_ERR BIT(3) | ||
39 | #define TD_STATUS_DT_ERR BIT(5) | ||
40 | #define TD_STATUS_HALTED BIT(6) | ||
41 | #define TD_STATUS_ACTIVE BIT(7) | ||
42 | #define TD_MULTO (0x0003UL << 10) | ||
43 | #define TD_IOC BIT(15) | ||
44 | #define TD_TOTAL_BYTES (0x7FFFUL << 16) | ||
45 | /* 2 */ | ||
46 | u32 page[5]; | ||
47 | #define TD_CURR_OFFSET (0x0FFFUL << 0) | ||
48 | #define TD_FRAME_NUM (0x07FFUL << 0) | ||
49 | #define TD_RESERVED_MASK (0x0FFFUL << 0) | ||
50 | } __attribute__ ((packed)); | ||
51 | |||
52 | /* DMA layout of queue heads */ | ||
53 | struct ci13xxx_qh { | ||
54 | /* 0 */ | ||
55 | u32 cap; | ||
56 | #define QH_IOS BIT(15) | ||
57 | #define QH_MAX_PKT (0x07FFUL << 16) | ||
58 | #define QH_ZLT BIT(29) | ||
59 | #define QH_MULT (0x0003UL << 30) | ||
60 | /* 1 */ | ||
61 | u32 curr; | ||
62 | /* 2 - 8 */ | ||
63 | struct ci13xxx_td td; | ||
64 | /* 9 */ | ||
65 | u32 RESERVED; | ||
66 | struct usb_ctrlrequest setup; | ||
67 | } __attribute__ ((packed)); | ||
68 | |||
69 | /* Extension of usb_request */ | ||
70 | struct ci13xxx_req { | ||
71 | struct usb_request req; | ||
72 | unsigned map; | ||
73 | struct list_head queue; | ||
74 | struct ci13xxx_td *ptr; | ||
75 | dma_addr_t dma; | ||
76 | }; | ||
77 | |||
78 | /* Extension of usb_ep */ | ||
79 | struct ci13xxx_ep { | ||
80 | struct usb_ep ep; | ||
81 | const struct usb_endpoint_descriptor *desc; | ||
82 | u8 dir; | ||
83 | u8 num; | ||
84 | u8 type; | ||
85 | char name[16]; | ||
86 | struct { | ||
87 | struct list_head queue; | ||
88 | struct ci13xxx_qh *ptr; | ||
89 | dma_addr_t dma; | ||
90 | } qh[2]; | ||
91 | struct usb_request *status; | ||
92 | int wedge; | ||
93 | |||
94 | /* global resources */ | ||
95 | spinlock_t *lock; | ||
96 | struct device *device; | ||
97 | struct dma_pool *td_pool; | ||
98 | }; | ||
99 | |||
100 | /* CI13XXX UDC descriptor & global resources */ | ||
101 | struct ci13xxx { | ||
102 | spinlock_t *lock; /* ctrl register bank access */ | ||
103 | |||
104 | struct dma_pool *qh_pool; /* DMA pool for queue heads */ | ||
105 | struct dma_pool *td_pool; /* DMA pool for transfer descs */ | ||
106 | |||
107 | struct usb_gadget gadget; /* USB slave device */ | ||
108 | struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */ | ||
109 | |||
110 | struct usb_gadget_driver *driver; /* 3rd party gadget driver */ | ||
111 | }; | ||
112 | |||
113 | /****************************************************************************** | ||
114 | * REGISTERS | ||
115 | *****************************************************************************/ | ||
116 | /* register size */ | ||
117 | #define REG_BITS (32) | ||
118 | |||
119 | /* HCCPARAMS */ | ||
120 | #define HCCPARAMS_LEN BIT(17) | ||
121 | |||
122 | /* DCCPARAMS */ | ||
123 | #define DCCPARAMS_DEN (0x1F << 0) | ||
124 | #define DCCPARAMS_DC BIT(7) | ||
125 | |||
126 | /* TESTMODE */ | ||
127 | #define TESTMODE_FORCE BIT(0) | ||
128 | |||
129 | /* USBCMD */ | ||
130 | #define USBCMD_RS BIT(0) | ||
131 | #define USBCMD_RST BIT(1) | ||
132 | #define USBCMD_SUTW BIT(13) | ||
133 | |||
134 | /* USBSTS & USBINTR */ | ||
135 | #define USBi_UI BIT(0) | ||
136 | #define USBi_UEI BIT(1) | ||
137 | #define USBi_PCI BIT(2) | ||
138 | #define USBi_URI BIT(6) | ||
139 | #define USBi_SLI BIT(8) | ||
140 | |||
141 | /* DEVICEADDR */ | ||
142 | #define DEVICEADDR_USBADRA BIT(24) | ||
143 | #define DEVICEADDR_USBADR (0x7FUL << 25) | ||
144 | |||
145 | /* PORTSC */ | ||
146 | #define PORTSC_SUSP BIT(7) | ||
147 | #define PORTSC_HSP BIT(9) | ||
148 | #define PORTSC_PTC (0x0FUL << 16) | ||
149 | |||
150 | /* DEVLC */ | ||
151 | #define DEVLC_PSPD (0x03UL << 25) | ||
152 | #define DEVLC_PSPD_HS (0x02UL << 25) | ||
153 | |||
154 | /* USBMODE */ | ||
155 | #define USBMODE_CM (0x03UL << 0) | ||
156 | #define USBMODE_CM_IDLE (0x00UL << 0) | ||
157 | #define USBMODE_CM_DEVICE (0x02UL << 0) | ||
158 | #define USBMODE_CM_HOST (0x03UL << 0) | ||
159 | #define USBMODE_SLOM BIT(3) | ||
160 | |||
161 | /* ENDPTCTRL */ | ||
162 | #define ENDPTCTRL_RXS BIT(0) | ||
163 | #define ENDPTCTRL_RXT (0x03UL << 2) | ||
164 | #define ENDPTCTRL_RXR BIT(6) /* reserved for port 0 */ | ||
165 | #define ENDPTCTRL_RXE BIT(7) | ||
166 | #define ENDPTCTRL_TXS BIT(16) | ||
167 | #define ENDPTCTRL_TXT (0x03UL << 18) | ||
168 | #define ENDPTCTRL_TXR BIT(22) /* reserved for port 0 */ | ||
169 | #define ENDPTCTRL_TXE BIT(23) | ||
170 | |||
171 | /****************************************************************************** | ||
172 | * LOGGING | ||
173 | *****************************************************************************/ | ||
174 | #define ci13xxx_printk(level, format, args...) \ | ||
175 | do { \ | ||
176 | if (_udc == NULL) \ | ||
177 | printk(level "[%s] " format "\n", __func__, ## args); \ | ||
178 | else \ | ||
179 | dev_printk(level, _udc->gadget.dev.parent, \ | ||
180 | "[%s] " format "\n", __func__, ## args); \ | ||
181 | } while (0) | ||
182 | |||
183 | #define err(format, args...) ci13xxx_printk(KERN_ERR, format, ## args) | ||
184 | #define warn(format, args...) ci13xxx_printk(KERN_WARNING, format, ## args) | ||
185 | #define info(format, args...) ci13xxx_printk(KERN_INFO, format, ## args) | ||
186 | |||
187 | #ifdef TRACE | ||
188 | #define trace(format, args...) ci13xxx_printk(KERN_DEBUG, format, ## args) | ||
189 | #define dbg_trace(format, args...) dev_dbg(dev, format, ##args) | ||
190 | #else | ||
191 | #define trace(format, args...) do {} while (0) | ||
192 | #define dbg_trace(format, args...) do {} while (0) | ||
193 | #endif | ||
194 | |||
195 | #endif /* _CI13XXX_h_ */ | ||
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 9462e30192d8..a36b1175b18d 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c | |||
@@ -161,7 +161,7 @@ ep_matches ( | |||
161 | /* report address */ | 161 | /* report address */ |
162 | desc->bEndpointAddress &= USB_DIR_IN; | 162 | desc->bEndpointAddress &= USB_DIR_IN; |
163 | if (isdigit (ep->name [2])) { | 163 | if (isdigit (ep->name [2])) { |
164 | u8 num = simple_strtol (&ep->name [2], NULL, 10); | 164 | u8 num = simple_strtoul (&ep->name [2], NULL, 10); |
165 | desc->bEndpointAddress |= num; | 165 | desc->bEndpointAddress |= num; |
166 | #ifdef MANY_ENDPOINTS | 166 | #ifdef MANY_ENDPOINTS |
167 | } else if (desc->bEndpointAddress & USB_DIR_IN) { | 167 | } else if (desc->bEndpointAddress & USB_DIR_IN) { |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 2e71368f45b4..b10fa31cc915 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * file_storage.c -- File-backed USB Storage Gadget, for USB development | 2 | * file_storage.c -- File-backed USB Storage Gadget, for USB development |
3 | * | 3 | * |
4 | * Copyright (C) 2003-2007 Alan Stern | 4 | * Copyright (C) 2003-2008 Alan Stern |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without |
@@ -38,16 +38,17 @@ | |||
38 | 38 | ||
39 | /* | 39 | /* |
40 | * The File-backed Storage Gadget acts as a USB Mass Storage device, | 40 | * The File-backed Storage Gadget acts as a USB Mass Storage device, |
41 | * appearing to the host as a disk drive. In addition to providing an | 41 | * appearing to the host as a disk drive or as a CD-ROM drive. In addition |
42 | * example of a genuinely useful gadget driver for a USB device, it also | 42 | * to providing an example of a genuinely useful gadget driver for a USB |
43 | * illustrates a technique of double-buffering for increased throughput. | 43 | * device, it also illustrates a technique of double-buffering for increased |
44 | * Last but not least, it gives an easy way to probe the behavior of the | 44 | * throughput. Last but not least, it gives an easy way to probe the |
45 | * Mass Storage drivers in a USB host. | 45 | * behavior of the Mass Storage drivers in a USB host. |
46 | * | 46 | * |
47 | * Backing storage is provided by a regular file or a block device, specified | 47 | * Backing storage is provided by a regular file or a block device, specified |
48 | * by the "file" module parameter. Access can be limited to read-only by | 48 | * by the "file" module parameter. Access can be limited to read-only by |
49 | * setting the optional "ro" module parameter. The gadget will indicate that | 49 | * setting the optional "ro" module parameter. (For CD-ROM emulation, |
50 | * it has removable media if the optional "removable" module parameter is set. | 50 | * access is always read-only.) The gadget will indicate that it has |
51 | * removable media if the optional "removable" module parameter is set. | ||
51 | * | 52 | * |
52 | * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI), | 53 | * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI), |
53 | * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected | 54 | * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected |
@@ -64,7 +65,12 @@ | |||
64 | * The default number of LUNs is taken from the number of "file" elements; | 65 | * The default number of LUNs is taken from the number of "file" elements; |
65 | * it is 1 if "file" is not given. If "removable" is not set then a backing | 66 | * it is 1 if "file" is not given. If "removable" is not set then a backing |
66 | * file must be specified for each LUN. If it is set, then an unspecified | 67 | * file must be specified for each LUN. If it is set, then an unspecified |
67 | * or empty backing filename means the LUN's medium is not loaded. | 68 | * or empty backing filename means the LUN's medium is not loaded. Ideally |
69 | * each LUN would be settable independently as a disk drive or a CD-ROM | ||
70 | * drive, but currently all LUNs have to be the same type. The CD-ROM | ||
71 | * emulation includes a single data track and no audio tracks; hence there | ||
72 | * need be only one backing file per LUN. Note also that the CD-ROM block | ||
73 | * length is set to 512 rather than the more common value 2048. | ||
68 | * | 74 | * |
69 | * Requirements are modest; only a bulk-in and a bulk-out endpoint are | 75 | * Requirements are modest; only a bulk-in and a bulk-out endpoint are |
70 | * needed (an interrupt-out endpoint is also needed for CBI). The memory | 76 | * needed (an interrupt-out endpoint is also needed for CBI). The memory |
@@ -91,6 +97,8 @@ | |||
91 | * USB device controller (usually true), | 97 | * USB device controller (usually true), |
92 | * boolean to permit the driver to halt | 98 | * boolean to permit the driver to halt |
93 | * bulk endpoints | 99 | * bulk endpoints |
100 | * cdrom Default false, boolean for whether to emulate | ||
101 | * a CD-ROM drive | ||
94 | * transport=XXX Default BBB, transport name (CB, CBI, or BBB) | 102 | * transport=XXX Default BBB, transport name (CB, CBI, or BBB) |
95 | * protocol=YYY Default SCSI, protocol name (RBC, 8020 or | 103 | * protocol=YYY Default SCSI, protocol name (RBC, 8020 or |
96 | * ATAPI, QIC, UFI, 8070, or SCSI; | 104 | * ATAPI, QIC, UFI, 8070, or SCSI; |
@@ -103,15 +111,16 @@ | |||
103 | * PAGE_CACHE_SIZE) | 111 | * PAGE_CACHE_SIZE) |
104 | * | 112 | * |
105 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", | 113 | * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "ro", |
106 | * "removable", "luns", and "stall" options are available; default values | 114 | * "removable", "luns", "stall", and "cdrom" options are available; default |
107 | * are used for everything else. | 115 | * values are used for everything else. |
108 | * | 116 | * |
109 | * The pathnames of the backing files and the ro settings are available in | 117 | * The pathnames of the backing files and the ro settings are available in |
110 | * the attribute files "file" and "ro" in the lun<n> subdirectory of the | 118 | * the attribute files "file" and "ro" in the lun<n> subdirectory of the |
111 | * gadget's sysfs directory. If the "removable" option is set, writing to | 119 | * gadget's sysfs directory. If the "removable" option is set, writing to |
112 | * these files will simulate ejecting/loading the medium (writing an empty | 120 | * these files will simulate ejecting/loading the medium (writing an empty |
113 | * line means eject) and adjusting a write-enable tab. Changes to the ro | 121 | * line means eject) and adjusting a write-enable tab. Changes to the ro |
114 | * setting are not allowed when the medium is loaded. | 122 | * setting are not allowed when the medium is loaded or if CD-ROM emulation |
123 | * is being used. | ||
115 | * | 124 | * |
116 | * This gadget driver is heavily based on "Gadget Zero" by David Brownell. | 125 | * This gadget driver is heavily based on "Gadget Zero" by David Brownell. |
117 | * The driver's SCSI command interface was based on the "Information | 126 | * The driver's SCSI command interface was based on the "Information |
@@ -261,7 +270,7 @@ | |||
261 | 270 | ||
262 | #define DRIVER_DESC "File-backed Storage Gadget" | 271 | #define DRIVER_DESC "File-backed Storage Gadget" |
263 | #define DRIVER_NAME "g_file_storage" | 272 | #define DRIVER_NAME "g_file_storage" |
264 | #define DRIVER_VERSION "7 August 2007" | 273 | #define DRIVER_VERSION "20 November 2008" |
265 | 274 | ||
266 | static const char longname[] = DRIVER_DESC; | 275 | static const char longname[] = DRIVER_DESC; |
267 | static const char shortname[] = DRIVER_NAME; | 276 | static const char shortname[] = DRIVER_NAME; |
@@ -341,6 +350,7 @@ static struct { | |||
341 | 350 | ||
342 | int removable; | 351 | int removable; |
343 | int can_stall; | 352 | int can_stall; |
353 | int cdrom; | ||
344 | 354 | ||
345 | char *transport_parm; | 355 | char *transport_parm; |
346 | char *protocol_parm; | 356 | char *protocol_parm; |
@@ -359,6 +369,7 @@ static struct { | |||
359 | .protocol_parm = "SCSI", | 369 | .protocol_parm = "SCSI", |
360 | .removable = 0, | 370 | .removable = 0, |
361 | .can_stall = 1, | 371 | .can_stall = 1, |
372 | .cdrom = 0, | ||
362 | .vendor = DRIVER_VENDOR_ID, | 373 | .vendor = DRIVER_VENDOR_ID, |
363 | .product = DRIVER_PRODUCT_ID, | 374 | .product = DRIVER_PRODUCT_ID, |
364 | .release = 0xffff, // Use controller chip type | 375 | .release = 0xffff, // Use controller chip type |
@@ -382,6 +393,9 @@ MODULE_PARM_DESC(removable, "true to simulate removable media"); | |||
382 | module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); | 393 | module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); |
383 | MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); | 394 | MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); |
384 | 395 | ||
396 | module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO); | ||
397 | MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); | ||
398 | |||
385 | 399 | ||
386 | /* In the non-TEST version, only the module parameters listed above | 400 | /* In the non-TEST version, only the module parameters listed above |
387 | * are available. */ | 401 | * are available. */ |
@@ -411,6 +425,10 @@ MODULE_PARM_DESC(buflen, "I/O buffer size"); | |||
411 | 425 | ||
412 | /*-------------------------------------------------------------------------*/ | 426 | /*-------------------------------------------------------------------------*/ |
413 | 427 | ||
428 | /* SCSI device types */ | ||
429 | #define TYPE_DISK 0x00 | ||
430 | #define TYPE_CDROM 0x05 | ||
431 | |||
414 | /* USB protocol value = the transport method */ | 432 | /* USB protocol value = the transport method */ |
415 | #define USB_PR_CBI 0x00 // Control/Bulk/Interrupt | 433 | #define USB_PR_CBI 0x00 // Control/Bulk/Interrupt |
416 | #define USB_PR_CB 0x01 // Control/Bulk w/o interrupt | 434 | #define USB_PR_CB 0x01 // Control/Bulk w/o interrupt |
@@ -487,6 +505,8 @@ struct interrupt_data { | |||
487 | #define SC_READ_12 0xa8 | 505 | #define SC_READ_12 0xa8 |
488 | #define SC_READ_CAPACITY 0x25 | 506 | #define SC_READ_CAPACITY 0x25 |
489 | #define SC_READ_FORMAT_CAPACITIES 0x23 | 507 | #define SC_READ_FORMAT_CAPACITIES 0x23 |
508 | #define SC_READ_HEADER 0x44 | ||
509 | #define SC_READ_TOC 0x43 | ||
490 | #define SC_RELEASE 0x17 | 510 | #define SC_RELEASE 0x17 |
491 | #define SC_REQUEST_SENSE 0x03 | 511 | #define SC_REQUEST_SENSE 0x03 |
492 | #define SC_RESERVE 0x16 | 512 | #define SC_RESERVE 0x16 |
@@ -2006,23 +2026,28 @@ static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
2006 | u8 *buf = (u8 *) bh->buf; | 2026 | u8 *buf = (u8 *) bh->buf; |
2007 | 2027 | ||
2008 | static char vendor_id[] = "Linux "; | 2028 | static char vendor_id[] = "Linux "; |
2009 | static char product_id[] = "File-Stor Gadget"; | 2029 | static char product_disk_id[] = "File-Stor Gadget"; |
2030 | static char product_cdrom_id[] = "File-CD Gadget "; | ||
2010 | 2031 | ||
2011 | if (!fsg->curlun) { // Unsupported LUNs are okay | 2032 | if (!fsg->curlun) { // Unsupported LUNs are okay |
2012 | fsg->bad_lun_okay = 1; | 2033 | fsg->bad_lun_okay = 1; |
2013 | memset(buf, 0, 36); | 2034 | memset(buf, 0, 36); |
2014 | buf[0] = 0x7f; // Unsupported, no device-type | 2035 | buf[0] = 0x7f; // Unsupported, no device-type |
2036 | buf[4] = 31; // Additional length | ||
2015 | return 36; | 2037 | return 36; |
2016 | } | 2038 | } |
2017 | 2039 | ||
2018 | memset(buf, 0, 8); // Non-removable, direct-access device | 2040 | memset(buf, 0, 8); |
2041 | buf[0] = (mod_data.cdrom ? TYPE_CDROM : TYPE_DISK); | ||
2019 | if (mod_data.removable) | 2042 | if (mod_data.removable) |
2020 | buf[1] = 0x80; | 2043 | buf[1] = 0x80; |
2021 | buf[2] = 2; // ANSI SCSI level 2 | 2044 | buf[2] = 2; // ANSI SCSI level 2 |
2022 | buf[3] = 2; // SCSI-2 INQUIRY data format | 2045 | buf[3] = 2; // SCSI-2 INQUIRY data format |
2023 | buf[4] = 31; // Additional length | 2046 | buf[4] = 31; // Additional length |
2024 | // No special options | 2047 | // No special options |
2025 | sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, product_id, | 2048 | sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, |
2049 | (mod_data.cdrom ? product_cdrom_id : | ||
2050 | product_disk_id), | ||
2026 | mod_data.release); | 2051 | mod_data.release); |
2027 | return 36; | 2052 | return 36; |
2028 | } | 2053 | } |
@@ -2101,6 +2126,75 @@ static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) | |||
2101 | } | 2126 | } |
2102 | 2127 | ||
2103 | 2128 | ||
2129 | static void store_cdrom_address(u8 *dest, int msf, u32 addr) | ||
2130 | { | ||
2131 | if (msf) { | ||
2132 | /* Convert to Minutes-Seconds-Frames */ | ||
2133 | addr >>= 2; /* Convert to 2048-byte frames */ | ||
2134 | addr += 2*75; /* Lead-in occupies 2 seconds */ | ||
2135 | dest[3] = addr % 75; /* Frames */ | ||
2136 | addr /= 75; | ||
2137 | dest[2] = addr % 60; /* Seconds */ | ||
2138 | addr /= 60; | ||
2139 | dest[1] = addr; /* Minutes */ | ||
2140 | dest[0] = 0; /* Reserved */ | ||
2141 | } else { | ||
2142 | /* Absolute sector */ | ||
2143 | put_be32(dest, addr); | ||
2144 | } | ||
2145 | } | ||
2146 | |||
2147 | static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
2148 | { | ||
2149 | struct lun *curlun = fsg->curlun; | ||
2150 | int msf = fsg->cmnd[1] & 0x02; | ||
2151 | u32 lba = get_be32(&fsg->cmnd[2]); | ||
2152 | u8 *buf = (u8 *) bh->buf; | ||
2153 | |||
2154 | if ((fsg->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */ | ||
2155 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
2156 | return -EINVAL; | ||
2157 | } | ||
2158 | if (lba >= curlun->num_sectors) { | ||
2159 | curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; | ||
2160 | return -EINVAL; | ||
2161 | } | ||
2162 | |||
2163 | memset(buf, 0, 8); | ||
2164 | buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ | ||
2165 | store_cdrom_address(&buf[4], msf, lba); | ||
2166 | return 8; | ||
2167 | } | ||
2168 | |||
2169 | |||
2170 | static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh) | ||
2171 | { | ||
2172 | struct lun *curlun = fsg->curlun; | ||
2173 | int msf = fsg->cmnd[1] & 0x02; | ||
2174 | int start_track = fsg->cmnd[6]; | ||
2175 | u8 *buf = (u8 *) bh->buf; | ||
2176 | |||
2177 | if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ | ||
2178 | start_track > 1) { | ||
2179 | curlun->sense_data = SS_INVALID_FIELD_IN_CDB; | ||
2180 | return -EINVAL; | ||
2181 | } | ||
2182 | |||
2183 | memset(buf, 0, 20); | ||
2184 | buf[1] = (20-2); /* TOC data length */ | ||
2185 | buf[2] = 1; /* First track number */ | ||
2186 | buf[3] = 1; /* Last track number */ | ||
2187 | buf[5] = 0x16; /* Data track, copying allowed */ | ||
2188 | buf[6] = 0x01; /* Only track is number 1 */ | ||
2189 | store_cdrom_address(&buf[8], msf, 0); | ||
2190 | |||
2191 | buf[13] = 0x16; /* Lead-out track is data */ | ||
2192 | buf[14] = 0xAA; /* Lead-out track number */ | ||
2193 | store_cdrom_address(&buf[16], msf, curlun->num_sectors); | ||
2194 | return 20; | ||
2195 | } | ||
2196 | |||
2197 | |||
2104 | static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) | 2198 | static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) |
2105 | { | 2199 | { |
2106 | struct lun *curlun = fsg->curlun; | 2200 | struct lun *curlun = fsg->curlun; |
@@ -2848,6 +2942,26 @@ static int do_scsi_command(struct fsg_dev *fsg) | |||
2848 | reply = do_read_capacity(fsg, bh); | 2942 | reply = do_read_capacity(fsg, bh); |
2849 | break; | 2943 | break; |
2850 | 2944 | ||
2945 | case SC_READ_HEADER: | ||
2946 | if (!mod_data.cdrom) | ||
2947 | goto unknown_cmnd; | ||
2948 | fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); | ||
2949 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | ||
2950 | (3<<7) | (0x1f<<1), 1, | ||
2951 | "READ HEADER")) == 0) | ||
2952 | reply = do_read_header(fsg, bh); | ||
2953 | break; | ||
2954 | |||
2955 | case SC_READ_TOC: | ||
2956 | if (!mod_data.cdrom) | ||
2957 | goto unknown_cmnd; | ||
2958 | fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); | ||
2959 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | ||
2960 | (7<<6) | (1<<1), 1, | ||
2961 | "READ TOC")) == 0) | ||
2962 | reply = do_read_toc(fsg, bh); | ||
2963 | break; | ||
2964 | |||
2851 | case SC_READ_FORMAT_CAPACITIES: | 2965 | case SC_READ_FORMAT_CAPACITIES: |
2852 | fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); | 2966 | fsg->data_size_from_cmnd = get_be16(&fsg->cmnd[7]); |
2853 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, | 2967 | if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, |
@@ -2933,6 +3047,7 @@ static int do_scsi_command(struct fsg_dev *fsg) | |||
2933 | // Fall through | 3047 | // Fall through |
2934 | 3048 | ||
2935 | default: | 3049 | default: |
3050 | unknown_cmnd: | ||
2936 | fsg->data_size_from_cmnd = 0; | 3051 | fsg->data_size_from_cmnd = 0; |
2937 | sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); | 3052 | sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); |
2938 | if ((reply = check_command(fsg, fsg->cmnd_size, | 3053 | if ((reply = check_command(fsg, fsg->cmnd_size, |
@@ -3498,6 +3613,7 @@ static int open_backing_file(struct lun *curlun, const char *filename) | |||
3498 | struct inode *inode = NULL; | 3613 | struct inode *inode = NULL; |
3499 | loff_t size; | 3614 | loff_t size; |
3500 | loff_t num_sectors; | 3615 | loff_t num_sectors; |
3616 | loff_t min_sectors; | ||
3501 | 3617 | ||
3502 | /* R/W if we can, R/O if we must */ | 3618 | /* R/W if we can, R/O if we must */ |
3503 | ro = curlun->ro; | 3619 | ro = curlun->ro; |
@@ -3541,8 +3657,19 @@ static int open_backing_file(struct lun *curlun, const char *filename) | |||
3541 | rc = (int) size; | 3657 | rc = (int) size; |
3542 | goto out; | 3658 | goto out; |
3543 | } | 3659 | } |
3544 | num_sectors = size >> 9; // File size in 512-byte sectors | 3660 | num_sectors = size >> 9; // File size in 512-byte blocks |
3545 | if (num_sectors == 0) { | 3661 | min_sectors = 1; |
3662 | if (mod_data.cdrom) { | ||
3663 | num_sectors &= ~3; // Reduce to a multiple of 2048 | ||
3664 | min_sectors = 300*4; // Smallest track is 300 frames | ||
3665 | if (num_sectors >= 256*60*75*4) { | ||
3666 | num_sectors = (256*60*75 - 1) * 4; | ||
3667 | LINFO(curlun, "file too big: %s\n", filename); | ||
3668 | LINFO(curlun, "using only first %d blocks\n", | ||
3669 | (int) num_sectors); | ||
3670 | } | ||
3671 | } | ||
3672 | if (num_sectors < min_sectors) { | ||
3546 | LINFO(curlun, "file too small: %s\n", filename); | 3673 | LINFO(curlun, "file too small: %s\n", filename); |
3547 | rc = -ETOOSMALL; | 3674 | rc = -ETOOSMALL; |
3548 | goto out; | 3675 | goto out; |
@@ -3845,9 +3972,12 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3845 | goto out; | 3972 | goto out; |
3846 | 3973 | ||
3847 | if (mod_data.removable) { // Enable the store_xxx attributes | 3974 | if (mod_data.removable) { // Enable the store_xxx attributes |
3848 | dev_attr_ro.attr.mode = dev_attr_file.attr.mode = 0644; | 3975 | dev_attr_file.attr.mode = 0644; |
3849 | dev_attr_ro.store = store_ro; | ||
3850 | dev_attr_file.store = store_file; | 3976 | dev_attr_file.store = store_file; |
3977 | if (!mod_data.cdrom) { | ||
3978 | dev_attr_ro.attr.mode = 0644; | ||
3979 | dev_attr_ro.store = store_ro; | ||
3980 | } | ||
3851 | } | 3981 | } |
3852 | 3982 | ||
3853 | /* Find out how many LUNs there should be */ | 3983 | /* Find out how many LUNs there should be */ |
@@ -3872,6 +4002,8 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3872 | for (i = 0; i < fsg->nluns; ++i) { | 4002 | for (i = 0; i < fsg->nluns; ++i) { |
3873 | curlun = &fsg->luns[i]; | 4003 | curlun = &fsg->luns[i]; |
3874 | curlun->ro = mod_data.ro[i]; | 4004 | curlun->ro = mod_data.ro[i]; |
4005 | if (mod_data.cdrom) | ||
4006 | curlun->ro = 1; | ||
3875 | curlun->dev.release = lun_release; | 4007 | curlun->dev.release = lun_release; |
3876 | curlun->dev.parent = &gadget->dev; | 4008 | curlun->dev.parent = &gadget->dev; |
3877 | curlun->dev.driver = &fsg_driver.driver; | 4009 | curlun->dev.driver = &fsg_driver.driver; |
@@ -4031,9 +4163,9 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
4031 | mod_data.protocol_name, mod_data.protocol_type); | 4163 | mod_data.protocol_name, mod_data.protocol_type); |
4032 | DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n", | 4164 | DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n", |
4033 | mod_data.vendor, mod_data.product, mod_data.release); | 4165 | mod_data.vendor, mod_data.product, mod_data.release); |
4034 | DBG(fsg, "removable=%d, stall=%d, buflen=%u\n", | 4166 | DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n", |
4035 | mod_data.removable, mod_data.can_stall, | 4167 | mod_data.removable, mod_data.can_stall, |
4036 | mod_data.buflen); | 4168 | mod_data.cdrom, mod_data.buflen); |
4037 | DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task)); | 4169 | DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task)); |
4038 | 4170 | ||
4039 | set_bit(REGISTERED, &fsg->atomic_bitflags); | 4171 | set_bit(REGISTERED, &fsg->atomic_bitflags); |
@@ -4050,6 +4182,7 @@ out: | |||
4050 | fsg->state = FSG_STATE_TERMINATED; // The thread is dead | 4182 | fsg->state = FSG_STATE_TERMINATED; // The thread is dead |
4051 | fsg_unbind(gadget); | 4183 | fsg_unbind(gadget); |
4052 | close_all_backing_files(fsg); | 4184 | close_all_backing_files(fsg); |
4185 | complete(&fsg->thread_notifier); | ||
4053 | return rc; | 4186 | return rc; |
4054 | } | 4187 | } |
4055 | 4188 | ||
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index f40272565098..d6c5bcd40064 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/ioport.h> | 26 | #include <linux/ioport.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
29 | #include <linux/err.h> | ||
29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
30 | #include <linux/list.h> | 31 | #include <linux/list.h> |
31 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
@@ -370,6 +371,9 @@ static int qe_ep_bd_init(struct qe_udc *udc, unsigned char pipe_num) | |||
370 | /* alloc multi-ram for BD rings and set the ep parameters */ | 371 | /* alloc multi-ram for BD rings and set the ep parameters */ |
371 | tmp_addr = cpm_muram_alloc(sizeof(struct qe_bd) * (bdring_len + | 372 | tmp_addr = cpm_muram_alloc(sizeof(struct qe_bd) * (bdring_len + |
372 | USB_BDRING_LEN_TX), QE_ALIGNMENT_OF_BD); | 373 | USB_BDRING_LEN_TX), QE_ALIGNMENT_OF_BD); |
374 | if (IS_ERR_VALUE(tmp_addr)) | ||
375 | return -ENOMEM; | ||
376 | |||
373 | out_be16(&epparam->rbase, (u16)tmp_addr); | 377 | out_be16(&epparam->rbase, (u16)tmp_addr); |
374 | out_be16(&epparam->tbase, (u16)(tmp_addr + | 378 | out_be16(&epparam->tbase, (u16)(tmp_addr + |
375 | (sizeof(struct qe_bd) * bdring_len))); | 379 | (sizeof(struct qe_bd) * bdring_len))); |
@@ -689,7 +693,7 @@ en_done2: | |||
689 | en_done1: | 693 | en_done1: |
690 | spin_unlock_irqrestore(&udc->lock, flags); | 694 | spin_unlock_irqrestore(&udc->lock, flags); |
691 | en_done: | 695 | en_done: |
692 | dev_dbg(udc->dev, "failed to initialize %s\n", ep->ep.name); | 696 | dev_err(udc->dev, "failed to initialize %s\n", ep->ep.name); |
693 | return -ENODEV; | 697 | return -ENODEV; |
694 | } | 698 | } |
695 | 699 | ||
@@ -2408,6 +2412,8 @@ static struct qe_udc __devinit *qe_udc_config(struct of_device *ofdev) | |||
2408 | tmp_addr = cpm_muram_alloc((USB_MAX_ENDPOINTS * | 2412 | tmp_addr = cpm_muram_alloc((USB_MAX_ENDPOINTS * |
2409 | sizeof(struct usb_ep_para)), | 2413 | sizeof(struct usb_ep_para)), |
2410 | USB_EP_PARA_ALIGNMENT); | 2414 | USB_EP_PARA_ALIGNMENT); |
2415 | if (IS_ERR_VALUE(tmp_addr)) | ||
2416 | goto cleanup; | ||
2411 | 2417 | ||
2412 | for (i = 0; i < USB_MAX_ENDPOINTS; i++) { | 2418 | for (i = 0; i < USB_MAX_ENDPOINTS; i++) { |
2413 | out_be16(&usbpram->epptr[i], (u16)tmp_addr); | 2419 | out_be16(&usbpram->epptr[i], (u16)tmp_addr); |
@@ -2513,7 +2519,7 @@ static int __devinit qe_udc_probe(struct of_device *ofdev, | |||
2513 | /* Initialize the udc structure including QH member and other member */ | 2519 | /* Initialize the udc structure including QH member and other member */ |
2514 | udc_controller = qe_udc_config(ofdev); | 2520 | udc_controller = qe_udc_config(ofdev); |
2515 | if (!udc_controller) { | 2521 | if (!udc_controller) { |
2516 | dev_dbg(&ofdev->dev, "udc_controll is NULL\n"); | 2522 | dev_err(&ofdev->dev, "failed to initialize\n"); |
2517 | return -ENOMEM; | 2523 | return -ENOMEM; |
2518 | } | 2524 | } |
2519 | 2525 | ||
@@ -2568,7 +2574,7 @@ static int __devinit qe_udc_probe(struct of_device *ofdev, | |||
2568 | /* create a buf for ZLP send, need to remain zeroed */ | 2574 | /* create a buf for ZLP send, need to remain zeroed */ |
2569 | udc_controller->nullbuf = kzalloc(256, GFP_KERNEL); | 2575 | udc_controller->nullbuf = kzalloc(256, GFP_KERNEL); |
2570 | if (udc_controller->nullbuf == NULL) { | 2576 | if (udc_controller->nullbuf == NULL) { |
2571 | dev_dbg(udc_controller->dev, "cannot alloc nullbuf\n"); | 2577 | dev_err(udc_controller->dev, "cannot alloc nullbuf\n"); |
2572 | ret = -ENOMEM; | 2578 | ret = -ENOMEM; |
2573 | goto err3; | 2579 | goto err3; |
2574 | } | 2580 | } |
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 4e3107dd2f34..ec6d439a2aa5 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h | |||
@@ -110,7 +110,6 @@ | |||
110 | #define gadget_is_at91(g) 0 | 110 | #define gadget_is_at91(g) 0 |
111 | #endif | 111 | #endif |
112 | 112 | ||
113 | /* status unclear */ | ||
114 | #ifdef CONFIG_USB_GADGET_IMX | 113 | #ifdef CONFIG_USB_GADGET_IMX |
115 | #define gadget_is_imx(g) !strcmp("imx_udc", (g)->name) | 114 | #define gadget_is_imx(g) !strcmp("imx_udc", (g)->name) |
116 | #else | 115 | #else |
@@ -158,6 +157,11 @@ | |||
158 | #define gadget_is_fsl_qe(g) 0 | 157 | #define gadget_is_fsl_qe(g) 0 |
159 | #endif | 158 | #endif |
160 | 159 | ||
160 | #ifdef CONFIG_USB_GADGET_CI13XXX | ||
161 | #define gadget_is_ci13xxx(g) (!strcmp("ci13xxx_udc", (g)->name)) | ||
162 | #else | ||
163 | #define gadget_is_ci13xxx(g) 0 | ||
164 | #endif | ||
161 | 165 | ||
162 | // CONFIG_USB_GADGET_SX2 | 166 | // CONFIG_USB_GADGET_SX2 |
163 | // CONFIG_USB_GADGET_AU1X00 | 167 | // CONFIG_USB_GADGET_AU1X00 |
@@ -225,6 +229,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) | |||
225 | return 0x21; | 229 | return 0x21; |
226 | else if (gadget_is_fsl_qe(gadget)) | 230 | else if (gadget_is_fsl_qe(gadget)) |
227 | return 0x22; | 231 | return 0x22; |
232 | else if (gadget_is_ci13xxx(gadget)) | ||
233 | return 0x23; | ||
228 | return -ENOENT; | 234 | return -ENOENT; |
229 | } | 235 | } |
230 | 236 | ||
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 60aa04847b18..63419c4d503c 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
@@ -1349,7 +1349,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) | |||
1349 | int retval; | 1349 | int retval; |
1350 | 1350 | ||
1351 | if (!driver | 1351 | if (!driver |
1352 | || driver->speed != USB_SPEED_FULL | 1352 | || driver->speed < USB_SPEED_FULL |
1353 | || !driver->bind | 1353 | || !driver->bind |
1354 | || !driver->disconnect | 1354 | || !driver->disconnect |
1355 | || !driver->setup) | 1355 | || !driver->setup) |
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c new file mode 100644 index 000000000000..cde8fdf15d5b --- /dev/null +++ b/drivers/usb/gadget/imx_udc.c | |||
@@ -0,0 +1,1516 @@ | |||
1 | /* | ||
2 | * driver/usb/gadget/imx_udc.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Mike Lee(eemike@gmail.com) | ||
5 | * Copyright (C) 2008 Darius Augulis <augulis.darius@gmail.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/init.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/device.h> | ||
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/clk.h> | ||
30 | #include <linux/delay.h> | ||
31 | |||
32 | #include <linux/usb/ch9.h> | ||
33 | #include <linux/usb/gadget.h> | ||
34 | |||
35 | #include <mach/usb.h> | ||
36 | #include <mach/hardware.h> | ||
37 | |||
38 | #include "imx_udc.h" | ||
39 | |||
40 | static const char driver_name[] = "imx_udc"; | ||
41 | static const char ep0name[] = "ep0"; | ||
42 | |||
43 | void ep0_chg_stat(const char *label, struct imx_udc_struct *imx_usb, | ||
44 | enum ep0_state stat); | ||
45 | |||
46 | /******************************************************************************* | ||
47 | * IMX UDC hardware related functions | ||
48 | ******************************************************************************* | ||
49 | */ | ||
50 | |||
51 | void imx_udc_enable(struct imx_udc_struct *imx_usb) | ||
52 | { | ||
53 | int temp = __raw_readl(imx_usb->base + USB_CTRL); | ||
54 | __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, imx_usb->base + USB_CTRL); | ||
55 | imx_usb->gadget.speed = USB_SPEED_FULL; | ||
56 | } | ||
57 | |||
58 | void imx_udc_disable(struct imx_udc_struct *imx_usb) | ||
59 | { | ||
60 | int temp = __raw_readl(imx_usb->base + USB_CTRL); | ||
61 | |||
62 | __raw_writel(temp & ~(CTRL_FE_ENA | CTRL_AFE_ENA), | ||
63 | imx_usb->base + USB_CTRL); | ||
64 | |||
65 | ep0_chg_stat(__func__, imx_usb, EP0_IDLE); | ||
66 | imx_usb->gadget.speed = USB_SPEED_UNKNOWN; | ||
67 | } | ||
68 | |||
69 | void imx_udc_reset(struct imx_udc_struct *imx_usb) | ||
70 | { | ||
71 | int temp = __raw_readl(imx_usb->base + USB_ENAB); | ||
72 | |||
73 | /* set RST bit */ | ||
74 | __raw_writel(temp | ENAB_RST, imx_usb->base + USB_ENAB); | ||
75 | |||
76 | /* wait RST bit to clear */ | ||
77 | do {} while (__raw_readl(imx_usb->base + USB_ENAB) & ENAB_RST); | ||
78 | |||
79 | /* wait CFG bit to assert */ | ||
80 | do {} while (!(__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG)); | ||
81 | |||
82 | /* udc module is now ready */ | ||
83 | } | ||
84 | |||
85 | void imx_udc_config(struct imx_udc_struct *imx_usb) | ||
86 | { | ||
87 | u8 ep_conf[5]; | ||
88 | u8 i, j, cfg; | ||
89 | struct imx_ep_struct *imx_ep; | ||
90 | |||
91 | /* wait CFG bit to assert */ | ||
92 | do {} while (!(__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG)); | ||
93 | |||
94 | /* Download the endpoint buffer for endpoint 0. */ | ||
95 | for (j = 0; j < 5; j++) { | ||
96 | i = (j == 2 ? imx_usb->imx_ep[0].fifosize : 0x00); | ||
97 | __raw_writeb(i, imx_usb->base + USB_DDAT); | ||
98 | do {} while (__raw_readl(imx_usb->base + USB_DADR) & DADR_BSY); | ||
99 | } | ||
100 | |||
101 | /* Download the endpoint buffers for endpoints 1-5. | ||
102 | * We specify two configurations, one interface | ||
103 | */ | ||
104 | for (cfg = 1; cfg < 3; cfg++) { | ||
105 | for (i = 1; i < IMX_USB_NB_EP; i++) { | ||
106 | imx_ep = &imx_usb->imx_ep[i]; | ||
107 | /* EP no | Config no */ | ||
108 | ep_conf[0] = (i << 4) | (cfg << 2); | ||
109 | /* Type | Direction */ | ||
110 | ep_conf[1] = (imx_ep->bmAttributes << 3) | | ||
111 | (EP_DIR(imx_ep) << 2); | ||
112 | /* Max packet size */ | ||
113 | ep_conf[2] = imx_ep->fifosize; | ||
114 | /* TRXTYP */ | ||
115 | ep_conf[3] = 0xC0; | ||
116 | /* FIFO no */ | ||
117 | ep_conf[4] = i; | ||
118 | |||
119 | D_INI(imx_usb->dev, | ||
120 | "<%s> ep%d_conf[%d]:" | ||
121 | "[%02x-%02x-%02x-%02x-%02x]\n", | ||
122 | __func__, i, cfg, | ||
123 | ep_conf[0], ep_conf[1], ep_conf[2], | ||
124 | ep_conf[3], ep_conf[4]); | ||
125 | |||
126 | for (j = 0; j < 5; j++) { | ||
127 | __raw_writeb(ep_conf[j], | ||
128 | imx_usb->base + USB_DDAT); | ||
129 | do {} while (__raw_readl(imx_usb->base + USB_DADR) | ||
130 | & DADR_BSY); | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | |||
135 | /* wait CFG bit to clear */ | ||
136 | do {} while (__raw_readl(imx_usb->base + USB_DADR) & DADR_CFG); | ||
137 | } | ||
138 | |||
139 | void imx_udc_init_irq(struct imx_udc_struct *imx_usb) | ||
140 | { | ||
141 | int i; | ||
142 | |||
143 | /* Mask and clear all irqs */ | ||
144 | __raw_writel(0xFFFFFFFF, imx_usb->base + USB_MASK); | ||
145 | __raw_writel(0xFFFFFFFF, imx_usb->base + USB_INTR); | ||
146 | for (i = 0; i < IMX_USB_NB_EP; i++) { | ||
147 | __raw_writel(0x1FF, imx_usb->base + USB_EP_MASK(i)); | ||
148 | __raw_writel(0x1FF, imx_usb->base + USB_EP_INTR(i)); | ||
149 | } | ||
150 | |||
151 | /* Enable USB irqs */ | ||
152 | __raw_writel(INTR_MSOF | INTR_FRAME_MATCH, imx_usb->base + USB_MASK); | ||
153 | |||
154 | /* Enable EP0 irqs */ | ||
155 | __raw_writel(0x1FF & ~(EPINTR_DEVREQ | EPINTR_MDEVREQ | EPINTR_EOT | ||
156 | | EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL), | ||
157 | imx_usb->base + USB_EP_MASK(0)); | ||
158 | } | ||
159 | |||
160 | void imx_udc_init_ep(struct imx_udc_struct *imx_usb) | ||
161 | { | ||
162 | int i, max, temp; | ||
163 | struct imx_ep_struct *imx_ep; | ||
164 | for (i = 0; i < IMX_USB_NB_EP; i++) { | ||
165 | imx_ep = &imx_usb->imx_ep[i]; | ||
166 | switch (imx_ep->fifosize) { | ||
167 | case 8: | ||
168 | max = 0; | ||
169 | break; | ||
170 | case 16: | ||
171 | max = 1; | ||
172 | break; | ||
173 | case 32: | ||
174 | max = 2; | ||
175 | break; | ||
176 | case 64: | ||
177 | max = 3; | ||
178 | break; | ||
179 | default: | ||
180 | max = 1; | ||
181 | break; | ||
182 | } | ||
183 | temp = (EP_DIR(imx_ep) << 7) | (max << 5) | ||
184 | | (imx_ep->bmAttributes << 3); | ||
185 | __raw_writel(temp, imx_usb->base + USB_EP_STAT(i)); | ||
186 | __raw_writel(temp | EPSTAT_FLUSH, imx_usb->base + USB_EP_STAT(i)); | ||
187 | D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i, | ||
188 | __raw_readl(imx_usb->base + USB_EP_STAT(i))); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | void imx_udc_init_fifo(struct imx_udc_struct *imx_usb) | ||
193 | { | ||
194 | int i, temp; | ||
195 | struct imx_ep_struct *imx_ep; | ||
196 | for (i = 0; i < IMX_USB_NB_EP; i++) { | ||
197 | imx_ep = &imx_usb->imx_ep[i]; | ||
198 | |||
199 | /* Fifo control */ | ||
200 | temp = EP_DIR(imx_ep) ? 0x0B000000 : 0x0F000000; | ||
201 | __raw_writel(temp, imx_usb->base + USB_EP_FCTRL(i)); | ||
202 | D_INI(imx_usb->dev, "<%s> ep%d_fctrl %08x\n", __func__, i, | ||
203 | __raw_readl(imx_usb->base + USB_EP_FCTRL(i))); | ||
204 | |||
205 | /* Fifo alarm */ | ||
206 | temp = (i ? imx_ep->fifosize / 2 : 0); | ||
207 | __raw_writel(temp, imx_usb->base + USB_EP_FALRM(i)); | ||
208 | D_INI(imx_usb->dev, "<%s> ep%d_falrm %08x\n", __func__, i, | ||
209 | __raw_readl(imx_usb->base + USB_EP_FALRM(i))); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | static void imx_udc_init(struct imx_udc_struct *imx_usb) | ||
214 | { | ||
215 | /* Reset UDC */ | ||
216 | imx_udc_reset(imx_usb); | ||
217 | |||
218 | /* Download config to enpoint buffer */ | ||
219 | imx_udc_config(imx_usb); | ||
220 | |||
221 | /* Setup interrups */ | ||
222 | imx_udc_init_irq(imx_usb); | ||
223 | |||
224 | /* Setup endpoints */ | ||
225 | imx_udc_init_ep(imx_usb); | ||
226 | |||
227 | /* Setup fifos */ | ||
228 | imx_udc_init_fifo(imx_usb); | ||
229 | } | ||
230 | |||
231 | void imx_ep_irq_enable(struct imx_ep_struct *imx_ep) | ||
232 | { | ||
233 | |||
234 | int i = EP_NO(imx_ep); | ||
235 | |||
236 | __raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_MASK(i)); | ||
237 | __raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_INTR(i)); | ||
238 | __raw_writel(0x1FF & ~(EPINTR_EOT | EPINTR_EOF), | ||
239 | imx_ep->imx_usb->base + USB_EP_MASK(i)); | ||
240 | } | ||
241 | |||
242 | void imx_ep_irq_disable(struct imx_ep_struct *imx_ep) | ||
243 | { | ||
244 | |||
245 | int i = EP_NO(imx_ep); | ||
246 | |||
247 | __raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_MASK(i)); | ||
248 | __raw_writel(0x1FF, imx_ep->imx_usb->base + USB_EP_INTR(i)); | ||
249 | } | ||
250 | |||
251 | int imx_ep_empty(struct imx_ep_struct *imx_ep) | ||
252 | { | ||
253 | struct imx_udc_struct *imx_usb = imx_ep->imx_usb; | ||
254 | |||
255 | return __raw_readl(imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep))) | ||
256 | & FSTAT_EMPTY; | ||
257 | } | ||
258 | |||
259 | unsigned imx_fifo_bcount(struct imx_ep_struct *imx_ep) | ||
260 | { | ||
261 | struct imx_udc_struct *imx_usb = imx_ep->imx_usb; | ||
262 | |||
263 | return (__raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))) | ||
264 | & EPSTAT_BCOUNT) >> 16; | ||
265 | } | ||
266 | |||
267 | void imx_flush(struct imx_ep_struct *imx_ep) | ||
268 | { | ||
269 | struct imx_udc_struct *imx_usb = imx_ep->imx_usb; | ||
270 | |||
271 | int temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); | ||
272 | __raw_writel(temp | EPSTAT_FLUSH, | ||
273 | imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); | ||
274 | } | ||
275 | |||
276 | void imx_ep_stall(struct imx_ep_struct *imx_ep) | ||
277 | { | ||
278 | struct imx_udc_struct *imx_usb = imx_ep->imx_usb; | ||
279 | int temp, i; | ||
280 | |||
281 | D_ERR(imx_usb->dev, "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name); | ||
282 | |||
283 | imx_flush(imx_ep); | ||
284 | |||
285 | /* Special care for ep0 */ | ||
286 | if (EP_NO(imx_ep)) { | ||
287 | temp = __raw_readl(imx_usb->base + USB_CTRL); | ||
288 | __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL); | ||
289 | do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER); | ||
290 | temp = __raw_readl(imx_usb->base + USB_CTRL); | ||
291 | __raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL); | ||
292 | } | ||
293 | else { | ||
294 | temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); | ||
295 | __raw_writel(temp | EPSTAT_STALL, | ||
296 | imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); | ||
297 | |||
298 | for (i = 0; i < 100; i ++) { | ||
299 | temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); | ||
300 | if (!temp & EPSTAT_STALL) | ||
301 | break; | ||
302 | udelay(20); | ||
303 | } | ||
304 | if (i == 50) | ||
305 | D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n", | ||
306 | __func__, imx_ep->ep.name); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static int imx_udc_get_frame(struct usb_gadget *_gadget) | ||
311 | { | ||
312 | struct imx_udc_struct *imx_usb = container_of(_gadget, | ||
313 | struct imx_udc_struct, gadget); | ||
314 | |||
315 | return __raw_readl(imx_usb->base + USB_FRAME) & 0x7FF; | ||
316 | } | ||
317 | |||
318 | static int imx_udc_wakeup(struct usb_gadget *_gadget) | ||
319 | { | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | /******************************************************************************* | ||
324 | * USB request control functions | ||
325 | ******************************************************************************* | ||
326 | */ | ||
327 | |||
328 | static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req) | ||
329 | { | ||
330 | if (unlikely(!req)) | ||
331 | return; | ||
332 | |||
333 | req->in_use = 1; | ||
334 | list_add_tail(&req->queue, &imx_ep->queue); | ||
335 | } | ||
336 | |||
337 | static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req) | ||
338 | { | ||
339 | if (unlikely(!req)) | ||
340 | return; | ||
341 | |||
342 | list_del_init(&req->queue); | ||
343 | req->in_use = 0; | ||
344 | } | ||
345 | |||
346 | static void done(struct imx_ep_struct *imx_ep, struct imx_request *req, int status) | ||
347 | { | ||
348 | ep_del_request(imx_ep, req); | ||
349 | |||
350 | if (likely(req->req.status == -EINPROGRESS)) | ||
351 | req->req.status = status; | ||
352 | else | ||
353 | status = req->req.status; | ||
354 | |||
355 | if (status && status != -ESHUTDOWN) | ||
356 | D_ERR(imx_ep->imx_usb->dev, | ||
357 | "<%s> complete %s req %p stat %d len %u/%u\n", __func__, | ||
358 | imx_ep->ep.name, &req->req, status, | ||
359 | req->req.actual, req->req.length); | ||
360 | |||
361 | req->req.complete(&imx_ep->ep, &req->req); | ||
362 | } | ||
363 | |||
364 | static void nuke(struct imx_ep_struct *imx_ep, int status) | ||
365 | { | ||
366 | struct imx_request *req; | ||
367 | |||
368 | while (!list_empty(&imx_ep->queue)) { | ||
369 | req = list_entry(imx_ep->queue.next, struct imx_request, queue); | ||
370 | done(imx_ep, req, status); | ||
371 | } | ||
372 | } | ||
373 | |||
374 | /******************************************************************************* | ||
375 | * Data tansfer over USB functions | ||
376 | ******************************************************************************* | ||
377 | */ | ||
378 | static int read_packet(struct imx_ep_struct *imx_ep, struct imx_request *req) | ||
379 | { | ||
380 | u8 *buf; | ||
381 | int bytes_ep, bufferspace, count, i; | ||
382 | |||
383 | bytes_ep = imx_fifo_bcount(imx_ep); | ||
384 | bufferspace = req->req.length - req->req.actual; | ||
385 | |||
386 | buf = req->req.buf + req->req.actual; | ||
387 | prefetchw(buf); | ||
388 | |||
389 | if (unlikely(imx_ep_empty(imx_ep))) | ||
390 | count = 0; /* zlp */ | ||
391 | else | ||
392 | count = min(bytes_ep, bufferspace); | ||
393 | |||
394 | for (i = count; i > 0; i--) | ||
395 | *buf++ = __raw_readb(imx_ep->imx_usb->base | ||
396 | + USB_EP_FDAT0(EP_NO(imx_ep))); | ||
397 | req->req.actual += count; | ||
398 | |||
399 | return count; | ||
400 | } | ||
401 | |||
402 | static int write_packet(struct imx_ep_struct *imx_ep, struct imx_request *req) | ||
403 | { | ||
404 | u8 *buf; | ||
405 | int length, count, temp; | ||
406 | |||
407 | buf = req->req.buf + req->req.actual; | ||
408 | prefetch(buf); | ||
409 | |||
410 | length = min(req->req.length - req->req.actual, (u32)imx_ep->fifosize); | ||
411 | |||
412 | if (imx_fifo_bcount(imx_ep) + length > imx_ep->fifosize) { | ||
413 | D_TRX(imx_ep->imx_usb->dev, "<%s> packet overfill %s fifo\n", | ||
414 | __func__, imx_ep->ep.name); | ||
415 | return -1; | ||
416 | } | ||
417 | |||
418 | req->req.actual += length; | ||
419 | count = length; | ||
420 | |||
421 | if (!count && req->req.zero) { /* zlp */ | ||
422 | temp = __raw_readl(imx_ep->imx_usb->base | ||
423 | + USB_EP_STAT(EP_NO(imx_ep))); | ||
424 | __raw_writel(temp | EPSTAT_ZLPS, imx_ep->imx_usb->base | ||
425 | + USB_EP_STAT(EP_NO(imx_ep))); | ||
426 | D_TRX(imx_ep->imx_usb->dev, "<%s> zero packet\n", __func__); | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | while (count--) { | ||
431 | if (count == 0) { /* last byte */ | ||
432 | temp = __raw_readl(imx_ep->imx_usb->base | ||
433 | + USB_EP_FCTRL(EP_NO(imx_ep))); | ||
434 | __raw_writel(temp | FCTRL_WFR, imx_ep->imx_usb->base | ||
435 | + USB_EP_FCTRL(EP_NO(imx_ep))); | ||
436 | } | ||
437 | __raw_writeb(*buf++, | ||
438 | imx_ep->imx_usb->base + USB_EP_FDAT0(EP_NO(imx_ep))); | ||
439 | } | ||
440 | |||
441 | return length; | ||
442 | } | ||
443 | |||
444 | static int read_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req) | ||
445 | { | ||
446 | int bytes = 0, | ||
447 | count, | ||
448 | completed = 0; | ||
449 | |||
450 | while (__raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep))) | ||
451 | & FSTAT_FR) { | ||
452 | count = read_packet(imx_ep, req); | ||
453 | bytes += count; | ||
454 | |||
455 | completed = (count != imx_ep->fifosize); | ||
456 | if (completed || req->req.actual == req->req.length) { | ||
457 | completed = 1; | ||
458 | break; | ||
459 | } | ||
460 | } | ||
461 | |||
462 | if (completed || !req->req.length) { | ||
463 | done(imx_ep, req, 0); | ||
464 | D_REQ(imx_ep->imx_usb->dev, "<%s> %s req<%p> %s\n", | ||
465 | __func__, imx_ep->ep.name, req, | ||
466 | completed ? "completed" : "not completed"); | ||
467 | if (!EP_NO(imx_ep)) | ||
468 | ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE); | ||
469 | } | ||
470 | |||
471 | D_TRX(imx_ep->imx_usb->dev, "<%s> bytes read: %d\n", __func__, bytes); | ||
472 | |||
473 | return completed; | ||
474 | } | ||
475 | |||
476 | static int write_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req) | ||
477 | { | ||
478 | int bytes = 0, | ||
479 | count, | ||
480 | completed = 0; | ||
481 | |||
482 | while (!completed) { | ||
483 | count = write_packet(imx_ep, req); | ||
484 | if (count < 0) | ||
485 | break; /* busy */ | ||
486 | bytes += count; | ||
487 | |||
488 | /* last packet "must be" short (or a zlp) */ | ||
489 | completed = (count != imx_ep->fifosize); | ||
490 | |||
491 | if (unlikely(completed)) { | ||
492 | done(imx_ep, req, 0); | ||
493 | D_REQ(imx_ep->imx_usb->dev, "<%s> %s req<%p> %s\n", | ||
494 | __func__, imx_ep->ep.name, req, | ||
495 | completed ? "completed" : "not completed"); | ||
496 | if (!EP_NO(imx_ep)) | ||
497 | ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE); | ||
498 | } | ||
499 | } | ||
500 | |||
501 | D_TRX(imx_ep->imx_usb->dev, "<%s> bytes sent: %d\n", __func__, bytes); | ||
502 | |||
503 | return completed; | ||
504 | } | ||
505 | |||
506 | /******************************************************************************* | ||
507 | * Endpoint handlers | ||
508 | ******************************************************************************* | ||
509 | */ | ||
510 | static int handle_ep(struct imx_ep_struct *imx_ep) | ||
511 | { | ||
512 | struct imx_request *req; | ||
513 | int completed = 0; | ||
514 | |||
515 | do { | ||
516 | if (!list_empty(&imx_ep->queue)) | ||
517 | req = list_entry(imx_ep->queue.next, | ||
518 | struct imx_request, queue); | ||
519 | else { | ||
520 | D_REQ(imx_ep->imx_usb->dev, "<%s> no request on %s\n", | ||
521 | __func__, imx_ep->ep.name); | ||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | if (EP_DIR(imx_ep)) /* to host */ | ||
526 | completed = write_fifo(imx_ep, req); | ||
527 | else /* to device */ | ||
528 | completed = read_fifo(imx_ep, req); | ||
529 | |||
530 | dump_ep_stat(__func__, imx_ep); | ||
531 | |||
532 | } while (completed); | ||
533 | |||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | static int handle_ep0(struct imx_ep_struct *imx_ep) | ||
538 | { | ||
539 | struct imx_request *req = NULL; | ||
540 | int ret = 0; | ||
541 | |||
542 | if (!list_empty(&imx_ep->queue)) | ||
543 | req = list_entry(imx_ep->queue.next, struct imx_request, queue); | ||
544 | |||
545 | if (req) { | ||
546 | switch (imx_ep->imx_usb->ep0state) { | ||
547 | |||
548 | case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR */ | ||
549 | write_fifo(imx_ep, req); | ||
550 | break; | ||
551 | case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR */ | ||
552 | read_fifo(imx_ep, req); | ||
553 | break; | ||
554 | default: | ||
555 | D_EP0(imx_ep->imx_usb->dev, | ||
556 | "<%s> ep0 i/o, odd state %d\n", | ||
557 | __func__, imx_ep->imx_usb->ep0state); | ||
558 | ep_del_request(imx_ep, req); | ||
559 | ret = -EL2HLT; | ||
560 | break; | ||
561 | } | ||
562 | } | ||
563 | |||
564 | return ret; | ||
565 | } | ||
566 | |||
567 | static void handle_ep0_devreq(struct imx_udc_struct *imx_usb) | ||
568 | { | ||
569 | struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0]; | ||
570 | union { | ||
571 | struct usb_ctrlrequest r; | ||
572 | u8 raw[8]; | ||
573 | u32 word[2]; | ||
574 | } u; | ||
575 | int temp, i; | ||
576 | |||
577 | nuke(imx_ep, -EPROTO); | ||
578 | |||
579 | /* read SETUP packet */ | ||
580 | for (i = 0; i < 2; i++) { | ||
581 | if (imx_ep_empty(imx_ep)) { | ||
582 | D_ERR(imx_usb->dev, | ||
583 | "<%s> no setup packet received\n", __func__); | ||
584 | goto stall; | ||
585 | } | ||
586 | u.word[i] = __raw_readl(imx_usb->base + USB_EP_FDAT(EP_NO(imx_ep))); | ||
587 | } | ||
588 | |||
589 | temp = imx_ep_empty(imx_ep); | ||
590 | while (!imx_ep_empty(imx_ep)) { | ||
591 | i = __raw_readl(imx_usb->base + USB_EP_FDAT(EP_NO(imx_ep))); | ||
592 | D_ERR(imx_usb->dev, | ||
593 | "<%s> wrong to have extra bytes for setup : 0x%08x\n", | ||
594 | __func__, i); | ||
595 | } | ||
596 | if (!temp) | ||
597 | goto stall; | ||
598 | |||
599 | le16_to_cpus(&u.r.wValue); | ||
600 | le16_to_cpus(&u.r.wIndex); | ||
601 | le16_to_cpus(&u.r.wLength); | ||
602 | |||
603 | D_REQ(imx_usb->dev, "<%s> SETUP %02x.%02x v%04x i%04x l%04x\n", | ||
604 | __func__, u.r.bRequestType, u.r.bRequest, | ||
605 | u.r.wValue, u.r.wIndex, u.r.wLength); | ||
606 | |||
607 | if (imx_usb->set_config) { | ||
608 | /* NACK the host by using CMDOVER */ | ||
609 | temp = __raw_readl(imx_usb->base + USB_CTRL); | ||
610 | __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL); | ||
611 | |||
612 | D_ERR(imx_usb->dev, | ||
613 | "<%s> set config req is pending, NACK the host\n", | ||
614 | __func__); | ||
615 | return; | ||
616 | } | ||
617 | |||
618 | if (u.r.bRequestType & USB_DIR_IN) | ||
619 | ep0_chg_stat(__func__, imx_usb, EP0_IN_DATA_PHASE); | ||
620 | else | ||
621 | ep0_chg_stat(__func__, imx_usb, EP0_OUT_DATA_PHASE); | ||
622 | |||
623 | i = imx_usb->driver->setup(&imx_usb->gadget, &u.r); | ||
624 | if (i < 0) { | ||
625 | D_ERR(imx_usb->dev, "<%s> device setup error %d\n", | ||
626 | __func__, i); | ||
627 | goto stall; | ||
628 | } | ||
629 | |||
630 | return; | ||
631 | stall: | ||
632 | D_ERR(imx_usb->dev, "<%s> protocol STALL\n", __func__); | ||
633 | imx_ep_stall(imx_ep); | ||
634 | ep0_chg_stat(__func__, imx_usb, EP0_STALL); | ||
635 | return; | ||
636 | } | ||
637 | |||
638 | /******************************************************************************* | ||
639 | * USB gadget callback functions | ||
640 | ******************************************************************************* | ||
641 | */ | ||
642 | |||
643 | static int imx_ep_enable(struct usb_ep *usb_ep, | ||
644 | const struct usb_endpoint_descriptor *desc) | ||
645 | { | ||
646 | struct imx_ep_struct *imx_ep = container_of(usb_ep, | ||
647 | struct imx_ep_struct, ep); | ||
648 | struct imx_udc_struct *imx_usb = imx_ep->imx_usb; | ||
649 | unsigned long flags; | ||
650 | |||
651 | if (!usb_ep | ||
652 | || !desc | ||
653 | || !EP_NO(imx_ep) | ||
654 | || desc->bDescriptorType != USB_DT_ENDPOINT | ||
655 | || imx_ep->bEndpointAddress != desc->bEndpointAddress) { | ||
656 | D_ERR(imx_usb->dev, | ||
657 | "<%s> bad ep or descriptor\n", __func__); | ||
658 | return -EINVAL; | ||
659 | } | ||
660 | |||
661 | if (imx_ep->bmAttributes != desc->bmAttributes) { | ||
662 | D_ERR(imx_usb->dev, | ||
663 | "<%s> %s type mismatch\n", __func__, usb_ep->name); | ||
664 | return -EINVAL; | ||
665 | } | ||
666 | |||
667 | if (imx_ep->fifosize < le16_to_cpu(desc->wMaxPacketSize)) { | ||
668 | D_ERR(imx_usb->dev, | ||
669 | "<%s> bad %s maxpacket\n", __func__, usb_ep->name); | ||
670 | return -ERANGE; | ||
671 | } | ||
672 | |||
673 | if (!imx_usb->driver || imx_usb->gadget.speed == USB_SPEED_UNKNOWN) { | ||
674 | D_ERR(imx_usb->dev, "<%s> bogus device state\n", __func__); | ||
675 | return -ESHUTDOWN; | ||
676 | } | ||
677 | |||
678 | local_irq_save(flags); | ||
679 | |||
680 | imx_ep->stopped = 0; | ||
681 | imx_flush(imx_ep); | ||
682 | imx_ep_irq_enable(imx_ep); | ||
683 | |||
684 | local_irq_restore(flags); | ||
685 | |||
686 | D_EPX(imx_usb->dev, "<%s> ENABLED %s\n", __func__, usb_ep->name); | ||
687 | return 0; | ||
688 | } | ||
689 | |||
690 | static int imx_ep_disable(struct usb_ep *usb_ep) | ||
691 | { | ||
692 | struct imx_ep_struct *imx_ep = container_of(usb_ep, | ||
693 | struct imx_ep_struct, ep); | ||
694 | unsigned long flags; | ||
695 | |||
696 | if (!usb_ep || !EP_NO(imx_ep) || !list_empty(&imx_ep->queue)) { | ||
697 | D_ERR(imx_ep->imx_usb->dev, "<%s> %s can not be disabled\n", | ||
698 | __func__, usb_ep ? imx_ep->ep.name : NULL); | ||
699 | return -EINVAL; | ||
700 | } | ||
701 | |||
702 | local_irq_save(flags); | ||
703 | |||
704 | imx_ep->stopped = 1; | ||
705 | nuke(imx_ep, -ESHUTDOWN); | ||
706 | imx_flush(imx_ep); | ||
707 | imx_ep_irq_disable(imx_ep); | ||
708 | |||
709 | local_irq_restore(flags); | ||
710 | |||
711 | D_EPX(imx_ep->imx_usb->dev, | ||
712 | "<%s> DISABLED %s\n", __func__, usb_ep->name); | ||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | static struct usb_request *imx_ep_alloc_request | ||
717 | (struct usb_ep *usb_ep, gfp_t gfp_flags) | ||
718 | { | ||
719 | struct imx_request *req; | ||
720 | |||
721 | req = kzalloc(sizeof *req, gfp_flags); | ||
722 | if (!req || !usb_ep) | ||
723 | return 0; | ||
724 | |||
725 | INIT_LIST_HEAD(&req->queue); | ||
726 | req->in_use = 0; | ||
727 | |||
728 | return &req->req; | ||
729 | } | ||
730 | |||
731 | static void imx_ep_free_request | ||
732 | (struct usb_ep *usb_ep, struct usb_request *usb_req) | ||
733 | { | ||
734 | struct imx_request *req; | ||
735 | |||
736 | req = container_of(usb_req, struct imx_request, req); | ||
737 | WARN_ON(!list_empty(&req->queue)); | ||
738 | kfree(req); | ||
739 | } | ||
740 | |||
741 | static int imx_ep_queue | ||
742 | (struct usb_ep *usb_ep, struct usb_request *usb_req, gfp_t gfp_flags) | ||
743 | { | ||
744 | struct imx_ep_struct *imx_ep; | ||
745 | struct imx_udc_struct *imx_usb; | ||
746 | struct imx_request *req; | ||
747 | unsigned long flags; | ||
748 | int ret = 0; | ||
749 | |||
750 | imx_ep = container_of(usb_ep, struct imx_ep_struct, ep); | ||
751 | imx_usb = imx_ep->imx_usb; | ||
752 | req = container_of(usb_req, struct imx_request, req); | ||
753 | |||
754 | /* | ||
755 | Special care on IMX udc. | ||
756 | Ignore enqueue when after set configuration from the | ||
757 | host. This assume all gadget drivers reply set | ||
758 | configuration with the next ep0 req enqueue. | ||
759 | */ | ||
760 | if (imx_usb->set_config && !EP_NO(imx_ep)) { | ||
761 | imx_usb->set_config = 0; | ||
762 | D_EPX(imx_usb->dev, | ||
763 | "<%s> gadget reply set config\n", __func__); | ||
764 | return 0; | ||
765 | } | ||
766 | |||
767 | if (unlikely(!usb_req || !req || !usb_req->complete || !usb_req->buf)) { | ||
768 | D_ERR(imx_usb->dev, "<%s> bad params\n", __func__); | ||
769 | return -EINVAL; | ||
770 | } | ||
771 | |||
772 | if (unlikely(!usb_ep || !imx_ep)) { | ||
773 | D_ERR(imx_usb->dev, "<%s> bad ep\n", __func__); | ||
774 | return -EINVAL; | ||
775 | } | ||
776 | |||
777 | if (!imx_usb->driver || imx_usb->gadget.speed == USB_SPEED_UNKNOWN) { | ||
778 | D_ERR(imx_usb->dev, "<%s> bogus device state\n", __func__); | ||
779 | return -ESHUTDOWN; | ||
780 | } | ||
781 | |||
782 | local_irq_save(flags); | ||
783 | |||
784 | /* Debug */ | ||
785 | D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n", | ||
786 | __func__, EP_NO(imx_ep), | ||
787 | ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) | ||
788 | || (EP_NO(imx_ep) && EP_DIR(imx_ep))) ? "IN" : "OUT", usb_req->length); | ||
789 | dump_req(__func__, imx_ep, usb_req); | ||
790 | |||
791 | if (imx_ep->stopped) { | ||
792 | usb_req->status = -ESHUTDOWN; | ||
793 | ret = -ESHUTDOWN; | ||
794 | goto out; | ||
795 | } | ||
796 | |||
797 | if (req->in_use) { | ||
798 | D_ERR(imx_usb->dev, | ||
799 | "<%s> refusing to queue req %p (already queued)\n", | ||
800 | __func__, req); | ||
801 | goto out; | ||
802 | } | ||
803 | |||
804 | usb_req->status = -EINPROGRESS; | ||
805 | usb_req->actual = 0; | ||
806 | |||
807 | ep_add_request(imx_ep, req); | ||
808 | |||
809 | if (!EP_NO(imx_ep)) | ||
810 | ret = handle_ep0(imx_ep); | ||
811 | else | ||
812 | ret = handle_ep(imx_ep); | ||
813 | out: | ||
814 | local_irq_restore(flags); | ||
815 | return ret; | ||
816 | } | ||
817 | |||
818 | static int imx_ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req) | ||
819 | { | ||
820 | |||
821 | struct imx_ep_struct *imx_ep = container_of | ||
822 | (usb_ep, struct imx_ep_struct, ep); | ||
823 | struct imx_request *req; | ||
824 | unsigned long flags; | ||
825 | |||
826 | if (unlikely(!usb_ep || !EP_NO(imx_ep))) { | ||
827 | D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__); | ||
828 | return -EINVAL; | ||
829 | } | ||
830 | |||
831 | local_irq_save(flags); | ||
832 | |||
833 | /* make sure it's actually queued on this endpoint */ | ||
834 | list_for_each_entry(req, &imx_ep->queue, queue) { | ||
835 | if (&req->req == usb_req) | ||
836 | break; | ||
837 | } | ||
838 | if (&req->req != usb_req) { | ||
839 | local_irq_restore(flags); | ||
840 | return -EINVAL; | ||
841 | } | ||
842 | |||
843 | done(imx_ep, req, -ECONNRESET); | ||
844 | |||
845 | local_irq_restore(flags); | ||
846 | return 0; | ||
847 | } | ||
848 | |||
849 | static int imx_ep_set_halt(struct usb_ep *usb_ep, int value) | ||
850 | { | ||
851 | struct imx_ep_struct *imx_ep = container_of | ||
852 | (usb_ep, struct imx_ep_struct, ep); | ||
853 | unsigned long flags; | ||
854 | |||
855 | if (unlikely(!usb_ep || !EP_NO(imx_ep))) { | ||
856 | D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__); | ||
857 | return -EINVAL; | ||
858 | } | ||
859 | |||
860 | local_irq_save(flags); | ||
861 | |||
862 | if ((imx_ep->bEndpointAddress & USB_DIR_IN) | ||
863 | && !list_empty(&imx_ep->queue)) { | ||
864 | local_irq_restore(flags); | ||
865 | return -EAGAIN; | ||
866 | } | ||
867 | |||
868 | imx_ep_stall(imx_ep); | ||
869 | |||
870 | local_irq_restore(flags); | ||
871 | |||
872 | D_EPX(imx_ep->imx_usb->dev, "<%s> %s halt\n", __func__, usb_ep->name); | ||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | static int imx_ep_fifo_status(struct usb_ep *usb_ep) | ||
877 | { | ||
878 | struct imx_ep_struct *imx_ep = container_of | ||
879 | (usb_ep, struct imx_ep_struct, ep); | ||
880 | |||
881 | if (!usb_ep) { | ||
882 | D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__); | ||
883 | return -ENODEV; | ||
884 | } | ||
885 | |||
886 | if (imx_ep->imx_usb->gadget.speed == USB_SPEED_UNKNOWN) | ||
887 | return 0; | ||
888 | else | ||
889 | return imx_fifo_bcount(imx_ep); | ||
890 | } | ||
891 | |||
892 | static void imx_ep_fifo_flush(struct usb_ep *usb_ep) | ||
893 | { | ||
894 | struct imx_ep_struct *imx_ep = container_of | ||
895 | (usb_ep, struct imx_ep_struct, ep); | ||
896 | unsigned long flags; | ||
897 | |||
898 | local_irq_save(flags); | ||
899 | |||
900 | if (!usb_ep || !EP_NO(imx_ep) || !list_empty(&imx_ep->queue)) { | ||
901 | D_ERR(imx_ep->imx_usb->dev, "<%s> bad ep\n", __func__); | ||
902 | local_irq_restore(flags); | ||
903 | return; | ||
904 | } | ||
905 | |||
906 | /* toggle and halt bits stay unchanged */ | ||
907 | imx_flush(imx_ep); | ||
908 | |||
909 | local_irq_restore(flags); | ||
910 | } | ||
911 | |||
912 | static struct usb_ep_ops imx_ep_ops = { | ||
913 | .enable = imx_ep_enable, | ||
914 | .disable = imx_ep_disable, | ||
915 | |||
916 | .alloc_request = imx_ep_alloc_request, | ||
917 | .free_request = imx_ep_free_request, | ||
918 | |||
919 | .queue = imx_ep_queue, | ||
920 | .dequeue = imx_ep_dequeue, | ||
921 | |||
922 | .set_halt = imx_ep_set_halt, | ||
923 | .fifo_status = imx_ep_fifo_status, | ||
924 | .fifo_flush = imx_ep_fifo_flush, | ||
925 | }; | ||
926 | |||
927 | /******************************************************************************* | ||
928 | * USB endpoint control functions | ||
929 | ******************************************************************************* | ||
930 | */ | ||
931 | |||
932 | void ep0_chg_stat(const char *label, | ||
933 | struct imx_udc_struct *imx_usb, enum ep0_state stat) | ||
934 | { | ||
935 | D_EP0(imx_usb->dev, "<%s> from %15s to %15s\n", | ||
936 | label, state_name[imx_usb->ep0state], state_name[stat]); | ||
937 | |||
938 | if (imx_usb->ep0state == stat) | ||
939 | return; | ||
940 | |||
941 | imx_usb->ep0state = stat; | ||
942 | } | ||
943 | |||
944 | static void usb_init_data(struct imx_udc_struct *imx_usb) | ||
945 | { | ||
946 | struct imx_ep_struct *imx_ep; | ||
947 | u8 i; | ||
948 | |||
949 | /* device/ep0 records init */ | ||
950 | INIT_LIST_HEAD(&imx_usb->gadget.ep_list); | ||
951 | INIT_LIST_HEAD(&imx_usb->gadget.ep0->ep_list); | ||
952 | ep0_chg_stat(__func__, imx_usb, EP0_IDLE); | ||
953 | |||
954 | /* basic endpoint records init */ | ||
955 | for (i = 0; i < IMX_USB_NB_EP; i++) { | ||
956 | imx_ep = &imx_usb->imx_ep[i]; | ||
957 | |||
958 | if (i) { | ||
959 | list_add_tail(&imx_ep->ep.ep_list, | ||
960 | &imx_usb->gadget.ep_list); | ||
961 | imx_ep->stopped = 1; | ||
962 | } else | ||
963 | imx_ep->stopped = 0; | ||
964 | |||
965 | INIT_LIST_HEAD(&imx_ep->queue); | ||
966 | } | ||
967 | } | ||
968 | |||
969 | static void udc_stop_activity(struct imx_udc_struct *imx_usb, | ||
970 | struct usb_gadget_driver *driver) | ||
971 | { | ||
972 | struct imx_ep_struct *imx_ep; | ||
973 | int i; | ||
974 | |||
975 | if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN) | ||
976 | driver = NULL; | ||
977 | |||
978 | /* prevent new request submissions, kill any outstanding requests */ | ||
979 | for (i = 1; i < IMX_USB_NB_EP; i++) { | ||
980 | imx_ep = &imx_usb->imx_ep[i]; | ||
981 | imx_flush(imx_ep); | ||
982 | imx_ep->stopped = 1; | ||
983 | imx_ep_irq_disable(imx_ep); | ||
984 | nuke(imx_ep, -ESHUTDOWN); | ||
985 | } | ||
986 | |||
987 | imx_usb->cfg = 0; | ||
988 | imx_usb->intf = 0; | ||
989 | imx_usb->alt = 0; | ||
990 | |||
991 | if (driver) | ||
992 | driver->disconnect(&imx_usb->gadget); | ||
993 | } | ||
994 | |||
995 | /******************************************************************************* | ||
996 | * Interrupt handlers | ||
997 | ******************************************************************************* | ||
998 | */ | ||
999 | |||
1000 | static irqreturn_t imx_udc_irq(int irq, void *dev) | ||
1001 | { | ||
1002 | struct imx_udc_struct *imx_usb = dev; | ||
1003 | struct usb_ctrlrequest u; | ||
1004 | int temp, cfg, intf, alt; | ||
1005 | int intr = __raw_readl(imx_usb->base + USB_INTR); | ||
1006 | |||
1007 | if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START | ||
1008 | | INTR_RESET_STOP | INTR_CFG_CHG)) { | ||
1009 | dump_intr(__func__, intr, imx_usb->dev); | ||
1010 | dump_usb_stat(__func__, imx_usb); | ||
1011 | } | ||
1012 | |||
1013 | if (!imx_usb->driver) { | ||
1014 | /*imx_udc_disable(imx_usb);*/ | ||
1015 | goto end_irq; | ||
1016 | } | ||
1017 | |||
1018 | if (intr & INTR_WAKEUP) { | ||
1019 | if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN | ||
1020 | && imx_usb->driver && imx_usb->driver->resume) | ||
1021 | imx_usb->driver->resume(&imx_usb->gadget); | ||
1022 | imx_usb->set_config = 0; | ||
1023 | imx_usb->gadget.speed = USB_SPEED_FULL; | ||
1024 | } | ||
1025 | |||
1026 | if (intr & INTR_SUSPEND) { | ||
1027 | if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN | ||
1028 | && imx_usb->driver && imx_usb->driver->suspend) | ||
1029 | imx_usb->driver->suspend(&imx_usb->gadget); | ||
1030 | imx_usb->set_config = 0; | ||
1031 | imx_usb->gadget.speed = USB_SPEED_UNKNOWN; | ||
1032 | } | ||
1033 | |||
1034 | if (intr & INTR_RESET_START) { | ||
1035 | __raw_writel(intr, imx_usb->base + USB_INTR); | ||
1036 | udc_stop_activity(imx_usb, imx_usb->driver); | ||
1037 | imx_usb->set_config = 0; | ||
1038 | imx_usb->gadget.speed = USB_SPEED_UNKNOWN; | ||
1039 | } | ||
1040 | |||
1041 | if (intr & INTR_RESET_STOP) | ||
1042 | imx_usb->gadget.speed = USB_SPEED_FULL; | ||
1043 | |||
1044 | if (intr & INTR_CFG_CHG) { | ||
1045 | __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR); | ||
1046 | temp = __raw_readl(imx_usb->base + USB_STAT); | ||
1047 | cfg = (temp & STAT_CFG) >> 5; | ||
1048 | intf = (temp & STAT_INTF) >> 3; | ||
1049 | alt = temp & STAT_ALTSET; | ||
1050 | |||
1051 | D_REQ(imx_usb->dev, | ||
1052 | "<%s> orig config C=%d, I=%d, A=%d / " | ||
1053 | "req config C=%d, I=%d, A=%d\n", | ||
1054 | __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt, | ||
1055 | cfg, intf, alt); | ||
1056 | |||
1057 | if (cfg != 1 && cfg != 2) | ||
1058 | goto end_irq; | ||
1059 | |||
1060 | imx_usb->set_config = 0; | ||
1061 | |||
1062 | /* Config setup */ | ||
1063 | if (imx_usb->cfg != cfg) { | ||
1064 | D_REQ(imx_usb->dev, "<%s> Change config start\n",__func__); | ||
1065 | u.bRequest = USB_REQ_SET_CONFIGURATION; | ||
1066 | u.bRequestType = USB_DIR_OUT | | ||
1067 | USB_TYPE_STANDARD | | ||
1068 | USB_RECIP_DEVICE; | ||
1069 | u.wValue = cfg; | ||
1070 | u.wIndex = 0; | ||
1071 | u.wLength = 0; | ||
1072 | imx_usb->cfg = cfg; | ||
1073 | imx_usb->set_config = 1; | ||
1074 | imx_usb->driver->setup(&imx_usb->gadget, &u); | ||
1075 | imx_usb->set_config = 0; | ||
1076 | D_REQ(imx_usb->dev, "<%s> Change config done\n",__func__); | ||
1077 | |||
1078 | } | ||
1079 | if (imx_usb->intf != intf || imx_usb->alt != alt) { | ||
1080 | D_REQ(imx_usb->dev, "<%s> Change interface start\n",__func__); | ||
1081 | u.bRequest = USB_REQ_SET_INTERFACE; | ||
1082 | u.bRequestType = USB_DIR_OUT | | ||
1083 | USB_TYPE_STANDARD | | ||
1084 | USB_RECIP_INTERFACE; | ||
1085 | u.wValue = alt; | ||
1086 | u.wIndex = intf; | ||
1087 | u.wLength = 0; | ||
1088 | imx_usb->intf = intf; | ||
1089 | imx_usb->alt = alt; | ||
1090 | imx_usb->set_config = 1; | ||
1091 | imx_usb->driver->setup(&imx_usb->gadget, &u); | ||
1092 | imx_usb->set_config = 0; | ||
1093 | D_REQ(imx_usb->dev, "<%s> Change interface done\n",__func__); | ||
1094 | } | ||
1095 | } | ||
1096 | |||
1097 | if (intr & INTR_SOF) { | ||
1098 | if (imx_usb->ep0state == EP0_IDLE) { | ||
1099 | temp = __raw_readl(imx_usb->base + USB_CTRL); | ||
1100 | __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL); | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1104 | end_irq: | ||
1105 | __raw_writel(intr, imx_usb->base + USB_INTR); | ||
1106 | return IRQ_HANDLED; | ||
1107 | } | ||
1108 | |||
1109 | static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) | ||
1110 | { | ||
1111 | struct imx_udc_struct *imx_usb = dev; | ||
1112 | int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0)); | ||
1113 | |||
1114 | dump_ep_intr(__func__, 0, intr, imx_usb->dev); | ||
1115 | |||
1116 | if (!imx_usb->driver) { | ||
1117 | __raw_writel(intr, imx_usb->base + USB_EP_INTR(0)); | ||
1118 | return IRQ_HANDLED; | ||
1119 | } | ||
1120 | |||
1121 | /* DEVREQ IRQ has highest priority */ | ||
1122 | if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ)) | ||
1123 | handle_ep0_devreq(imx_usb); | ||
1124 | /* Seem i.MX is missing EOF interrupt sometimes. | ||
1125 | * Therefore we monitor both EOF and FIFO_EMPTY interrups | ||
1126 | * when transmiting, and both EOF and FIFO_FULL when | ||
1127 | * receiving data. | ||
1128 | */ | ||
1129 | else if (intr & (EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL)) | ||
1130 | handle_ep0(&imx_usb->imx_ep[0]); | ||
1131 | |||
1132 | __raw_writel(intr, imx_usb->base + USB_EP_INTR(0)); | ||
1133 | |||
1134 | return IRQ_HANDLED; | ||
1135 | } | ||
1136 | |||
1137 | static irqreturn_t imx_udc_bulk_irq(int irq, void *dev) | ||
1138 | { | ||
1139 | struct imx_udc_struct *imx_usb = dev; | ||
1140 | struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[irq - USBD_INT0]; | ||
1141 | int intr = __raw_readl(imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); | ||
1142 | |||
1143 | dump_ep_intr(__func__, irq - USBD_INT0, intr, imx_usb->dev); | ||
1144 | |||
1145 | if (!imx_usb->driver) { | ||
1146 | __raw_writel(intr, imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); | ||
1147 | return IRQ_HANDLED; | ||
1148 | } | ||
1149 | |||
1150 | handle_ep(imx_ep); | ||
1151 | |||
1152 | __raw_writel(intr, imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); | ||
1153 | |||
1154 | return IRQ_HANDLED; | ||
1155 | } | ||
1156 | |||
1157 | irq_handler_t intr_handler(int i) | ||
1158 | { | ||
1159 | switch (i) { | ||
1160 | case 0: | ||
1161 | return imx_udc_ctrl_irq; | ||
1162 | case 1: | ||
1163 | case 2: | ||
1164 | case 3: | ||
1165 | case 4: | ||
1166 | case 5: | ||
1167 | return imx_udc_bulk_irq; | ||
1168 | default: | ||
1169 | return imx_udc_irq; | ||
1170 | } | ||
1171 | } | ||
1172 | |||
1173 | /******************************************************************************* | ||
1174 | * Static defined IMX UDC structure | ||
1175 | ******************************************************************************* | ||
1176 | */ | ||
1177 | |||
1178 | static const struct usb_gadget_ops imx_udc_ops = { | ||
1179 | .get_frame = imx_udc_get_frame, | ||
1180 | .wakeup = imx_udc_wakeup, | ||
1181 | }; | ||
1182 | |||
1183 | static struct imx_udc_struct controller = { | ||
1184 | .gadget = { | ||
1185 | .ops = &imx_udc_ops, | ||
1186 | .ep0 = &controller.imx_ep[0].ep, | ||
1187 | .name = driver_name, | ||
1188 | .dev = { | ||
1189 | .bus_id = "gadget", | ||
1190 | }, | ||
1191 | }, | ||
1192 | |||
1193 | .imx_ep[0] = { | ||
1194 | .ep = { | ||
1195 | .name = ep0name, | ||
1196 | .ops = &imx_ep_ops, | ||
1197 | .maxpacket = 32, | ||
1198 | }, | ||
1199 | .imx_usb = &controller, | ||
1200 | .fifosize = 32, | ||
1201 | .bEndpointAddress = 0, | ||
1202 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, | ||
1203 | }, | ||
1204 | .imx_ep[1] = { | ||
1205 | .ep = { | ||
1206 | .name = "ep1in-bulk", | ||
1207 | .ops = &imx_ep_ops, | ||
1208 | .maxpacket = 64, | ||
1209 | }, | ||
1210 | .imx_usb = &controller, | ||
1211 | .fifosize = 64, | ||
1212 | .bEndpointAddress = USB_DIR_IN | 1, | ||
1213 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
1214 | }, | ||
1215 | .imx_ep[2] = { | ||
1216 | .ep = { | ||
1217 | .name = "ep2out-bulk", | ||
1218 | .ops = &imx_ep_ops, | ||
1219 | .maxpacket = 64, | ||
1220 | }, | ||
1221 | .imx_usb = &controller, | ||
1222 | .fifosize = 64, | ||
1223 | .bEndpointAddress = USB_DIR_OUT | 2, | ||
1224 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
1225 | }, | ||
1226 | .imx_ep[3] = { | ||
1227 | .ep = { | ||
1228 | .name = "ep3out-bulk", | ||
1229 | .ops = &imx_ep_ops, | ||
1230 | .maxpacket = 32, | ||
1231 | }, | ||
1232 | .imx_usb = &controller, | ||
1233 | .fifosize = 32, | ||
1234 | .bEndpointAddress = USB_DIR_OUT | 3, | ||
1235 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
1236 | }, | ||
1237 | .imx_ep[4] = { | ||
1238 | .ep = { | ||
1239 | .name = "ep4in-int", | ||
1240 | .ops = &imx_ep_ops, | ||
1241 | .maxpacket = 32, | ||
1242 | }, | ||
1243 | .imx_usb = &controller, | ||
1244 | .fifosize = 32, | ||
1245 | .bEndpointAddress = USB_DIR_IN | 4, | ||
1246 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
1247 | }, | ||
1248 | .imx_ep[5] = { | ||
1249 | .ep = { | ||
1250 | .name = "ep5out-int", | ||
1251 | .ops = &imx_ep_ops, | ||
1252 | .maxpacket = 32, | ||
1253 | }, | ||
1254 | .imx_usb = &controller, | ||
1255 | .fifosize = 32, | ||
1256 | .bEndpointAddress = USB_DIR_OUT | 5, | ||
1257 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
1258 | }, | ||
1259 | }; | ||
1260 | |||
1261 | /******************************************************************************* | ||
1262 | * USB gadged driver functions | ||
1263 | ******************************************************************************* | ||
1264 | */ | ||
1265 | int usb_gadget_register_driver(struct usb_gadget_driver *driver) | ||
1266 | { | ||
1267 | struct imx_udc_struct *imx_usb = &controller; | ||
1268 | int retval; | ||
1269 | |||
1270 | if (!driver | ||
1271 | || driver->speed < USB_SPEED_FULL | ||
1272 | || !driver->bind | ||
1273 | || !driver->disconnect | ||
1274 | || !driver->setup) | ||
1275 | return -EINVAL; | ||
1276 | if (!imx_usb) | ||
1277 | return -ENODEV; | ||
1278 | if (imx_usb->driver) | ||
1279 | return -EBUSY; | ||
1280 | |||
1281 | /* first hook up the driver ... */ | ||
1282 | imx_usb->driver = driver; | ||
1283 | imx_usb->gadget.dev.driver = &driver->driver; | ||
1284 | |||
1285 | retval = device_add(&imx_usb->gadget.dev); | ||
1286 | if (retval) | ||
1287 | goto fail; | ||
1288 | retval = driver->bind(&imx_usb->gadget); | ||
1289 | if (retval) { | ||
1290 | D_ERR(imx_usb->dev, "<%s> bind to driver %s --> error %d\n", | ||
1291 | __func__, driver->driver.name, retval); | ||
1292 | device_del(&imx_usb->gadget.dev); | ||
1293 | |||
1294 | goto fail; | ||
1295 | } | ||
1296 | |||
1297 | D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n", | ||
1298 | __func__, driver->driver.name); | ||
1299 | |||
1300 | imx_udc_enable(imx_usb); | ||
1301 | |||
1302 | return 0; | ||
1303 | fail: | ||
1304 | imx_usb->driver = NULL; | ||
1305 | imx_usb->gadget.dev.driver = NULL; | ||
1306 | return retval; | ||
1307 | } | ||
1308 | EXPORT_SYMBOL(usb_gadget_register_driver); | ||
1309 | |||
1310 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | ||
1311 | { | ||
1312 | struct imx_udc_struct *imx_usb = &controller; | ||
1313 | |||
1314 | if (!imx_usb) | ||
1315 | return -ENODEV; | ||
1316 | if (!driver || driver != imx_usb->driver || !driver->unbind) | ||
1317 | return -EINVAL; | ||
1318 | |||
1319 | udc_stop_activity(imx_usb, driver); | ||
1320 | imx_udc_disable(imx_usb); | ||
1321 | |||
1322 | driver->unbind(&imx_usb->gadget); | ||
1323 | imx_usb->gadget.dev.driver = NULL; | ||
1324 | imx_usb->driver = NULL; | ||
1325 | |||
1326 | device_del(&imx_usb->gadget.dev); | ||
1327 | |||
1328 | D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n", | ||
1329 | __func__, driver->driver.name); | ||
1330 | |||
1331 | return 0; | ||
1332 | } | ||
1333 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | ||
1334 | |||
1335 | /******************************************************************************* | ||
1336 | * Module functions | ||
1337 | ******************************************************************************* | ||
1338 | */ | ||
1339 | |||
1340 | static int __init imx_udc_probe(struct platform_device *pdev) | ||
1341 | { | ||
1342 | struct imx_udc_struct *imx_usb = &controller; | ||
1343 | struct resource *res; | ||
1344 | struct imxusb_platform_data *pdata; | ||
1345 | struct clk *clk; | ||
1346 | void __iomem *base; | ||
1347 | int ret = 0; | ||
1348 | int i, res_size; | ||
1349 | |||
1350 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1351 | if (!res) { | ||
1352 | dev_err(&pdev->dev, "can't get device resources\n"); | ||
1353 | return -ENODEV; | ||
1354 | } | ||
1355 | |||
1356 | pdata = pdev->dev.platform_data; | ||
1357 | if (!pdata) { | ||
1358 | dev_err(&pdev->dev, "driver needs platform data\n"); | ||
1359 | return -ENODEV; | ||
1360 | } | ||
1361 | |||
1362 | res_size = res->end - res->start + 1; | ||
1363 | if (!request_mem_region(res->start, res_size, res->name)) { | ||
1364 | dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n", | ||
1365 | res_size, res->start); | ||
1366 | return -ENOMEM; | ||
1367 | } | ||
1368 | |||
1369 | if (pdata->init) { | ||
1370 | ret = pdata->init(&pdev->dev); | ||
1371 | if (ret) | ||
1372 | goto fail0; | ||
1373 | } | ||
1374 | |||
1375 | base = ioremap(res->start, res_size); | ||
1376 | if (!base) { | ||
1377 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
1378 | ret = -EIO; | ||
1379 | goto fail1; | ||
1380 | } | ||
1381 | |||
1382 | clk = clk_get(NULL, "usbd_clk"); | ||
1383 | if (IS_ERR(clk)) { | ||
1384 | ret = PTR_ERR(clk); | ||
1385 | dev_err(&pdev->dev, "can't get USB clock\n"); | ||
1386 | goto fail2; | ||
1387 | } | ||
1388 | clk_enable(clk); | ||
1389 | |||
1390 | if (clk_get_rate(clk) != 48000000) { | ||
1391 | D_INI(&pdev->dev, | ||
1392 | "Bad USB clock (%d Hz), changing to 48000000 Hz\n", | ||
1393 | (int)clk_get_rate(clk)); | ||
1394 | if (clk_set_rate(clk, 48000000)) { | ||
1395 | dev_err(&pdev->dev, | ||
1396 | "Unable to set correct USB clock (48MHz)\n"); | ||
1397 | ret = -EIO; | ||
1398 | goto fail3; | ||
1399 | } | ||
1400 | } | ||
1401 | |||
1402 | for (i = 0; i < IMX_USB_NB_EP + 1; i++) { | ||
1403 | imx_usb->usbd_int[i] = platform_get_irq(pdev, i); | ||
1404 | if (imx_usb->usbd_int[i] < 0) { | ||
1405 | dev_err(&pdev->dev, "can't get irq number\n"); | ||
1406 | ret = -ENODEV; | ||
1407 | goto fail3; | ||
1408 | } | ||
1409 | } | ||
1410 | |||
1411 | for (i = 0; i < IMX_USB_NB_EP + 1; i++) { | ||
1412 | ret = request_irq(imx_usb->usbd_int[i], intr_handler(i), | ||
1413 | IRQF_DISABLED, driver_name, imx_usb); | ||
1414 | if (ret) { | ||
1415 | dev_err(&pdev->dev, "can't get irq %i, err %d\n", | ||
1416 | imx_usb->usbd_int[i], ret); | ||
1417 | for (--i; i >= 0; i--) | ||
1418 | free_irq(imx_usb->usbd_int[i], imx_usb); | ||
1419 | goto fail3; | ||
1420 | } | ||
1421 | } | ||
1422 | |||
1423 | imx_usb->res = res; | ||
1424 | imx_usb->base = base; | ||
1425 | imx_usb->clk = clk; | ||
1426 | imx_usb->dev = &pdev->dev; | ||
1427 | |||
1428 | device_initialize(&imx_usb->gadget.dev); | ||
1429 | |||
1430 | imx_usb->gadget.dev.parent = &pdev->dev; | ||
1431 | imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask; | ||
1432 | |||
1433 | platform_set_drvdata(pdev, imx_usb); | ||
1434 | |||
1435 | usb_init_data(imx_usb); | ||
1436 | imx_udc_init(imx_usb); | ||
1437 | |||
1438 | return 0; | ||
1439 | |||
1440 | fail3: | ||
1441 | clk_put(clk); | ||
1442 | clk_disable(clk); | ||
1443 | fail2: | ||
1444 | iounmap(base); | ||
1445 | fail1: | ||
1446 | if (pdata->exit) | ||
1447 | pdata->exit(&pdev->dev); | ||
1448 | fail0: | ||
1449 | release_mem_region(res->start, res_size); | ||
1450 | return ret; | ||
1451 | } | ||
1452 | |||
1453 | static int __exit imx_udc_remove(struct platform_device *pdev) | ||
1454 | { | ||
1455 | struct imx_udc_struct *imx_usb = platform_get_drvdata(pdev); | ||
1456 | struct imxusb_platform_data *pdata = pdev->dev.platform_data; | ||
1457 | int i; | ||
1458 | |||
1459 | imx_udc_disable(imx_usb); | ||
1460 | |||
1461 | for (i = 0; i < IMX_USB_NB_EP + 1; i++) | ||
1462 | free_irq(imx_usb->usbd_int[i], imx_usb); | ||
1463 | |||
1464 | clk_put(imx_usb->clk); | ||
1465 | clk_disable(imx_usb->clk); | ||
1466 | iounmap(imx_usb->base); | ||
1467 | |||
1468 | release_mem_region(imx_usb->res->start, | ||
1469 | imx_usb->res->end - imx_usb->res->start + 1); | ||
1470 | |||
1471 | if (pdata->exit) | ||
1472 | pdata->exit(&pdev->dev); | ||
1473 | |||
1474 | platform_set_drvdata(pdev, NULL); | ||
1475 | |||
1476 | return 0; | ||
1477 | } | ||
1478 | |||
1479 | /*----------------------------------------------------------------------------*/ | ||
1480 | |||
1481 | #ifdef CONFIG_PM | ||
1482 | #define imx_udc_suspend NULL | ||
1483 | #define imx_udc_resume NULL | ||
1484 | #else | ||
1485 | #define imx_udc_suspend NULL | ||
1486 | #define imx_udc_resume NULL | ||
1487 | #endif | ||
1488 | |||
1489 | /*----------------------------------------------------------------------------*/ | ||
1490 | |||
1491 | static struct platform_driver udc_driver = { | ||
1492 | .driver = { | ||
1493 | .name = driver_name, | ||
1494 | .owner = THIS_MODULE, | ||
1495 | }, | ||
1496 | .remove = __exit_p(imx_udc_remove), | ||
1497 | .suspend = imx_udc_suspend, | ||
1498 | .resume = imx_udc_resume, | ||
1499 | }; | ||
1500 | |||
1501 | static int __init udc_init(void) | ||
1502 | { | ||
1503 | return platform_driver_probe(&udc_driver, imx_udc_probe); | ||
1504 | } | ||
1505 | module_init(udc_init); | ||
1506 | |||
1507 | static void __exit udc_exit(void) | ||
1508 | { | ||
1509 | platform_driver_unregister(&udc_driver); | ||
1510 | } | ||
1511 | module_exit(udc_exit); | ||
1512 | |||
1513 | MODULE_DESCRIPTION("IMX USB Device Controller driver"); | ||
1514 | MODULE_AUTHOR("Darius Augulis <augulis.darius@gmail.com>"); | ||
1515 | MODULE_LICENSE("GPL"); | ||
1516 | MODULE_ALIAS("platform:imx_udc"); | ||
diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h new file mode 100644 index 000000000000..850076937d8d --- /dev/null +++ b/drivers/usb/gadget/imx_udc.h | |||
@@ -0,0 +1,344 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Mike Lee(eemike@gmail.com) | ||
3 | * | ||
4 | * This udc driver is now under testing and code is based on pxa2xx_udc.h | ||
5 | * Please use it with your own risk! | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #ifndef __LINUX_USB_GADGET_IMX_H | ||
19 | #define __LINUX_USB_GADGET_IMX_H | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | |||
23 | /* Helper macros */ | ||
24 | #define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */ | ||
25 | #define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0) | ||
26 | #define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/ | ||
27 | #define ep_to_irq(ep) (EP_NO((ep)) + USBD_INT0) | ||
28 | #define IMX_USB_NB_EP 6 | ||
29 | |||
30 | /* Driver structures */ | ||
31 | struct imx_request { | ||
32 | struct usb_request req; | ||
33 | struct list_head queue; | ||
34 | unsigned int in_use; | ||
35 | }; | ||
36 | |||
37 | enum ep0_state { | ||
38 | EP0_IDLE, | ||
39 | EP0_IN_DATA_PHASE, | ||
40 | EP0_OUT_DATA_PHASE, | ||
41 | EP0_CONFIG, | ||
42 | EP0_STALL, | ||
43 | }; | ||
44 | |||
45 | struct imx_ep_struct { | ||
46 | struct usb_ep ep; | ||
47 | struct imx_udc_struct *imx_usb; | ||
48 | struct list_head queue; | ||
49 | unsigned char stopped; | ||
50 | unsigned char fifosize; | ||
51 | unsigned char bEndpointAddress; | ||
52 | unsigned char bmAttributes; | ||
53 | }; | ||
54 | |||
55 | struct imx_udc_struct { | ||
56 | struct usb_gadget gadget; | ||
57 | struct usb_gadget_driver *driver; | ||
58 | struct device *dev; | ||
59 | struct imx_ep_struct imx_ep[IMX_USB_NB_EP]; | ||
60 | struct clk *clk; | ||
61 | enum ep0_state ep0state; | ||
62 | struct resource *res; | ||
63 | void __iomem *base; | ||
64 | unsigned char set_config; | ||
65 | int cfg, | ||
66 | intf, | ||
67 | alt, | ||
68 | usbd_int[7]; | ||
69 | }; | ||
70 | |||
71 | /* USB registers */ | ||
72 | #define USB_FRAME (0x00) /* USB frame */ | ||
73 | #define USB_SPEC (0x04) /* USB Spec */ | ||
74 | #define USB_STAT (0x08) /* USB Status */ | ||
75 | #define USB_CTRL (0x0C) /* USB Control */ | ||
76 | #define USB_DADR (0x10) /* USB Desc RAM addr */ | ||
77 | #define USB_DDAT (0x14) /* USB Desc RAM/EP buffer data */ | ||
78 | #define USB_INTR (0x18) /* USB interrupt */ | ||
79 | #define USB_MASK (0x1C) /* USB Mask */ | ||
80 | #define USB_ENAB (0x24) /* USB Enable */ | ||
81 | #define USB_EP_STAT(x) (0x30 + (x*0x30)) /* USB status/control */ | ||
82 | #define USB_EP_INTR(x) (0x34 + (x*0x30)) /* USB interrupt */ | ||
83 | #define USB_EP_MASK(x) (0x38 + (x*0x30)) /* USB mask */ | ||
84 | #define USB_EP_FDAT(x) (0x3C + (x*0x30)) /* USB FIFO data */ | ||
85 | #define USB_EP_FDAT0(x) (0x3C + (x*0x30)) /* USB FIFO data */ | ||
86 | #define USB_EP_FDAT1(x) (0x3D + (x*0x30)) /* USB FIFO data */ | ||
87 | #define USB_EP_FDAT2(x) (0x3E + (x*0x30)) /* USB FIFO data */ | ||
88 | #define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */ | ||
89 | #define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */ | ||
90 | #define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */ | ||
91 | #define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last read frame pointer */ | ||
92 | #define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last write frame pointer */ | ||
93 | #define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */ | ||
94 | #define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */ | ||
95 | #define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */ | ||
96 | /* USB Control Register Bit Fields.*/ | ||
97 | #define CTRL_CMDOVER (1<<6) /* UDC status */ | ||
98 | #define CTRL_CMDERROR (1<<5) /* UDC status */ | ||
99 | #define CTRL_FE_ENA (1<<3) /* Enable Font End logic */ | ||
100 | #define CTRL_UDC_RST (1<<2) /* UDC reset */ | ||
101 | #define CTRL_AFE_ENA (1<<1) /* Analog Font end enable */ | ||
102 | #define CTRL_RESUME (1<<0) /* UDC resume */ | ||
103 | /* USB Status Register Bit Fields.*/ | ||
104 | #define STAT_RST (1<<8) | ||
105 | #define STAT_SUSP (1<<7) | ||
106 | #define STAT_CFG (3<<5) | ||
107 | #define STAT_INTF (3<<3) | ||
108 | #define STAT_ALTSET (7<<0) | ||
109 | /* USB Interrupt Status/Mask Registers Bit fields */ | ||
110 | #define INTR_WAKEUP (1<<31) /* Wake up Interrupt */ | ||
111 | #define INTR_MSOF (1<<7) /* Missed Start of Frame */ | ||
112 | #define INTR_SOF (1<<6) /* Start of Frame */ | ||
113 | #define INTR_RESET_STOP (1<<5) /* Reset Signaling stop */ | ||
114 | #define INTR_RESET_START (1<<4) /* Reset Signaling start */ | ||
115 | #define INTR_RESUME (1<<3) /* Suspend to resume */ | ||
116 | #define INTR_SUSPEND (1<<2) /* Active to suspend */ | ||
117 | #define INTR_FRAME_MATCH (1<<1) /* Frame matched */ | ||
118 | #define INTR_CFG_CHG (1<<0) /* Configuration change occurred */ | ||
119 | /* USB Enable Register Bit Fields.*/ | ||
120 | #define ENAB_RST (1<<31) /* Reset USB modules */ | ||
121 | #define ENAB_ENAB (1<<30) /* Enable USB modules*/ | ||
122 | #define ENAB_SUSPEND (1<<29) /* Suspend USB modules */ | ||
123 | #define ENAB_ENDIAN (1<<28) /* Endian of USB modules */ | ||
124 | #define ENAB_PWRMD (1<<0) /* Power mode of USB modules */ | ||
125 | /* USB Descriptor Ram Address Register bit fields */ | ||
126 | #define DADR_CFG (1<<31) /* Configuration */ | ||
127 | #define DADR_BSY (1<<30) /* Busy status */ | ||
128 | #define DADR_DADR (0x1FF) /* Descriptor Ram Address */ | ||
129 | /* USB Descriptor RAM/Endpoint Buffer Data Register bit fields */ | ||
130 | #define DDAT_DDAT (0xFF) /* Descriptor Endpoint Buffer */ | ||
131 | /* USB Endpoint Status Register bit fields */ | ||
132 | #define EPSTAT_BCOUNT (0x7F<<16) /* Endpoint FIFO byte count */ | ||
133 | #define EPSTAT_SIP (1<<8) /* Endpoint setup in progress */ | ||
134 | #define EPSTAT_DIR (1<<7) /* Endpoint transfer direction */ | ||
135 | #define EPSTAT_MAX (3<<5) /* Endpoint Max packet size */ | ||
136 | #define EPSTAT_TYP (3<<3) /* Endpoint type */ | ||
137 | #define EPSTAT_ZLPS (1<<2) /* Send zero length packet */ | ||
138 | #define EPSTAT_FLUSH (1<<1) /* Endpoint FIFO Flush */ | ||
139 | #define EPSTAT_STALL (1<<0) /* Force stall */ | ||
140 | /* USB Endpoint FIFO Status Register bit fields */ | ||
141 | #define FSTAT_FRAME_STAT (0xF<<24) /* Frame status bit [0-3] */ | ||
142 | #define FSTAT_ERR (1<<22) /* FIFO error */ | ||
143 | #define FSTAT_UF (1<<21) /* FIFO underflow */ | ||
144 | #define FSTAT_OF (1<<20) /* FIFO overflow */ | ||
145 | #define FSTAT_FR (1<<19) /* FIFO frame ready */ | ||
146 | #define FSTAT_FULL (1<<18) /* FIFO full */ | ||
147 | #define FSTAT_ALRM (1<<17) /* FIFO alarm */ | ||
148 | #define FSTAT_EMPTY (1<<16) /* FIFO empty */ | ||
149 | /* USB Endpoint FIFO Control Register bit fields */ | ||
150 | #define FCTRL_WFR (1<<29) /* Write frame end */ | ||
151 | /* USB Endpoint Interrupt Status Regsiter bit fields */ | ||
152 | #define EPINTR_FIFO_FULL (1<<8) /* fifo full */ | ||
153 | #define EPINTR_FIFO_EMPTY (1<<7) /* fifo empty */ | ||
154 | #define EPINTR_FIFO_ERROR (1<<6) /* fifo error */ | ||
155 | #define EPINTR_FIFO_HIGH (1<<5) /* fifo high */ | ||
156 | #define EPINTR_FIFO_LOW (1<<4) /* fifo low */ | ||
157 | #define EPINTR_MDEVREQ (1<<3) /* multi Device request */ | ||
158 | #define EPINTR_EOT (1<<2) /* fifo end of transfer */ | ||
159 | #define EPINTR_DEVREQ (1<<1) /* Device request */ | ||
160 | #define EPINTR_EOF (1<<0) /* fifo end of frame */ | ||
161 | |||
162 | /* Debug macros */ | ||
163 | #ifdef DEBUG | ||
164 | |||
165 | /* #define DEBUG_REQ */ | ||
166 | /* #define DEBUG_TRX */ | ||
167 | /* #define DEBUG_INIT */ | ||
168 | /* #define DEBUG_EP0 */ | ||
169 | /* #define DEBUG_EPX */ | ||
170 | /* #define DEBUG_IRQ */ | ||
171 | /* #define DEBUG_EPIRQ */ | ||
172 | /* #define DEBUG_DUMP */ | ||
173 | #define DEBUG_ERR | ||
174 | |||
175 | #ifdef DEBUG_REQ | ||
176 | #define D_REQ(dev, args...) dev_dbg(dev, ## args) | ||
177 | #else | ||
178 | #define D_REQ(dev, args...) do {} while (0) | ||
179 | #endif /* DEBUG_REQ */ | ||
180 | |||
181 | #ifdef DEBUG_TRX | ||
182 | #define D_TRX(dev, args...) dev_dbg(dev, ## args) | ||
183 | #else | ||
184 | #define D_TRX(dev, args...) do {} while (0) | ||
185 | #endif /* DEBUG_TRX */ | ||
186 | |||
187 | #ifdef DEBUG_INIT | ||
188 | #define D_INI(dev, args...) dev_dbg(dev, ## args) | ||
189 | #else | ||
190 | #define D_INI(dev, args...) do {} while (0) | ||
191 | #endif /* DEBUG_INIT */ | ||
192 | |||
193 | #ifdef DEBUG_EP0 | ||
194 | static const char *state_name[] = { | ||
195 | "EP0_IDLE", | ||
196 | "EP0_IN_DATA_PHASE", | ||
197 | "EP0_OUT_DATA_PHASE", | ||
198 | "EP0_CONFIG", | ||
199 | "EP0_STALL" | ||
200 | }; | ||
201 | #define D_EP0(dev, args...) dev_dbg(dev, ## args) | ||
202 | #else | ||
203 | #define D_EP0(dev, args...) do {} while (0) | ||
204 | #endif /* DEBUG_EP0 */ | ||
205 | |||
206 | #ifdef DEBUG_EPX | ||
207 | #define D_EPX(dev, args...) dev_dbg(dev, ## args) | ||
208 | #else | ||
209 | #define D_EPX(dev, args...) do {} while (0) | ||
210 | #endif /* DEBUG_EP0 */ | ||
211 | |||
212 | #ifdef DEBUG_IRQ | ||
213 | static void dump_intr(const char *label, int irqreg, struct device *dev) | ||
214 | { | ||
215 | dev_dbg(dev, "<%s> USB_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, | ||
216 | (irqreg & INTR_WAKEUP) ? " wake" : "", | ||
217 | (irqreg & INTR_MSOF) ? " msof" : "", | ||
218 | (irqreg & INTR_SOF) ? " sof" : "", | ||
219 | (irqreg & INTR_RESUME) ? " resume" : "", | ||
220 | (irqreg & INTR_SUSPEND) ? " suspend" : "", | ||
221 | (irqreg & INTR_RESET_STOP) ? " noreset" : "", | ||
222 | (irqreg & INTR_RESET_START) ? " reset" : "", | ||
223 | (irqreg & INTR_FRAME_MATCH) ? " fmatch" : "", | ||
224 | (irqreg & INTR_CFG_CHG) ? " config" : ""); | ||
225 | } | ||
226 | #else | ||
227 | #define dump_intr(x, y, z) do {} while (0) | ||
228 | #endif /* DEBUG_IRQ */ | ||
229 | |||
230 | #ifdef DEBUG_EPIRQ | ||
231 | static void dump_ep_intr(const char *label, int nr, int irqreg, struct device *dev) | ||
232 | { | ||
233 | dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr, | ||
234 | (irqreg & EPINTR_FIFO_FULL) ? " full" : "", | ||
235 | (irqreg & EPINTR_FIFO_EMPTY) ? " fempty" : "", | ||
236 | (irqreg & EPINTR_FIFO_ERROR) ? " ferr" : "", | ||
237 | (irqreg & EPINTR_FIFO_HIGH) ? " fhigh" : "", | ||
238 | (irqreg & EPINTR_FIFO_LOW) ? " flow" : "", | ||
239 | (irqreg & EPINTR_MDEVREQ) ? " mreq" : "", | ||
240 | (irqreg & EPINTR_EOF) ? " eof" : "", | ||
241 | (irqreg & EPINTR_DEVREQ) ? " devreq" : "", | ||
242 | (irqreg & EPINTR_EOT) ? " eot" : ""); | ||
243 | } | ||
244 | #else | ||
245 | #define dump_ep_intr(x, y, z, i) do {} while (0) | ||
246 | #endif /* DEBUG_IRQ */ | ||
247 | |||
248 | #ifdef DEBUG_DUMP | ||
249 | static void dump_usb_stat(const char *label, struct imx_udc_struct *imx_usb) | ||
250 | { | ||
251 | int temp = __raw_readl(imx_usb->base + USB_STAT); | ||
252 | |||
253 | dev_dbg(imx_usb->dev, | ||
254 | "<%s> USB_STAT=[%s%s CFG=%d, INTF=%d, ALTR=%d]\n", label, | ||
255 | (temp & STAT_RST) ? " reset" : "", | ||
256 | (temp & STAT_SUSP) ? " suspend" : "", | ||
257 | (temp & STAT_CFG) >> 5, | ||
258 | (temp & STAT_INTF) >> 3, | ||
259 | (temp & STAT_ALTSET)); | ||
260 | } | ||
261 | |||
262 | static void dump_ep_stat(const char *label, struct imx_ep_struct *imx_ep) | ||
263 | { | ||
264 | int temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); | ||
265 | |||
266 | dev_dbg(imx_ep->imx_usb->dev, | ||
267 | "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), | ||
268 | (temp & EPINTR_FIFO_FULL) ? " full" : "", | ||
269 | (temp & EPINTR_FIFO_EMPTY) ? " fempty" : "", | ||
270 | (temp & EPINTR_FIFO_ERROR) ? " ferr" : "", | ||
271 | (temp & EPINTR_FIFO_HIGH) ? " fhigh" : "", | ||
272 | (temp & EPINTR_FIFO_LOW) ? " flow" : "", | ||
273 | (temp & EPINTR_MDEVREQ) ? " mreq" : "", | ||
274 | (temp & EPINTR_EOF) ? " eof" : "", | ||
275 | (temp & EPINTR_DEVREQ) ? " devreq" : "", | ||
276 | (temp & EPINTR_EOT) ? " eot" : ""); | ||
277 | |||
278 | temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); | ||
279 | |||
280 | dev_dbg(imx_ep->imx_usb->dev, | ||
281 | "<%s> EP%d_STAT=[%s%s bcount=%d]\n", label, EP_NO(imx_ep), | ||
282 | (temp & EPSTAT_SIP) ? " sip" : "", | ||
283 | (temp & EPSTAT_STALL) ? " stall" : "", | ||
284 | (temp & EPSTAT_BCOUNT) >> 16); | ||
285 | |||
286 | temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep))); | ||
287 | |||
288 | dev_dbg(imx_ep->imx_usb->dev, | ||
289 | "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), | ||
290 | (temp & FSTAT_ERR) ? " ferr" : "", | ||
291 | (temp & FSTAT_UF) ? " funder" : "", | ||
292 | (temp & FSTAT_OF) ? " fover" : "", | ||
293 | (temp & FSTAT_FR) ? " fready" : "", | ||
294 | (temp & FSTAT_FULL) ? " ffull" : "", | ||
295 | (temp & FSTAT_ALRM) ? " falarm" : "", | ||
296 | (temp & FSTAT_EMPTY) ? " fempty" : ""); | ||
297 | } | ||
298 | |||
299 | static void dump_req(const char *label, struct imx_ep_struct *imx_ep, struct usb_request *req) | ||
300 | { | ||
301 | int i; | ||
302 | |||
303 | if (!req || !req->buf) { | ||
304 | dev_dbg(imx_ep->imx_usb->dev, "<%s> req or req buf is free\n", label); | ||
305 | return; | ||
306 | } | ||
307 | |||
308 | if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) | ||
309 | || (EP_NO(imx_ep) && EP_DIR(imx_ep))) { | ||
310 | |||
311 | dev_dbg(imx_ep->imx_usb->dev, "<%s> request dump <", label); | ||
312 | for (i = 0; i < req->length; i++) | ||
313 | printk("%02x-", *((u8 *)req->buf + i)); | ||
314 | printk(">\n"); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | #else | ||
319 | #define dump_ep_stat(x, y) do {} while (0) | ||
320 | #define dump_usb_stat(x, y) do {} while (0) | ||
321 | #define dump_req(x, y, z) do {} while (0) | ||
322 | #endif /* DEBUG_DUMP */ | ||
323 | |||
324 | #ifdef DEBUG_ERR | ||
325 | #define D_ERR(dev, args...) dev_dbg(dev, ## args) | ||
326 | #else | ||
327 | #define D_ERR(dev, args...) do {} while (0) | ||
328 | #endif | ||
329 | |||
330 | #else | ||
331 | #define D_REQ(dev, args...) do {} while (0) | ||
332 | #define D_TRX(dev, args...) do {} while (0) | ||
333 | #define D_INI(dev, args...) do {} while (0) | ||
334 | #define D_EP0(dev, args...) do {} while (0) | ||
335 | #define D_EPX(dev, args...) do {} while (0) | ||
336 | #define dump_ep_intr(x, y, z, i) do {} while (0) | ||
337 | #define dump_intr(x, y, z) do {} while (0) | ||
338 | #define dump_ep_stat(x, y) do {} while (0) | ||
339 | #define dump_usb_stat(x, y) do {} while (0) | ||
340 | #define dump_req(x, y, z) do {} while (0) | ||
341 | #define D_ERR(dev, args...) do {} while (0) | ||
342 | #endif /* DEBUG */ | ||
343 | |||
344 | #endif /* __LINUX_USB_GADGET_IMX_H */ | ||
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 3a8879ec2061..43dcf9e1af6b 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c | |||
@@ -1546,8 +1546,6 @@ static void nop_completion(struct usb_ep *ep, struct usb_request *r) | |||
1546 | { | 1546 | { |
1547 | } | 1547 | } |
1548 | 1548 | ||
1549 | #define resource_len(r) (((r)->end - (r)->start) + 1) | ||
1550 | |||
1551 | static int __init m66592_probe(struct platform_device *pdev) | 1549 | static int __init m66592_probe(struct platform_device *pdev) |
1552 | { | 1550 | { |
1553 | struct resource *res; | 1551 | struct resource *res; |
@@ -1560,11 +1558,10 @@ static int __init m66592_probe(struct platform_device *pdev) | |||
1560 | int ret = 0; | 1558 | int ret = 0; |
1561 | int i; | 1559 | int i; |
1562 | 1560 | ||
1563 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 1561 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1564 | (char *)udc_name); | ||
1565 | if (!res) { | 1562 | if (!res) { |
1566 | ret = -ENODEV; | 1563 | ret = -ENODEV; |
1567 | pr_err("platform_get_resource_byname error.\n"); | 1564 | pr_err("platform_get_resource error.\n"); |
1568 | goto clean_up; | 1565 | goto clean_up; |
1569 | } | 1566 | } |
1570 | 1567 | ||
@@ -1575,7 +1572,7 @@ static int __init m66592_probe(struct platform_device *pdev) | |||
1575 | goto clean_up; | 1572 | goto clean_up; |
1576 | } | 1573 | } |
1577 | 1574 | ||
1578 | reg = ioremap(res->start, resource_len(res)); | 1575 | reg = ioremap(res->start, resource_size(res)); |
1579 | if (reg == NULL) { | 1576 | if (reg == NULL) { |
1580 | ret = -ENOMEM; | 1577 | ret = -ENOMEM; |
1581 | pr_err("ioremap error.\n"); | 1578 | pr_err("ioremap error.\n"); |
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 8ae70de2c37d..12c6d83b218c 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
@@ -669,7 +669,7 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid) | |||
669 | 669 | ||
670 | /* 2280 may be polling VALID_BIT through ep->dma->dmadesc */ | 670 | /* 2280 may be polling VALID_BIT through ep->dma->dmadesc */ |
671 | wmb (); | 671 | wmb (); |
672 | td->dmacount = cpu_to_le32p (&dmacount); | 672 | td->dmacount = cpu_to_le32(dmacount); |
673 | } | 673 | } |
674 | 674 | ||
675 | static const u32 dmactl_default = | 675 | static const u32 dmactl_default = |
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 34e9e393f929..57d9641c6bf8 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
@@ -3006,7 +3006,7 @@ cleanup1: | |||
3006 | 3006 | ||
3007 | cleanup0: | 3007 | cleanup0: |
3008 | if (xceiv) | 3008 | if (xceiv) |
3009 | put_device(xceiv->dev); | 3009 | otg_put_transceiver(xceiv); |
3010 | 3010 | ||
3011 | if (cpu_is_omap16xx() || cpu_is_omap24xx()) { | 3011 | if (cpu_is_omap16xx() || cpu_is_omap24xx()) { |
3012 | clk_disable(hhc_clk); | 3012 | clk_disable(hhc_clk); |
@@ -3034,7 +3034,7 @@ static int __exit omap_udc_remove(struct platform_device *pdev) | |||
3034 | 3034 | ||
3035 | pullup_disable(udc); | 3035 | pullup_disable(udc); |
3036 | if (udc->transceiver) { | 3036 | if (udc->transceiver) { |
3037 | put_device(udc->transceiver->dev); | 3037 | otg_put_transceiver(udc->transceiver); |
3038 | udc->transceiver = NULL; | 3038 | udc->transceiver = NULL; |
3039 | } | 3039 | } |
3040 | omap_writew(0, UDC_SYSCON1); | 3040 | omap_writew(0, UDC_SYSCON1); |
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 697a0ca349bf..9b36205c5759 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c | |||
@@ -2198,7 +2198,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) | |||
2198 | udc_disable(dev); | 2198 | udc_disable(dev); |
2199 | udc_reinit(dev); | 2199 | udc_reinit(dev); |
2200 | 2200 | ||
2201 | dev->vbus = is_vbus_present(); | 2201 | dev->vbus = !!is_vbus_present(); |
2202 | 2202 | ||
2203 | /* irq setup after old hardware state is cleaned up */ | 2203 | /* irq setup after old hardware state is cleaned up */ |
2204 | retval = request_irq(irq, pxa25x_udc_irq, | 2204 | retval = request_irq(irq, pxa25x_udc_irq, |
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 65110d02a206..990f40f988d4 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c | |||
@@ -430,7 +430,6 @@ static void pio_irq_enable(struct pxa_ep *ep) | |||
430 | /** | 430 | /** |
431 | * pio_irq_disable - Disables irq generation for one endpoint | 431 | * pio_irq_disable - Disables irq generation for one endpoint |
432 | * @ep: udc endpoint | 432 | * @ep: udc endpoint |
433 | * @index: endpoint number | ||
434 | */ | 433 | */ |
435 | static void pio_irq_disable(struct pxa_ep *ep) | 434 | static void pio_irq_disable(struct pxa_ep *ep) |
436 | { | 435 | { |
@@ -586,7 +585,6 @@ static void inc_ep_stats_reqs(struct pxa_ep *ep, int is_in) | |||
586 | * inc_ep_stats_bytes - Update ep stats counts | 585 | * inc_ep_stats_bytes - Update ep stats counts |
587 | * @ep: physical endpoint | 586 | * @ep: physical endpoint |
588 | * @count: bytes transfered on endpoint | 587 | * @count: bytes transfered on endpoint |
589 | * @req: usb request | ||
590 | * @is_in: ep direction (USB_DIR_IN or 0) | 588 | * @is_in: ep direction (USB_DIR_IN or 0) |
591 | */ | 589 | */ |
592 | static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in) | 590 | static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in) |
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index c7e255636803..9a2b8920532d 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
38 | #include <linux/clk.h> | 38 | #include <linux/clk.h> |
39 | #include <linux/gpio.h> | ||
39 | 40 | ||
40 | #include <linux/debugfs.h> | 41 | #include <linux/debugfs.h> |
41 | #include <linux/seq_file.h> | 42 | #include <linux/seq_file.h> |
@@ -51,7 +52,6 @@ | |||
51 | #include <mach/irqs.h> | 52 | #include <mach/irqs.h> |
52 | 53 | ||
53 | #include <mach/hardware.h> | 54 | #include <mach/hardware.h> |
54 | #include <mach/regs-gpio.h> | ||
55 | 55 | ||
56 | #include <plat/regs-udc.h> | 56 | #include <plat/regs-udc.h> |
57 | #include <plat/udc.h> | 57 | #include <plat/udc.h> |
@@ -1510,11 +1510,7 @@ static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev) | |||
1510 | 1510 | ||
1511 | dprintk(DEBUG_NORMAL, "%s()\n", __func__); | 1511 | dprintk(DEBUG_NORMAL, "%s()\n", __func__); |
1512 | 1512 | ||
1513 | /* some cpus cannot read from an line configured to IRQ! */ | 1513 | value = gpio_get_value(udc_info->vbus_pin) ? 1 : 0; |
1514 | s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_INPUT); | ||
1515 | value = s3c2410_gpio_getpin(udc_info->vbus_pin); | ||
1516 | s3c2410_gpio_cfgpin(udc_info->vbus_pin, S3C2410_GPIO_SFN2); | ||
1517 | |||
1518 | if (udc_info->vbus_pin_inverted) | 1514 | if (udc_info->vbus_pin_inverted) |
1519 | value = !value; | 1515 | value = !value; |
1520 | 1516 | ||
@@ -1802,7 +1798,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) | |||
1802 | struct s3c2410_udc *udc = &memory; | 1798 | struct s3c2410_udc *udc = &memory; |
1803 | struct device *dev = &pdev->dev; | 1799 | struct device *dev = &pdev->dev; |
1804 | int retval; | 1800 | int retval; |
1805 | unsigned int irq; | 1801 | int irq; |
1806 | 1802 | ||
1807 | dev_dbg(dev, "%s()\n", __func__); | 1803 | dev_dbg(dev, "%s()\n", __func__); |
1808 | 1804 | ||
@@ -1861,7 +1857,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) | |||
1861 | 1857 | ||
1862 | /* irq setup after old hardware state is cleaned up */ | 1858 | /* irq setup after old hardware state is cleaned up */ |
1863 | retval = request_irq(IRQ_USBD, s3c2410_udc_irq, | 1859 | retval = request_irq(IRQ_USBD, s3c2410_udc_irq, |
1864 | IRQF_DISABLED, gadget_name, udc); | 1860 | IRQF_DISABLED, gadget_name, udc); |
1865 | 1861 | ||
1866 | if (retval != 0) { | 1862 | if (retval != 0) { |
1867 | dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval); | 1863 | dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval); |
@@ -1872,17 +1868,28 @@ static int s3c2410_udc_probe(struct platform_device *pdev) | |||
1872 | dev_dbg(dev, "got irq %i\n", IRQ_USBD); | 1868 | dev_dbg(dev, "got irq %i\n", IRQ_USBD); |
1873 | 1869 | ||
1874 | if (udc_info && udc_info->vbus_pin > 0) { | 1870 | if (udc_info && udc_info->vbus_pin > 0) { |
1875 | irq = s3c2410_gpio_getirq(udc_info->vbus_pin); | 1871 | retval = gpio_request(udc_info->vbus_pin, "udc vbus"); |
1872 | if (retval < 0) { | ||
1873 | dev_err(dev, "cannot claim vbus pin\n"); | ||
1874 | goto err_int; | ||
1875 | } | ||
1876 | |||
1877 | irq = gpio_to_irq(udc_info->vbus_pin); | ||
1878 | if (irq < 0) { | ||
1879 | dev_err(dev, "no irq for gpio vbus pin\n"); | ||
1880 | goto err_gpio_claim; | ||
1881 | } | ||
1882 | |||
1876 | retval = request_irq(irq, s3c2410_udc_vbus_irq, | 1883 | retval = request_irq(irq, s3c2410_udc_vbus_irq, |
1877 | IRQF_DISABLED | IRQF_TRIGGER_RISING | 1884 | IRQF_DISABLED | IRQF_TRIGGER_RISING |
1878 | | IRQF_TRIGGER_FALLING | IRQF_SHARED, | 1885 | | IRQF_TRIGGER_FALLING | IRQF_SHARED, |
1879 | gadget_name, udc); | 1886 | gadget_name, udc); |
1880 | 1887 | ||
1881 | if (retval != 0) { | 1888 | if (retval != 0) { |
1882 | dev_err(dev, "can't get vbus irq %i, err %d\n", | 1889 | dev_err(dev, "can't get vbus irq %d, err %d\n", |
1883 | irq, retval); | 1890 | irq, retval); |
1884 | retval = -EBUSY; | 1891 | retval = -EBUSY; |
1885 | goto err_int; | 1892 | goto err_gpio_claim; |
1886 | } | 1893 | } |
1887 | 1894 | ||
1888 | dev_dbg(dev, "got irq %i\n", irq); | 1895 | dev_dbg(dev, "got irq %i\n", irq); |
@@ -1902,6 +1909,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev) | |||
1902 | 1909 | ||
1903 | return 0; | 1910 | return 0; |
1904 | 1911 | ||
1912 | err_gpio_claim: | ||
1913 | if (udc_info && udc_info->vbus_pin > 0) | ||
1914 | gpio_free(udc_info->vbus_pin); | ||
1905 | err_int: | 1915 | err_int: |
1906 | free_irq(IRQ_USBD, udc); | 1916 | free_irq(IRQ_USBD, udc); |
1907 | err_map: | 1917 | err_map: |
@@ -1927,7 +1937,7 @@ static int s3c2410_udc_remove(struct platform_device *pdev) | |||
1927 | debugfs_remove(udc->regs_info); | 1937 | debugfs_remove(udc->regs_info); |
1928 | 1938 | ||
1929 | if (udc_info && udc_info->vbus_pin > 0) { | 1939 | if (udc_info && udc_info->vbus_pin > 0) { |
1930 | irq = s3c2410_gpio_getirq(udc_info->vbus_pin); | 1940 | irq = gpio_to_irq(udc_info->vbus_pin); |
1931 | free_irq(irq, udc); | 1941 | free_irq(irq, udc); |
1932 | } | 1942 | } |
1933 | 1943 | ||
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f3a75a929e0a..2b476b6b3d4d 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -96,6 +96,19 @@ config USB_EHCI_HCD_PPC_OF | |||
96 | Enables support for the USB controller present on the PowerPC | 96 | Enables support for the USB controller present on the PowerPC |
97 | OpenFirmware platform bus. | 97 | OpenFirmware platform bus. |
98 | 98 | ||
99 | config USB_OXU210HP_HCD | ||
100 | tristate "OXU210HP HCD support" | ||
101 | depends on USB | ||
102 | ---help--- | ||
103 | The OXU210HP is an USB host/OTG/device controller. Enable this | ||
104 | option if your board has this chip. If unsure, say N. | ||
105 | |||
106 | This driver does not support isochronous transfers and doesn't | ||
107 | implement OTG nor USB device controllers. | ||
108 | |||
109 | To compile this driver as a module, choose M here: the | ||
110 | module will be called oxu210hp-hcd. | ||
111 | |||
99 | config USB_ISP116X_HCD | 112 | config USB_ISP116X_HCD |
100 | tristate "ISP116X HCD support" | 113 | tristate "ISP116X HCD support" |
101 | depends on USB | 114 | depends on USB |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 23be22224044..e5f3f20787e4 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci/ | |||
13 | obj-$(CONFIG_PCI) += pci-quirks.o | 13 | obj-$(CONFIG_PCI) += pci-quirks.o |
14 | 14 | ||
15 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o | 15 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o |
16 | obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o | ||
16 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o | 17 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o |
17 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o | 18 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o |
18 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o | 19 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o |
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 0cb53ca8d343..7f4ace73d44a 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -455,9 +455,7 @@ static void qh_lines ( | |||
455 | (scratch >> 16) & 0x7fff, | 455 | (scratch >> 16) & 0x7fff, |
456 | scratch, | 456 | scratch, |
457 | td->urb); | 457 | td->urb); |
458 | if (temp < 0) | 458 | if (size < temp) |
459 | temp = 0; | ||
460 | else if (size < temp) | ||
461 | temp = size; | 459 | temp = size; |
462 | size -= temp; | 460 | size -= temp; |
463 | next += temp; | 461 | next += temp; |
@@ -466,9 +464,7 @@ static void qh_lines ( | |||
466 | } | 464 | } |
467 | 465 | ||
468 | temp = snprintf (next, size, "\n"); | 466 | temp = snprintf (next, size, "\n"); |
469 | if (temp < 0) | 467 | if (size < temp) |
470 | temp = 0; | ||
471 | else if (size < temp) | ||
472 | temp = size; | 468 | temp = size; |
473 | size -= temp; | 469 | size -= temp; |
474 | next += temp; | 470 | next += temp; |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 218f9660d7ee..97a53a48a3d8 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -194,6 +194,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
194 | u32 temp; | 194 | u32 temp; |
195 | u32 power_okay; | 195 | u32 power_okay; |
196 | int i; | 196 | int i; |
197 | u8 resume_needed = 0; | ||
197 | 198 | ||
198 | if (time_before (jiffies, ehci->next_statechange)) | 199 | if (time_before (jiffies, ehci->next_statechange)) |
199 | msleep(5); | 200 | msleep(5); |
@@ -228,7 +229,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
228 | 229 | ||
229 | /* Some controller/firmware combinations need a delay during which | 230 | /* Some controller/firmware combinations need a delay during which |
230 | * they set up the port statuses. See Bugzilla #8190. */ | 231 | * they set up the port statuses. See Bugzilla #8190. */ |
231 | mdelay(8); | 232 | spin_unlock_irq(&ehci->lock); |
233 | msleep(8); | ||
234 | spin_lock_irq(&ehci->lock); | ||
232 | 235 | ||
233 | /* manually resume the ports we suspended during bus_suspend() */ | 236 | /* manually resume the ports we suspended during bus_suspend() */ |
234 | i = HCS_N_PORTS (ehci->hcs_params); | 237 | i = HCS_N_PORTS (ehci->hcs_params); |
@@ -236,12 +239,21 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
236 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); | 239 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); |
237 | temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); | 240 | temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); |
238 | if (test_bit(i, &ehci->bus_suspended) && | 241 | if (test_bit(i, &ehci->bus_suspended) && |
239 | (temp & PORT_SUSPEND)) | 242 | (temp & PORT_SUSPEND)) { |
240 | temp |= PORT_RESUME; | 243 | temp |= PORT_RESUME; |
244 | resume_needed = 1; | ||
245 | } | ||
241 | ehci_writel(ehci, temp, &ehci->regs->port_status [i]); | 246 | ehci_writel(ehci, temp, &ehci->regs->port_status [i]); |
242 | } | 247 | } |
248 | |||
249 | /* msleep for 20ms only if code is trying to resume port */ | ||
250 | if (resume_needed) { | ||
251 | spin_unlock_irq(&ehci->lock); | ||
252 | msleep(20); | ||
253 | spin_lock_irq(&ehci->lock); | ||
254 | } | ||
255 | |||
243 | i = HCS_N_PORTS (ehci->hcs_params); | 256 | i = HCS_N_PORTS (ehci->hcs_params); |
244 | mdelay (20); | ||
245 | while (i--) { | 257 | while (i--) { |
246 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); | 258 | temp = ehci_readl(ehci, &ehci->regs->port_status [i]); |
247 | if (test_bit(i, &ehci->bus_suspended) && | 259 | if (test_bit(i, &ehci->bus_suspended) && |
@@ -422,8 +434,15 @@ static int check_reset_complete ( | |||
422 | port_status &= ~PORT_RWC_BITS; | 434 | port_status &= ~PORT_RWC_BITS; |
423 | ehci_writel(ehci, port_status, status_reg); | 435 | ehci_writel(ehci, port_status, status_reg); |
424 | 436 | ||
425 | } else | 437 | /* ensure 440EPX ohci controller state is operational */ |
438 | if (ehci->has_amcc_usb23) | ||
439 | set_ohci_hcfs(ehci, 1); | ||
440 | } else { | ||
426 | ehci_dbg (ehci, "port %d high speed\n", index + 1); | 441 | ehci_dbg (ehci, "port %d high speed\n", index + 1); |
442 | /* ensure 440EPx ohci controller state is suspended */ | ||
443 | if (ehci->has_amcc_usb23) | ||
444 | set_ohci_hcfs(ehci, 0); | ||
445 | } | ||
427 | 446 | ||
428 | return port_status; | 447 | return port_status; |
429 | } | 448 | } |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 36864f958444..bdc6e86e1f8b 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -219,15 +219,19 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
219 | /* Serial Bus Release Number is at PCI 0x60 offset */ | 219 | /* Serial Bus Release Number is at PCI 0x60 offset */ |
220 | pci_read_config_byte(pdev, 0x60, &ehci->sbrn); | 220 | pci_read_config_byte(pdev, 0x60, &ehci->sbrn); |
221 | 221 | ||
222 | /* Workaround current PCI init glitch: wakeup bits aren't | 222 | /* Keep this around for a while just in case some EHCI |
223 | * being set from PCI PM capability. | 223 | * implementation uses legacy PCI PM support. This test |
224 | * can be removed on 17 Dec 2009 if the dev_warn() hasn't | ||
225 | * been triggered by then. | ||
224 | */ | 226 | */ |
225 | if (!device_can_wakeup(&pdev->dev)) { | 227 | if (!device_can_wakeup(&pdev->dev)) { |
226 | u16 port_wake; | 228 | u16 port_wake; |
227 | 229 | ||
228 | pci_read_config_word(pdev, 0x62, &port_wake); | 230 | pci_read_config_word(pdev, 0x62, &port_wake); |
229 | if (port_wake & 0x0001) | 231 | if (port_wake & 0x0001) { |
232 | dev_warn(&pdev->dev, "Enabling legacy PCI PM\n"); | ||
230 | device_init_wakeup(&pdev->dev, 1); | 233 | device_init_wakeup(&pdev->dev, 1); |
234 | } | ||
231 | } | 235 | } |
232 | 236 | ||
233 | #ifdef CONFIG_USB_SUSPEND | 237 | #ifdef CONFIG_USB_SUSPEND |
@@ -428,6 +432,8 @@ static struct pci_driver ehci_pci_driver = { | |||
428 | 432 | ||
429 | #ifdef CONFIG_PM | 433 | #ifdef CONFIG_PM |
430 | .suspend = usb_hcd_pci_suspend, | 434 | .suspend = usb_hcd_pci_suspend, |
435 | .suspend_late = usb_hcd_pci_suspend_late, | ||
436 | .resume_early = usb_hcd_pci_resume_early, | ||
431 | .resume = usb_hcd_pci_resume, | 437 | .resume = usb_hcd_pci_resume, |
432 | #endif | 438 | #endif |
433 | .shutdown = usb_hcd_pci_shutdown, | 439 | .shutdown = usb_hcd_pci_shutdown, |
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index b018deed2e8f..ef732b704f53 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c | |||
@@ -107,11 +107,13 @@ ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | |||
107 | { | 107 | { |
108 | struct device_node *dn = op->node; | 108 | struct device_node *dn = op->node; |
109 | struct usb_hcd *hcd; | 109 | struct usb_hcd *hcd; |
110 | struct ehci_hcd *ehci; | 110 | struct ehci_hcd *ehci = NULL; |
111 | struct resource res; | 111 | struct resource res; |
112 | int irq; | 112 | int irq; |
113 | int rv; | 113 | int rv; |
114 | 114 | ||
115 | struct device_node *np; | ||
116 | |||
115 | if (usb_disabled()) | 117 | if (usb_disabled()) |
116 | return -ENODEV; | 118 | return -ENODEV; |
117 | 119 | ||
@@ -149,6 +151,20 @@ ehci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | |||
149 | } | 151 | } |
150 | 152 | ||
151 | ehci = hcd_to_ehci(hcd); | 153 | ehci = hcd_to_ehci(hcd); |
154 | np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx"); | ||
155 | if (np != NULL) { | ||
156 | /* claim we really affected by usb23 erratum */ | ||
157 | if (!of_address_to_resource(np, 0, &res)) | ||
158 | ehci->ohci_hcctrl_reg = ioremap(res.start + | ||
159 | OHCI_HCCTRL_OFFSET, OHCI_HCCTRL_LEN); | ||
160 | else | ||
161 | pr_debug(__FILE__ ": no ohci offset in fdt\n"); | ||
162 | if (!ehci->ohci_hcctrl_reg) { | ||
163 | pr_debug(__FILE__ ": ioremap for ohci hcctrl failed\n"); | ||
164 | } else { | ||
165 | ehci->has_amcc_usb23 = 1; | ||
166 | } | ||
167 | } | ||
152 | 168 | ||
153 | if (of_get_property(dn, "big-endian", NULL)) { | 169 | if (of_get_property(dn, "big-endian", NULL)) { |
154 | ehci->big_endian_mmio = 1; | 170 | ehci->big_endian_mmio = 1; |
@@ -181,6 +197,9 @@ err_ioremap: | |||
181 | irq_dispose_mapping(irq); | 197 | irq_dispose_mapping(irq); |
182 | err_irq: | 198 | err_irq: |
183 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 199 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
200 | |||
201 | if (ehci->has_amcc_usb23) | ||
202 | iounmap(ehci->ohci_hcctrl_reg); | ||
184 | err_rmr: | 203 | err_rmr: |
185 | usb_put_hcd(hcd); | 204 | usb_put_hcd(hcd); |
186 | 205 | ||
@@ -191,6 +210,11 @@ err_rmr: | |||
191 | static int ehci_hcd_ppc_of_remove(struct of_device *op) | 210 | static int ehci_hcd_ppc_of_remove(struct of_device *op) |
192 | { | 211 | { |
193 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 212 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); |
213 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
214 | |||
215 | struct device_node *np; | ||
216 | struct resource res; | ||
217 | |||
194 | dev_set_drvdata(&op->dev, NULL); | 218 | dev_set_drvdata(&op->dev, NULL); |
195 | 219 | ||
196 | dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); | 220 | dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); |
@@ -201,6 +225,25 @@ static int ehci_hcd_ppc_of_remove(struct of_device *op) | |||
201 | irq_dispose_mapping(hcd->irq); | 225 | irq_dispose_mapping(hcd->irq); |
202 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 226 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
203 | 227 | ||
228 | /* use request_mem_region to test if the ohci driver is loaded. if so | ||
229 | * ensure the ohci core is operational. | ||
230 | */ | ||
231 | if (ehci->has_amcc_usb23) { | ||
232 | np = of_find_compatible_node(NULL, NULL, "ibm,usb-ohci-440epx"); | ||
233 | if (np != NULL) { | ||
234 | if (!of_address_to_resource(np, 0, &res)) | ||
235 | if (!request_mem_region(res.start, | ||
236 | 0x4, hcd_name)) | ||
237 | set_ohci_hcfs(ehci, 1); | ||
238 | else | ||
239 | release_mem_region(res.start, 0x4); | ||
240 | else | ||
241 | pr_debug(__FILE__ ": no ohci offset in fdt\n"); | ||
242 | of_node_put(np); | ||
243 | } | ||
244 | |||
245 | iounmap(ehci->ohci_hcctrl_reg); | ||
246 | } | ||
204 | usb_put_hcd(hcd); | 247 | usb_put_hcd(hcd); |
205 | 248 | ||
206 | return 0; | 249 | return 0; |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index c7d4b5a06bdb..fb7054ccf4fc 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -120,6 +120,16 @@ struct ehci_hcd { /* one per controller */ | |||
120 | unsigned has_fsl_port_bug:1; /* FreeScale */ | 120 | unsigned has_fsl_port_bug:1; /* FreeScale */ |
121 | unsigned big_endian_mmio:1; | 121 | unsigned big_endian_mmio:1; |
122 | unsigned big_endian_desc:1; | 122 | unsigned big_endian_desc:1; |
123 | unsigned has_amcc_usb23:1; | ||
124 | |||
125 | /* required for usb32 quirk */ | ||
126 | #define OHCI_CTRL_HCFS (3 << 6) | ||
127 | #define OHCI_USB_OPER (2 << 6) | ||
128 | #define OHCI_USB_SUSPEND (3 << 6) | ||
129 | |||
130 | #define OHCI_HCCTRL_OFFSET 0x4 | ||
131 | #define OHCI_HCCTRL_LEN 0x4 | ||
132 | __hc32 *ohci_hcctrl_reg; | ||
123 | 133 | ||
124 | u8 sbrn; /* packed release number */ | 134 | u8 sbrn; /* packed release number */ |
125 | 135 | ||
@@ -636,6 +646,30 @@ static inline void ehci_writel(const struct ehci_hcd *ehci, | |||
636 | #endif | 646 | #endif |
637 | } | 647 | } |
638 | 648 | ||
649 | /* | ||
650 | * On certain ppc-44x SoC there is a HW issue, that could only worked around with | ||
651 | * explicit suspend/operate of OHCI. This function hereby makes sense only on that arch. | ||
652 | * Other common bits are dependant on has_amcc_usb23 quirk flag. | ||
653 | */ | ||
654 | #ifdef CONFIG_44x | ||
655 | static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) | ||
656 | { | ||
657 | u32 hc_control; | ||
658 | |||
659 | hc_control = (readl_be(ehci->ohci_hcctrl_reg) & ~OHCI_CTRL_HCFS); | ||
660 | if (operational) | ||
661 | hc_control |= OHCI_USB_OPER; | ||
662 | else | ||
663 | hc_control |= OHCI_USB_SUSPEND; | ||
664 | |||
665 | writel_be(hc_control, ehci->ohci_hcctrl_reg); | ||
666 | (void) readl_be(ehci->ohci_hcctrl_reg); | ||
667 | } | ||
668 | #else | ||
669 | static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) | ||
670 | { } | ||
671 | #endif | ||
672 | |||
639 | /*-------------------------------------------------------------------------*/ | 673 | /*-------------------------------------------------------------------------*/ |
640 | 674 | ||
641 | /* | 675 | /* |
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 8017f1cf78e2..b899f1a59c26 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c | |||
@@ -435,14 +435,13 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) | |||
435 | 435 | ||
436 | /* | 436 | /* |
437 | * PORT 1 Control register of the ISP1760 is the OTG control | 437 | * PORT 1 Control register of the ISP1760 is the OTG control |
438 | * register on ISP1761. | 438 | * register on ISP1761. Since there is no OTG or device controller |
439 | * support in this driver, we use port 1 as a "normal" USB host port on | ||
440 | * both chips. | ||
439 | */ | 441 | */ |
440 | if (!(priv->devflags & ISP1760_FLAG_ISP1761) && | 442 | isp1760_writel(PORT1_POWER | PORT1_INIT2, |
441 | !(priv->devflags & ISP1760_FLAG_PORT1_DIS)) { | 443 | hcd->regs + HC_PORT1_CTRL); |
442 | isp1760_writel(PORT1_POWER | PORT1_INIT2, | 444 | mdelay(10); |
443 | hcd->regs + HC_PORT1_CTRL); | ||
444 | mdelay(10); | ||
445 | } | ||
446 | 445 | ||
447 | priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS); | 446 | priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS); |
448 | 447 | ||
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index 4377277667d9..a9daea587962 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h | |||
@@ -135,7 +135,6 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, | |||
135 | * indicate the most "atypical" case, so that a devflags of 0 is | 135 | * indicate the most "atypical" case, so that a devflags of 0 is |
136 | * a sane default configuration. | 136 | * a sane default configuration. |
137 | */ | 137 | */ |
138 | #define ISP1760_FLAG_PORT1_DIS 0x00000001 /* Port 1 disabled */ | ||
139 | #define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */ | 138 | #define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */ |
140 | #define ISP1760_FLAG_OTG_EN 0x00000004 /* Port 1 supports OTG */ | 139 | #define ISP1760_FLAG_OTG_EN 0x00000004 /* Port 1 supports OTG */ |
141 | #define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */ | 140 | #define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */ |
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index b87ca7cf4b37..4cf7ca428b33 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
@@ -60,9 +60,6 @@ static int of_isp1760_probe(struct of_device *dev, | |||
60 | if (of_device_is_compatible(dp, "nxp,usb-isp1761")) | 60 | if (of_device_is_compatible(dp, "nxp,usb-isp1761")) |
61 | devflags |= ISP1760_FLAG_ISP1761; | 61 | devflags |= ISP1760_FLAG_ISP1761; |
62 | 62 | ||
63 | if (of_get_property(dp, "port1-disable", NULL) != NULL) | ||
64 | devflags |= ISP1760_FLAG_PORT1_DIS; | ||
65 | |||
66 | /* Some systems wire up only 16 of the 32 data lines */ | 63 | /* Some systems wire up only 16 of the 32 data lines */ |
67 | prop = of_get_property(dp, "bus-width", NULL); | 64 | prop = of_get_property(dp, "bus-width", NULL); |
68 | if (prop && *prop == 16) | 65 | if (prop && *prop == 16) |
@@ -129,23 +126,23 @@ static struct of_platform_driver isp1760_of_driver = { | |||
129 | #endif | 126 | #endif |
130 | 127 | ||
131 | #ifdef CONFIG_PCI | 128 | #ifdef CONFIG_PCI |
132 | static u32 nxp_pci_io_base; | ||
133 | static u32 iolength; | ||
134 | static u32 pci_mem_phy0; | ||
135 | static u32 length; | ||
136 | static u8 __iomem *chip_addr; | ||
137 | static u8 __iomem *iobase; | ||
138 | |||
139 | static int __devinit isp1761_pci_probe(struct pci_dev *dev, | 129 | static int __devinit isp1761_pci_probe(struct pci_dev *dev, |
140 | const struct pci_device_id *id) | 130 | const struct pci_device_id *id) |
141 | { | 131 | { |
142 | u8 latency, limit; | 132 | u8 latency, limit; |
143 | __u32 reg_data; | 133 | __u32 reg_data; |
144 | int retry_count; | 134 | int retry_count; |
145 | int length; | ||
146 | int status = 1; | ||
147 | struct usb_hcd *hcd; | 135 | struct usb_hcd *hcd; |
148 | unsigned int devflags = 0; | 136 | unsigned int devflags = 0; |
137 | int ret_status = 0; | ||
138 | |||
139 | resource_size_t pci_mem_phy0; | ||
140 | resource_size_t memlength; | ||
141 | |||
142 | u8 __iomem *chip_addr; | ||
143 | u8 __iomem *iobase; | ||
144 | resource_size_t nxp_pci_io_base; | ||
145 | resource_size_t iolength; | ||
149 | 146 | ||
150 | if (usb_disabled()) | 147 | if (usb_disabled()) |
151 | return -ENODEV; | 148 | return -ENODEV; |
@@ -168,26 +165,30 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, | |||
168 | iobase = ioremap_nocache(nxp_pci_io_base, iolength); | 165 | iobase = ioremap_nocache(nxp_pci_io_base, iolength); |
169 | if (!iobase) { | 166 | if (!iobase) { |
170 | printk(KERN_ERR "ioremap #1\n"); | 167 | printk(KERN_ERR "ioremap #1\n"); |
171 | release_mem_region(nxp_pci_io_base, iolength); | 168 | ret_status = -ENOMEM; |
172 | return -ENOMEM; | 169 | goto cleanup1; |
173 | } | 170 | } |
174 | /* Grab the PLX PCI shared memory of the ISP 1761 we need */ | 171 | /* Grab the PLX PCI shared memory of the ISP 1761 we need */ |
175 | pci_mem_phy0 = pci_resource_start(dev, 3); | 172 | pci_mem_phy0 = pci_resource_start(dev, 3); |
176 | length = pci_resource_len(dev, 3); | 173 | memlength = pci_resource_len(dev, 3); |
177 | 174 | if (memlength < 0xffff) { | |
178 | if (length < 0xffff) { | 175 | printk(KERN_ERR "memory length for this resource is wrong\n"); |
179 | printk(KERN_ERR "memory length for this resource is less than " | 176 | ret_status = -ENOMEM; |
180 | "required\n"); | 177 | goto cleanup2; |
181 | release_mem_region(nxp_pci_io_base, iolength); | ||
182 | iounmap(iobase); | ||
183 | return -ENOMEM; | ||
184 | } | 178 | } |
185 | 179 | ||
186 | if (!request_mem_region(pci_mem_phy0, length, "ISP-PCI")) { | 180 | if (!request_mem_region(pci_mem_phy0, memlength, "ISP-PCI")) { |
187 | printk(KERN_ERR "host controller already in use\n"); | 181 | printk(KERN_ERR "host controller already in use\n"); |
188 | release_mem_region(nxp_pci_io_base, iolength); | 182 | ret_status = -EBUSY; |
189 | iounmap(iobase); | 183 | goto cleanup2; |
190 | return -EBUSY; | 184 | } |
185 | |||
186 | /* map available memory */ | ||
187 | chip_addr = ioremap_nocache(pci_mem_phy0,memlength); | ||
188 | if (!chip_addr) { | ||
189 | printk(KERN_ERR "Error ioremap failed\n"); | ||
190 | ret_status = -ENOMEM; | ||
191 | goto cleanup3; | ||
191 | } | 192 | } |
192 | 193 | ||
193 | /* bad pci latencies can contribute to overruns */ | 194 | /* bad pci latencies can contribute to overruns */ |
@@ -210,39 +211,54 @@ static int __devinit isp1761_pci_probe(struct pci_dev *dev, | |||
210 | * */ | 211 | * */ |
211 | writel(0xface, chip_addr + HC_SCRATCH_REG); | 212 | writel(0xface, chip_addr + HC_SCRATCH_REG); |
212 | udelay(100); | 213 | udelay(100); |
213 | reg_data = readl(chip_addr + HC_SCRATCH_REG); | 214 | reg_data = readl(chip_addr + HC_SCRATCH_REG) & 0x0000ffff; |
214 | retry_count--; | 215 | retry_count--; |
215 | } | 216 | } |
216 | 217 | ||
218 | iounmap(chip_addr); | ||
219 | |||
217 | /* Host Controller presence is detected by writing to scratch register | 220 | /* Host Controller presence is detected by writing to scratch register |
218 | * and reading back and checking the contents are same or not | 221 | * and reading back and checking the contents are same or not |
219 | */ | 222 | */ |
220 | if (reg_data != 0xFACE) { | 223 | if (reg_data != 0xFACE) { |
221 | dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data); | 224 | dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data); |
222 | goto clean; | 225 | ret_status = -ENOMEM; |
226 | goto cleanup3; | ||
223 | } | 227 | } |
224 | 228 | ||
225 | pci_set_master(dev); | 229 | pci_set_master(dev); |
226 | 230 | ||
227 | status = readl(iobase + 0x68); | 231 | /* configure PLX PCI chip to pass interrupts */ |
228 | status |= 0x900; | 232 | #define PLX_INT_CSR_REG 0x68 |
229 | writel(status, iobase + 0x68); | 233 | reg_data = readl(iobase + PLX_INT_CSR_REG); |
234 | reg_data |= 0x900; | ||
235 | writel(reg_data, iobase + PLX_INT_CSR_REG); | ||
230 | 236 | ||
231 | dev->dev.dma_mask = NULL; | 237 | dev->dev.dma_mask = NULL; |
232 | hcd = isp1760_register(pci_mem_phy0, length, dev->irq, | 238 | hcd = isp1760_register(pci_mem_phy0, memlength, dev->irq, |
233 | IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), | 239 | IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev), |
234 | devflags); | 240 | devflags); |
235 | if (!IS_ERR(hcd)) { | 241 | if (IS_ERR(hcd)) { |
236 | pci_set_drvdata(dev, hcd); | 242 | ret_status = -ENODEV; |
237 | return 0; | 243 | goto cleanup3; |
238 | } | 244 | } |
239 | clean: | 245 | |
240 | status = -ENODEV; | 246 | /* done with PLX IO access */ |
247 | iounmap(iobase); | ||
248 | release_mem_region(nxp_pci_io_base, iolength); | ||
249 | |||
250 | pci_set_drvdata(dev, hcd); | ||
251 | return 0; | ||
252 | |||
253 | cleanup3: | ||
254 | release_mem_region(pci_mem_phy0, memlength); | ||
255 | cleanup2: | ||
241 | iounmap(iobase); | 256 | iounmap(iobase); |
242 | release_mem_region(pci_mem_phy0, length); | 257 | cleanup1: |
243 | release_mem_region(nxp_pci_io_base, iolength); | 258 | release_mem_region(nxp_pci_io_base, iolength); |
244 | return status; | 259 | return ret_status; |
245 | } | 260 | } |
261 | |||
246 | static void isp1761_pci_remove(struct pci_dev *dev) | 262 | static void isp1761_pci_remove(struct pci_dev *dev) |
247 | { | 263 | { |
248 | struct usb_hcd *hcd; | 264 | struct usb_hcd *hcd; |
@@ -255,12 +271,6 @@ static void isp1761_pci_remove(struct pci_dev *dev) | |||
255 | usb_put_hcd(hcd); | 271 | usb_put_hcd(hcd); |
256 | 272 | ||
257 | pci_disable_device(dev); | 273 | pci_disable_device(dev); |
258 | |||
259 | iounmap(iobase); | ||
260 | iounmap(chip_addr); | ||
261 | |||
262 | release_mem_region(nxp_pci_io_base, iolength); | ||
263 | release_mem_region(pci_mem_phy0, length); | ||
264 | } | 274 | } |
265 | 275 | ||
266 | static void isp1761_pci_shutdown(struct pci_dev *dev) | 276 | static void isp1761_pci_shutdown(struct pci_dev *dev) |
@@ -268,12 +278,16 @@ static void isp1761_pci_shutdown(struct pci_dev *dev) | |||
268 | printk(KERN_ERR "ips1761_pci_shutdown\n"); | 278 | printk(KERN_ERR "ips1761_pci_shutdown\n"); |
269 | } | 279 | } |
270 | 280 | ||
271 | static const struct pci_device_id isp1760_plx [] = { { | 281 | static const struct pci_device_id isp1760_plx [] = { |
272 | /* handle any USB 2.0 EHCI controller */ | 282 | { |
273 | PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_OTHER << 8) | (0x06 << 16)), ~0), | 283 | .class = PCI_CLASS_BRIDGE_OTHER << 8, |
274 | .driver_data = 0, | 284 | .class_mask = ~0, |
275 | }, | 285 | .vendor = PCI_VENDOR_ID_PLX, |
276 | { /* end: all zeroes */ } | 286 | .device = 0x5406, |
287 | .subvendor = PCI_VENDOR_ID_PLX, | ||
288 | .subdevice = 0x9054, | ||
289 | }, | ||
290 | { } | ||
277 | }; | 291 | }; |
278 | MODULE_DEVICE_TABLE(pci, isp1760_plx); | 292 | MODULE_DEVICE_TABLE(pci, isp1760_plx); |
279 | 293 | ||
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 8aa3f4556a32..65a9609f4ad6 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -589,13 +589,15 @@ static int ohci_run (struct ohci_hcd *ohci) | |||
589 | /* also: power/overcurrent flags in roothub.a */ | 589 | /* also: power/overcurrent flags in roothub.a */ |
590 | } | 590 | } |
591 | 591 | ||
592 | /* Reset USB nearly "by the book". RemoteWakeupConnected was | 592 | /* Reset USB nearly "by the book". RemoteWakeupConnected has |
593 | * saved if boot firmware (BIOS/SMM/...) told us it's connected, | 593 | * to be checked in case boot firmware (BIOS/SMM/...) has set up |
594 | * or if bus glue did the same (e.g. for PCI add-in cards with | 594 | * wakeup in a way the bus isn't aware of (e.g., legacy PCI PM). |
595 | * PCI PM support). | 595 | * If the bus glue detected wakeup capability then it should |
596 | * already be enabled. Either way, if wakeup should be enabled | ||
597 | * but isn't, we'll enable it now. | ||
596 | */ | 598 | */ |
597 | if ((ohci->hc_control & OHCI_CTRL_RWC) != 0 | 599 | if ((ohci->hc_control & OHCI_CTRL_RWC) != 0 |
598 | && !device_may_wakeup(hcd->self.controller)) | 600 | && !device_can_wakeup(hcd->self.controller)) |
599 | device_init_wakeup(hcd->self.controller, 1); | 601 | device_init_wakeup(hcd->self.controller, 1); |
600 | 602 | ||
601 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { | 603 | switch (ohci->hc_control & OHCI_CTRL_HCFS) { |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index a9c2ae36c7ad..8b28ae7865ba 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -355,9 +355,9 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd) | |||
355 | 355 | ||
356 | /* RWC may not be set for add-in PCI cards, since boot | 356 | /* RWC may not be set for add-in PCI cards, since boot |
357 | * firmware probably ignored them. This transfers PCI | 357 | * firmware probably ignored them. This transfers PCI |
358 | * PM wakeup capabilities (once the PCI layer is fixed). | 358 | * PM wakeup capabilities. |
359 | */ | 359 | */ |
360 | if (device_may_wakeup(&pdev->dev)) | 360 | if (device_can_wakeup(&pdev->dev)) |
361 | ohci->hc_control |= OHCI_CTRL_RWC; | 361 | ohci->hc_control |= OHCI_CTRL_RWC; |
362 | } | 362 | } |
363 | #endif /* CONFIG_PM */ | 363 | #endif /* CONFIG_PM */ |
@@ -487,6 +487,8 @@ static struct pci_driver ohci_pci_driver = { | |||
487 | 487 | ||
488 | #ifdef CONFIG_PM | 488 | #ifdef CONFIG_PM |
489 | .suspend = usb_hcd_pci_suspend, | 489 | .suspend = usb_hcd_pci_suspend, |
490 | .suspend_late = usb_hcd_pci_suspend_late, | ||
491 | .resume_early = usb_hcd_pci_resume_early, | ||
490 | .resume = usb_hcd_pci_resume, | 492 | .resume = usb_hcd_pci_resume, |
491 | #endif | 493 | #endif |
492 | 494 | ||
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index e306ca6aef3d..100bf3d8437c 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c | |||
@@ -106,65 +106,34 @@ extern int ocpi_enable(void); | |||
106 | 106 | ||
107 | static struct clk *usb_clk; | 107 | static struct clk *usb_clk; |
108 | 108 | ||
109 | static int isp1301_probe(struct i2c_adapter *adap); | ||
110 | static int isp1301_detach(struct i2c_client *client); | ||
111 | |||
112 | static const unsigned short normal_i2c[] = | 109 | static const unsigned short normal_i2c[] = |
113 | { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END }; | 110 | { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END }; |
114 | static const unsigned short dummy_i2c_addrlist[] = { I2C_CLIENT_END }; | ||
115 | |||
116 | static struct i2c_client_address_data addr_data = { | ||
117 | .normal_i2c = normal_i2c, | ||
118 | .probe = dummy_i2c_addrlist, | ||
119 | .ignore = dummy_i2c_addrlist, | ||
120 | }; | ||
121 | |||
122 | struct i2c_driver isp1301_driver = { | ||
123 | .driver = { | ||
124 | .name = "isp1301_pnx", | ||
125 | }, | ||
126 | .attach_adapter = isp1301_probe, | ||
127 | .detach_client = isp1301_detach, | ||
128 | }; | ||
129 | 111 | ||
130 | static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind) | 112 | static int isp1301_probe(struct i2c_client *client, |
113 | const struct i2c_device_id *id) | ||
131 | { | 114 | { |
132 | struct i2c_client *c; | ||
133 | int err; | ||
134 | |||
135 | c = kzalloc(sizeof(*c), GFP_KERNEL); | ||
136 | if (!c) | ||
137 | return -ENOMEM; | ||
138 | |||
139 | strlcpy(c->name, "isp1301_pnx", I2C_NAME_SIZE); | ||
140 | c->flags = 0; | ||
141 | c->addr = addr; | ||
142 | c->adapter = adap; | ||
143 | c->driver = &isp1301_driver; | ||
144 | |||
145 | err = i2c_attach_client(c); | ||
146 | if (err) { | ||
147 | kfree(c); | ||
148 | return err; | ||
149 | } | ||
150 | |||
151 | isp1301_i2c_client = c; | ||
152 | |||
153 | return 0; | 115 | return 0; |
154 | } | 116 | } |
155 | 117 | ||
156 | static int isp1301_probe(struct i2c_adapter *adap) | 118 | static int isp1301_remove(struct i2c_client *client) |
157 | { | 119 | { |
158 | return i2c_probe(adap, &addr_data, isp1301_attach); | ||
159 | } | ||
160 | |||
161 | static int isp1301_detach(struct i2c_client *client) | ||
162 | { | ||
163 | i2c_detach_client(client); | ||
164 | kfree(isp1301_i2c_client); | ||
165 | return 0; | 120 | return 0; |
166 | } | 121 | } |
167 | 122 | ||
123 | const struct i2c_device_id isp1301_id[] = { | ||
124 | { "isp1301_pnx", 0 }, | ||
125 | { } | ||
126 | }; | ||
127 | |||
128 | struct i2c_driver isp1301_driver = { | ||
129 | .driver = { | ||
130 | .name = "isp1301_pnx", | ||
131 | }, | ||
132 | .probe = isp1301_probe, | ||
133 | .remove = isp1301_remove, | ||
134 | .id_table = isp1301_id, | ||
135 | }; | ||
136 | |||
168 | static void i2c_write(u8 buf, u8 subaddr) | 137 | static void i2c_write(u8 buf, u8 subaddr) |
169 | { | 138 | { |
170 | char tmpbuf[2]; | 139 | char tmpbuf[2]; |
@@ -328,6 +297,8 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) | |||
328 | struct usb_hcd *hcd = 0; | 297 | struct usb_hcd *hcd = 0; |
329 | struct ohci_hcd *ohci; | 298 | struct ohci_hcd *ohci; |
330 | const struct hc_driver *driver = &ohci_pnx4008_hc_driver; | 299 | const struct hc_driver *driver = &ohci_pnx4008_hc_driver; |
300 | struct i2c_adapter *i2c_adap; | ||
301 | struct i2c_board_info i2c_info; | ||
331 | 302 | ||
332 | int ret = 0, irq; | 303 | int ret = 0, irq; |
333 | 304 | ||
@@ -351,9 +322,20 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) | |||
351 | 322 | ||
352 | ret = i2c_add_driver(&isp1301_driver); | 323 | ret = i2c_add_driver(&isp1301_driver); |
353 | if (ret < 0) { | 324 | if (ret < 0) { |
354 | err("failed to connect I2C to ISP1301 USB Transceiver"); | 325 | err("failed to add ISP1301 driver"); |
355 | goto out; | 326 | goto out; |
356 | } | 327 | } |
328 | i2c_adap = i2c_get_adapter(2); | ||
329 | memset(&i2c_info, 0, sizeof(struct i2c_board_info)); | ||
330 | strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE); | ||
331 | isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info, | ||
332 | normal_i2c); | ||
333 | i2c_put_adapter(i2c_adap); | ||
334 | if (!isp1301_i2c_client) { | ||
335 | err("failed to connect I2C to ISP1301 USB Transceiver"); | ||
336 | ret = -ENODEV; | ||
337 | goto out_i2c_driver; | ||
338 | } | ||
357 | 339 | ||
358 | isp1301_configure(); | 340 | isp1301_configure(); |
359 | 341 | ||
@@ -429,6 +411,9 @@ out3: | |||
429 | out2: | 411 | out2: |
430 | clk_put(usb_clk); | 412 | clk_put(usb_clk); |
431 | out1: | 413 | out1: |
414 | i2c_unregister_client(isp1301_i2c_client); | ||
415 | isp1301_i2c_client = NULL; | ||
416 | out_i2c_driver: | ||
432 | i2c_del_driver(&isp1301_driver); | 417 | i2c_del_driver(&isp1301_driver); |
433 | out: | 418 | out: |
434 | return ret; | 419 | return ret; |
@@ -445,6 +430,8 @@ static int usb_hcd_pnx4008_remove(struct platform_device *pdev) | |||
445 | pnx4008_unset_usb_bits(); | 430 | pnx4008_unset_usb_bits(); |
446 | clk_disable(usb_clk); | 431 | clk_disable(usb_clk); |
447 | clk_put(usb_clk); | 432 | clk_put(usb_clk); |
433 | i2c_unregister_client(isp1301_i2c_client); | ||
434 | isp1301_i2c_client = NULL; | ||
448 | i2c_del_driver(&isp1301_driver); | 435 | i2c_del_driver(&isp1301_driver); |
449 | 436 | ||
450 | platform_set_drvdata(pdev, NULL); | 437 | platform_set_drvdata(pdev, NULL); |
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 7ac53264ead3..68a301710297 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c | |||
@@ -91,6 +91,7 @@ ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | |||
91 | 91 | ||
92 | int rv; | 92 | int rv; |
93 | int is_bigendian; | 93 | int is_bigendian; |
94 | struct device_node *np; | ||
94 | 95 | ||
95 | if (usb_disabled()) | 96 | if (usb_disabled()) |
96 | return -ENODEV; | 97 | return -ENODEV; |
@@ -147,6 +148,30 @@ ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) | |||
147 | if (rv == 0) | 148 | if (rv == 0) |
148 | return 0; | 149 | return 0; |
149 | 150 | ||
151 | /* by now, 440epx is known to show usb_23 erratum */ | ||
152 | np = of_find_compatible_node(NULL, NULL, "ibm,usb-ehci-440epx"); | ||
153 | |||
154 | /* Work around - At this point ohci_run has executed, the | ||
155 | * controller is running, everything, the root ports, etc., is | ||
156 | * set up. If the ehci driver is loaded, put the ohci core in | ||
157 | * the suspended state. The ehci driver will bring it out of | ||
158 | * suspended state when / if a non-high speed USB device is | ||
159 | * attached to the USB Host port. If the ehci driver is not | ||
160 | * loaded, do nothing. request_mem_region is used to test if | ||
161 | * the ehci driver is loaded. | ||
162 | */ | ||
163 | if (np != NULL) { | ||
164 | if (!of_address_to_resource(np, 0, &res)) { | ||
165 | if (!request_mem_region(res.start, 0x4, hcd_name)) { | ||
166 | writel_be((readl_be(&ohci->regs->control) | | ||
167 | OHCI_USB_SUSPEND), &ohci->regs->control); | ||
168 | (void) readl_be(&ohci->regs->control); | ||
169 | } else | ||
170 | release_mem_region(res.start, 0x4); | ||
171 | } else | ||
172 | pr_debug(__FILE__ ": cannot get ehci offset from fdt\n"); | ||
173 | } | ||
174 | |||
150 | iounmap(hcd->regs); | 175 | iounmap(hcd->regs); |
151 | err_ioremap: | 176 | err_ioremap: |
152 | irq_dispose_mapping(irq); | 177 | irq_dispose_mapping(irq); |
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index f9f134af0bd1..8dabe8e31d8c 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c | |||
@@ -201,7 +201,7 @@ static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev) | |||
201 | if (!cell) | 201 | if (!cell) |
202 | return -EINVAL; | 202 | return -EINVAL; |
203 | 203 | ||
204 | hcd = usb_create_hcd(&ohci_tmio_hc_driver, &dev->dev, dev->dev.bus_id); | 204 | hcd = usb_create_hcd(&ohci_tmio_hc_driver, &dev->dev, dev_name(&dev->dev)); |
205 | if (!hcd) { | 205 | if (!hcd) { |
206 | ret = -ENOMEM; | 206 | ret = -ENOMEM; |
207 | goto err_usb_create_hcd; | 207 | goto err_usb_create_hcd; |
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c new file mode 100644 index 000000000000..75548f7c716b --- /dev/null +++ b/drivers/usb/host/oxu210hp-hcd.c | |||
@@ -0,0 +1,3985 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Rodolfo Giometti <giometti@linux.it> | ||
3 | * Copyright (c) 2008 Eurotech S.p.A. <info@eurtech.it> | ||
4 | * | ||
5 | * This code is *strongly* based on EHCI-HCD code by David Brownell since | ||
6 | * the chip is a quasi-EHCI compatible. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
15 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
16 | * for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software Foundation, | ||
20 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/dmapool.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/ioport.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/errno.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/timer.h> | ||
34 | #include <linux/list.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/reboot.h> | ||
37 | #include <linux/usb.h> | ||
38 | #include <linux/moduleparam.h> | ||
39 | #include <linux/dma-mapping.h> | ||
40 | #include <linux/io.h> | ||
41 | |||
42 | #include "../core/hcd.h" | ||
43 | |||
44 | #include <asm/irq.h> | ||
45 | #include <asm/system.h> | ||
46 | #include <asm/unaligned.h> | ||
47 | |||
48 | #include <linux/irq.h> | ||
49 | #include <linux/platform_device.h> | ||
50 | |||
51 | #include "oxu210hp.h" | ||
52 | |||
53 | #define DRIVER_VERSION "0.0.50" | ||
54 | |||
55 | /* | ||
56 | * Main defines | ||
57 | */ | ||
58 | |||
59 | #define oxu_dbg(oxu, fmt, args...) \ | ||
60 | dev_dbg(oxu_to_hcd(oxu)->self.controller , fmt , ## args) | ||
61 | #define oxu_err(oxu, fmt, args...) \ | ||
62 | dev_err(oxu_to_hcd(oxu)->self.controller , fmt , ## args) | ||
63 | #define oxu_info(oxu, fmt, args...) \ | ||
64 | dev_info(oxu_to_hcd(oxu)->self.controller , fmt , ## args) | ||
65 | |||
66 | static inline struct usb_hcd *oxu_to_hcd(struct oxu_hcd *oxu) | ||
67 | { | ||
68 | return container_of((void *) oxu, struct usb_hcd, hcd_priv); | ||
69 | } | ||
70 | |||
71 | static inline struct oxu_hcd *hcd_to_oxu(struct usb_hcd *hcd) | ||
72 | { | ||
73 | return (struct oxu_hcd *) (hcd->hcd_priv); | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Debug stuff | ||
78 | */ | ||
79 | |||
80 | #undef OXU_URB_TRACE | ||
81 | #undef OXU_VERBOSE_DEBUG | ||
82 | |||
83 | #ifdef OXU_VERBOSE_DEBUG | ||
84 | #define oxu_vdbg oxu_dbg | ||
85 | #else | ||
86 | #define oxu_vdbg(oxu, fmt, args...) /* Nop */ | ||
87 | #endif | ||
88 | |||
89 | #ifdef DEBUG | ||
90 | |||
91 | static int __attribute__((__unused__)) | ||
92 | dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) | ||
93 | { | ||
94 | return scnprintf(buf, len, "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", | ||
95 | label, label[0] ? " " : "", status, | ||
96 | (status & STS_ASS) ? " Async" : "", | ||
97 | (status & STS_PSS) ? " Periodic" : "", | ||
98 | (status & STS_RECL) ? " Recl" : "", | ||
99 | (status & STS_HALT) ? " Halt" : "", | ||
100 | (status & STS_IAA) ? " IAA" : "", | ||
101 | (status & STS_FATAL) ? " FATAL" : "", | ||
102 | (status & STS_FLR) ? " FLR" : "", | ||
103 | (status & STS_PCD) ? " PCD" : "", | ||
104 | (status & STS_ERR) ? " ERR" : "", | ||
105 | (status & STS_INT) ? " INT" : "" | ||
106 | ); | ||
107 | } | ||
108 | |||
109 | static int __attribute__((__unused__)) | ||
110 | dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) | ||
111 | { | ||
112 | return scnprintf(buf, len, "%s%sintrenable %02x%s%s%s%s%s%s", | ||
113 | label, label[0] ? " " : "", enable, | ||
114 | (enable & STS_IAA) ? " IAA" : "", | ||
115 | (enable & STS_FATAL) ? " FATAL" : "", | ||
116 | (enable & STS_FLR) ? " FLR" : "", | ||
117 | (enable & STS_PCD) ? " PCD" : "", | ||
118 | (enable & STS_ERR) ? " ERR" : "", | ||
119 | (enable & STS_INT) ? " INT" : "" | ||
120 | ); | ||
121 | } | ||
122 | |||
123 | static const char *const fls_strings[] = | ||
124 | { "1024", "512", "256", "??" }; | ||
125 | |||
126 | static int dbg_command_buf(char *buf, unsigned len, | ||
127 | const char *label, u32 command) | ||
128 | { | ||
129 | return scnprintf(buf, len, | ||
130 | "%s%scommand %06x %s=%d ithresh=%d%s%s%s%s period=%s%s %s", | ||
131 | label, label[0] ? " " : "", command, | ||
132 | (command & CMD_PARK) ? "park" : "(park)", | ||
133 | CMD_PARK_CNT(command), | ||
134 | (command >> 16) & 0x3f, | ||
135 | (command & CMD_LRESET) ? " LReset" : "", | ||
136 | (command & CMD_IAAD) ? " IAAD" : "", | ||
137 | (command & CMD_ASE) ? " Async" : "", | ||
138 | (command & CMD_PSE) ? " Periodic" : "", | ||
139 | fls_strings[(command >> 2) & 0x3], | ||
140 | (command & CMD_RESET) ? " Reset" : "", | ||
141 | (command & CMD_RUN) ? "RUN" : "HALT" | ||
142 | ); | ||
143 | } | ||
144 | |||
145 | static int dbg_port_buf(char *buf, unsigned len, const char *label, | ||
146 | int port, u32 status) | ||
147 | { | ||
148 | char *sig; | ||
149 | |||
150 | /* signaling state */ | ||
151 | switch (status & (3 << 10)) { | ||
152 | case 0 << 10: | ||
153 | sig = "se0"; | ||
154 | break; | ||
155 | case 1 << 10: | ||
156 | sig = "k"; /* low speed */ | ||
157 | break; | ||
158 | case 2 << 10: | ||
159 | sig = "j"; | ||
160 | break; | ||
161 | default: | ||
162 | sig = "?"; | ||
163 | break; | ||
164 | } | ||
165 | |||
166 | return scnprintf(buf, len, | ||
167 | "%s%sport %d status %06x%s%s sig=%s%s%s%s%s%s%s%s%s%s", | ||
168 | label, label[0] ? " " : "", port, status, | ||
169 | (status & PORT_POWER) ? " POWER" : "", | ||
170 | (status & PORT_OWNER) ? " OWNER" : "", | ||
171 | sig, | ||
172 | (status & PORT_RESET) ? " RESET" : "", | ||
173 | (status & PORT_SUSPEND) ? " SUSPEND" : "", | ||
174 | (status & PORT_RESUME) ? " RESUME" : "", | ||
175 | (status & PORT_OCC) ? " OCC" : "", | ||
176 | (status & PORT_OC) ? " OC" : "", | ||
177 | (status & PORT_PEC) ? " PEC" : "", | ||
178 | (status & PORT_PE) ? " PE" : "", | ||
179 | (status & PORT_CSC) ? " CSC" : "", | ||
180 | (status & PORT_CONNECT) ? " CONNECT" : "" | ||
181 | ); | ||
182 | } | ||
183 | |||
184 | #else | ||
185 | |||
186 | static inline int __attribute__((__unused__)) | ||
187 | dbg_status_buf(char *buf, unsigned len, const char *label, u32 status) | ||
188 | { return 0; } | ||
189 | |||
190 | static inline int __attribute__((__unused__)) | ||
191 | dbg_command_buf(char *buf, unsigned len, const char *label, u32 command) | ||
192 | { return 0; } | ||
193 | |||
194 | static inline int __attribute__((__unused__)) | ||
195 | dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable) | ||
196 | { return 0; } | ||
197 | |||
198 | static inline int __attribute__((__unused__)) | ||
199 | dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status) | ||
200 | { return 0; } | ||
201 | |||
202 | #endif /* DEBUG */ | ||
203 | |||
204 | /* functions have the "wrong" filename when they're output... */ | ||
205 | #define dbg_status(oxu, label, status) { \ | ||
206 | char _buf[80]; \ | ||
207 | dbg_status_buf(_buf, sizeof _buf, label, status); \ | ||
208 | oxu_dbg(oxu, "%s\n", _buf); \ | ||
209 | } | ||
210 | |||
211 | #define dbg_cmd(oxu, label, command) { \ | ||
212 | char _buf[80]; \ | ||
213 | dbg_command_buf(_buf, sizeof _buf, label, command); \ | ||
214 | oxu_dbg(oxu, "%s\n", _buf); \ | ||
215 | } | ||
216 | |||
217 | #define dbg_port(oxu, label, port, status) { \ | ||
218 | char _buf[80]; \ | ||
219 | dbg_port_buf(_buf, sizeof _buf, label, port, status); \ | ||
220 | oxu_dbg(oxu, "%s\n", _buf); \ | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Module parameters | ||
225 | */ | ||
226 | |||
227 | /* Initial IRQ latency: faster than hw default */ | ||
228 | static int log2_irq_thresh; /* 0 to 6 */ | ||
229 | module_param(log2_irq_thresh, int, S_IRUGO); | ||
230 | MODULE_PARM_DESC(log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); | ||
231 | |||
232 | /* Initial park setting: slower than hw default */ | ||
233 | static unsigned park; | ||
234 | module_param(park, uint, S_IRUGO); | ||
235 | MODULE_PARM_DESC(park, "park setting; 1-3 back-to-back async packets"); | ||
236 | |||
237 | /* For flakey hardware, ignore overcurrent indicators */ | ||
238 | static int ignore_oc; | ||
239 | module_param(ignore_oc, bool, S_IRUGO); | ||
240 | MODULE_PARM_DESC(ignore_oc, "ignore bogus hardware overcurrent indications"); | ||
241 | |||
242 | |||
243 | static void ehci_work(struct oxu_hcd *oxu); | ||
244 | static int oxu_hub_control(struct usb_hcd *hcd, | ||
245 | u16 typeReq, u16 wValue, u16 wIndex, | ||
246 | char *buf, u16 wLength); | ||
247 | |||
248 | /* | ||
249 | * Local functions | ||
250 | */ | ||
251 | |||
252 | /* Low level read/write registers functions */ | ||
253 | static inline u32 oxu_readl(void *base, u32 reg) | ||
254 | { | ||
255 | return readl(base + reg); | ||
256 | } | ||
257 | |||
258 | static inline void oxu_writel(void *base, u32 reg, u32 val) | ||
259 | { | ||
260 | writel(val, base + reg); | ||
261 | } | ||
262 | |||
263 | static inline void timer_action_done(struct oxu_hcd *oxu, | ||
264 | enum ehci_timer_action action) | ||
265 | { | ||
266 | clear_bit(action, &oxu->actions); | ||
267 | } | ||
268 | |||
269 | static inline void timer_action(struct oxu_hcd *oxu, | ||
270 | enum ehci_timer_action action) | ||
271 | { | ||
272 | if (!test_and_set_bit(action, &oxu->actions)) { | ||
273 | unsigned long t; | ||
274 | |||
275 | switch (action) { | ||
276 | case TIMER_IAA_WATCHDOG: | ||
277 | t = EHCI_IAA_JIFFIES; | ||
278 | break; | ||
279 | case TIMER_IO_WATCHDOG: | ||
280 | t = EHCI_IO_JIFFIES; | ||
281 | break; | ||
282 | case TIMER_ASYNC_OFF: | ||
283 | t = EHCI_ASYNC_JIFFIES; | ||
284 | break; | ||
285 | case TIMER_ASYNC_SHRINK: | ||
286 | default: | ||
287 | t = EHCI_SHRINK_JIFFIES; | ||
288 | break; | ||
289 | } | ||
290 | t += jiffies; | ||
291 | /* all timings except IAA watchdog can be overridden. | ||
292 | * async queue SHRINK often precedes IAA. while it's ready | ||
293 | * to go OFF neither can matter, and afterwards the IO | ||
294 | * watchdog stops unless there's still periodic traffic. | ||
295 | */ | ||
296 | if (action != TIMER_IAA_WATCHDOG | ||
297 | && t > oxu->watchdog.expires | ||
298 | && timer_pending(&oxu->watchdog)) | ||
299 | return; | ||
300 | mod_timer(&oxu->watchdog, t); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * handshake - spin reading hc until handshake completes or fails | ||
306 | * @ptr: address of hc register to be read | ||
307 | * @mask: bits to look at in result of read | ||
308 | * @done: value of those bits when handshake succeeds | ||
309 | * @usec: timeout in microseconds | ||
310 | * | ||
311 | * Returns negative errno, or zero on success | ||
312 | * | ||
313 | * Success happens when the "mask" bits have the specified value (hardware | ||
314 | * handshake done). There are two failure modes: "usec" have passed (major | ||
315 | * hardware flakeout), or the register reads as all-ones (hardware removed). | ||
316 | * | ||
317 | * That last failure should_only happen in cases like physical cardbus eject | ||
318 | * before driver shutdown. But it also seems to be caused by bugs in cardbus | ||
319 | * bridge shutdown: shutting down the bridge before the devices using it. | ||
320 | */ | ||
321 | static int handshake(struct oxu_hcd *oxu, void __iomem *ptr, | ||
322 | u32 mask, u32 done, int usec) | ||
323 | { | ||
324 | u32 result; | ||
325 | |||
326 | do { | ||
327 | result = readl(ptr); | ||
328 | if (result == ~(u32)0) /* card removed */ | ||
329 | return -ENODEV; | ||
330 | result &= mask; | ||
331 | if (result == done) | ||
332 | return 0; | ||
333 | udelay(1); | ||
334 | usec--; | ||
335 | } while (usec > 0); | ||
336 | return -ETIMEDOUT; | ||
337 | } | ||
338 | |||
339 | /* Force HC to halt state from unknown (EHCI spec section 2.3) */ | ||
340 | static int ehci_halt(struct oxu_hcd *oxu) | ||
341 | { | ||
342 | u32 temp = readl(&oxu->regs->status); | ||
343 | |||
344 | /* disable any irqs left enabled by previous code */ | ||
345 | writel(0, &oxu->regs->intr_enable); | ||
346 | |||
347 | if ((temp & STS_HALT) != 0) | ||
348 | return 0; | ||
349 | |||
350 | temp = readl(&oxu->regs->command); | ||
351 | temp &= ~CMD_RUN; | ||
352 | writel(temp, &oxu->regs->command); | ||
353 | return handshake(oxu, &oxu->regs->status, | ||
354 | STS_HALT, STS_HALT, 16 * 125); | ||
355 | } | ||
356 | |||
357 | /* Put TDI/ARC silicon into EHCI mode */ | ||
358 | static void tdi_reset(struct oxu_hcd *oxu) | ||
359 | { | ||
360 | u32 __iomem *reg_ptr; | ||
361 | u32 tmp; | ||
362 | |||
363 | reg_ptr = (u32 __iomem *)(((u8 __iomem *)oxu->regs) + 0x68); | ||
364 | tmp = readl(reg_ptr); | ||
365 | tmp |= 0x3; | ||
366 | writel(tmp, reg_ptr); | ||
367 | } | ||
368 | |||
369 | /* Reset a non-running (STS_HALT == 1) controller */ | ||
370 | static int ehci_reset(struct oxu_hcd *oxu) | ||
371 | { | ||
372 | int retval; | ||
373 | u32 command = readl(&oxu->regs->command); | ||
374 | |||
375 | command |= CMD_RESET; | ||
376 | dbg_cmd(oxu, "reset", command); | ||
377 | writel(command, &oxu->regs->command); | ||
378 | oxu_to_hcd(oxu)->state = HC_STATE_HALT; | ||
379 | oxu->next_statechange = jiffies; | ||
380 | retval = handshake(oxu, &oxu->regs->command, | ||
381 | CMD_RESET, 0, 250 * 1000); | ||
382 | |||
383 | if (retval) | ||
384 | return retval; | ||
385 | |||
386 | tdi_reset(oxu); | ||
387 | |||
388 | return retval; | ||
389 | } | ||
390 | |||
391 | /* Idle the controller (from running) */ | ||
392 | static void ehci_quiesce(struct oxu_hcd *oxu) | ||
393 | { | ||
394 | u32 temp; | ||
395 | |||
396 | #ifdef DEBUG | ||
397 | if (!HC_IS_RUNNING(oxu_to_hcd(oxu)->state)) | ||
398 | BUG(); | ||
399 | #endif | ||
400 | |||
401 | /* wait for any schedule enables/disables to take effect */ | ||
402 | temp = readl(&oxu->regs->command) << 10; | ||
403 | temp &= STS_ASS | STS_PSS; | ||
404 | if (handshake(oxu, &oxu->regs->status, STS_ASS | STS_PSS, | ||
405 | temp, 16 * 125) != 0) { | ||
406 | oxu_to_hcd(oxu)->state = HC_STATE_HALT; | ||
407 | return; | ||
408 | } | ||
409 | |||
410 | /* then disable anything that's still active */ | ||
411 | temp = readl(&oxu->regs->command); | ||
412 | temp &= ~(CMD_ASE | CMD_IAAD | CMD_PSE); | ||
413 | writel(temp, &oxu->regs->command); | ||
414 | |||
415 | /* hardware can take 16 microframes to turn off ... */ | ||
416 | if (handshake(oxu, &oxu->regs->status, STS_ASS | STS_PSS, | ||
417 | 0, 16 * 125) != 0) { | ||
418 | oxu_to_hcd(oxu)->state = HC_STATE_HALT; | ||
419 | return; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | static int check_reset_complete(struct oxu_hcd *oxu, int index, | ||
424 | u32 __iomem *status_reg, int port_status) | ||
425 | { | ||
426 | if (!(port_status & PORT_CONNECT)) { | ||
427 | oxu->reset_done[index] = 0; | ||
428 | return port_status; | ||
429 | } | ||
430 | |||
431 | /* if reset finished and it's still not enabled -- handoff */ | ||
432 | if (!(port_status & PORT_PE)) { | ||
433 | oxu_dbg(oxu, "Failed to enable port %d on root hub TT\n", | ||
434 | index+1); | ||
435 | return port_status; | ||
436 | } else | ||
437 | oxu_dbg(oxu, "port %d high speed\n", index + 1); | ||
438 | |||
439 | return port_status; | ||
440 | } | ||
441 | |||
442 | static void ehci_hub_descriptor(struct oxu_hcd *oxu, | ||
443 | struct usb_hub_descriptor *desc) | ||
444 | { | ||
445 | int ports = HCS_N_PORTS(oxu->hcs_params); | ||
446 | u16 temp; | ||
447 | |||
448 | desc->bDescriptorType = 0x29; | ||
449 | desc->bPwrOn2PwrGood = 10; /* oxu 1.0, 2.3.9 says 20ms max */ | ||
450 | desc->bHubContrCurrent = 0; | ||
451 | |||
452 | desc->bNbrPorts = ports; | ||
453 | temp = 1 + (ports / 8); | ||
454 | desc->bDescLength = 7 + 2 * temp; | ||
455 | |||
456 | /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ | ||
457 | memset(&desc->bitmap[0], 0, temp); | ||
458 | memset(&desc->bitmap[temp], 0xff, temp); | ||
459 | |||
460 | temp = 0x0008; /* per-port overcurrent reporting */ | ||
461 | if (HCS_PPC(oxu->hcs_params)) | ||
462 | temp |= 0x0001; /* per-port power control */ | ||
463 | else | ||
464 | temp |= 0x0002; /* no power switching */ | ||
465 | desc->wHubCharacteristics = (__force __u16)cpu_to_le16(temp); | ||
466 | } | ||
467 | |||
468 | |||
469 | /* Allocate an OXU210HP on-chip memory data buffer | ||
470 | * | ||
471 | * An on-chip memory data buffer is required for each OXU210HP USB transfer. | ||
472 | * Each transfer descriptor has one or more on-chip memory data buffers. | ||
473 | * | ||
474 | * Data buffers are allocated from a fix sized pool of data blocks. | ||
475 | * To minimise fragmentation and give reasonable memory utlisation, | ||
476 | * data buffers are allocated with sizes the power of 2 multiples of | ||
477 | * the block size, starting on an address a multiple of the allocated size. | ||
478 | * | ||
479 | * FIXME: callers of this function require a buffer to be allocated for | ||
480 | * len=0. This is a waste of on-chip memory and should be fix. Then this | ||
481 | * function should be changed to not allocate a buffer for len=0. | ||
482 | */ | ||
483 | static int oxu_buf_alloc(struct oxu_hcd *oxu, struct ehci_qtd *qtd, int len) | ||
484 | { | ||
485 | int n_blocks; /* minium blocks needed to hold len */ | ||
486 | int a_blocks; /* blocks allocated */ | ||
487 | int i, j; | ||
488 | |||
489 | /* Don't allocte bigger than supported */ | ||
490 | if (len > BUFFER_SIZE * BUFFER_NUM) { | ||
491 | oxu_err(oxu, "buffer too big (%d)\n", len); | ||
492 | return -ENOMEM; | ||
493 | } | ||
494 | |||
495 | spin_lock(&oxu->mem_lock); | ||
496 | |||
497 | /* Number of blocks needed to hold len */ | ||
498 | n_blocks = (len + BUFFER_SIZE - 1) / BUFFER_SIZE; | ||
499 | |||
500 | /* Round the number of blocks up to the power of 2 */ | ||
501 | for (a_blocks = 1; a_blocks < n_blocks; a_blocks <<= 1) | ||
502 | ; | ||
503 | |||
504 | /* Find a suitable available data buffer */ | ||
505 | for (i = 0; i < BUFFER_NUM; | ||
506 | i += max(a_blocks, (int)oxu->db_used[i])) { | ||
507 | |||
508 | /* Check all the required blocks are available */ | ||
509 | for (j = 0; j < a_blocks; j++) | ||
510 | if (oxu->db_used[i + j]) | ||
511 | break; | ||
512 | |||
513 | if (j != a_blocks) | ||
514 | continue; | ||
515 | |||
516 | /* Allocate blocks found! */ | ||
517 | qtd->buffer = (void *) &oxu->mem->db_pool[i]; | ||
518 | qtd->buffer_dma = virt_to_phys(qtd->buffer); | ||
519 | |||
520 | qtd->qtd_buffer_len = BUFFER_SIZE * a_blocks; | ||
521 | oxu->db_used[i] = a_blocks; | ||
522 | |||
523 | spin_unlock(&oxu->mem_lock); | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | /* Failed */ | ||
529 | |||
530 | spin_unlock(&oxu->mem_lock); | ||
531 | |||
532 | return -ENOMEM; | ||
533 | } | ||
534 | |||
535 | static void oxu_buf_free(struct oxu_hcd *oxu, struct ehci_qtd *qtd) | ||
536 | { | ||
537 | int index; | ||
538 | |||
539 | spin_lock(&oxu->mem_lock); | ||
540 | |||
541 | index = (qtd->buffer - (void *) &oxu->mem->db_pool[0]) | ||
542 | / BUFFER_SIZE; | ||
543 | oxu->db_used[index] = 0; | ||
544 | qtd->qtd_buffer_len = 0; | ||
545 | qtd->buffer_dma = 0; | ||
546 | qtd->buffer = NULL; | ||
547 | |||
548 | spin_unlock(&oxu->mem_lock); | ||
549 | |||
550 | return; | ||
551 | } | ||
552 | |||
553 | static inline void ehci_qtd_init(struct ehci_qtd *qtd, dma_addr_t dma) | ||
554 | { | ||
555 | memset(qtd, 0, sizeof *qtd); | ||
556 | qtd->qtd_dma = dma; | ||
557 | qtd->hw_token = cpu_to_le32(QTD_STS_HALT); | ||
558 | qtd->hw_next = EHCI_LIST_END; | ||
559 | qtd->hw_alt_next = EHCI_LIST_END; | ||
560 | INIT_LIST_HEAD(&qtd->qtd_list); | ||
561 | } | ||
562 | |||
563 | static inline void oxu_qtd_free(struct oxu_hcd *oxu, struct ehci_qtd *qtd) | ||
564 | { | ||
565 | int index; | ||
566 | |||
567 | if (qtd->buffer) | ||
568 | oxu_buf_free(oxu, qtd); | ||
569 | |||
570 | spin_lock(&oxu->mem_lock); | ||
571 | |||
572 | index = qtd - &oxu->mem->qtd_pool[0]; | ||
573 | oxu->qtd_used[index] = 0; | ||
574 | |||
575 | spin_unlock(&oxu->mem_lock); | ||
576 | |||
577 | return; | ||
578 | } | ||
579 | |||
580 | static struct ehci_qtd *ehci_qtd_alloc(struct oxu_hcd *oxu) | ||
581 | { | ||
582 | int i; | ||
583 | struct ehci_qtd *qtd = NULL; | ||
584 | |||
585 | spin_lock(&oxu->mem_lock); | ||
586 | |||
587 | for (i = 0; i < QTD_NUM; i++) | ||
588 | if (!oxu->qtd_used[i]) | ||
589 | break; | ||
590 | |||
591 | if (i < QTD_NUM) { | ||
592 | qtd = (struct ehci_qtd *) &oxu->mem->qtd_pool[i]; | ||
593 | memset(qtd, 0, sizeof *qtd); | ||
594 | |||
595 | qtd->hw_token = cpu_to_le32(QTD_STS_HALT); | ||
596 | qtd->hw_next = EHCI_LIST_END; | ||
597 | qtd->hw_alt_next = EHCI_LIST_END; | ||
598 | INIT_LIST_HEAD(&qtd->qtd_list); | ||
599 | |||
600 | qtd->qtd_dma = virt_to_phys(qtd); | ||
601 | |||
602 | oxu->qtd_used[i] = 1; | ||
603 | } | ||
604 | |||
605 | spin_unlock(&oxu->mem_lock); | ||
606 | |||
607 | return qtd; | ||
608 | } | ||
609 | |||
610 | static void oxu_qh_free(struct oxu_hcd *oxu, struct ehci_qh *qh) | ||
611 | { | ||
612 | int index; | ||
613 | |||
614 | spin_lock(&oxu->mem_lock); | ||
615 | |||
616 | index = qh - &oxu->mem->qh_pool[0]; | ||
617 | oxu->qh_used[index] = 0; | ||
618 | |||
619 | spin_unlock(&oxu->mem_lock); | ||
620 | |||
621 | return; | ||
622 | } | ||
623 | |||
624 | static void qh_destroy(struct kref *kref) | ||
625 | { | ||
626 | struct ehci_qh *qh = container_of(kref, struct ehci_qh, kref); | ||
627 | struct oxu_hcd *oxu = qh->oxu; | ||
628 | |||
629 | /* clean qtds first, and know this is not linked */ | ||
630 | if (!list_empty(&qh->qtd_list) || qh->qh_next.ptr) { | ||
631 | oxu_dbg(oxu, "unused qh not empty!\n"); | ||
632 | BUG(); | ||
633 | } | ||
634 | if (qh->dummy) | ||
635 | oxu_qtd_free(oxu, qh->dummy); | ||
636 | oxu_qh_free(oxu, qh); | ||
637 | } | ||
638 | |||
639 | static struct ehci_qh *oxu_qh_alloc(struct oxu_hcd *oxu) | ||
640 | { | ||
641 | int i; | ||
642 | struct ehci_qh *qh = NULL; | ||
643 | |||
644 | spin_lock(&oxu->mem_lock); | ||
645 | |||
646 | for (i = 0; i < QHEAD_NUM; i++) | ||
647 | if (!oxu->qh_used[i]) | ||
648 | break; | ||
649 | |||
650 | if (i < QHEAD_NUM) { | ||
651 | qh = (struct ehci_qh *) &oxu->mem->qh_pool[i]; | ||
652 | memset(qh, 0, sizeof *qh); | ||
653 | |||
654 | kref_init(&qh->kref); | ||
655 | qh->oxu = oxu; | ||
656 | qh->qh_dma = virt_to_phys(qh); | ||
657 | INIT_LIST_HEAD(&qh->qtd_list); | ||
658 | |||
659 | /* dummy td enables safe urb queuing */ | ||
660 | qh->dummy = ehci_qtd_alloc(oxu); | ||
661 | if (qh->dummy == NULL) { | ||
662 | oxu_dbg(oxu, "no dummy td\n"); | ||
663 | oxu->qh_used[i] = 0; | ||
664 | |||
665 | return NULL; | ||
666 | } | ||
667 | |||
668 | oxu->qh_used[i] = 1; | ||
669 | } | ||
670 | |||
671 | spin_unlock(&oxu->mem_lock); | ||
672 | |||
673 | return qh; | ||
674 | } | ||
675 | |||
676 | /* to share a qh (cpu threads, or hc) */ | ||
677 | static inline struct ehci_qh *qh_get(struct ehci_qh *qh) | ||
678 | { | ||
679 | kref_get(&qh->kref); | ||
680 | return qh; | ||
681 | } | ||
682 | |||
683 | static inline void qh_put(struct ehci_qh *qh) | ||
684 | { | ||
685 | kref_put(&qh->kref, qh_destroy); | ||
686 | } | ||
687 | |||
688 | static void oxu_murb_free(struct oxu_hcd *oxu, struct oxu_murb *murb) | ||
689 | { | ||
690 | int index; | ||
691 | |||
692 | spin_lock(&oxu->mem_lock); | ||
693 | |||
694 | index = murb - &oxu->murb_pool[0]; | ||
695 | oxu->murb_used[index] = 0; | ||
696 | |||
697 | spin_unlock(&oxu->mem_lock); | ||
698 | |||
699 | return; | ||
700 | } | ||
701 | |||
702 | static struct oxu_murb *oxu_murb_alloc(struct oxu_hcd *oxu) | ||
703 | |||
704 | { | ||
705 | int i; | ||
706 | struct oxu_murb *murb = NULL; | ||
707 | |||
708 | spin_lock(&oxu->mem_lock); | ||
709 | |||
710 | for (i = 0; i < MURB_NUM; i++) | ||
711 | if (!oxu->murb_used[i]) | ||
712 | break; | ||
713 | |||
714 | if (i < MURB_NUM) { | ||
715 | murb = &(oxu->murb_pool)[i]; | ||
716 | |||
717 | oxu->murb_used[i] = 1; | ||
718 | } | ||
719 | |||
720 | spin_unlock(&oxu->mem_lock); | ||
721 | |||
722 | return murb; | ||
723 | } | ||
724 | |||
725 | /* The queue heads and transfer descriptors are managed from pools tied | ||
726 | * to each of the "per device" structures. | ||
727 | * This is the initialisation and cleanup code. | ||
728 | */ | ||
729 | static void ehci_mem_cleanup(struct oxu_hcd *oxu) | ||
730 | { | ||
731 | kfree(oxu->murb_pool); | ||
732 | oxu->murb_pool = NULL; | ||
733 | |||
734 | if (oxu->async) | ||
735 | qh_put(oxu->async); | ||
736 | oxu->async = NULL; | ||
737 | |||
738 | del_timer(&oxu->urb_timer); | ||
739 | |||
740 | oxu->periodic = NULL; | ||
741 | |||
742 | /* shadow periodic table */ | ||
743 | kfree(oxu->pshadow); | ||
744 | oxu->pshadow = NULL; | ||
745 | } | ||
746 | |||
747 | /* Remember to add cleanup code (above) if you add anything here. | ||
748 | */ | ||
749 | static int ehci_mem_init(struct oxu_hcd *oxu, gfp_t flags) | ||
750 | { | ||
751 | int i; | ||
752 | |||
753 | for (i = 0; i < oxu->periodic_size; i++) | ||
754 | oxu->mem->frame_list[i] = EHCI_LIST_END; | ||
755 | for (i = 0; i < QHEAD_NUM; i++) | ||
756 | oxu->qh_used[i] = 0; | ||
757 | for (i = 0; i < QTD_NUM; i++) | ||
758 | oxu->qtd_used[i] = 0; | ||
759 | |||
760 | oxu->murb_pool = kcalloc(MURB_NUM, sizeof(struct oxu_murb), flags); | ||
761 | if (!oxu->murb_pool) | ||
762 | goto fail; | ||
763 | |||
764 | for (i = 0; i < MURB_NUM; i++) | ||
765 | oxu->murb_used[i] = 0; | ||
766 | |||
767 | oxu->async = oxu_qh_alloc(oxu); | ||
768 | if (!oxu->async) | ||
769 | goto fail; | ||
770 | |||
771 | oxu->periodic = (__le32 *) &oxu->mem->frame_list; | ||
772 | oxu->periodic_dma = virt_to_phys(oxu->periodic); | ||
773 | |||
774 | for (i = 0; i < oxu->periodic_size; i++) | ||
775 | oxu->periodic[i] = EHCI_LIST_END; | ||
776 | |||
777 | /* software shadow of hardware table */ | ||
778 | oxu->pshadow = kcalloc(oxu->periodic_size, sizeof(void *), flags); | ||
779 | if (oxu->pshadow != NULL) | ||
780 | return 0; | ||
781 | |||
782 | fail: | ||
783 | oxu_dbg(oxu, "couldn't init memory\n"); | ||
784 | ehci_mem_cleanup(oxu); | ||
785 | return -ENOMEM; | ||
786 | } | ||
787 | |||
788 | /* Fill a qtd, returning how much of the buffer we were able to queue up. | ||
789 | */ | ||
790 | static int qtd_fill(struct ehci_qtd *qtd, dma_addr_t buf, size_t len, | ||
791 | int token, int maxpacket) | ||
792 | { | ||
793 | int i, count; | ||
794 | u64 addr = buf; | ||
795 | |||
796 | /* one buffer entry per 4K ... first might be short or unaligned */ | ||
797 | qtd->hw_buf[0] = cpu_to_le32((u32)addr); | ||
798 | qtd->hw_buf_hi[0] = cpu_to_le32((u32)(addr >> 32)); | ||
799 | count = 0x1000 - (buf & 0x0fff); /* rest of that page */ | ||
800 | if (likely(len < count)) /* ... iff needed */ | ||
801 | count = len; | ||
802 | else { | ||
803 | buf += 0x1000; | ||
804 | buf &= ~0x0fff; | ||
805 | |||
806 | /* per-qtd limit: from 16K to 20K (best alignment) */ | ||
807 | for (i = 1; count < len && i < 5; i++) { | ||
808 | addr = buf; | ||
809 | qtd->hw_buf[i] = cpu_to_le32((u32)addr); | ||
810 | qtd->hw_buf_hi[i] = cpu_to_le32((u32)(addr >> 32)); | ||
811 | buf += 0x1000; | ||
812 | if ((count + 0x1000) < len) | ||
813 | count += 0x1000; | ||
814 | else | ||
815 | count = len; | ||
816 | } | ||
817 | |||
818 | /* short packets may only terminate transfers */ | ||
819 | if (count != len) | ||
820 | count -= (count % maxpacket); | ||
821 | } | ||
822 | qtd->hw_token = cpu_to_le32((count << 16) | token); | ||
823 | qtd->length = count; | ||
824 | |||
825 | return count; | ||
826 | } | ||
827 | |||
828 | static inline void qh_update(struct oxu_hcd *oxu, | ||
829 | struct ehci_qh *qh, struct ehci_qtd *qtd) | ||
830 | { | ||
831 | /* writes to an active overlay are unsafe */ | ||
832 | BUG_ON(qh->qh_state != QH_STATE_IDLE); | ||
833 | |||
834 | qh->hw_qtd_next = QTD_NEXT(qtd->qtd_dma); | ||
835 | qh->hw_alt_next = EHCI_LIST_END; | ||
836 | |||
837 | /* Except for control endpoints, we make hardware maintain data | ||
838 | * toggle (like OHCI) ... here (re)initialize the toggle in the QH, | ||
839 | * and set the pseudo-toggle in udev. Only usb_clear_halt() will | ||
840 | * ever clear it. | ||
841 | */ | ||
842 | if (!(qh->hw_info1 & cpu_to_le32(1 << 14))) { | ||
843 | unsigned is_out, epnum; | ||
844 | |||
845 | is_out = !(qtd->hw_token & cpu_to_le32(1 << 8)); | ||
846 | epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f; | ||
847 | if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) { | ||
848 | qh->hw_token &= ~__constant_cpu_to_le32(QTD_TOGGLE); | ||
849 | usb_settoggle(qh->dev, epnum, is_out, 1); | ||
850 | } | ||
851 | } | ||
852 | |||
853 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ | ||
854 | wmb(); | ||
855 | qh->hw_token &= __constant_cpu_to_le32(QTD_TOGGLE | QTD_STS_PING); | ||
856 | } | ||
857 | |||
858 | /* If it weren't for a common silicon quirk (writing the dummy into the qh | ||
859 | * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault | ||
860 | * recovery (including urb dequeue) would need software changes to a QH... | ||
861 | */ | ||
862 | static void qh_refresh(struct oxu_hcd *oxu, struct ehci_qh *qh) | ||
863 | { | ||
864 | struct ehci_qtd *qtd; | ||
865 | |||
866 | if (list_empty(&qh->qtd_list)) | ||
867 | qtd = qh->dummy; | ||
868 | else { | ||
869 | qtd = list_entry(qh->qtd_list.next, | ||
870 | struct ehci_qtd, qtd_list); | ||
871 | /* first qtd may already be partially processed */ | ||
872 | if (cpu_to_le32(qtd->qtd_dma) == qh->hw_current) | ||
873 | qtd = NULL; | ||
874 | } | ||
875 | |||
876 | if (qtd) | ||
877 | qh_update(oxu, qh, qtd); | ||
878 | } | ||
879 | |||
880 | static void qtd_copy_status(struct oxu_hcd *oxu, struct urb *urb, | ||
881 | size_t length, u32 token) | ||
882 | { | ||
883 | /* count IN/OUT bytes, not SETUP (even short packets) */ | ||
884 | if (likely(QTD_PID(token) != 2)) | ||
885 | urb->actual_length += length - QTD_LENGTH(token); | ||
886 | |||
887 | /* don't modify error codes */ | ||
888 | if (unlikely(urb->status != -EINPROGRESS)) | ||
889 | return; | ||
890 | |||
891 | /* force cleanup after short read; not always an error */ | ||
892 | if (unlikely(IS_SHORT_READ(token))) | ||
893 | urb->status = -EREMOTEIO; | ||
894 | |||
895 | /* serious "can't proceed" faults reported by the hardware */ | ||
896 | if (token & QTD_STS_HALT) { | ||
897 | if (token & QTD_STS_BABBLE) { | ||
898 | /* FIXME "must" disable babbling device's port too */ | ||
899 | urb->status = -EOVERFLOW; | ||
900 | } else if (token & QTD_STS_MMF) { | ||
901 | /* fs/ls interrupt xfer missed the complete-split */ | ||
902 | urb->status = -EPROTO; | ||
903 | } else if (token & QTD_STS_DBE) { | ||
904 | urb->status = (QTD_PID(token) == 1) /* IN ? */ | ||
905 | ? -ENOSR /* hc couldn't read data */ | ||
906 | : -ECOMM; /* hc couldn't write data */ | ||
907 | } else if (token & QTD_STS_XACT) { | ||
908 | /* timeout, bad crc, wrong PID, etc; retried */ | ||
909 | if (QTD_CERR(token)) | ||
910 | urb->status = -EPIPE; | ||
911 | else { | ||
912 | oxu_dbg(oxu, "devpath %s ep%d%s 3strikes\n", | ||
913 | urb->dev->devpath, | ||
914 | usb_pipeendpoint(urb->pipe), | ||
915 | usb_pipein(urb->pipe) ? "in" : "out"); | ||
916 | urb->status = -EPROTO; | ||
917 | } | ||
918 | /* CERR nonzero + no errors + halt --> stall */ | ||
919 | } else if (QTD_CERR(token)) | ||
920 | urb->status = -EPIPE; | ||
921 | else /* unknown */ | ||
922 | urb->status = -EPROTO; | ||
923 | |||
924 | oxu_vdbg(oxu, "dev%d ep%d%s qtd token %08x --> status %d\n", | ||
925 | usb_pipedevice(urb->pipe), | ||
926 | usb_pipeendpoint(urb->pipe), | ||
927 | usb_pipein(urb->pipe) ? "in" : "out", | ||
928 | token, urb->status); | ||
929 | } | ||
930 | } | ||
931 | |||
932 | static void ehci_urb_done(struct oxu_hcd *oxu, struct urb *urb) | ||
933 | __releases(oxu->lock) | ||
934 | __acquires(oxu->lock) | ||
935 | { | ||
936 | if (likely(urb->hcpriv != NULL)) { | ||
937 | struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; | ||
938 | |||
939 | /* S-mask in a QH means it's an interrupt urb */ | ||
940 | if ((qh->hw_info2 & __constant_cpu_to_le32(QH_SMASK)) != 0) { | ||
941 | |||
942 | /* ... update hc-wide periodic stats (for usbfs) */ | ||
943 | oxu_to_hcd(oxu)->self.bandwidth_int_reqs--; | ||
944 | } | ||
945 | qh_put(qh); | ||
946 | } | ||
947 | |||
948 | urb->hcpriv = NULL; | ||
949 | switch (urb->status) { | ||
950 | case -EINPROGRESS: /* success */ | ||
951 | urb->status = 0; | ||
952 | default: /* fault */ | ||
953 | break; | ||
954 | case -EREMOTEIO: /* fault or normal */ | ||
955 | if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) | ||
956 | urb->status = 0; | ||
957 | break; | ||
958 | case -ECONNRESET: /* canceled */ | ||
959 | case -ENOENT: | ||
960 | break; | ||
961 | } | ||
962 | |||
963 | #ifdef OXU_URB_TRACE | ||
964 | oxu_dbg(oxu, "%s %s urb %p ep%d%s status %d len %d/%d\n", | ||
965 | __func__, urb->dev->devpath, urb, | ||
966 | usb_pipeendpoint(urb->pipe), | ||
967 | usb_pipein(urb->pipe) ? "in" : "out", | ||
968 | urb->status, | ||
969 | urb->actual_length, urb->transfer_buffer_length); | ||
970 | #endif | ||
971 | |||
972 | /* complete() can reenter this HCD */ | ||
973 | spin_unlock(&oxu->lock); | ||
974 | usb_hcd_giveback_urb(oxu_to_hcd(oxu), urb, urb->status); | ||
975 | spin_lock(&oxu->lock); | ||
976 | } | ||
977 | |||
978 | static void start_unlink_async(struct oxu_hcd *oxu, struct ehci_qh *qh); | ||
979 | static void unlink_async(struct oxu_hcd *oxu, struct ehci_qh *qh); | ||
980 | |||
981 | static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh); | ||
982 | static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh); | ||
983 | |||
984 | #define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT) | ||
985 | |||
986 | /* Process and free completed qtds for a qh, returning URBs to drivers. | ||
987 | * Chases up to qh->hw_current. Returns number of completions called, | ||
988 | * indicating how much "real" work we did. | ||
989 | */ | ||
990 | static unsigned qh_completions(struct oxu_hcd *oxu, struct ehci_qh *qh) | ||
991 | { | ||
992 | struct ehci_qtd *last = NULL, *end = qh->dummy; | ||
993 | struct list_head *entry, *tmp; | ||
994 | int stopped; | ||
995 | unsigned count = 0; | ||
996 | int do_status = 0; | ||
997 | u8 state; | ||
998 | struct oxu_murb *murb = NULL; | ||
999 | |||
1000 | if (unlikely(list_empty(&qh->qtd_list))) | ||
1001 | return count; | ||
1002 | |||
1003 | /* completions (or tasks on other cpus) must never clobber HALT | ||
1004 | * till we've gone through and cleaned everything up, even when | ||
1005 | * they add urbs to this qh's queue or mark them for unlinking. | ||
1006 | * | ||
1007 | * NOTE: unlinking expects to be done in queue order. | ||
1008 | */ | ||
1009 | state = qh->qh_state; | ||
1010 | qh->qh_state = QH_STATE_COMPLETING; | ||
1011 | stopped = (state == QH_STATE_IDLE); | ||
1012 | |||
1013 | /* remove de-activated QTDs from front of queue. | ||
1014 | * after faults (including short reads), cleanup this urb | ||
1015 | * then let the queue advance. | ||
1016 | * if queue is stopped, handles unlinks. | ||
1017 | */ | ||
1018 | list_for_each_safe(entry, tmp, &qh->qtd_list) { | ||
1019 | struct ehci_qtd *qtd; | ||
1020 | struct urb *urb; | ||
1021 | u32 token = 0; | ||
1022 | |||
1023 | qtd = list_entry(entry, struct ehci_qtd, qtd_list); | ||
1024 | urb = qtd->urb; | ||
1025 | |||
1026 | /* Clean up any state from previous QTD ...*/ | ||
1027 | if (last) { | ||
1028 | if (likely(last->urb != urb)) { | ||
1029 | if (last->urb->complete == NULL) { | ||
1030 | murb = (struct oxu_murb *) last->urb; | ||
1031 | last->urb = murb->main; | ||
1032 | if (murb->last) { | ||
1033 | ehci_urb_done(oxu, last->urb); | ||
1034 | count++; | ||
1035 | } | ||
1036 | oxu_murb_free(oxu, murb); | ||
1037 | } else { | ||
1038 | ehci_urb_done(oxu, last->urb); | ||
1039 | count++; | ||
1040 | } | ||
1041 | } | ||
1042 | oxu_qtd_free(oxu, last); | ||
1043 | last = NULL; | ||
1044 | } | ||
1045 | |||
1046 | /* ignore urbs submitted during completions we reported */ | ||
1047 | if (qtd == end) | ||
1048 | break; | ||
1049 | |||
1050 | /* hardware copies qtd out of qh overlay */ | ||
1051 | rmb(); | ||
1052 | token = le32_to_cpu(qtd->hw_token); | ||
1053 | |||
1054 | /* always clean up qtds the hc de-activated */ | ||
1055 | if ((token & QTD_STS_ACTIVE) == 0) { | ||
1056 | |||
1057 | if ((token & QTD_STS_HALT) != 0) { | ||
1058 | stopped = 1; | ||
1059 | |||
1060 | /* magic dummy for some short reads; qh won't advance. | ||
1061 | * that silicon quirk can kick in with this dummy too. | ||
1062 | */ | ||
1063 | } else if (IS_SHORT_READ(token) && | ||
1064 | !(qtd->hw_alt_next & EHCI_LIST_END)) { | ||
1065 | stopped = 1; | ||
1066 | goto halt; | ||
1067 | } | ||
1068 | |||
1069 | /* stop scanning when we reach qtds the hc is using */ | ||
1070 | } else if (likely(!stopped && | ||
1071 | HC_IS_RUNNING(oxu_to_hcd(oxu)->state))) { | ||
1072 | break; | ||
1073 | |||
1074 | } else { | ||
1075 | stopped = 1; | ||
1076 | |||
1077 | if (unlikely(!HC_IS_RUNNING(oxu_to_hcd(oxu)->state))) | ||
1078 | urb->status = -ESHUTDOWN; | ||
1079 | |||
1080 | /* ignore active urbs unless some previous qtd | ||
1081 | * for the urb faulted (including short read) or | ||
1082 | * its urb was canceled. we may patch qh or qtds. | ||
1083 | */ | ||
1084 | if (likely(urb->status == -EINPROGRESS)) | ||
1085 | continue; | ||
1086 | |||
1087 | /* issue status after short control reads */ | ||
1088 | if (unlikely(do_status != 0) | ||
1089 | && QTD_PID(token) == 0 /* OUT */) { | ||
1090 | do_status = 0; | ||
1091 | continue; | ||
1092 | } | ||
1093 | |||
1094 | /* token in overlay may be most current */ | ||
1095 | if (state == QH_STATE_IDLE | ||
1096 | && cpu_to_le32(qtd->qtd_dma) | ||
1097 | == qh->hw_current) | ||
1098 | token = le32_to_cpu(qh->hw_token); | ||
1099 | |||
1100 | /* force halt for unlinked or blocked qh, so we'll | ||
1101 | * patch the qh later and so that completions can't | ||
1102 | * activate it while we "know" it's stopped. | ||
1103 | */ | ||
1104 | if ((HALT_BIT & qh->hw_token) == 0) { | ||
1105 | halt: | ||
1106 | qh->hw_token |= HALT_BIT; | ||
1107 | wmb(); | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | /* Remove it from the queue */ | ||
1112 | qtd_copy_status(oxu, urb->complete ? | ||
1113 | urb : ((struct oxu_murb *) urb)->main, | ||
1114 | qtd->length, token); | ||
1115 | if ((usb_pipein(qtd->urb->pipe)) && | ||
1116 | (NULL != qtd->transfer_buffer)) | ||
1117 | memcpy(qtd->transfer_buffer, qtd->buffer, qtd->length); | ||
1118 | do_status = (urb->status == -EREMOTEIO) | ||
1119 | && usb_pipecontrol(urb->pipe); | ||
1120 | |||
1121 | if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { | ||
1122 | last = list_entry(qtd->qtd_list.prev, | ||
1123 | struct ehci_qtd, qtd_list); | ||
1124 | last->hw_next = qtd->hw_next; | ||
1125 | } | ||
1126 | list_del(&qtd->qtd_list); | ||
1127 | last = qtd; | ||
1128 | } | ||
1129 | |||
1130 | /* last urb's completion might still need calling */ | ||
1131 | if (likely(last != NULL)) { | ||
1132 | if (last->urb->complete == NULL) { | ||
1133 | murb = (struct oxu_murb *) last->urb; | ||
1134 | last->urb = murb->main; | ||
1135 | if (murb->last) { | ||
1136 | ehci_urb_done(oxu, last->urb); | ||
1137 | count++; | ||
1138 | } | ||
1139 | oxu_murb_free(oxu, murb); | ||
1140 | } else { | ||
1141 | ehci_urb_done(oxu, last->urb); | ||
1142 | count++; | ||
1143 | } | ||
1144 | oxu_qtd_free(oxu, last); | ||
1145 | } | ||
1146 | |||
1147 | /* restore original state; caller must unlink or relink */ | ||
1148 | qh->qh_state = state; | ||
1149 | |||
1150 | /* be sure the hardware's done with the qh before refreshing | ||
1151 | * it after fault cleanup, or recovering from silicon wrongly | ||
1152 | * overlaying the dummy qtd (which reduces DMA chatter). | ||
1153 | */ | ||
1154 | if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END) { | ||
1155 | switch (state) { | ||
1156 | case QH_STATE_IDLE: | ||
1157 | qh_refresh(oxu, qh); | ||
1158 | break; | ||
1159 | case QH_STATE_LINKED: | ||
1160 | /* should be rare for periodic transfers, | ||
1161 | * except maybe high bandwidth ... | ||
1162 | */ | ||
1163 | if ((__constant_cpu_to_le32(QH_SMASK) | ||
1164 | & qh->hw_info2) != 0) { | ||
1165 | intr_deschedule(oxu, qh); | ||
1166 | (void) qh_schedule(oxu, qh); | ||
1167 | } else | ||
1168 | unlink_async(oxu, qh); | ||
1169 | break; | ||
1170 | /* otherwise, unlink already started */ | ||
1171 | } | ||
1172 | } | ||
1173 | |||
1174 | return count; | ||
1175 | } | ||
1176 | |||
1177 | /* High bandwidth multiplier, as encoded in highspeed endpoint descriptors */ | ||
1178 | #define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) | ||
1179 | /* ... and packet size, for any kind of endpoint descriptor */ | ||
1180 | #define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) | ||
1181 | |||
1182 | /* Reverse of qh_urb_transaction: free a list of TDs. | ||
1183 | * used for cleanup after errors, before HC sees an URB's TDs. | ||
1184 | */ | ||
1185 | static void qtd_list_free(struct oxu_hcd *oxu, | ||
1186 | struct urb *urb, struct list_head *qtd_list) | ||
1187 | { | ||
1188 | struct list_head *entry, *temp; | ||
1189 | |||
1190 | list_for_each_safe(entry, temp, qtd_list) { | ||
1191 | struct ehci_qtd *qtd; | ||
1192 | |||
1193 | qtd = list_entry(entry, struct ehci_qtd, qtd_list); | ||
1194 | list_del(&qtd->qtd_list); | ||
1195 | oxu_qtd_free(oxu, qtd); | ||
1196 | } | ||
1197 | } | ||
1198 | |||
1199 | /* Create a list of filled qtds for this URB; won't link into qh. | ||
1200 | */ | ||
1201 | static struct list_head *qh_urb_transaction(struct oxu_hcd *oxu, | ||
1202 | struct urb *urb, | ||
1203 | struct list_head *head, | ||
1204 | gfp_t flags) | ||
1205 | { | ||
1206 | struct ehci_qtd *qtd, *qtd_prev; | ||
1207 | dma_addr_t buf; | ||
1208 | int len, maxpacket; | ||
1209 | int is_input; | ||
1210 | u32 token; | ||
1211 | void *transfer_buf = NULL; | ||
1212 | int ret; | ||
1213 | |||
1214 | /* | ||
1215 | * URBs map to sequences of QTDs: one logical transaction | ||
1216 | */ | ||
1217 | qtd = ehci_qtd_alloc(oxu); | ||
1218 | if (unlikely(!qtd)) | ||
1219 | return NULL; | ||
1220 | list_add_tail(&qtd->qtd_list, head); | ||
1221 | qtd->urb = urb; | ||
1222 | |||
1223 | token = QTD_STS_ACTIVE; | ||
1224 | token |= (EHCI_TUNE_CERR << 10); | ||
1225 | /* for split transactions, SplitXState initialized to zero */ | ||
1226 | |||
1227 | len = urb->transfer_buffer_length; | ||
1228 | is_input = usb_pipein(urb->pipe); | ||
1229 | if (!urb->transfer_buffer && urb->transfer_buffer_length && is_input) | ||
1230 | urb->transfer_buffer = phys_to_virt(urb->transfer_dma); | ||
1231 | |||
1232 | if (usb_pipecontrol(urb->pipe)) { | ||
1233 | /* SETUP pid */ | ||
1234 | ret = oxu_buf_alloc(oxu, qtd, sizeof(struct usb_ctrlrequest)); | ||
1235 | if (ret) | ||
1236 | goto cleanup; | ||
1237 | |||
1238 | qtd_fill(qtd, qtd->buffer_dma, sizeof(struct usb_ctrlrequest), | ||
1239 | token | (2 /* "setup" */ << 8), 8); | ||
1240 | memcpy(qtd->buffer, qtd->urb->setup_packet, | ||
1241 | sizeof(struct usb_ctrlrequest)); | ||
1242 | |||
1243 | /* ... and always at least one more pid */ | ||
1244 | token ^= QTD_TOGGLE; | ||
1245 | qtd_prev = qtd; | ||
1246 | qtd = ehci_qtd_alloc(oxu); | ||
1247 | if (unlikely(!qtd)) | ||
1248 | goto cleanup; | ||
1249 | qtd->urb = urb; | ||
1250 | qtd_prev->hw_next = QTD_NEXT(qtd->qtd_dma); | ||
1251 | list_add_tail(&qtd->qtd_list, head); | ||
1252 | |||
1253 | /* for zero length DATA stages, STATUS is always IN */ | ||
1254 | if (len == 0) | ||
1255 | token |= (1 /* "in" */ << 8); | ||
1256 | } | ||
1257 | |||
1258 | /* | ||
1259 | * Data transfer stage: buffer setup | ||
1260 | */ | ||
1261 | |||
1262 | ret = oxu_buf_alloc(oxu, qtd, len); | ||
1263 | if (ret) | ||
1264 | goto cleanup; | ||
1265 | |||
1266 | buf = qtd->buffer_dma; | ||
1267 | transfer_buf = urb->transfer_buffer; | ||
1268 | |||
1269 | if (!is_input) | ||
1270 | memcpy(qtd->buffer, qtd->urb->transfer_buffer, len); | ||
1271 | |||
1272 | if (is_input) | ||
1273 | token |= (1 /* "in" */ << 8); | ||
1274 | /* else it's already initted to "out" pid (0 << 8) */ | ||
1275 | |||
1276 | maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); | ||
1277 | |||
1278 | /* | ||
1279 | * buffer gets wrapped in one or more qtds; | ||
1280 | * last one may be "short" (including zero len) | ||
1281 | * and may serve as a control status ack | ||
1282 | */ | ||
1283 | for (;;) { | ||
1284 | int this_qtd_len; | ||
1285 | |||
1286 | this_qtd_len = qtd_fill(qtd, buf, len, token, maxpacket); | ||
1287 | qtd->transfer_buffer = transfer_buf; | ||
1288 | len -= this_qtd_len; | ||
1289 | buf += this_qtd_len; | ||
1290 | transfer_buf += this_qtd_len; | ||
1291 | if (is_input) | ||
1292 | qtd->hw_alt_next = oxu->async->hw_alt_next; | ||
1293 | |||
1294 | /* qh makes control packets use qtd toggle; maybe switch it */ | ||
1295 | if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) | ||
1296 | token ^= QTD_TOGGLE; | ||
1297 | |||
1298 | if (likely(len <= 0)) | ||
1299 | break; | ||
1300 | |||
1301 | qtd_prev = qtd; | ||
1302 | qtd = ehci_qtd_alloc(oxu); | ||
1303 | if (unlikely(!qtd)) | ||
1304 | goto cleanup; | ||
1305 | if (likely(len > 0)) { | ||
1306 | ret = oxu_buf_alloc(oxu, qtd, len); | ||
1307 | if (ret) | ||
1308 | goto cleanup; | ||
1309 | } | ||
1310 | qtd->urb = urb; | ||
1311 | qtd_prev->hw_next = QTD_NEXT(qtd->qtd_dma); | ||
1312 | list_add_tail(&qtd->qtd_list, head); | ||
1313 | } | ||
1314 | |||
1315 | /* unless the bulk/interrupt caller wants a chance to clean | ||
1316 | * up after short reads, hc should advance qh past this urb | ||
1317 | */ | ||
1318 | if (likely((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 | ||
1319 | || usb_pipecontrol(urb->pipe))) | ||
1320 | qtd->hw_alt_next = EHCI_LIST_END; | ||
1321 | |||
1322 | /* | ||
1323 | * control requests may need a terminating data "status" ack; | ||
1324 | * bulk ones may need a terminating short packet (zero length). | ||
1325 | */ | ||
1326 | if (likely(urb->transfer_buffer_length != 0)) { | ||
1327 | int one_more = 0; | ||
1328 | |||
1329 | if (usb_pipecontrol(urb->pipe)) { | ||
1330 | one_more = 1; | ||
1331 | token ^= 0x0100; /* "in" <--> "out" */ | ||
1332 | token |= QTD_TOGGLE; /* force DATA1 */ | ||
1333 | } else if (usb_pipebulk(urb->pipe) | ||
1334 | && (urb->transfer_flags & URB_ZERO_PACKET) | ||
1335 | && !(urb->transfer_buffer_length % maxpacket)) { | ||
1336 | one_more = 1; | ||
1337 | } | ||
1338 | if (one_more) { | ||
1339 | qtd_prev = qtd; | ||
1340 | qtd = ehci_qtd_alloc(oxu); | ||
1341 | if (unlikely(!qtd)) | ||
1342 | goto cleanup; | ||
1343 | qtd->urb = urb; | ||
1344 | qtd_prev->hw_next = QTD_NEXT(qtd->qtd_dma); | ||
1345 | list_add_tail(&qtd->qtd_list, head); | ||
1346 | |||
1347 | /* never any data in such packets */ | ||
1348 | qtd_fill(qtd, 0, 0, token, 0); | ||
1349 | } | ||
1350 | } | ||
1351 | |||
1352 | /* by default, enable interrupt on urb completion */ | ||
1353 | qtd->hw_token |= __constant_cpu_to_le32(QTD_IOC); | ||
1354 | return head; | ||
1355 | |||
1356 | cleanup: | ||
1357 | qtd_list_free(oxu, urb, head); | ||
1358 | return NULL; | ||
1359 | } | ||
1360 | |||
1361 | /* Each QH holds a qtd list; a QH is used for everything except iso. | ||
1362 | * | ||
1363 | * For interrupt urbs, the scheduler must set the microframe scheduling | ||
1364 | * mask(s) each time the QH gets scheduled. For highspeed, that's | ||
1365 | * just one microframe in the s-mask. For split interrupt transactions | ||
1366 | * there are additional complications: c-mask, maybe FSTNs. | ||
1367 | */ | ||
1368 | static struct ehci_qh *qh_make(struct oxu_hcd *oxu, | ||
1369 | struct urb *urb, gfp_t flags) | ||
1370 | { | ||
1371 | struct ehci_qh *qh = oxu_qh_alloc(oxu); | ||
1372 | u32 info1 = 0, info2 = 0; | ||
1373 | int is_input, type; | ||
1374 | int maxp = 0; | ||
1375 | |||
1376 | if (!qh) | ||
1377 | return qh; | ||
1378 | |||
1379 | /* | ||
1380 | * init endpoint/device data for this QH | ||
1381 | */ | ||
1382 | info1 |= usb_pipeendpoint(urb->pipe) << 8; | ||
1383 | info1 |= usb_pipedevice(urb->pipe) << 0; | ||
1384 | |||
1385 | is_input = usb_pipein(urb->pipe); | ||
1386 | type = usb_pipetype(urb->pipe); | ||
1387 | maxp = usb_maxpacket(urb->dev, urb->pipe, !is_input); | ||
1388 | |||
1389 | /* Compute interrupt scheduling parameters just once, and save. | ||
1390 | * - allowing for high bandwidth, how many nsec/uframe are used? | ||
1391 | * - split transactions need a second CSPLIT uframe; same question | ||
1392 | * - splits also need a schedule gap (for full/low speed I/O) | ||
1393 | * - qh has a polling interval | ||
1394 | * | ||
1395 | * For control/bulk requests, the HC or TT handles these. | ||
1396 | */ | ||
1397 | if (type == PIPE_INTERRUPT) { | ||
1398 | qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, | ||
1399 | is_input, 0, | ||
1400 | hb_mult(maxp) * max_packet(maxp))); | ||
1401 | qh->start = NO_FRAME; | ||
1402 | |||
1403 | if (urb->dev->speed == USB_SPEED_HIGH) { | ||
1404 | qh->c_usecs = 0; | ||
1405 | qh->gap_uf = 0; | ||
1406 | |||
1407 | qh->period = urb->interval >> 3; | ||
1408 | if (qh->period == 0 && urb->interval != 1) { | ||
1409 | /* NOTE interval 2 or 4 uframes could work. | ||
1410 | * But interval 1 scheduling is simpler, and | ||
1411 | * includes high bandwidth. | ||
1412 | */ | ||
1413 | dbg("intr period %d uframes, NYET!", | ||
1414 | urb->interval); | ||
1415 | goto done; | ||
1416 | } | ||
1417 | } else { | ||
1418 | struct usb_tt *tt = urb->dev->tt; | ||
1419 | int think_time; | ||
1420 | |||
1421 | /* gap is f(FS/LS transfer times) */ | ||
1422 | qh->gap_uf = 1 + usb_calc_bus_time(urb->dev->speed, | ||
1423 | is_input, 0, maxp) / (125 * 1000); | ||
1424 | |||
1425 | /* FIXME this just approximates SPLIT/CSPLIT times */ | ||
1426 | if (is_input) { /* SPLIT, gap, CSPLIT+DATA */ | ||
1427 | qh->c_usecs = qh->usecs + HS_USECS(0); | ||
1428 | qh->usecs = HS_USECS(1); | ||
1429 | } else { /* SPLIT+DATA, gap, CSPLIT */ | ||
1430 | qh->usecs += HS_USECS(1); | ||
1431 | qh->c_usecs = HS_USECS(0); | ||
1432 | } | ||
1433 | |||
1434 | think_time = tt ? tt->think_time : 0; | ||
1435 | qh->tt_usecs = NS_TO_US(think_time + | ||
1436 | usb_calc_bus_time(urb->dev->speed, | ||
1437 | is_input, 0, max_packet(maxp))); | ||
1438 | qh->period = urb->interval; | ||
1439 | } | ||
1440 | } | ||
1441 | |||
1442 | /* support for tt scheduling, and access to toggles */ | ||
1443 | qh->dev = urb->dev; | ||
1444 | |||
1445 | /* using TT? */ | ||
1446 | switch (urb->dev->speed) { | ||
1447 | case USB_SPEED_LOW: | ||
1448 | info1 |= (1 << 12); /* EPS "low" */ | ||
1449 | /* FALL THROUGH */ | ||
1450 | |||
1451 | case USB_SPEED_FULL: | ||
1452 | /* EPS 0 means "full" */ | ||
1453 | if (type != PIPE_INTERRUPT) | ||
1454 | info1 |= (EHCI_TUNE_RL_TT << 28); | ||
1455 | if (type == PIPE_CONTROL) { | ||
1456 | info1 |= (1 << 27); /* for TT */ | ||
1457 | info1 |= 1 << 14; /* toggle from qtd */ | ||
1458 | } | ||
1459 | info1 |= maxp << 16; | ||
1460 | |||
1461 | info2 |= (EHCI_TUNE_MULT_TT << 30); | ||
1462 | info2 |= urb->dev->ttport << 23; | ||
1463 | |||
1464 | /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */ | ||
1465 | |||
1466 | break; | ||
1467 | |||
1468 | case USB_SPEED_HIGH: /* no TT involved */ | ||
1469 | info1 |= (2 << 12); /* EPS "high" */ | ||
1470 | if (type == PIPE_CONTROL) { | ||
1471 | info1 |= (EHCI_TUNE_RL_HS << 28); | ||
1472 | info1 |= 64 << 16; /* usb2 fixed maxpacket */ | ||
1473 | info1 |= 1 << 14; /* toggle from qtd */ | ||
1474 | info2 |= (EHCI_TUNE_MULT_HS << 30); | ||
1475 | } else if (type == PIPE_BULK) { | ||
1476 | info1 |= (EHCI_TUNE_RL_HS << 28); | ||
1477 | info1 |= 512 << 16; /* usb2 fixed maxpacket */ | ||
1478 | info2 |= (EHCI_TUNE_MULT_HS << 30); | ||
1479 | } else { /* PIPE_INTERRUPT */ | ||
1480 | info1 |= max_packet(maxp) << 16; | ||
1481 | info2 |= hb_mult(maxp) << 30; | ||
1482 | } | ||
1483 | break; | ||
1484 | default: | ||
1485 | dbg("bogus dev %p speed %d", urb->dev, urb->dev->speed); | ||
1486 | done: | ||
1487 | qh_put(qh); | ||
1488 | return NULL; | ||
1489 | } | ||
1490 | |||
1491 | /* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */ | ||
1492 | |||
1493 | /* init as live, toggle clear, advance to dummy */ | ||
1494 | qh->qh_state = QH_STATE_IDLE; | ||
1495 | qh->hw_info1 = cpu_to_le32(info1); | ||
1496 | qh->hw_info2 = cpu_to_le32(info2); | ||
1497 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), !is_input, 1); | ||
1498 | qh_refresh(oxu, qh); | ||
1499 | return qh; | ||
1500 | } | ||
1501 | |||
1502 | /* Move qh (and its qtds) onto async queue; maybe enable queue. | ||
1503 | */ | ||
1504 | static void qh_link_async(struct oxu_hcd *oxu, struct ehci_qh *qh) | ||
1505 | { | ||
1506 | __le32 dma = QH_NEXT(qh->qh_dma); | ||
1507 | struct ehci_qh *head; | ||
1508 | |||
1509 | /* (re)start the async schedule? */ | ||
1510 | head = oxu->async; | ||
1511 | timer_action_done(oxu, TIMER_ASYNC_OFF); | ||
1512 | if (!head->qh_next.qh) { | ||
1513 | u32 cmd = readl(&oxu->regs->command); | ||
1514 | |||
1515 | if (!(cmd & CMD_ASE)) { | ||
1516 | /* in case a clear of CMD_ASE didn't take yet */ | ||
1517 | (void)handshake(oxu, &oxu->regs->status, | ||
1518 | STS_ASS, 0, 150); | ||
1519 | cmd |= CMD_ASE | CMD_RUN; | ||
1520 | writel(cmd, &oxu->regs->command); | ||
1521 | oxu_to_hcd(oxu)->state = HC_STATE_RUNNING; | ||
1522 | /* posted write need not be known to HC yet ... */ | ||
1523 | } | ||
1524 | } | ||
1525 | |||
1526 | /* clear halt and/or toggle; and maybe recover from silicon quirk */ | ||
1527 | if (qh->qh_state == QH_STATE_IDLE) | ||
1528 | qh_refresh(oxu, qh); | ||
1529 | |||
1530 | /* splice right after start */ | ||
1531 | qh->qh_next = head->qh_next; | ||
1532 | qh->hw_next = head->hw_next; | ||
1533 | wmb(); | ||
1534 | |||
1535 | head->qh_next.qh = qh; | ||
1536 | head->hw_next = dma; | ||
1537 | |||
1538 | qh->qh_state = QH_STATE_LINKED; | ||
1539 | /* qtd completions reported later by interrupt */ | ||
1540 | } | ||
1541 | |||
1542 | #define QH_ADDR_MASK __constant_cpu_to_le32(0x7f) | ||
1543 | |||
1544 | /* | ||
1545 | * For control/bulk/interrupt, return QH with these TDs appended. | ||
1546 | * Allocates and initializes the QH if necessary. | ||
1547 | * Returns null if it can't allocate a QH it needs to. | ||
1548 | * If the QH has TDs (urbs) already, that's great. | ||
1549 | */ | ||
1550 | static struct ehci_qh *qh_append_tds(struct oxu_hcd *oxu, | ||
1551 | struct urb *urb, struct list_head *qtd_list, | ||
1552 | int epnum, void **ptr) | ||
1553 | { | ||
1554 | struct ehci_qh *qh = NULL; | ||
1555 | |||
1556 | qh = (struct ehci_qh *) *ptr; | ||
1557 | if (unlikely(qh == NULL)) { | ||
1558 | /* can't sleep here, we have oxu->lock... */ | ||
1559 | qh = qh_make(oxu, urb, GFP_ATOMIC); | ||
1560 | *ptr = qh; | ||
1561 | } | ||
1562 | if (likely(qh != NULL)) { | ||
1563 | struct ehci_qtd *qtd; | ||
1564 | |||
1565 | if (unlikely(list_empty(qtd_list))) | ||
1566 | qtd = NULL; | ||
1567 | else | ||
1568 | qtd = list_entry(qtd_list->next, struct ehci_qtd, | ||
1569 | qtd_list); | ||
1570 | |||
1571 | /* control qh may need patching ... */ | ||
1572 | if (unlikely(epnum == 0)) { | ||
1573 | |||
1574 | /* usb_reset_device() briefly reverts to address 0 */ | ||
1575 | if (usb_pipedevice(urb->pipe) == 0) | ||
1576 | qh->hw_info1 &= ~QH_ADDR_MASK; | ||
1577 | } | ||
1578 | |||
1579 | /* just one way to queue requests: swap with the dummy qtd. | ||
1580 | * only hc or qh_refresh() ever modify the overlay. | ||
1581 | */ | ||
1582 | if (likely(qtd != NULL)) { | ||
1583 | struct ehci_qtd *dummy; | ||
1584 | dma_addr_t dma; | ||
1585 | __le32 token; | ||
1586 | |||
1587 | /* to avoid racing the HC, use the dummy td instead of | ||
1588 | * the first td of our list (becomes new dummy). both | ||
1589 | * tds stay deactivated until we're done, when the | ||
1590 | * HC is allowed to fetch the old dummy (4.10.2). | ||
1591 | */ | ||
1592 | token = qtd->hw_token; | ||
1593 | qtd->hw_token = HALT_BIT; | ||
1594 | wmb(); | ||
1595 | dummy = qh->dummy; | ||
1596 | |||
1597 | dma = dummy->qtd_dma; | ||
1598 | *dummy = *qtd; | ||
1599 | dummy->qtd_dma = dma; | ||
1600 | |||
1601 | list_del(&qtd->qtd_list); | ||
1602 | list_add(&dummy->qtd_list, qtd_list); | ||
1603 | list_splice(qtd_list, qh->qtd_list.prev); | ||
1604 | |||
1605 | ehci_qtd_init(qtd, qtd->qtd_dma); | ||
1606 | qh->dummy = qtd; | ||
1607 | |||
1608 | /* hc must see the new dummy at list end */ | ||
1609 | dma = qtd->qtd_dma; | ||
1610 | qtd = list_entry(qh->qtd_list.prev, | ||
1611 | struct ehci_qtd, qtd_list); | ||
1612 | qtd->hw_next = QTD_NEXT(dma); | ||
1613 | |||
1614 | /* let the hc process these next qtds */ | ||
1615 | dummy->hw_token = (token & ~(0x80)); | ||
1616 | wmb(); | ||
1617 | dummy->hw_token = token; | ||
1618 | |||
1619 | urb->hcpriv = qh_get(qh); | ||
1620 | } | ||
1621 | } | ||
1622 | return qh; | ||
1623 | } | ||
1624 | |||
1625 | static int submit_async(struct oxu_hcd *oxu, struct urb *urb, | ||
1626 | struct list_head *qtd_list, gfp_t mem_flags) | ||
1627 | { | ||
1628 | struct ehci_qtd *qtd; | ||
1629 | int epnum; | ||
1630 | unsigned long flags; | ||
1631 | struct ehci_qh *qh = NULL; | ||
1632 | int rc = 0; | ||
1633 | |||
1634 | qtd = list_entry(qtd_list->next, struct ehci_qtd, qtd_list); | ||
1635 | epnum = urb->ep->desc.bEndpointAddress; | ||
1636 | |||
1637 | #ifdef OXU_URB_TRACE | ||
1638 | oxu_dbg(oxu, "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n", | ||
1639 | __func__, urb->dev->devpath, urb, | ||
1640 | epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", | ||
1641 | urb->transfer_buffer_length, | ||
1642 | qtd, urb->ep->hcpriv); | ||
1643 | #endif | ||
1644 | |||
1645 | spin_lock_irqsave(&oxu->lock, flags); | ||
1646 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | ||
1647 | &oxu_to_hcd(oxu)->flags))) { | ||
1648 | rc = -ESHUTDOWN; | ||
1649 | goto done; | ||
1650 | } | ||
1651 | |||
1652 | qh = qh_append_tds(oxu, urb, qtd_list, epnum, &urb->ep->hcpriv); | ||
1653 | if (unlikely(qh == NULL)) { | ||
1654 | rc = -ENOMEM; | ||
1655 | goto done; | ||
1656 | } | ||
1657 | |||
1658 | /* Control/bulk operations through TTs don't need scheduling, | ||
1659 | * the HC and TT handle it when the TT has a buffer ready. | ||
1660 | */ | ||
1661 | if (likely(qh->qh_state == QH_STATE_IDLE)) | ||
1662 | qh_link_async(oxu, qh_get(qh)); | ||
1663 | done: | ||
1664 | spin_unlock_irqrestore(&oxu->lock, flags); | ||
1665 | if (unlikely(qh == NULL)) | ||
1666 | qtd_list_free(oxu, urb, qtd_list); | ||
1667 | return rc; | ||
1668 | } | ||
1669 | |||
1670 | /* The async qh for the qtds being reclaimed are now unlinked from the HC */ | ||
1671 | |||
1672 | static void end_unlink_async(struct oxu_hcd *oxu) | ||
1673 | { | ||
1674 | struct ehci_qh *qh = oxu->reclaim; | ||
1675 | struct ehci_qh *next; | ||
1676 | |||
1677 | timer_action_done(oxu, TIMER_IAA_WATCHDOG); | ||
1678 | |||
1679 | qh->qh_state = QH_STATE_IDLE; | ||
1680 | qh->qh_next.qh = NULL; | ||
1681 | qh_put(qh); /* refcount from reclaim */ | ||
1682 | |||
1683 | /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ | ||
1684 | next = qh->reclaim; | ||
1685 | oxu->reclaim = next; | ||
1686 | oxu->reclaim_ready = 0; | ||
1687 | qh->reclaim = NULL; | ||
1688 | |||
1689 | qh_completions(oxu, qh); | ||
1690 | |||
1691 | if (!list_empty(&qh->qtd_list) | ||
1692 | && HC_IS_RUNNING(oxu_to_hcd(oxu)->state)) | ||
1693 | qh_link_async(oxu, qh); | ||
1694 | else { | ||
1695 | qh_put(qh); /* refcount from async list */ | ||
1696 | |||
1697 | /* it's not free to turn the async schedule on/off; leave it | ||
1698 | * active but idle for a while once it empties. | ||
1699 | */ | ||
1700 | if (HC_IS_RUNNING(oxu_to_hcd(oxu)->state) | ||
1701 | && oxu->async->qh_next.qh == NULL) | ||
1702 | timer_action(oxu, TIMER_ASYNC_OFF); | ||
1703 | } | ||
1704 | |||
1705 | if (next) { | ||
1706 | oxu->reclaim = NULL; | ||
1707 | start_unlink_async(oxu, next); | ||
1708 | } | ||
1709 | } | ||
1710 | |||
1711 | /* makes sure the async qh will become idle */ | ||
1712 | /* caller must own oxu->lock */ | ||
1713 | |||
1714 | static void start_unlink_async(struct oxu_hcd *oxu, struct ehci_qh *qh) | ||
1715 | { | ||
1716 | int cmd = readl(&oxu->regs->command); | ||
1717 | struct ehci_qh *prev; | ||
1718 | |||
1719 | #ifdef DEBUG | ||
1720 | assert_spin_locked(&oxu->lock); | ||
1721 | if (oxu->reclaim || (qh->qh_state != QH_STATE_LINKED | ||
1722 | && qh->qh_state != QH_STATE_UNLINK_WAIT)) | ||
1723 | BUG(); | ||
1724 | #endif | ||
1725 | |||
1726 | /* stop async schedule right now? */ | ||
1727 | if (unlikely(qh == oxu->async)) { | ||
1728 | /* can't get here without STS_ASS set */ | ||
1729 | if (oxu_to_hcd(oxu)->state != HC_STATE_HALT | ||
1730 | && !oxu->reclaim) { | ||
1731 | /* ... and CMD_IAAD clear */ | ||
1732 | writel(cmd & ~CMD_ASE, &oxu->regs->command); | ||
1733 | wmb(); | ||
1734 | /* handshake later, if we need to */ | ||
1735 | timer_action_done(oxu, TIMER_ASYNC_OFF); | ||
1736 | } | ||
1737 | return; | ||
1738 | } | ||
1739 | |||
1740 | qh->qh_state = QH_STATE_UNLINK; | ||
1741 | oxu->reclaim = qh = qh_get(qh); | ||
1742 | |||
1743 | prev = oxu->async; | ||
1744 | while (prev->qh_next.qh != qh) | ||
1745 | prev = prev->qh_next.qh; | ||
1746 | |||
1747 | prev->hw_next = qh->hw_next; | ||
1748 | prev->qh_next = qh->qh_next; | ||
1749 | wmb(); | ||
1750 | |||
1751 | if (unlikely(oxu_to_hcd(oxu)->state == HC_STATE_HALT)) { | ||
1752 | /* if (unlikely(qh->reclaim != 0)) | ||
1753 | * this will recurse, probably not much | ||
1754 | */ | ||
1755 | end_unlink_async(oxu); | ||
1756 | return; | ||
1757 | } | ||
1758 | |||
1759 | oxu->reclaim_ready = 0; | ||
1760 | cmd |= CMD_IAAD; | ||
1761 | writel(cmd, &oxu->regs->command); | ||
1762 | (void) readl(&oxu->regs->command); | ||
1763 | timer_action(oxu, TIMER_IAA_WATCHDOG); | ||
1764 | } | ||
1765 | |||
1766 | static void scan_async(struct oxu_hcd *oxu) | ||
1767 | { | ||
1768 | struct ehci_qh *qh; | ||
1769 | enum ehci_timer_action action = TIMER_IO_WATCHDOG; | ||
1770 | |||
1771 | if (!++(oxu->stamp)) | ||
1772 | oxu->stamp++; | ||
1773 | timer_action_done(oxu, TIMER_ASYNC_SHRINK); | ||
1774 | rescan: | ||
1775 | qh = oxu->async->qh_next.qh; | ||
1776 | if (likely(qh != NULL)) { | ||
1777 | do { | ||
1778 | /* clean any finished work for this qh */ | ||
1779 | if (!list_empty(&qh->qtd_list) | ||
1780 | && qh->stamp != oxu->stamp) { | ||
1781 | int temp; | ||
1782 | |||
1783 | /* unlinks could happen here; completion | ||
1784 | * reporting drops the lock. rescan using | ||
1785 | * the latest schedule, but don't rescan | ||
1786 | * qhs we already finished (no looping). | ||
1787 | */ | ||
1788 | qh = qh_get(qh); | ||
1789 | qh->stamp = oxu->stamp; | ||
1790 | temp = qh_completions(oxu, qh); | ||
1791 | qh_put(qh); | ||
1792 | if (temp != 0) | ||
1793 | goto rescan; | ||
1794 | } | ||
1795 | |||
1796 | /* unlink idle entries, reducing HC PCI usage as well | ||
1797 | * as HCD schedule-scanning costs. delay for any qh | ||
1798 | * we just scanned, there's a not-unusual case that it | ||
1799 | * doesn't stay idle for long. | ||
1800 | * (plus, avoids some kind of re-activation race.) | ||
1801 | */ | ||
1802 | if (list_empty(&qh->qtd_list)) { | ||
1803 | if (qh->stamp == oxu->stamp) | ||
1804 | action = TIMER_ASYNC_SHRINK; | ||
1805 | else if (!oxu->reclaim | ||
1806 | && qh->qh_state == QH_STATE_LINKED) | ||
1807 | start_unlink_async(oxu, qh); | ||
1808 | } | ||
1809 | |||
1810 | qh = qh->qh_next.qh; | ||
1811 | } while (qh); | ||
1812 | } | ||
1813 | if (action == TIMER_ASYNC_SHRINK) | ||
1814 | timer_action(oxu, TIMER_ASYNC_SHRINK); | ||
1815 | } | ||
1816 | |||
1817 | /* | ||
1818 | * periodic_next_shadow - return "next" pointer on shadow list | ||
1819 | * @periodic: host pointer to qh/itd/sitd | ||
1820 | * @tag: hardware tag for type of this record | ||
1821 | */ | ||
1822 | static union ehci_shadow *periodic_next_shadow(union ehci_shadow *periodic, | ||
1823 | __le32 tag) | ||
1824 | { | ||
1825 | switch (tag) { | ||
1826 | default: | ||
1827 | case Q_TYPE_QH: | ||
1828 | return &periodic->qh->qh_next; | ||
1829 | } | ||
1830 | } | ||
1831 | |||
1832 | /* caller must hold oxu->lock */ | ||
1833 | static void periodic_unlink(struct oxu_hcd *oxu, unsigned frame, void *ptr) | ||
1834 | { | ||
1835 | union ehci_shadow *prev_p = &oxu->pshadow[frame]; | ||
1836 | __le32 *hw_p = &oxu->periodic[frame]; | ||
1837 | union ehci_shadow here = *prev_p; | ||
1838 | |||
1839 | /* find predecessor of "ptr"; hw and shadow lists are in sync */ | ||
1840 | while (here.ptr && here.ptr != ptr) { | ||
1841 | prev_p = periodic_next_shadow(prev_p, Q_NEXT_TYPE(*hw_p)); | ||
1842 | hw_p = here.hw_next; | ||
1843 | here = *prev_p; | ||
1844 | } | ||
1845 | /* an interrupt entry (at list end) could have been shared */ | ||
1846 | if (!here.ptr) | ||
1847 | return; | ||
1848 | |||
1849 | /* update shadow and hardware lists ... the old "next" pointers | ||
1850 | * from ptr may still be in use, the caller updates them. | ||
1851 | */ | ||
1852 | *prev_p = *periodic_next_shadow(&here, Q_NEXT_TYPE(*hw_p)); | ||
1853 | *hw_p = *here.hw_next; | ||
1854 | } | ||
1855 | |||
1856 | /* how many of the uframe's 125 usecs are allocated? */ | ||
1857 | static unsigned short periodic_usecs(struct oxu_hcd *oxu, | ||
1858 | unsigned frame, unsigned uframe) | ||
1859 | { | ||
1860 | __le32 *hw_p = &oxu->periodic[frame]; | ||
1861 | union ehci_shadow *q = &oxu->pshadow[frame]; | ||
1862 | unsigned usecs = 0; | ||
1863 | |||
1864 | while (q->ptr) { | ||
1865 | switch (Q_NEXT_TYPE(*hw_p)) { | ||
1866 | case Q_TYPE_QH: | ||
1867 | default: | ||
1868 | /* is it in the S-mask? */ | ||
1869 | if (q->qh->hw_info2 & cpu_to_le32(1 << uframe)) | ||
1870 | usecs += q->qh->usecs; | ||
1871 | /* ... or C-mask? */ | ||
1872 | if (q->qh->hw_info2 & cpu_to_le32(1 << (8 + uframe))) | ||
1873 | usecs += q->qh->c_usecs; | ||
1874 | hw_p = &q->qh->hw_next; | ||
1875 | q = &q->qh->qh_next; | ||
1876 | break; | ||
1877 | } | ||
1878 | } | ||
1879 | #ifdef DEBUG | ||
1880 | if (usecs > 100) | ||
1881 | oxu_err(oxu, "uframe %d sched overrun: %d usecs\n", | ||
1882 | frame * 8 + uframe, usecs); | ||
1883 | #endif | ||
1884 | return usecs; | ||
1885 | } | ||
1886 | |||
1887 | static int enable_periodic(struct oxu_hcd *oxu) | ||
1888 | { | ||
1889 | u32 cmd; | ||
1890 | int status; | ||
1891 | |||
1892 | /* did clearing PSE did take effect yet? | ||
1893 | * takes effect only at frame boundaries... | ||
1894 | */ | ||
1895 | status = handshake(oxu, &oxu->regs->status, STS_PSS, 0, 9 * 125); | ||
1896 | if (status != 0) { | ||
1897 | oxu_to_hcd(oxu)->state = HC_STATE_HALT; | ||
1898 | return status; | ||
1899 | } | ||
1900 | |||
1901 | cmd = readl(&oxu->regs->command) | CMD_PSE; | ||
1902 | writel(cmd, &oxu->regs->command); | ||
1903 | /* posted write ... PSS happens later */ | ||
1904 | oxu_to_hcd(oxu)->state = HC_STATE_RUNNING; | ||
1905 | |||
1906 | /* make sure ehci_work scans these */ | ||
1907 | oxu->next_uframe = readl(&oxu->regs->frame_index) | ||
1908 | % (oxu->periodic_size << 3); | ||
1909 | return 0; | ||
1910 | } | ||
1911 | |||
1912 | static int disable_periodic(struct oxu_hcd *oxu) | ||
1913 | { | ||
1914 | u32 cmd; | ||
1915 | int status; | ||
1916 | |||
1917 | /* did setting PSE not take effect yet? | ||
1918 | * takes effect only at frame boundaries... | ||
1919 | */ | ||
1920 | status = handshake(oxu, &oxu->regs->status, STS_PSS, STS_PSS, 9 * 125); | ||
1921 | if (status != 0) { | ||
1922 | oxu_to_hcd(oxu)->state = HC_STATE_HALT; | ||
1923 | return status; | ||
1924 | } | ||
1925 | |||
1926 | cmd = readl(&oxu->regs->command) & ~CMD_PSE; | ||
1927 | writel(cmd, &oxu->regs->command); | ||
1928 | /* posted write ... */ | ||
1929 | |||
1930 | oxu->next_uframe = -1; | ||
1931 | return 0; | ||
1932 | } | ||
1933 | |||
1934 | /* periodic schedule slots have iso tds (normal or split) first, then a | ||
1935 | * sparse tree for active interrupt transfers. | ||
1936 | * | ||
1937 | * this just links in a qh; caller guarantees uframe masks are set right. | ||
1938 | * no FSTN support (yet; oxu 0.96+) | ||
1939 | */ | ||
1940 | static int qh_link_periodic(struct oxu_hcd *oxu, struct ehci_qh *qh) | ||
1941 | { | ||
1942 | unsigned i; | ||
1943 | unsigned period = qh->period; | ||
1944 | |||
1945 | dev_dbg(&qh->dev->dev, | ||
1946 | "link qh%d-%04x/%p start %d [%d/%d us]\n", | ||
1947 | period, le32_to_cpup(&qh->hw_info2) & (QH_CMASK | QH_SMASK), | ||
1948 | qh, qh->start, qh->usecs, qh->c_usecs); | ||
1949 | |||
1950 | /* high bandwidth, or otherwise every microframe */ | ||
1951 | if (period == 0) | ||
1952 | period = 1; | ||
1953 | |||
1954 | for (i = qh->start; i < oxu->periodic_size; i += period) { | ||
1955 | union ehci_shadow *prev = &oxu->pshadow[i]; | ||
1956 | __le32 *hw_p = &oxu->periodic[i]; | ||
1957 | union ehci_shadow here = *prev; | ||
1958 | __le32 type = 0; | ||
1959 | |||
1960 | /* skip the iso nodes at list head */ | ||
1961 | while (here.ptr) { | ||
1962 | type = Q_NEXT_TYPE(*hw_p); | ||
1963 | if (type == Q_TYPE_QH) | ||
1964 | break; | ||
1965 | prev = periodic_next_shadow(prev, type); | ||
1966 | hw_p = &here.qh->hw_next; | ||
1967 | here = *prev; | ||
1968 | } | ||
1969 | |||
1970 | /* sorting each branch by period (slow-->fast) | ||
1971 | * enables sharing interior tree nodes | ||
1972 | */ | ||
1973 | while (here.ptr && qh != here.qh) { | ||
1974 | if (qh->period > here.qh->period) | ||
1975 | break; | ||
1976 | prev = &here.qh->qh_next; | ||
1977 | hw_p = &here.qh->hw_next; | ||
1978 | here = *prev; | ||
1979 | } | ||
1980 | /* link in this qh, unless some earlier pass did that */ | ||
1981 | if (qh != here.qh) { | ||
1982 | qh->qh_next = here; | ||
1983 | if (here.qh) | ||
1984 | qh->hw_next = *hw_p; | ||
1985 | wmb(); | ||
1986 | prev->qh = qh; | ||
1987 | *hw_p = QH_NEXT(qh->qh_dma); | ||
1988 | } | ||
1989 | } | ||
1990 | qh->qh_state = QH_STATE_LINKED; | ||
1991 | qh_get(qh); | ||
1992 | |||
1993 | /* update per-qh bandwidth for usbfs */ | ||
1994 | oxu_to_hcd(oxu)->self.bandwidth_allocated += qh->period | ||
1995 | ? ((qh->usecs + qh->c_usecs) / qh->period) | ||
1996 | : (qh->usecs * 8); | ||
1997 | |||
1998 | /* maybe enable periodic schedule processing */ | ||
1999 | if (!oxu->periodic_sched++) | ||
2000 | return enable_periodic(oxu); | ||
2001 | |||
2002 | return 0; | ||
2003 | } | ||
2004 | |||
2005 | static void qh_unlink_periodic(struct oxu_hcd *oxu, struct ehci_qh *qh) | ||
2006 | { | ||
2007 | unsigned i; | ||
2008 | unsigned period; | ||
2009 | |||
2010 | /* FIXME: | ||
2011 | * IF this isn't high speed | ||
2012 | * and this qh is active in the current uframe | ||
2013 | * (and overlay token SplitXstate is false?) | ||
2014 | * THEN | ||
2015 | * qh->hw_info1 |= __constant_cpu_to_le32(1 << 7 "ignore"); | ||
2016 | */ | ||
2017 | |||
2018 | /* high bandwidth, or otherwise part of every microframe */ | ||
2019 | period = qh->period; | ||
2020 | if (period == 0) | ||
2021 | period = 1; | ||
2022 | |||
2023 | for (i = qh->start; i < oxu->periodic_size; i += period) | ||
2024 | periodic_unlink(oxu, i, qh); | ||
2025 | |||
2026 | /* update per-qh bandwidth for usbfs */ | ||
2027 | oxu_to_hcd(oxu)->self.bandwidth_allocated -= qh->period | ||
2028 | ? ((qh->usecs + qh->c_usecs) / qh->period) | ||
2029 | : (qh->usecs * 8); | ||
2030 | |||
2031 | dev_dbg(&qh->dev->dev, | ||
2032 | "unlink qh%d-%04x/%p start %d [%d/%d us]\n", | ||
2033 | qh->period, | ||
2034 | le32_to_cpup(&qh->hw_info2) & (QH_CMASK | QH_SMASK), | ||
2035 | qh, qh->start, qh->usecs, qh->c_usecs); | ||
2036 | |||
2037 | /* qh->qh_next still "live" to HC */ | ||
2038 | qh->qh_state = QH_STATE_UNLINK; | ||
2039 | qh->qh_next.ptr = NULL; | ||
2040 | qh_put(qh); | ||
2041 | |||
2042 | /* maybe turn off periodic schedule */ | ||
2043 | oxu->periodic_sched--; | ||
2044 | if (!oxu->periodic_sched) | ||
2045 | (void) disable_periodic(oxu); | ||
2046 | } | ||
2047 | |||
2048 | static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh) | ||
2049 | { | ||
2050 | unsigned wait; | ||
2051 | |||
2052 | qh_unlink_periodic(oxu, qh); | ||
2053 | |||
2054 | /* simple/paranoid: always delay, expecting the HC needs to read | ||
2055 | * qh->hw_next or finish a writeback after SPLIT/CSPLIT ... and | ||
2056 | * expect khubd to clean up after any CSPLITs we won't issue. | ||
2057 | * active high speed queues may need bigger delays... | ||
2058 | */ | ||
2059 | if (list_empty(&qh->qtd_list) | ||
2060 | || (__constant_cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0) | ||
2061 | wait = 2; | ||
2062 | else | ||
2063 | wait = 55; /* worst case: 3 * 1024 */ | ||
2064 | |||
2065 | udelay(wait); | ||
2066 | qh->qh_state = QH_STATE_IDLE; | ||
2067 | qh->hw_next = EHCI_LIST_END; | ||
2068 | wmb(); | ||
2069 | } | ||
2070 | |||
2071 | static int check_period(struct oxu_hcd *oxu, | ||
2072 | unsigned frame, unsigned uframe, | ||
2073 | unsigned period, unsigned usecs) | ||
2074 | { | ||
2075 | int claimed; | ||
2076 | |||
2077 | /* complete split running into next frame? | ||
2078 | * given FSTN support, we could sometimes check... | ||
2079 | */ | ||
2080 | if (uframe >= 8) | ||
2081 | return 0; | ||
2082 | |||
2083 | /* | ||
2084 | * 80% periodic == 100 usec/uframe available | ||
2085 | * convert "usecs we need" to "max already claimed" | ||
2086 | */ | ||
2087 | usecs = 100 - usecs; | ||
2088 | |||
2089 | /* we "know" 2 and 4 uframe intervals were rejected; so | ||
2090 | * for period 0, check _every_ microframe in the schedule. | ||
2091 | */ | ||
2092 | if (unlikely(period == 0)) { | ||
2093 | do { | ||
2094 | for (uframe = 0; uframe < 7; uframe++) { | ||
2095 | claimed = periodic_usecs(oxu, frame, uframe); | ||
2096 | if (claimed > usecs) | ||
2097 | return 0; | ||
2098 | } | ||
2099 | } while ((frame += 1) < oxu->periodic_size); | ||
2100 | |||
2101 | /* just check the specified uframe, at that period */ | ||
2102 | } else { | ||
2103 | do { | ||
2104 | claimed = periodic_usecs(oxu, frame, uframe); | ||
2105 | if (claimed > usecs) | ||
2106 | return 0; | ||
2107 | } while ((frame += period) < oxu->periodic_size); | ||
2108 | } | ||
2109 | |||
2110 | return 1; | ||
2111 | } | ||
2112 | |||
2113 | static int check_intr_schedule(struct oxu_hcd *oxu, | ||
2114 | unsigned frame, unsigned uframe, | ||
2115 | const struct ehci_qh *qh, __le32 *c_maskp) | ||
2116 | { | ||
2117 | int retval = -ENOSPC; | ||
2118 | |||
2119 | if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ | ||
2120 | goto done; | ||
2121 | |||
2122 | if (!check_period(oxu, frame, uframe, qh->period, qh->usecs)) | ||
2123 | goto done; | ||
2124 | if (!qh->c_usecs) { | ||
2125 | retval = 0; | ||
2126 | *c_maskp = 0; | ||
2127 | goto done; | ||
2128 | } | ||
2129 | |||
2130 | done: | ||
2131 | return retval; | ||
2132 | } | ||
2133 | |||
2134 | /* "first fit" scheduling policy used the first time through, | ||
2135 | * or when the previous schedule slot can't be re-used. | ||
2136 | */ | ||
2137 | static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh) | ||
2138 | { | ||
2139 | int status; | ||
2140 | unsigned uframe; | ||
2141 | __le32 c_mask; | ||
2142 | unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ | ||
2143 | |||
2144 | qh_refresh(oxu, qh); | ||
2145 | qh->hw_next = EHCI_LIST_END; | ||
2146 | frame = qh->start; | ||
2147 | |||
2148 | /* reuse the previous schedule slots, if we can */ | ||
2149 | if (frame < qh->period) { | ||
2150 | uframe = ffs(le32_to_cpup(&qh->hw_info2) & QH_SMASK); | ||
2151 | status = check_intr_schedule(oxu, frame, --uframe, | ||
2152 | qh, &c_mask); | ||
2153 | } else { | ||
2154 | uframe = 0; | ||
2155 | c_mask = 0; | ||
2156 | status = -ENOSPC; | ||
2157 | } | ||
2158 | |||
2159 | /* else scan the schedule to find a group of slots such that all | ||
2160 | * uframes have enough periodic bandwidth available. | ||
2161 | */ | ||
2162 | if (status) { | ||
2163 | /* "normal" case, uframing flexible except with splits */ | ||
2164 | if (qh->period) { | ||
2165 | frame = qh->period - 1; | ||
2166 | do { | ||
2167 | for (uframe = 0; uframe < 8; uframe++) { | ||
2168 | status = check_intr_schedule(oxu, | ||
2169 | frame, uframe, qh, | ||
2170 | &c_mask); | ||
2171 | if (status == 0) | ||
2172 | break; | ||
2173 | } | ||
2174 | } while (status && frame--); | ||
2175 | |||
2176 | /* qh->period == 0 means every uframe */ | ||
2177 | } else { | ||
2178 | frame = 0; | ||
2179 | status = check_intr_schedule(oxu, 0, 0, qh, &c_mask); | ||
2180 | } | ||
2181 | if (status) | ||
2182 | goto done; | ||
2183 | qh->start = frame; | ||
2184 | |||
2185 | /* reset S-frame and (maybe) C-frame masks */ | ||
2186 | qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK)); | ||
2187 | qh->hw_info2 |= qh->period | ||
2188 | ? cpu_to_le32(1 << uframe) | ||
2189 | : __constant_cpu_to_le32(QH_SMASK); | ||
2190 | qh->hw_info2 |= c_mask; | ||
2191 | } else | ||
2192 | oxu_dbg(oxu, "reused qh %p schedule\n", qh); | ||
2193 | |||
2194 | /* stuff into the periodic schedule */ | ||
2195 | status = qh_link_periodic(oxu, qh); | ||
2196 | done: | ||
2197 | return status; | ||
2198 | } | ||
2199 | |||
2200 | static int intr_submit(struct oxu_hcd *oxu, struct urb *urb, | ||
2201 | struct list_head *qtd_list, gfp_t mem_flags) | ||
2202 | { | ||
2203 | unsigned epnum; | ||
2204 | unsigned long flags; | ||
2205 | struct ehci_qh *qh; | ||
2206 | int status = 0; | ||
2207 | struct list_head empty; | ||
2208 | |||
2209 | /* get endpoint and transfer/schedule data */ | ||
2210 | epnum = urb->ep->desc.bEndpointAddress; | ||
2211 | |||
2212 | spin_lock_irqsave(&oxu->lock, flags); | ||
2213 | |||
2214 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | ||
2215 | &oxu_to_hcd(oxu)->flags))) { | ||
2216 | status = -ESHUTDOWN; | ||
2217 | goto done; | ||
2218 | } | ||
2219 | |||
2220 | /* get qh and force any scheduling errors */ | ||
2221 | INIT_LIST_HEAD(&empty); | ||
2222 | qh = qh_append_tds(oxu, urb, &empty, epnum, &urb->ep->hcpriv); | ||
2223 | if (qh == NULL) { | ||
2224 | status = -ENOMEM; | ||
2225 | goto done; | ||
2226 | } | ||
2227 | if (qh->qh_state == QH_STATE_IDLE) { | ||
2228 | status = qh_schedule(oxu, qh); | ||
2229 | if (status != 0) | ||
2230 | goto done; | ||
2231 | } | ||
2232 | |||
2233 | /* then queue the urb's tds to the qh */ | ||
2234 | qh = qh_append_tds(oxu, urb, qtd_list, epnum, &urb->ep->hcpriv); | ||
2235 | BUG_ON(qh == NULL); | ||
2236 | |||
2237 | /* ... update usbfs periodic stats */ | ||
2238 | oxu_to_hcd(oxu)->self.bandwidth_int_reqs++; | ||
2239 | |||
2240 | done: | ||
2241 | spin_unlock_irqrestore(&oxu->lock, flags); | ||
2242 | if (status) | ||
2243 | qtd_list_free(oxu, urb, qtd_list); | ||
2244 | |||
2245 | return status; | ||
2246 | } | ||
2247 | |||
2248 | static inline int itd_submit(struct oxu_hcd *oxu, struct urb *urb, | ||
2249 | gfp_t mem_flags) | ||
2250 | { | ||
2251 | oxu_dbg(oxu, "iso support is missing!\n"); | ||
2252 | return -ENOSYS; | ||
2253 | } | ||
2254 | |||
2255 | static inline int sitd_submit(struct oxu_hcd *oxu, struct urb *urb, | ||
2256 | gfp_t mem_flags) | ||
2257 | { | ||
2258 | oxu_dbg(oxu, "split iso support is missing!\n"); | ||
2259 | return -ENOSYS; | ||
2260 | } | ||
2261 | |||
2262 | static void scan_periodic(struct oxu_hcd *oxu) | ||
2263 | { | ||
2264 | unsigned frame, clock, now_uframe, mod; | ||
2265 | unsigned modified; | ||
2266 | |||
2267 | mod = oxu->periodic_size << 3; | ||
2268 | |||
2269 | /* | ||
2270 | * When running, scan from last scan point up to "now" | ||
2271 | * else clean up by scanning everything that's left. | ||
2272 | * Touches as few pages as possible: cache-friendly. | ||
2273 | */ | ||
2274 | now_uframe = oxu->next_uframe; | ||
2275 | if (HC_IS_RUNNING(oxu_to_hcd(oxu)->state)) | ||
2276 | clock = readl(&oxu->regs->frame_index); | ||
2277 | else | ||
2278 | clock = now_uframe + mod - 1; | ||
2279 | clock %= mod; | ||
2280 | |||
2281 | for (;;) { | ||
2282 | union ehci_shadow q, *q_p; | ||
2283 | __le32 type, *hw_p; | ||
2284 | unsigned uframes; | ||
2285 | |||
2286 | /* don't scan past the live uframe */ | ||
2287 | frame = now_uframe >> 3; | ||
2288 | if (frame == (clock >> 3)) | ||
2289 | uframes = now_uframe & 0x07; | ||
2290 | else { | ||
2291 | /* safe to scan the whole frame at once */ | ||
2292 | now_uframe |= 0x07; | ||
2293 | uframes = 8; | ||
2294 | } | ||
2295 | |||
2296 | restart: | ||
2297 | /* scan each element in frame's queue for completions */ | ||
2298 | q_p = &oxu->pshadow[frame]; | ||
2299 | hw_p = &oxu->periodic[frame]; | ||
2300 | q.ptr = q_p->ptr; | ||
2301 | type = Q_NEXT_TYPE(*hw_p); | ||
2302 | modified = 0; | ||
2303 | |||
2304 | while (q.ptr != NULL) { | ||
2305 | union ehci_shadow temp; | ||
2306 | int live; | ||
2307 | |||
2308 | live = HC_IS_RUNNING(oxu_to_hcd(oxu)->state); | ||
2309 | switch (type) { | ||
2310 | case Q_TYPE_QH: | ||
2311 | /* handle any completions */ | ||
2312 | temp.qh = qh_get(q.qh); | ||
2313 | type = Q_NEXT_TYPE(q.qh->hw_next); | ||
2314 | q = q.qh->qh_next; | ||
2315 | modified = qh_completions(oxu, temp.qh); | ||
2316 | if (unlikely(list_empty(&temp.qh->qtd_list))) | ||
2317 | intr_deschedule(oxu, temp.qh); | ||
2318 | qh_put(temp.qh); | ||
2319 | break; | ||
2320 | default: | ||
2321 | dbg("corrupt type %d frame %d shadow %p", | ||
2322 | type, frame, q.ptr); | ||
2323 | q.ptr = NULL; | ||
2324 | } | ||
2325 | |||
2326 | /* assume completion callbacks modify the queue */ | ||
2327 | if (unlikely(modified)) | ||
2328 | goto restart; | ||
2329 | } | ||
2330 | |||
2331 | /* Stop when we catch up to the HC */ | ||
2332 | |||
2333 | /* FIXME: this assumes we won't get lapped when | ||
2334 | * latencies climb; that should be rare, but... | ||
2335 | * detect it, and just go all the way around. | ||
2336 | * FLR might help detect this case, so long as latencies | ||
2337 | * don't exceed periodic_size msec (default 1.024 sec). | ||
2338 | */ | ||
2339 | |||
2340 | /* FIXME: likewise assumes HC doesn't halt mid-scan */ | ||
2341 | |||
2342 | if (now_uframe == clock) { | ||
2343 | unsigned now; | ||
2344 | |||
2345 | if (!HC_IS_RUNNING(oxu_to_hcd(oxu)->state)) | ||
2346 | break; | ||
2347 | oxu->next_uframe = now_uframe; | ||
2348 | now = readl(&oxu->regs->frame_index) % mod; | ||
2349 | if (now_uframe == now) | ||
2350 | break; | ||
2351 | |||
2352 | /* rescan the rest of this frame, then ... */ | ||
2353 | clock = now; | ||
2354 | } else { | ||
2355 | now_uframe++; | ||
2356 | now_uframe %= mod; | ||
2357 | } | ||
2358 | } | ||
2359 | } | ||
2360 | |||
2361 | /* On some systems, leaving remote wakeup enabled prevents system shutdown. | ||
2362 | * The firmware seems to think that powering off is a wakeup event! | ||
2363 | * This routine turns off remote wakeup and everything else, on all ports. | ||
2364 | */ | ||
2365 | static void ehci_turn_off_all_ports(struct oxu_hcd *oxu) | ||
2366 | { | ||
2367 | int port = HCS_N_PORTS(oxu->hcs_params); | ||
2368 | |||
2369 | while (port--) | ||
2370 | writel(PORT_RWC_BITS, &oxu->regs->port_status[port]); | ||
2371 | } | ||
2372 | |||
2373 | static void ehci_port_power(struct oxu_hcd *oxu, int is_on) | ||
2374 | { | ||
2375 | unsigned port; | ||
2376 | |||
2377 | if (!HCS_PPC(oxu->hcs_params)) | ||
2378 | return; | ||
2379 | |||
2380 | oxu_dbg(oxu, "...power%s ports...\n", is_on ? "up" : "down"); | ||
2381 | for (port = HCS_N_PORTS(oxu->hcs_params); port > 0; ) | ||
2382 | (void) oxu_hub_control(oxu_to_hcd(oxu), | ||
2383 | is_on ? SetPortFeature : ClearPortFeature, | ||
2384 | USB_PORT_FEAT_POWER, | ||
2385 | port--, NULL, 0); | ||
2386 | msleep(20); | ||
2387 | } | ||
2388 | |||
2389 | /* Called from some interrupts, timers, and so on. | ||
2390 | * It calls driver completion functions, after dropping oxu->lock. | ||
2391 | */ | ||
2392 | static void ehci_work(struct oxu_hcd *oxu) | ||
2393 | { | ||
2394 | timer_action_done(oxu, TIMER_IO_WATCHDOG); | ||
2395 | if (oxu->reclaim_ready) | ||
2396 | end_unlink_async(oxu); | ||
2397 | |||
2398 | /* another CPU may drop oxu->lock during a schedule scan while | ||
2399 | * it reports urb completions. this flag guards against bogus | ||
2400 | * attempts at re-entrant schedule scanning. | ||
2401 | */ | ||
2402 | if (oxu->scanning) | ||
2403 | return; | ||
2404 | oxu->scanning = 1; | ||
2405 | scan_async(oxu); | ||
2406 | if (oxu->next_uframe != -1) | ||
2407 | scan_periodic(oxu); | ||
2408 | oxu->scanning = 0; | ||
2409 | |||
2410 | /* the IO watchdog guards against hardware or driver bugs that | ||
2411 | * misplace IRQs, and should let us run completely without IRQs. | ||
2412 | * such lossage has been observed on both VT6202 and VT8235. | ||
2413 | */ | ||
2414 | if (HC_IS_RUNNING(oxu_to_hcd(oxu)->state) && | ||
2415 | (oxu->async->qh_next.ptr != NULL || | ||
2416 | oxu->periodic_sched != 0)) | ||
2417 | timer_action(oxu, TIMER_IO_WATCHDOG); | ||
2418 | } | ||
2419 | |||
2420 | static void unlink_async(struct oxu_hcd *oxu, struct ehci_qh *qh) | ||
2421 | { | ||
2422 | /* if we need to use IAA and it's busy, defer */ | ||
2423 | if (qh->qh_state == QH_STATE_LINKED | ||
2424 | && oxu->reclaim | ||
2425 | && HC_IS_RUNNING(oxu_to_hcd(oxu)->state)) { | ||
2426 | struct ehci_qh *last; | ||
2427 | |||
2428 | for (last = oxu->reclaim; | ||
2429 | last->reclaim; | ||
2430 | last = last->reclaim) | ||
2431 | continue; | ||
2432 | qh->qh_state = QH_STATE_UNLINK_WAIT; | ||
2433 | last->reclaim = qh; | ||
2434 | |||
2435 | /* bypass IAA if the hc can't care */ | ||
2436 | } else if (!HC_IS_RUNNING(oxu_to_hcd(oxu)->state) && oxu->reclaim) | ||
2437 | end_unlink_async(oxu); | ||
2438 | |||
2439 | /* something else might have unlinked the qh by now */ | ||
2440 | if (qh->qh_state == QH_STATE_LINKED) | ||
2441 | start_unlink_async(oxu, qh); | ||
2442 | } | ||
2443 | |||
2444 | /* | ||
2445 | * USB host controller methods | ||
2446 | */ | ||
2447 | |||
2448 | static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd) | ||
2449 | { | ||
2450 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
2451 | u32 status, pcd_status = 0; | ||
2452 | int bh; | ||
2453 | |||
2454 | spin_lock(&oxu->lock); | ||
2455 | |||
2456 | status = readl(&oxu->regs->status); | ||
2457 | |||
2458 | /* e.g. cardbus physical eject */ | ||
2459 | if (status == ~(u32) 0) { | ||
2460 | oxu_dbg(oxu, "device removed\n"); | ||
2461 | goto dead; | ||
2462 | } | ||
2463 | |||
2464 | status &= INTR_MASK; | ||
2465 | if (!status) { /* irq sharing? */ | ||
2466 | spin_unlock(&oxu->lock); | ||
2467 | return IRQ_NONE; | ||
2468 | } | ||
2469 | |||
2470 | /* clear (just) interrupts */ | ||
2471 | writel(status, &oxu->regs->status); | ||
2472 | readl(&oxu->regs->command); /* unblock posted write */ | ||
2473 | bh = 0; | ||
2474 | |||
2475 | #ifdef OXU_VERBOSE_DEBUG | ||
2476 | /* unrequested/ignored: Frame List Rollover */ | ||
2477 | dbg_status(oxu, "irq", status); | ||
2478 | #endif | ||
2479 | |||
2480 | /* INT, ERR, and IAA interrupt rates can be throttled */ | ||
2481 | |||
2482 | /* normal [4.15.1.2] or error [4.15.1.1] completion */ | ||
2483 | if (likely((status & (STS_INT|STS_ERR)) != 0)) | ||
2484 | bh = 1; | ||
2485 | |||
2486 | /* complete the unlinking of some qh [4.15.2.3] */ | ||
2487 | if (status & STS_IAA) { | ||
2488 | oxu->reclaim_ready = 1; | ||
2489 | bh = 1; | ||
2490 | } | ||
2491 | |||
2492 | /* remote wakeup [4.3.1] */ | ||
2493 | if (status & STS_PCD) { | ||
2494 | unsigned i = HCS_N_PORTS(oxu->hcs_params); | ||
2495 | pcd_status = status; | ||
2496 | |||
2497 | /* resume root hub? */ | ||
2498 | if (!(readl(&oxu->regs->command) & CMD_RUN)) | ||
2499 | usb_hcd_resume_root_hub(hcd); | ||
2500 | |||
2501 | while (i--) { | ||
2502 | int pstatus = readl(&oxu->regs->port_status[i]); | ||
2503 | |||
2504 | if (pstatus & PORT_OWNER) | ||
2505 | continue; | ||
2506 | if (!(pstatus & PORT_RESUME) | ||
2507 | || oxu->reset_done[i] != 0) | ||
2508 | continue; | ||
2509 | |||
2510 | /* start 20 msec resume signaling from this port, | ||
2511 | * and make khubd collect PORT_STAT_C_SUSPEND to | ||
2512 | * stop that signaling. | ||
2513 | */ | ||
2514 | oxu->reset_done[i] = jiffies + msecs_to_jiffies(20); | ||
2515 | oxu_dbg(oxu, "port %d remote wakeup\n", i + 1); | ||
2516 | mod_timer(&hcd->rh_timer, oxu->reset_done[i]); | ||
2517 | } | ||
2518 | } | ||
2519 | |||
2520 | /* PCI errors [4.15.2.4] */ | ||
2521 | if (unlikely((status & STS_FATAL) != 0)) { | ||
2522 | /* bogus "fatal" IRQs appear on some chips... why? */ | ||
2523 | status = readl(&oxu->regs->status); | ||
2524 | dbg_cmd(oxu, "fatal", readl(&oxu->regs->command)); | ||
2525 | dbg_status(oxu, "fatal", status); | ||
2526 | if (status & STS_HALT) { | ||
2527 | oxu_err(oxu, "fatal error\n"); | ||
2528 | dead: | ||
2529 | ehci_reset(oxu); | ||
2530 | writel(0, &oxu->regs->configured_flag); | ||
2531 | /* generic layer kills/unlinks all urbs, then | ||
2532 | * uses oxu_stop to clean up the rest | ||
2533 | */ | ||
2534 | bh = 1; | ||
2535 | } | ||
2536 | } | ||
2537 | |||
2538 | if (bh) | ||
2539 | ehci_work(oxu); | ||
2540 | spin_unlock(&oxu->lock); | ||
2541 | if (pcd_status & STS_PCD) | ||
2542 | usb_hcd_poll_rh_status(hcd); | ||
2543 | return IRQ_HANDLED; | ||
2544 | } | ||
2545 | |||
2546 | static irqreturn_t oxu_irq(struct usb_hcd *hcd) | ||
2547 | { | ||
2548 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
2549 | int ret = IRQ_HANDLED; | ||
2550 | |||
2551 | u32 status = oxu_readl(hcd->regs, OXU_CHIPIRQSTATUS); | ||
2552 | u32 enable = oxu_readl(hcd->regs, OXU_CHIPIRQEN_SET); | ||
2553 | |||
2554 | /* Disable all interrupt */ | ||
2555 | oxu_writel(hcd->regs, OXU_CHIPIRQEN_CLR, enable); | ||
2556 | |||
2557 | if ((oxu->is_otg && (status & OXU_USBOTGI)) || | ||
2558 | (!oxu->is_otg && (status & OXU_USBSPHI))) | ||
2559 | oxu210_hcd_irq(hcd); | ||
2560 | else | ||
2561 | ret = IRQ_NONE; | ||
2562 | |||
2563 | /* Enable all interrupt back */ | ||
2564 | oxu_writel(hcd->regs, OXU_CHIPIRQEN_SET, enable); | ||
2565 | |||
2566 | return ret; | ||
2567 | } | ||
2568 | |||
2569 | static void oxu_watchdog(unsigned long param) | ||
2570 | { | ||
2571 | struct oxu_hcd *oxu = (struct oxu_hcd *) param; | ||
2572 | unsigned long flags; | ||
2573 | |||
2574 | spin_lock_irqsave(&oxu->lock, flags); | ||
2575 | |||
2576 | /* lost IAA irqs wedge things badly; seen with a vt8235 */ | ||
2577 | if (oxu->reclaim) { | ||
2578 | u32 status = readl(&oxu->regs->status); | ||
2579 | if (status & STS_IAA) { | ||
2580 | oxu_vdbg(oxu, "lost IAA\n"); | ||
2581 | writel(STS_IAA, &oxu->regs->status); | ||
2582 | oxu->reclaim_ready = 1; | ||
2583 | } | ||
2584 | } | ||
2585 | |||
2586 | /* stop async processing after it's idled a bit */ | ||
2587 | if (test_bit(TIMER_ASYNC_OFF, &oxu->actions)) | ||
2588 | start_unlink_async(oxu, oxu->async); | ||
2589 | |||
2590 | /* oxu could run by timer, without IRQs ... */ | ||
2591 | ehci_work(oxu); | ||
2592 | |||
2593 | spin_unlock_irqrestore(&oxu->lock, flags); | ||
2594 | } | ||
2595 | |||
2596 | /* One-time init, only for memory state. | ||
2597 | */ | ||
2598 | static int oxu_hcd_init(struct usb_hcd *hcd) | ||
2599 | { | ||
2600 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
2601 | u32 temp; | ||
2602 | int retval; | ||
2603 | u32 hcc_params; | ||
2604 | |||
2605 | spin_lock_init(&oxu->lock); | ||
2606 | |||
2607 | init_timer(&oxu->watchdog); | ||
2608 | oxu->watchdog.function = oxu_watchdog; | ||
2609 | oxu->watchdog.data = (unsigned long) oxu; | ||
2610 | |||
2611 | /* | ||
2612 | * hw default: 1K periodic list heads, one per frame. | ||
2613 | * periodic_size can shrink by USBCMD update if hcc_params allows. | ||
2614 | */ | ||
2615 | oxu->periodic_size = DEFAULT_I_TDPS; | ||
2616 | retval = ehci_mem_init(oxu, GFP_KERNEL); | ||
2617 | if (retval < 0) | ||
2618 | return retval; | ||
2619 | |||
2620 | /* controllers may cache some of the periodic schedule ... */ | ||
2621 | hcc_params = readl(&oxu->caps->hcc_params); | ||
2622 | if (HCC_ISOC_CACHE(hcc_params)) /* full frame cache */ | ||
2623 | oxu->i_thresh = 8; | ||
2624 | else /* N microframes cached */ | ||
2625 | oxu->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); | ||
2626 | |||
2627 | oxu->reclaim = NULL; | ||
2628 | oxu->reclaim_ready = 0; | ||
2629 | oxu->next_uframe = -1; | ||
2630 | |||
2631 | /* | ||
2632 | * dedicate a qh for the async ring head, since we couldn't unlink | ||
2633 | * a 'real' qh without stopping the async schedule [4.8]. use it | ||
2634 | * as the 'reclamation list head' too. | ||
2635 | * its dummy is used in hw_alt_next of many tds, to prevent the qh | ||
2636 | * from automatically advancing to the next td after short reads. | ||
2637 | */ | ||
2638 | oxu->async->qh_next.qh = NULL; | ||
2639 | oxu->async->hw_next = QH_NEXT(oxu->async->qh_dma); | ||
2640 | oxu->async->hw_info1 = cpu_to_le32(QH_HEAD); | ||
2641 | oxu->async->hw_token = cpu_to_le32(QTD_STS_HALT); | ||
2642 | oxu->async->hw_qtd_next = EHCI_LIST_END; | ||
2643 | oxu->async->qh_state = QH_STATE_LINKED; | ||
2644 | oxu->async->hw_alt_next = QTD_NEXT(oxu->async->dummy->qtd_dma); | ||
2645 | |||
2646 | /* clear interrupt enables, set irq latency */ | ||
2647 | if (log2_irq_thresh < 0 || log2_irq_thresh > 6) | ||
2648 | log2_irq_thresh = 0; | ||
2649 | temp = 1 << (16 + log2_irq_thresh); | ||
2650 | if (HCC_CANPARK(hcc_params)) { | ||
2651 | /* HW default park == 3, on hardware that supports it (like | ||
2652 | * NVidia and ALI silicon), maximizes throughput on the async | ||
2653 | * schedule by avoiding QH fetches between transfers. | ||
2654 | * | ||
2655 | * With fast usb storage devices and NForce2, "park" seems to | ||
2656 | * make problems: throughput reduction (!), data errors... | ||
2657 | */ | ||
2658 | if (park) { | ||
2659 | park = min(park, (unsigned) 3); | ||
2660 | temp |= CMD_PARK; | ||
2661 | temp |= park << 8; | ||
2662 | } | ||
2663 | oxu_dbg(oxu, "park %d\n", park); | ||
2664 | } | ||
2665 | if (HCC_PGM_FRAMELISTLEN(hcc_params)) { | ||
2666 | /* periodic schedule size can be smaller than default */ | ||
2667 | temp &= ~(3 << 2); | ||
2668 | temp |= (EHCI_TUNE_FLS << 2); | ||
2669 | } | ||
2670 | oxu->command = temp; | ||
2671 | |||
2672 | return 0; | ||
2673 | } | ||
2674 | |||
2675 | /* Called during probe() after chip reset completes. | ||
2676 | */ | ||
2677 | static int oxu_reset(struct usb_hcd *hcd) | ||
2678 | { | ||
2679 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
2680 | int ret; | ||
2681 | |||
2682 | spin_lock_init(&oxu->mem_lock); | ||
2683 | INIT_LIST_HEAD(&oxu->urb_list); | ||
2684 | oxu->urb_len = 0; | ||
2685 | |||
2686 | /* FIMXE */ | ||
2687 | hcd->self.controller->dma_mask = 0UL; | ||
2688 | |||
2689 | if (oxu->is_otg) { | ||
2690 | oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET; | ||
2691 | oxu->regs = hcd->regs + OXU_OTG_CAP_OFFSET + \ | ||
2692 | HC_LENGTH(readl(&oxu->caps->hc_capbase)); | ||
2693 | |||
2694 | oxu->mem = hcd->regs + OXU_SPH_MEM; | ||
2695 | } else { | ||
2696 | oxu->caps = hcd->regs + OXU_SPH_CAP_OFFSET; | ||
2697 | oxu->regs = hcd->regs + OXU_SPH_CAP_OFFSET + \ | ||
2698 | HC_LENGTH(readl(&oxu->caps->hc_capbase)); | ||
2699 | |||
2700 | oxu->mem = hcd->regs + OXU_OTG_MEM; | ||
2701 | } | ||
2702 | |||
2703 | oxu->hcs_params = readl(&oxu->caps->hcs_params); | ||
2704 | oxu->sbrn = 0x20; | ||
2705 | |||
2706 | ret = oxu_hcd_init(hcd); | ||
2707 | if (ret) | ||
2708 | return ret; | ||
2709 | |||
2710 | return 0; | ||
2711 | } | ||
2712 | |||
2713 | static int oxu_run(struct usb_hcd *hcd) | ||
2714 | { | ||
2715 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
2716 | int retval; | ||
2717 | u32 temp, hcc_params; | ||
2718 | |||
2719 | hcd->uses_new_polling = 1; | ||
2720 | hcd->poll_rh = 0; | ||
2721 | |||
2722 | /* EHCI spec section 4.1 */ | ||
2723 | retval = ehci_reset(oxu); | ||
2724 | if (retval != 0) { | ||
2725 | ehci_mem_cleanup(oxu); | ||
2726 | return retval; | ||
2727 | } | ||
2728 | writel(oxu->periodic_dma, &oxu->regs->frame_list); | ||
2729 | writel((u32) oxu->async->qh_dma, &oxu->regs->async_next); | ||
2730 | |||
2731 | /* hcc_params controls whether oxu->regs->segment must (!!!) | ||
2732 | * be used; it constrains QH/ITD/SITD and QTD locations. | ||
2733 | * pci_pool consistent memory always uses segment zero. | ||
2734 | * streaming mappings for I/O buffers, like pci_map_single(), | ||
2735 | * can return segments above 4GB, if the device allows. | ||
2736 | * | ||
2737 | * NOTE: the dma mask is visible through dma_supported(), so | ||
2738 | * drivers can pass this info along ... like NETIF_F_HIGHDMA, | ||
2739 | * Scsi_Host.highmem_io, and so forth. It's readonly to all | ||
2740 | * host side drivers though. | ||
2741 | */ | ||
2742 | hcc_params = readl(&oxu->caps->hcc_params); | ||
2743 | if (HCC_64BIT_ADDR(hcc_params)) | ||
2744 | writel(0, &oxu->regs->segment); | ||
2745 | |||
2746 | oxu->command &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | | ||
2747 | CMD_ASE | CMD_RESET); | ||
2748 | oxu->command |= CMD_RUN; | ||
2749 | writel(oxu->command, &oxu->regs->command); | ||
2750 | dbg_cmd(oxu, "init", oxu->command); | ||
2751 | |||
2752 | /* | ||
2753 | * Start, enabling full USB 2.0 functionality ... usb 1.1 devices | ||
2754 | * are explicitly handed to companion controller(s), so no TT is | ||
2755 | * involved with the root hub. (Except where one is integrated, | ||
2756 | * and there's no companion controller unless maybe for USB OTG.) | ||
2757 | */ | ||
2758 | hcd->state = HC_STATE_RUNNING; | ||
2759 | writel(FLAG_CF, &oxu->regs->configured_flag); | ||
2760 | readl(&oxu->regs->command); /* unblock posted writes */ | ||
2761 | |||
2762 | temp = HC_VERSION(readl(&oxu->caps->hc_capbase)); | ||
2763 | oxu_info(oxu, "USB %x.%x started, quasi-EHCI %x.%02x, driver %s%s\n", | ||
2764 | ((oxu->sbrn & 0xf0)>>4), (oxu->sbrn & 0x0f), | ||
2765 | temp >> 8, temp & 0xff, DRIVER_VERSION, | ||
2766 | ignore_oc ? ", overcurrent ignored" : ""); | ||
2767 | |||
2768 | writel(INTR_MASK, &oxu->regs->intr_enable); /* Turn On Interrupts */ | ||
2769 | |||
2770 | return 0; | ||
2771 | } | ||
2772 | |||
2773 | static void oxu_stop(struct usb_hcd *hcd) | ||
2774 | { | ||
2775 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
2776 | |||
2777 | /* Turn off port power on all root hub ports. */ | ||
2778 | ehci_port_power(oxu, 0); | ||
2779 | |||
2780 | /* no more interrupts ... */ | ||
2781 | del_timer_sync(&oxu->watchdog); | ||
2782 | |||
2783 | spin_lock_irq(&oxu->lock); | ||
2784 | if (HC_IS_RUNNING(hcd->state)) | ||
2785 | ehci_quiesce(oxu); | ||
2786 | |||
2787 | ehci_reset(oxu); | ||
2788 | writel(0, &oxu->regs->intr_enable); | ||
2789 | spin_unlock_irq(&oxu->lock); | ||
2790 | |||
2791 | /* let companion controllers work when we aren't */ | ||
2792 | writel(0, &oxu->regs->configured_flag); | ||
2793 | |||
2794 | /* root hub is shut down separately (first, when possible) */ | ||
2795 | spin_lock_irq(&oxu->lock); | ||
2796 | if (oxu->async) | ||
2797 | ehci_work(oxu); | ||
2798 | spin_unlock_irq(&oxu->lock); | ||
2799 | ehci_mem_cleanup(oxu); | ||
2800 | |||
2801 | dbg_status(oxu, "oxu_stop completed", readl(&oxu->regs->status)); | ||
2802 | } | ||
2803 | |||
2804 | /* Kick in for silicon on any bus (not just pci, etc). | ||
2805 | * This forcibly disables dma and IRQs, helping kexec and other cases | ||
2806 | * where the next system software may expect clean state. | ||
2807 | */ | ||
2808 | static void oxu_shutdown(struct usb_hcd *hcd) | ||
2809 | { | ||
2810 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
2811 | |||
2812 | (void) ehci_halt(oxu); | ||
2813 | ehci_turn_off_all_ports(oxu); | ||
2814 | |||
2815 | /* make BIOS/etc use companion controller during reboot */ | ||
2816 | writel(0, &oxu->regs->configured_flag); | ||
2817 | |||
2818 | /* unblock posted writes */ | ||
2819 | readl(&oxu->regs->configured_flag); | ||
2820 | } | ||
2821 | |||
2822 | /* Non-error returns are a promise to giveback() the urb later | ||
2823 | * we drop ownership so next owner (or urb unlink) can get it | ||
2824 | * | ||
2825 | * urb + dev is in hcd.self.controller.urb_list | ||
2826 | * we're queueing TDs onto software and hardware lists | ||
2827 | * | ||
2828 | * hcd-specific init for hcpriv hasn't been done yet | ||
2829 | * | ||
2830 | * NOTE: control, bulk, and interrupt share the same code to append TDs | ||
2831 | * to a (possibly active) QH, and the same QH scanning code. | ||
2832 | */ | ||
2833 | static int __oxu_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, | ||
2834 | gfp_t mem_flags) | ||
2835 | { | ||
2836 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
2837 | struct list_head qtd_list; | ||
2838 | |||
2839 | INIT_LIST_HEAD(&qtd_list); | ||
2840 | |||
2841 | switch (usb_pipetype(urb->pipe)) { | ||
2842 | case PIPE_CONTROL: | ||
2843 | case PIPE_BULK: | ||
2844 | default: | ||
2845 | if (!qh_urb_transaction(oxu, urb, &qtd_list, mem_flags)) | ||
2846 | return -ENOMEM; | ||
2847 | return submit_async(oxu, urb, &qtd_list, mem_flags); | ||
2848 | |||
2849 | case PIPE_INTERRUPT: | ||
2850 | if (!qh_urb_transaction(oxu, urb, &qtd_list, mem_flags)) | ||
2851 | return -ENOMEM; | ||
2852 | return intr_submit(oxu, urb, &qtd_list, mem_flags); | ||
2853 | |||
2854 | case PIPE_ISOCHRONOUS: | ||
2855 | if (urb->dev->speed == USB_SPEED_HIGH) | ||
2856 | return itd_submit(oxu, urb, mem_flags); | ||
2857 | else | ||
2858 | return sitd_submit(oxu, urb, mem_flags); | ||
2859 | } | ||
2860 | } | ||
2861 | |||
2862 | /* This function is responsible for breaking URBs with big data size | ||
2863 | * into smaller size and processing small urbs in sequence. | ||
2864 | */ | ||
2865 | static int oxu_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, | ||
2866 | gfp_t mem_flags) | ||
2867 | { | ||
2868 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
2869 | int num, rem; | ||
2870 | int transfer_buffer_length; | ||
2871 | void *transfer_buffer; | ||
2872 | struct urb *murb; | ||
2873 | int i, ret; | ||
2874 | |||
2875 | /* If not bulk pipe just enqueue the URB */ | ||
2876 | if (!usb_pipebulk(urb->pipe)) | ||
2877 | return __oxu_urb_enqueue(hcd, urb, mem_flags); | ||
2878 | |||
2879 | /* Otherwise we should verify the USB transfer buffer size! */ | ||
2880 | transfer_buffer = urb->transfer_buffer; | ||
2881 | transfer_buffer_length = urb->transfer_buffer_length; | ||
2882 | |||
2883 | num = urb->transfer_buffer_length / 4096; | ||
2884 | rem = urb->transfer_buffer_length % 4096; | ||
2885 | if (rem != 0) | ||
2886 | num++; | ||
2887 | |||
2888 | /* If URB is smaller than 4096 bytes just enqueue it! */ | ||
2889 | if (num == 1) | ||
2890 | return __oxu_urb_enqueue(hcd, urb, mem_flags); | ||
2891 | |||
2892 | /* Ok, we have more job to do! :) */ | ||
2893 | |||
2894 | for (i = 0; i < num - 1; i++) { | ||
2895 | /* Get free micro URB poll till a free urb is recieved */ | ||
2896 | |||
2897 | do { | ||
2898 | murb = (struct urb *) oxu_murb_alloc(oxu); | ||
2899 | if (!murb) | ||
2900 | schedule(); | ||
2901 | } while (!murb); | ||
2902 | |||
2903 | /* Coping the urb */ | ||
2904 | memcpy(murb, urb, sizeof(struct urb)); | ||
2905 | |||
2906 | murb->transfer_buffer_length = 4096; | ||
2907 | murb->transfer_buffer = transfer_buffer + i * 4096; | ||
2908 | |||
2909 | /* Null pointer for the encodes that this is a micro urb */ | ||
2910 | murb->complete = NULL; | ||
2911 | |||
2912 | ((struct oxu_murb *) murb)->main = urb; | ||
2913 | ((struct oxu_murb *) murb)->last = 0; | ||
2914 | |||
2915 | /* This loop is to guarantee urb to be processed when there's | ||
2916 | * not enough resources at a particular time by retrying. | ||
2917 | */ | ||
2918 | do { | ||
2919 | ret = __oxu_urb_enqueue(hcd, murb, mem_flags); | ||
2920 | if (ret) | ||
2921 | schedule(); | ||
2922 | } while (ret); | ||
2923 | } | ||
2924 | |||
2925 | /* Last urb requires special handling */ | ||
2926 | |||
2927 | /* Get free micro URB poll till a free urb is recieved */ | ||
2928 | do { | ||
2929 | murb = (struct urb *) oxu_murb_alloc(oxu); | ||
2930 | if (!murb) | ||
2931 | schedule(); | ||
2932 | } while (!murb); | ||
2933 | |||
2934 | /* Coping the urb */ | ||
2935 | memcpy(murb, urb, sizeof(struct urb)); | ||
2936 | |||
2937 | murb->transfer_buffer_length = rem > 0 ? rem : 4096; | ||
2938 | murb->transfer_buffer = transfer_buffer + (num - 1) * 4096; | ||
2939 | |||
2940 | /* Null pointer for the encodes that this is a micro urb */ | ||
2941 | murb->complete = NULL; | ||
2942 | |||
2943 | ((struct oxu_murb *) murb)->main = urb; | ||
2944 | ((struct oxu_murb *) murb)->last = 1; | ||
2945 | |||
2946 | do { | ||
2947 | ret = __oxu_urb_enqueue(hcd, murb, mem_flags); | ||
2948 | if (ret) | ||
2949 | schedule(); | ||
2950 | } while (ret); | ||
2951 | |||
2952 | return ret; | ||
2953 | } | ||
2954 | |||
2955 | /* Remove from hardware lists. | ||
2956 | * Completions normally happen asynchronously | ||
2957 | */ | ||
2958 | static int oxu_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | ||
2959 | { | ||
2960 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
2961 | struct ehci_qh *qh; | ||
2962 | unsigned long flags; | ||
2963 | |||
2964 | spin_lock_irqsave(&oxu->lock, flags); | ||
2965 | switch (usb_pipetype(urb->pipe)) { | ||
2966 | case PIPE_CONTROL: | ||
2967 | case PIPE_BULK: | ||
2968 | default: | ||
2969 | qh = (struct ehci_qh *) urb->hcpriv; | ||
2970 | if (!qh) | ||
2971 | break; | ||
2972 | unlink_async(oxu, qh); | ||
2973 | break; | ||
2974 | |||
2975 | case PIPE_INTERRUPT: | ||
2976 | qh = (struct ehci_qh *) urb->hcpriv; | ||
2977 | if (!qh) | ||
2978 | break; | ||
2979 | switch (qh->qh_state) { | ||
2980 | case QH_STATE_LINKED: | ||
2981 | intr_deschedule(oxu, qh); | ||
2982 | /* FALL THROUGH */ | ||
2983 | case QH_STATE_IDLE: | ||
2984 | qh_completions(oxu, qh); | ||
2985 | break; | ||
2986 | default: | ||
2987 | oxu_dbg(oxu, "bogus qh %p state %d\n", | ||
2988 | qh, qh->qh_state); | ||
2989 | goto done; | ||
2990 | } | ||
2991 | |||
2992 | /* reschedule QH iff another request is queued */ | ||
2993 | if (!list_empty(&qh->qtd_list) | ||
2994 | && HC_IS_RUNNING(hcd->state)) { | ||
2995 | int status; | ||
2996 | |||
2997 | status = qh_schedule(oxu, qh); | ||
2998 | spin_unlock_irqrestore(&oxu->lock, flags); | ||
2999 | |||
3000 | if (status != 0) { | ||
3001 | /* shouldn't happen often, but ... | ||
3002 | * FIXME kill those tds' urbs | ||
3003 | */ | ||
3004 | err("can't reschedule qh %p, err %d", | ||
3005 | qh, status); | ||
3006 | } | ||
3007 | return status; | ||
3008 | } | ||
3009 | break; | ||
3010 | } | ||
3011 | done: | ||
3012 | spin_unlock_irqrestore(&oxu->lock, flags); | ||
3013 | return 0; | ||
3014 | } | ||
3015 | |||
3016 | /* Bulk qh holds the data toggle */ | ||
3017 | static void oxu_endpoint_disable(struct usb_hcd *hcd, | ||
3018 | struct usb_host_endpoint *ep) | ||
3019 | { | ||
3020 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
3021 | unsigned long flags; | ||
3022 | struct ehci_qh *qh, *tmp; | ||
3023 | |||
3024 | /* ASSERT: any requests/urbs are being unlinked */ | ||
3025 | /* ASSERT: nobody can be submitting urbs for this any more */ | ||
3026 | |||
3027 | rescan: | ||
3028 | spin_lock_irqsave(&oxu->lock, flags); | ||
3029 | qh = ep->hcpriv; | ||
3030 | if (!qh) | ||
3031 | goto done; | ||
3032 | |||
3033 | /* endpoints can be iso streams. for now, we don't | ||
3034 | * accelerate iso completions ... so spin a while. | ||
3035 | */ | ||
3036 | if (qh->hw_info1 == 0) { | ||
3037 | oxu_vdbg(oxu, "iso delay\n"); | ||
3038 | goto idle_timeout; | ||
3039 | } | ||
3040 | |||
3041 | if (!HC_IS_RUNNING(hcd->state)) | ||
3042 | qh->qh_state = QH_STATE_IDLE; | ||
3043 | switch (qh->qh_state) { | ||
3044 | case QH_STATE_LINKED: | ||
3045 | for (tmp = oxu->async->qh_next.qh; | ||
3046 | tmp && tmp != qh; | ||
3047 | tmp = tmp->qh_next.qh) | ||
3048 | continue; | ||
3049 | /* periodic qh self-unlinks on empty */ | ||
3050 | if (!tmp) | ||
3051 | goto nogood; | ||
3052 | unlink_async(oxu, qh); | ||
3053 | /* FALL THROUGH */ | ||
3054 | case QH_STATE_UNLINK: /* wait for hw to finish? */ | ||
3055 | idle_timeout: | ||
3056 | spin_unlock_irqrestore(&oxu->lock, flags); | ||
3057 | schedule_timeout_uninterruptible(1); | ||
3058 | goto rescan; | ||
3059 | case QH_STATE_IDLE: /* fully unlinked */ | ||
3060 | if (list_empty(&qh->qtd_list)) { | ||
3061 | qh_put(qh); | ||
3062 | break; | ||
3063 | } | ||
3064 | /* else FALL THROUGH */ | ||
3065 | default: | ||
3066 | nogood: | ||
3067 | /* caller was supposed to have unlinked any requests; | ||
3068 | * that's not our job. just leak this memory. | ||
3069 | */ | ||
3070 | oxu_err(oxu, "qh %p (#%02x) state %d%s\n", | ||
3071 | qh, ep->desc.bEndpointAddress, qh->qh_state, | ||
3072 | list_empty(&qh->qtd_list) ? "" : "(has tds)"); | ||
3073 | break; | ||
3074 | } | ||
3075 | ep->hcpriv = NULL; | ||
3076 | done: | ||
3077 | spin_unlock_irqrestore(&oxu->lock, flags); | ||
3078 | return; | ||
3079 | } | ||
3080 | |||
3081 | static int oxu_get_frame(struct usb_hcd *hcd) | ||
3082 | { | ||
3083 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
3084 | |||
3085 | return (readl(&oxu->regs->frame_index) >> 3) % | ||
3086 | oxu->periodic_size; | ||
3087 | } | ||
3088 | |||
3089 | /* Build "status change" packet (one or two bytes) from HC registers */ | ||
3090 | static int oxu_hub_status_data(struct usb_hcd *hcd, char *buf) | ||
3091 | { | ||
3092 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
3093 | u32 temp, mask, status = 0; | ||
3094 | int ports, i, retval = 1; | ||
3095 | unsigned long flags; | ||
3096 | |||
3097 | /* if !USB_SUSPEND, root hub timers won't get shut down ... */ | ||
3098 | if (!HC_IS_RUNNING(hcd->state)) | ||
3099 | return 0; | ||
3100 | |||
3101 | /* init status to no-changes */ | ||
3102 | buf[0] = 0; | ||
3103 | ports = HCS_N_PORTS(oxu->hcs_params); | ||
3104 | if (ports > 7) { | ||
3105 | buf[1] = 0; | ||
3106 | retval++; | ||
3107 | } | ||
3108 | |||
3109 | /* Some boards (mostly VIA?) report bogus overcurrent indications, | ||
3110 | * causing massive log spam unless we completely ignore them. It | ||
3111 | * may be relevant that VIA VT8235 controlers, where PORT_POWER is | ||
3112 | * always set, seem to clear PORT_OCC and PORT_CSC when writing to | ||
3113 | * PORT_POWER; that's surprising, but maybe within-spec. | ||
3114 | */ | ||
3115 | if (!ignore_oc) | ||
3116 | mask = PORT_CSC | PORT_PEC | PORT_OCC; | ||
3117 | else | ||
3118 | mask = PORT_CSC | PORT_PEC; | ||
3119 | |||
3120 | /* no hub change reports (bit 0) for now (power, ...) */ | ||
3121 | |||
3122 | /* port N changes (bit N)? */ | ||
3123 | spin_lock_irqsave(&oxu->lock, flags); | ||
3124 | for (i = 0; i < ports; i++) { | ||
3125 | temp = readl(&oxu->regs->port_status[i]); | ||
3126 | |||
3127 | /* | ||
3128 | * Return status information even for ports with OWNER set. | ||
3129 | * Otherwise khubd wouldn't see the disconnect event when a | ||
3130 | * high-speed device is switched over to the companion | ||
3131 | * controller by the user. | ||
3132 | */ | ||
3133 | |||
3134 | if (!(temp & PORT_CONNECT)) | ||
3135 | oxu->reset_done[i] = 0; | ||
3136 | if ((temp & mask) != 0 || ((temp & PORT_RESUME) != 0 && | ||
3137 | time_after_eq(jiffies, oxu->reset_done[i]))) { | ||
3138 | if (i < 7) | ||
3139 | buf[0] |= 1 << (i + 1); | ||
3140 | else | ||
3141 | buf[1] |= 1 << (i - 7); | ||
3142 | status = STS_PCD; | ||
3143 | } | ||
3144 | } | ||
3145 | /* FIXME autosuspend idle root hubs */ | ||
3146 | spin_unlock_irqrestore(&oxu->lock, flags); | ||
3147 | return status ? retval : 0; | ||
3148 | } | ||
3149 | |||
3150 | /* Returns the speed of a device attached to a port on the root hub. */ | ||
3151 | static inline unsigned int oxu_port_speed(struct oxu_hcd *oxu, | ||
3152 | unsigned int portsc) | ||
3153 | { | ||
3154 | switch ((portsc >> 26) & 3) { | ||
3155 | case 0: | ||
3156 | return 0; | ||
3157 | case 1: | ||
3158 | return 1 << USB_PORT_FEAT_LOWSPEED; | ||
3159 | case 2: | ||
3160 | default: | ||
3161 | return 1 << USB_PORT_FEAT_HIGHSPEED; | ||
3162 | } | ||
3163 | } | ||
3164 | |||
3165 | #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) | ||
3166 | static int oxu_hub_control(struct usb_hcd *hcd, u16 typeReq, | ||
3167 | u16 wValue, u16 wIndex, char *buf, u16 wLength) | ||
3168 | { | ||
3169 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
3170 | int ports = HCS_N_PORTS(oxu->hcs_params); | ||
3171 | u32 __iomem *status_reg = &oxu->regs->port_status[wIndex - 1]; | ||
3172 | u32 temp, status; | ||
3173 | unsigned long flags; | ||
3174 | int retval = 0; | ||
3175 | unsigned selector; | ||
3176 | |||
3177 | /* | ||
3178 | * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. | ||
3179 | * HCS_INDICATOR may say we can change LEDs to off/amber/green. | ||
3180 | * (track current state ourselves) ... blink for diagnostics, | ||
3181 | * power, "this is the one", etc. EHCI spec supports this. | ||
3182 | */ | ||
3183 | |||
3184 | spin_lock_irqsave(&oxu->lock, flags); | ||
3185 | switch (typeReq) { | ||
3186 | case ClearHubFeature: | ||
3187 | switch (wValue) { | ||
3188 | case C_HUB_LOCAL_POWER: | ||
3189 | case C_HUB_OVER_CURRENT: | ||
3190 | /* no hub-wide feature/status flags */ | ||
3191 | break; | ||
3192 | default: | ||
3193 | goto error; | ||
3194 | } | ||
3195 | break; | ||
3196 | case ClearPortFeature: | ||
3197 | if (!wIndex || wIndex > ports) | ||
3198 | goto error; | ||
3199 | wIndex--; | ||
3200 | temp = readl(status_reg); | ||
3201 | |||
3202 | /* | ||
3203 | * Even if OWNER is set, so the port is owned by the | ||
3204 | * companion controller, khubd needs to be able to clear | ||
3205 | * the port-change status bits (especially | ||
3206 | * USB_PORT_FEAT_C_CONNECTION). | ||
3207 | */ | ||
3208 | |||
3209 | switch (wValue) { | ||
3210 | case USB_PORT_FEAT_ENABLE: | ||
3211 | writel(temp & ~PORT_PE, status_reg); | ||
3212 | break; | ||
3213 | case USB_PORT_FEAT_C_ENABLE: | ||
3214 | writel((temp & ~PORT_RWC_BITS) | PORT_PEC, status_reg); | ||
3215 | break; | ||
3216 | case USB_PORT_FEAT_SUSPEND: | ||
3217 | if (temp & PORT_RESET) | ||
3218 | goto error; | ||
3219 | if (temp & PORT_SUSPEND) { | ||
3220 | if ((temp & PORT_PE) == 0) | ||
3221 | goto error; | ||
3222 | /* resume signaling for 20 msec */ | ||
3223 | temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); | ||
3224 | writel(temp | PORT_RESUME, status_reg); | ||
3225 | oxu->reset_done[wIndex] = jiffies | ||
3226 | + msecs_to_jiffies(20); | ||
3227 | } | ||
3228 | break; | ||
3229 | case USB_PORT_FEAT_C_SUSPEND: | ||
3230 | /* we auto-clear this feature */ | ||
3231 | break; | ||
3232 | case USB_PORT_FEAT_POWER: | ||
3233 | if (HCS_PPC(oxu->hcs_params)) | ||
3234 | writel(temp & ~(PORT_RWC_BITS | PORT_POWER), | ||
3235 | status_reg); | ||
3236 | break; | ||
3237 | case USB_PORT_FEAT_C_CONNECTION: | ||
3238 | writel((temp & ~PORT_RWC_BITS) | PORT_CSC, status_reg); | ||
3239 | break; | ||
3240 | case USB_PORT_FEAT_C_OVER_CURRENT: | ||
3241 | writel((temp & ~PORT_RWC_BITS) | PORT_OCC, status_reg); | ||
3242 | break; | ||
3243 | case USB_PORT_FEAT_C_RESET: | ||
3244 | /* GetPortStatus clears reset */ | ||
3245 | break; | ||
3246 | default: | ||
3247 | goto error; | ||
3248 | } | ||
3249 | readl(&oxu->regs->command); /* unblock posted write */ | ||
3250 | break; | ||
3251 | case GetHubDescriptor: | ||
3252 | ehci_hub_descriptor(oxu, (struct usb_hub_descriptor *) | ||
3253 | buf); | ||
3254 | break; | ||
3255 | case GetHubStatus: | ||
3256 | /* no hub-wide feature/status flags */ | ||
3257 | memset(buf, 0, 4); | ||
3258 | break; | ||
3259 | case GetPortStatus: | ||
3260 | if (!wIndex || wIndex > ports) | ||
3261 | goto error; | ||
3262 | wIndex--; | ||
3263 | status = 0; | ||
3264 | temp = readl(status_reg); | ||
3265 | |||
3266 | /* wPortChange bits */ | ||
3267 | if (temp & PORT_CSC) | ||
3268 | status |= 1 << USB_PORT_FEAT_C_CONNECTION; | ||
3269 | if (temp & PORT_PEC) | ||
3270 | status |= 1 << USB_PORT_FEAT_C_ENABLE; | ||
3271 | if ((temp & PORT_OCC) && !ignore_oc) | ||
3272 | status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; | ||
3273 | |||
3274 | /* whoever resumes must GetPortStatus to complete it!! */ | ||
3275 | if (temp & PORT_RESUME) { | ||
3276 | |||
3277 | /* Remote Wakeup received? */ | ||
3278 | if (!oxu->reset_done[wIndex]) { | ||
3279 | /* resume signaling for 20 msec */ | ||
3280 | oxu->reset_done[wIndex] = jiffies | ||
3281 | + msecs_to_jiffies(20); | ||
3282 | /* check the port again */ | ||
3283 | mod_timer(&oxu_to_hcd(oxu)->rh_timer, | ||
3284 | oxu->reset_done[wIndex]); | ||
3285 | } | ||
3286 | |||
3287 | /* resume completed? */ | ||
3288 | else if (time_after_eq(jiffies, | ||
3289 | oxu->reset_done[wIndex])) { | ||
3290 | status |= 1 << USB_PORT_FEAT_C_SUSPEND; | ||
3291 | oxu->reset_done[wIndex] = 0; | ||
3292 | |||
3293 | /* stop resume signaling */ | ||
3294 | temp = readl(status_reg); | ||
3295 | writel(temp & ~(PORT_RWC_BITS | PORT_RESUME), | ||
3296 | status_reg); | ||
3297 | retval = handshake(oxu, status_reg, | ||
3298 | PORT_RESUME, 0, 2000 /* 2msec */); | ||
3299 | if (retval != 0) { | ||
3300 | oxu_err(oxu, | ||
3301 | "port %d resume error %d\n", | ||
3302 | wIndex + 1, retval); | ||
3303 | goto error; | ||
3304 | } | ||
3305 | temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); | ||
3306 | } | ||
3307 | } | ||
3308 | |||
3309 | /* whoever resets must GetPortStatus to complete it!! */ | ||
3310 | if ((temp & PORT_RESET) | ||
3311 | && time_after_eq(jiffies, | ||
3312 | oxu->reset_done[wIndex])) { | ||
3313 | status |= 1 << USB_PORT_FEAT_C_RESET; | ||
3314 | oxu->reset_done[wIndex] = 0; | ||
3315 | |||
3316 | /* force reset to complete */ | ||
3317 | writel(temp & ~(PORT_RWC_BITS | PORT_RESET), | ||
3318 | status_reg); | ||
3319 | /* REVISIT: some hardware needs 550+ usec to clear | ||
3320 | * this bit; seems too long to spin routinely... | ||
3321 | */ | ||
3322 | retval = handshake(oxu, status_reg, | ||
3323 | PORT_RESET, 0, 750); | ||
3324 | if (retval != 0) { | ||
3325 | oxu_err(oxu, "port %d reset error %d\n", | ||
3326 | wIndex + 1, retval); | ||
3327 | goto error; | ||
3328 | } | ||
3329 | |||
3330 | /* see what we found out */ | ||
3331 | temp = check_reset_complete(oxu, wIndex, status_reg, | ||
3332 | readl(status_reg)); | ||
3333 | } | ||
3334 | |||
3335 | /* transfer dedicated ports to the companion hc */ | ||
3336 | if ((temp & PORT_CONNECT) && | ||
3337 | test_bit(wIndex, &oxu->companion_ports)) { | ||
3338 | temp &= ~PORT_RWC_BITS; | ||
3339 | temp |= PORT_OWNER; | ||
3340 | writel(temp, status_reg); | ||
3341 | oxu_dbg(oxu, "port %d --> companion\n", wIndex + 1); | ||
3342 | temp = readl(status_reg); | ||
3343 | } | ||
3344 | |||
3345 | /* | ||
3346 | * Even if OWNER is set, there's no harm letting khubd | ||
3347 | * see the wPortStatus values (they should all be 0 except | ||
3348 | * for PORT_POWER anyway). | ||
3349 | */ | ||
3350 | |||
3351 | if (temp & PORT_CONNECT) { | ||
3352 | status |= 1 << USB_PORT_FEAT_CONNECTION; | ||
3353 | /* status may be from integrated TT */ | ||
3354 | status |= oxu_port_speed(oxu, temp); | ||
3355 | } | ||
3356 | if (temp & PORT_PE) | ||
3357 | status |= 1 << USB_PORT_FEAT_ENABLE; | ||
3358 | if (temp & (PORT_SUSPEND|PORT_RESUME)) | ||
3359 | status |= 1 << USB_PORT_FEAT_SUSPEND; | ||
3360 | if (temp & PORT_OC) | ||
3361 | status |= 1 << USB_PORT_FEAT_OVER_CURRENT; | ||
3362 | if (temp & PORT_RESET) | ||
3363 | status |= 1 << USB_PORT_FEAT_RESET; | ||
3364 | if (temp & PORT_POWER) | ||
3365 | status |= 1 << USB_PORT_FEAT_POWER; | ||
3366 | |||
3367 | #ifndef OXU_VERBOSE_DEBUG | ||
3368 | if (status & ~0xffff) /* only if wPortChange is interesting */ | ||
3369 | #endif | ||
3370 | dbg_port(oxu, "GetStatus", wIndex + 1, temp); | ||
3371 | put_unaligned(cpu_to_le32(status), (__le32 *) buf); | ||
3372 | break; | ||
3373 | case SetHubFeature: | ||
3374 | switch (wValue) { | ||
3375 | case C_HUB_LOCAL_POWER: | ||
3376 | case C_HUB_OVER_CURRENT: | ||
3377 | /* no hub-wide feature/status flags */ | ||
3378 | break; | ||
3379 | default: | ||
3380 | goto error; | ||
3381 | } | ||
3382 | break; | ||
3383 | case SetPortFeature: | ||
3384 | selector = wIndex >> 8; | ||
3385 | wIndex &= 0xff; | ||
3386 | if (!wIndex || wIndex > ports) | ||
3387 | goto error; | ||
3388 | wIndex--; | ||
3389 | temp = readl(status_reg); | ||
3390 | if (temp & PORT_OWNER) | ||
3391 | break; | ||
3392 | |||
3393 | temp &= ~PORT_RWC_BITS; | ||
3394 | switch (wValue) { | ||
3395 | case USB_PORT_FEAT_SUSPEND: | ||
3396 | if ((temp & PORT_PE) == 0 | ||
3397 | || (temp & PORT_RESET) != 0) | ||
3398 | goto error; | ||
3399 | if (device_may_wakeup(&hcd->self.root_hub->dev)) | ||
3400 | temp |= PORT_WAKE_BITS; | ||
3401 | writel(temp | PORT_SUSPEND, status_reg); | ||
3402 | break; | ||
3403 | case USB_PORT_FEAT_POWER: | ||
3404 | if (HCS_PPC(oxu->hcs_params)) | ||
3405 | writel(temp | PORT_POWER, status_reg); | ||
3406 | break; | ||
3407 | case USB_PORT_FEAT_RESET: | ||
3408 | if (temp & PORT_RESUME) | ||
3409 | goto error; | ||
3410 | /* line status bits may report this as low speed, | ||
3411 | * which can be fine if this root hub has a | ||
3412 | * transaction translator built in. | ||
3413 | */ | ||
3414 | oxu_vdbg(oxu, "port %d reset\n", wIndex + 1); | ||
3415 | temp |= PORT_RESET; | ||
3416 | temp &= ~PORT_PE; | ||
3417 | |||
3418 | /* | ||
3419 | * caller must wait, then call GetPortStatus | ||
3420 | * usb 2.0 spec says 50 ms resets on root | ||
3421 | */ | ||
3422 | oxu->reset_done[wIndex] = jiffies | ||
3423 | + msecs_to_jiffies(50); | ||
3424 | writel(temp, status_reg); | ||
3425 | break; | ||
3426 | |||
3427 | /* For downstream facing ports (these): one hub port is put | ||
3428 | * into test mode according to USB2 11.24.2.13, then the hub | ||
3429 | * must be reset (which for root hub now means rmmod+modprobe, | ||
3430 | * or else system reboot). See EHCI 2.3.9 and 4.14 for info | ||
3431 | * about the EHCI-specific stuff. | ||
3432 | */ | ||
3433 | case USB_PORT_FEAT_TEST: | ||
3434 | if (!selector || selector > 5) | ||
3435 | goto error; | ||
3436 | ehci_quiesce(oxu); | ||
3437 | ehci_halt(oxu); | ||
3438 | temp |= selector << 16; | ||
3439 | writel(temp, status_reg); | ||
3440 | break; | ||
3441 | |||
3442 | default: | ||
3443 | goto error; | ||
3444 | } | ||
3445 | readl(&oxu->regs->command); /* unblock posted writes */ | ||
3446 | break; | ||
3447 | |||
3448 | default: | ||
3449 | error: | ||
3450 | /* "stall" on error */ | ||
3451 | retval = -EPIPE; | ||
3452 | } | ||
3453 | spin_unlock_irqrestore(&oxu->lock, flags); | ||
3454 | return retval; | ||
3455 | } | ||
3456 | |||
3457 | #ifdef CONFIG_PM | ||
3458 | |||
3459 | static int oxu_bus_suspend(struct usb_hcd *hcd) | ||
3460 | { | ||
3461 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
3462 | int port; | ||
3463 | int mask; | ||
3464 | |||
3465 | oxu_dbg(oxu, "suspend root hub\n"); | ||
3466 | |||
3467 | if (time_before(jiffies, oxu->next_statechange)) | ||
3468 | msleep(5); | ||
3469 | |||
3470 | port = HCS_N_PORTS(oxu->hcs_params); | ||
3471 | spin_lock_irq(&oxu->lock); | ||
3472 | |||
3473 | /* stop schedules, clean any completed work */ | ||
3474 | if (HC_IS_RUNNING(hcd->state)) { | ||
3475 | ehci_quiesce(oxu); | ||
3476 | hcd->state = HC_STATE_QUIESCING; | ||
3477 | } | ||
3478 | oxu->command = readl(&oxu->regs->command); | ||
3479 | if (oxu->reclaim) | ||
3480 | oxu->reclaim_ready = 1; | ||
3481 | ehci_work(oxu); | ||
3482 | |||
3483 | /* Unlike other USB host controller types, EHCI doesn't have | ||
3484 | * any notion of "global" or bus-wide suspend. The driver has | ||
3485 | * to manually suspend all the active unsuspended ports, and | ||
3486 | * then manually resume them in the bus_resume() routine. | ||
3487 | */ | ||
3488 | oxu->bus_suspended = 0; | ||
3489 | while (port--) { | ||
3490 | u32 __iomem *reg = &oxu->regs->port_status[port]; | ||
3491 | u32 t1 = readl(reg) & ~PORT_RWC_BITS; | ||
3492 | u32 t2 = t1; | ||
3493 | |||
3494 | /* keep track of which ports we suspend */ | ||
3495 | if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) && | ||
3496 | !(t1 & PORT_SUSPEND)) { | ||
3497 | t2 |= PORT_SUSPEND; | ||
3498 | set_bit(port, &oxu->bus_suspended); | ||
3499 | } | ||
3500 | |||
3501 | /* enable remote wakeup on all ports */ | ||
3502 | if (device_may_wakeup(&hcd->self.root_hub->dev)) | ||
3503 | t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E; | ||
3504 | else | ||
3505 | t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E); | ||
3506 | |||
3507 | if (t1 != t2) { | ||
3508 | oxu_vdbg(oxu, "port %d, %08x -> %08x\n", | ||
3509 | port + 1, t1, t2); | ||
3510 | writel(t2, reg); | ||
3511 | } | ||
3512 | } | ||
3513 | |||
3514 | /* turn off now-idle HC */ | ||
3515 | del_timer_sync(&oxu->watchdog); | ||
3516 | ehci_halt(oxu); | ||
3517 | hcd->state = HC_STATE_SUSPENDED; | ||
3518 | |||
3519 | /* allow remote wakeup */ | ||
3520 | mask = INTR_MASK; | ||
3521 | if (!device_may_wakeup(&hcd->self.root_hub->dev)) | ||
3522 | mask &= ~STS_PCD; | ||
3523 | writel(mask, &oxu->regs->intr_enable); | ||
3524 | readl(&oxu->regs->intr_enable); | ||
3525 | |||
3526 | oxu->next_statechange = jiffies + msecs_to_jiffies(10); | ||
3527 | spin_unlock_irq(&oxu->lock); | ||
3528 | return 0; | ||
3529 | } | ||
3530 | |||
3531 | /* Caller has locked the root hub, and should reset/reinit on error */ | ||
3532 | static int oxu_bus_resume(struct usb_hcd *hcd) | ||
3533 | { | ||
3534 | struct oxu_hcd *oxu = hcd_to_oxu(hcd); | ||
3535 | u32 temp; | ||
3536 | int i; | ||
3537 | |||
3538 | if (time_before(jiffies, oxu->next_statechange)) | ||
3539 | msleep(5); | ||
3540 | spin_lock_irq(&oxu->lock); | ||
3541 | |||
3542 | /* Ideally and we've got a real resume here, and no port's power | ||
3543 | * was lost. (For PCI, that means Vaux was maintained.) But we | ||
3544 | * could instead be restoring a swsusp snapshot -- so that BIOS was | ||
3545 | * the last user of the controller, not reset/pm hardware keeping | ||
3546 | * state we gave to it. | ||
3547 | */ | ||
3548 | temp = readl(&oxu->regs->intr_enable); | ||
3549 | oxu_dbg(oxu, "resume root hub%s\n", temp ? "" : " after power loss"); | ||
3550 | |||
3551 | /* at least some APM implementations will try to deliver | ||
3552 | * IRQs right away, so delay them until we're ready. | ||
3553 | */ | ||
3554 | writel(0, &oxu->regs->intr_enable); | ||
3555 | |||
3556 | /* re-init operational registers */ | ||
3557 | writel(0, &oxu->regs->segment); | ||
3558 | writel(oxu->periodic_dma, &oxu->regs->frame_list); | ||
3559 | writel((u32) oxu->async->qh_dma, &oxu->regs->async_next); | ||
3560 | |||
3561 | /* restore CMD_RUN, framelist size, and irq threshold */ | ||
3562 | writel(oxu->command, &oxu->regs->command); | ||
3563 | |||
3564 | /* Some controller/firmware combinations need a delay during which | ||
3565 | * they set up the port statuses. See Bugzilla #8190. */ | ||
3566 | mdelay(8); | ||
3567 | |||
3568 | /* manually resume the ports we suspended during bus_suspend() */ | ||
3569 | i = HCS_N_PORTS(oxu->hcs_params); | ||
3570 | while (i--) { | ||
3571 | temp = readl(&oxu->regs->port_status[i]); | ||
3572 | temp &= ~(PORT_RWC_BITS | ||
3573 | | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); | ||
3574 | if (test_bit(i, &oxu->bus_suspended) && (temp & PORT_SUSPEND)) { | ||
3575 | oxu->reset_done[i] = jiffies + msecs_to_jiffies(20); | ||
3576 | temp |= PORT_RESUME; | ||
3577 | } | ||
3578 | writel(temp, &oxu->regs->port_status[i]); | ||
3579 | } | ||
3580 | i = HCS_N_PORTS(oxu->hcs_params); | ||
3581 | mdelay(20); | ||
3582 | while (i--) { | ||
3583 | temp = readl(&oxu->regs->port_status[i]); | ||
3584 | if (test_bit(i, &oxu->bus_suspended) && (temp & PORT_SUSPEND)) { | ||
3585 | temp &= ~(PORT_RWC_BITS | PORT_RESUME); | ||
3586 | writel(temp, &oxu->regs->port_status[i]); | ||
3587 | oxu_vdbg(oxu, "resumed port %d\n", i + 1); | ||
3588 | } | ||
3589 | } | ||
3590 | (void) readl(&oxu->regs->command); | ||
3591 | |||
3592 | /* maybe re-activate the schedule(s) */ | ||
3593 | temp = 0; | ||
3594 | if (oxu->async->qh_next.qh) | ||
3595 | temp |= CMD_ASE; | ||
3596 | if (oxu->periodic_sched) | ||
3597 | temp |= CMD_PSE; | ||
3598 | if (temp) { | ||
3599 | oxu->command |= temp; | ||
3600 | writel(oxu->command, &oxu->regs->command); | ||
3601 | } | ||
3602 | |||
3603 | oxu->next_statechange = jiffies + msecs_to_jiffies(5); | ||
3604 | hcd->state = HC_STATE_RUNNING; | ||
3605 | |||
3606 | /* Now we can safely re-enable irqs */ | ||
3607 | writel(INTR_MASK, &oxu->regs->intr_enable); | ||
3608 | |||
3609 | spin_unlock_irq(&oxu->lock); | ||
3610 | return 0; | ||
3611 | } | ||
3612 | |||
3613 | #else | ||
3614 | |||
3615 | static int oxu_bus_suspend(struct usb_hcd *hcd) | ||
3616 | { | ||
3617 | return 0; | ||
3618 | } | ||
3619 | |||
3620 | static int oxu_bus_resume(struct usb_hcd *hcd) | ||
3621 | { | ||
3622 | return 0; | ||
3623 | } | ||
3624 | |||
3625 | #endif /* CONFIG_PM */ | ||
3626 | |||
3627 | static const struct hc_driver oxu_hc_driver = { | ||
3628 | .description = "oxu210hp_hcd", | ||
3629 | .product_desc = "oxu210hp HCD", | ||
3630 | .hcd_priv_size = sizeof(struct oxu_hcd), | ||
3631 | |||
3632 | /* | ||
3633 | * Generic hardware linkage | ||
3634 | */ | ||
3635 | .irq = oxu_irq, | ||
3636 | .flags = HCD_MEMORY | HCD_USB2, | ||
3637 | |||
3638 | /* | ||
3639 | * Basic lifecycle operations | ||
3640 | */ | ||
3641 | .reset = oxu_reset, | ||
3642 | .start = oxu_run, | ||
3643 | .stop = oxu_stop, | ||
3644 | .shutdown = oxu_shutdown, | ||
3645 | |||
3646 | /* | ||
3647 | * Managing i/o requests and associated device resources | ||
3648 | */ | ||
3649 | .urb_enqueue = oxu_urb_enqueue, | ||
3650 | .urb_dequeue = oxu_urb_dequeue, | ||
3651 | .endpoint_disable = oxu_endpoint_disable, | ||
3652 | |||
3653 | /* | ||
3654 | * Scheduling support | ||
3655 | */ | ||
3656 | .get_frame_number = oxu_get_frame, | ||
3657 | |||
3658 | /* | ||
3659 | * Root hub support | ||
3660 | */ | ||
3661 | .hub_status_data = oxu_hub_status_data, | ||
3662 | .hub_control = oxu_hub_control, | ||
3663 | .bus_suspend = oxu_bus_suspend, | ||
3664 | .bus_resume = oxu_bus_resume, | ||
3665 | }; | ||
3666 | |||
3667 | /* | ||
3668 | * Module stuff | ||
3669 | */ | ||
3670 | |||
3671 | static void oxu_configuration(struct platform_device *pdev, void *base) | ||
3672 | { | ||
3673 | u32 tmp; | ||
3674 | |||
3675 | /* Initialize top level registers. | ||
3676 | * First write ever | ||
3677 | */ | ||
3678 | oxu_writel(base, OXU_HOSTIFCONFIG, 0x0000037D); | ||
3679 | oxu_writel(base, OXU_SOFTRESET, OXU_SRESET); | ||
3680 | oxu_writel(base, OXU_HOSTIFCONFIG, 0x0000037D); | ||
3681 | |||
3682 | tmp = oxu_readl(base, OXU_PIOBURSTREADCTRL); | ||
3683 | oxu_writel(base, OXU_PIOBURSTREADCTRL, tmp | 0x0040); | ||
3684 | |||
3685 | oxu_writel(base, OXU_ASO, OXU_SPHPOEN | OXU_OVRCCURPUPDEN | | ||
3686 | OXU_COMPARATOR | OXU_ASO_OP); | ||
3687 | |||
3688 | tmp = oxu_readl(base, OXU_CLKCTRL_SET); | ||
3689 | oxu_writel(base, OXU_CLKCTRL_SET, tmp | OXU_SYSCLKEN | OXU_USBOTGCLKEN); | ||
3690 | |||
3691 | /* Clear all top interrupt enable */ | ||
3692 | oxu_writel(base, OXU_CHIPIRQEN_CLR, 0xff); | ||
3693 | |||
3694 | /* Clear all top interrupt status */ | ||
3695 | oxu_writel(base, OXU_CHIPIRQSTATUS, 0xff); | ||
3696 | |||
3697 | /* Enable all needed top interrupt except OTG SPH core */ | ||
3698 | oxu_writel(base, OXU_CHIPIRQEN_SET, OXU_USBSPHLPWUI | OXU_USBOTGLPWUI); | ||
3699 | } | ||
3700 | |||
3701 | static int oxu_verify_id(struct platform_device *pdev, void *base) | ||
3702 | { | ||
3703 | u32 id; | ||
3704 | char *bo[] = { | ||
3705 | "reserved", | ||
3706 | "128-pin LQFP", | ||
3707 | "84-pin TFBGA", | ||
3708 | "reserved", | ||
3709 | }; | ||
3710 | |||
3711 | /* Read controller signature register to find a match */ | ||
3712 | id = oxu_readl(base, OXU_DEVICEID); | ||
3713 | dev_info(&pdev->dev, "device ID %x\n", id); | ||
3714 | if ((id & OXU_REV_MASK) != (OXU_REV_2100 << OXU_REV_SHIFT)) | ||
3715 | return -1; | ||
3716 | |||
3717 | dev_info(&pdev->dev, "found device %x %s (%04x:%04x)\n", | ||
3718 | id >> OXU_REV_SHIFT, | ||
3719 | bo[(id & OXU_BO_MASK) >> OXU_BO_SHIFT], | ||
3720 | (id & OXU_MAJ_REV_MASK) >> OXU_MAJ_REV_SHIFT, | ||
3721 | (id & OXU_MIN_REV_MASK) >> OXU_MIN_REV_SHIFT); | ||
3722 | |||
3723 | return 0; | ||
3724 | } | ||
3725 | |||
3726 | static const struct hc_driver oxu_hc_driver; | ||
3727 | static struct usb_hcd *oxu_create(struct platform_device *pdev, | ||
3728 | unsigned long memstart, unsigned long memlen, | ||
3729 | void *base, int irq, int otg) | ||
3730 | { | ||
3731 | struct device *dev = &pdev->dev; | ||
3732 | |||
3733 | struct usb_hcd *hcd; | ||
3734 | struct oxu_hcd *oxu; | ||
3735 | int ret; | ||
3736 | |||
3737 | /* Set endian mode and host mode */ | ||
3738 | oxu_writel(base + (otg ? OXU_OTG_CORE_OFFSET : OXU_SPH_CORE_OFFSET), | ||
3739 | OXU_USBMODE, | ||
3740 | OXU_CM_HOST_ONLY | OXU_ES_LITTLE | OXU_VBPS); | ||
3741 | |||
3742 | hcd = usb_create_hcd(&oxu_hc_driver, dev, | ||
3743 | otg ? "oxu210hp_otg" : "oxu210hp_sph"); | ||
3744 | if (!hcd) | ||
3745 | return ERR_PTR(-ENOMEM); | ||
3746 | |||
3747 | hcd->rsrc_start = memstart; | ||
3748 | hcd->rsrc_len = memlen; | ||
3749 | hcd->regs = base; | ||
3750 | hcd->irq = irq; | ||
3751 | hcd->state = HC_STATE_HALT; | ||
3752 | |||
3753 | oxu = hcd_to_oxu(hcd); | ||
3754 | oxu->is_otg = otg; | ||
3755 | |||
3756 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
3757 | if (ret < 0) | ||
3758 | return ERR_PTR(ret); | ||
3759 | |||
3760 | return hcd; | ||
3761 | } | ||
3762 | |||
3763 | static int oxu_init(struct platform_device *pdev, | ||
3764 | unsigned long memstart, unsigned long memlen, | ||
3765 | void *base, int irq) | ||
3766 | { | ||
3767 | struct oxu_info *info = platform_get_drvdata(pdev); | ||
3768 | struct usb_hcd *hcd; | ||
3769 | int ret; | ||
3770 | |||
3771 | /* First time configuration at start up */ | ||
3772 | oxu_configuration(pdev, base); | ||
3773 | |||
3774 | ret = oxu_verify_id(pdev, base); | ||
3775 | if (ret) { | ||
3776 | dev_err(&pdev->dev, "no devices found!\n"); | ||
3777 | return -ENODEV; | ||
3778 | } | ||
3779 | |||
3780 | /* Create the OTG controller */ | ||
3781 | hcd = oxu_create(pdev, memstart, memlen, base, irq, 1); | ||
3782 | if (IS_ERR(hcd)) { | ||
3783 | dev_err(&pdev->dev, "cannot create OTG controller!\n"); | ||
3784 | ret = PTR_ERR(hcd); | ||
3785 | goto error_create_otg; | ||
3786 | } | ||
3787 | info->hcd[0] = hcd; | ||
3788 | |||
3789 | /* Create the SPH host controller */ | ||
3790 | hcd = oxu_create(pdev, memstart, memlen, base, irq, 0); | ||
3791 | if (IS_ERR(hcd)) { | ||
3792 | dev_err(&pdev->dev, "cannot create SPH controller!\n"); | ||
3793 | ret = PTR_ERR(hcd); | ||
3794 | goto error_create_sph; | ||
3795 | } | ||
3796 | info->hcd[1] = hcd; | ||
3797 | |||
3798 | oxu_writel(base, OXU_CHIPIRQEN_SET, | ||
3799 | oxu_readl(base, OXU_CHIPIRQEN_SET) | 3); | ||
3800 | |||
3801 | return 0; | ||
3802 | |||
3803 | error_create_sph: | ||
3804 | usb_remove_hcd(info->hcd[0]); | ||
3805 | usb_put_hcd(info->hcd[0]); | ||
3806 | |||
3807 | error_create_otg: | ||
3808 | return ret; | ||
3809 | } | ||
3810 | |||
3811 | static int oxu_drv_probe(struct platform_device *pdev) | ||
3812 | { | ||
3813 | struct resource *res; | ||
3814 | void *base; | ||
3815 | unsigned long memstart, memlen; | ||
3816 | int irq, ret; | ||
3817 | struct oxu_info *info; | ||
3818 | |||
3819 | if (usb_disabled()) | ||
3820 | return -ENODEV; | ||
3821 | |||
3822 | /* | ||
3823 | * Get the platform resources | ||
3824 | */ | ||
3825 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
3826 | if (!res) { | ||
3827 | dev_err(&pdev->dev, | ||
3828 | "no IRQ! Check %s setup!\n", dev_name(&pdev->dev)); | ||
3829 | return -ENODEV; | ||
3830 | } | ||
3831 | irq = res->start; | ||
3832 | dev_dbg(&pdev->dev, "IRQ resource %d\n", irq); | ||
3833 | |||
3834 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
3835 | if (!res) { | ||
3836 | dev_err(&pdev->dev, "no registers address! Check %s setup!\n", | ||
3837 | dev_name(&pdev->dev)); | ||
3838 | return -ENODEV; | ||
3839 | } | ||
3840 | memstart = res->start; | ||
3841 | memlen = res->end - res->start + 1; | ||
3842 | dev_dbg(&pdev->dev, "MEM resource %lx-%lx\n", memstart, memlen); | ||
3843 | if (!request_mem_region(memstart, memlen, | ||
3844 | oxu_hc_driver.description)) { | ||
3845 | dev_dbg(&pdev->dev, "memory area already in use\n"); | ||
3846 | return -EBUSY; | ||
3847 | } | ||
3848 | |||
3849 | ret = set_irq_type(irq, IRQF_TRIGGER_FALLING); | ||
3850 | if (ret) { | ||
3851 | dev_err(&pdev->dev, "error setting irq type\n"); | ||
3852 | ret = -EFAULT; | ||
3853 | goto error_set_irq_type; | ||
3854 | } | ||
3855 | |||
3856 | base = ioremap(memstart, memlen); | ||
3857 | if (!base) { | ||
3858 | dev_dbg(&pdev->dev, "error mapping memory\n"); | ||
3859 | ret = -EFAULT; | ||
3860 | goto error_ioremap; | ||
3861 | } | ||
3862 | |||
3863 | /* Allocate a driver data struct to hold useful info for both | ||
3864 | * SPH & OTG devices | ||
3865 | */ | ||
3866 | info = kzalloc(sizeof(struct oxu_info), GFP_KERNEL); | ||
3867 | if (!info) { | ||
3868 | dev_dbg(&pdev->dev, "error allocating memory\n"); | ||
3869 | ret = -EFAULT; | ||
3870 | goto error_alloc; | ||
3871 | } | ||
3872 | platform_set_drvdata(pdev, info); | ||
3873 | |||
3874 | ret = oxu_init(pdev, memstart, memlen, base, irq); | ||
3875 | if (ret < 0) { | ||
3876 | dev_dbg(&pdev->dev, "cannot init USB devices\n"); | ||
3877 | goto error_init; | ||
3878 | } | ||
3879 | |||
3880 | dev_info(&pdev->dev, "devices enabled and running\n"); | ||
3881 | platform_set_drvdata(pdev, info); | ||
3882 | |||
3883 | return 0; | ||
3884 | |||
3885 | error_init: | ||
3886 | kfree(info); | ||
3887 | platform_set_drvdata(pdev, NULL); | ||
3888 | |||
3889 | error_alloc: | ||
3890 | iounmap(base); | ||
3891 | |||
3892 | error_set_irq_type: | ||
3893 | error_ioremap: | ||
3894 | release_mem_region(memstart, memlen); | ||
3895 | |||
3896 | dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), ret); | ||
3897 | return ret; | ||
3898 | } | ||
3899 | |||
3900 | static void oxu_remove(struct platform_device *pdev, struct usb_hcd *hcd) | ||
3901 | { | ||
3902 | usb_remove_hcd(hcd); | ||
3903 | usb_put_hcd(hcd); | ||
3904 | } | ||
3905 | |||
3906 | static int oxu_drv_remove(struct platform_device *pdev) | ||
3907 | { | ||
3908 | struct oxu_info *info = platform_get_drvdata(pdev); | ||
3909 | unsigned long memstart = info->hcd[0]->rsrc_start, | ||
3910 | memlen = info->hcd[0]->rsrc_len; | ||
3911 | void *base = info->hcd[0]->regs; | ||
3912 | |||
3913 | oxu_remove(pdev, info->hcd[0]); | ||
3914 | oxu_remove(pdev, info->hcd[1]); | ||
3915 | |||
3916 | iounmap(base); | ||
3917 | release_mem_region(memstart, memlen); | ||
3918 | |||
3919 | kfree(info); | ||
3920 | platform_set_drvdata(pdev, NULL); | ||
3921 | |||
3922 | return 0; | ||
3923 | } | ||
3924 | |||
3925 | static void oxu_drv_shutdown(struct platform_device *pdev) | ||
3926 | { | ||
3927 | oxu_drv_remove(pdev); | ||
3928 | } | ||
3929 | |||
3930 | #if 0 | ||
3931 | /* FIXME: TODO */ | ||
3932 | static int oxu_drv_suspend(struct device *dev) | ||
3933 | { | ||
3934 | struct platform_device *pdev = to_platform_device(dev); | ||
3935 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
3936 | |||
3937 | return 0; | ||
3938 | } | ||
3939 | |||
3940 | static int oxu_drv_resume(struct device *dev) | ||
3941 | { | ||
3942 | struct platform_device *pdev = to_platform_device(dev); | ||
3943 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
3944 | |||
3945 | return 0; | ||
3946 | } | ||
3947 | #else | ||
3948 | #define oxu_drv_suspend NULL | ||
3949 | #define oxu_drv_resume NULL | ||
3950 | #endif | ||
3951 | |||
3952 | static struct platform_driver oxu_driver = { | ||
3953 | .probe = oxu_drv_probe, | ||
3954 | .remove = oxu_drv_remove, | ||
3955 | .shutdown = oxu_drv_shutdown, | ||
3956 | .suspend = oxu_drv_suspend, | ||
3957 | .resume = oxu_drv_resume, | ||
3958 | .driver = { | ||
3959 | .name = "oxu210hp-hcd", | ||
3960 | .bus = &platform_bus_type | ||
3961 | } | ||
3962 | }; | ||
3963 | |||
3964 | static int __init oxu_module_init(void) | ||
3965 | { | ||
3966 | int retval = 0; | ||
3967 | |||
3968 | retval = platform_driver_register(&oxu_driver); | ||
3969 | if (retval < 0) | ||
3970 | return retval; | ||
3971 | |||
3972 | return retval; | ||
3973 | } | ||
3974 | |||
3975 | static void __exit oxu_module_cleanup(void) | ||
3976 | { | ||
3977 | platform_driver_unregister(&oxu_driver); | ||
3978 | } | ||
3979 | |||
3980 | module_init(oxu_module_init); | ||
3981 | module_exit(oxu_module_cleanup); | ||
3982 | |||
3983 | MODULE_DESCRIPTION("Oxford OXU210HP HCD driver - ver. " DRIVER_VERSION); | ||
3984 | MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); | ||
3985 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/host/oxu210hp.h b/drivers/usb/host/oxu210hp.h new file mode 100644 index 000000000000..8910e271cc7d --- /dev/null +++ b/drivers/usb/host/oxu210hp.h | |||
@@ -0,0 +1,447 @@ | |||
1 | /* | ||
2 | * Host interface registers | ||
3 | */ | ||
4 | |||
5 | #define OXU_DEVICEID 0x00 | ||
6 | #define OXU_REV_MASK 0xffff0000 | ||
7 | #define OXU_REV_SHIFT 16 | ||
8 | #define OXU_REV_2100 0x2100 | ||
9 | #define OXU_BO_SHIFT 8 | ||
10 | #define OXU_BO_MASK (0x3 << OXU_BO_SHIFT) | ||
11 | #define OXU_MAJ_REV_SHIFT 4 | ||
12 | #define OXU_MAJ_REV_MASK (0xf << OXU_MAJ_REV_SHIFT) | ||
13 | #define OXU_MIN_REV_SHIFT 0 | ||
14 | #define OXU_MIN_REV_MASK (0xf << OXU_MIN_REV_SHIFT) | ||
15 | #define OXU_HOSTIFCONFIG 0x04 | ||
16 | #define OXU_SOFTRESET 0x08 | ||
17 | #define OXU_SRESET (1 << 0) | ||
18 | |||
19 | #define OXU_PIOBURSTREADCTRL 0x0C | ||
20 | |||
21 | #define OXU_CHIPIRQSTATUS 0x10 | ||
22 | #define OXU_CHIPIRQEN_SET 0x14 | ||
23 | #define OXU_CHIPIRQEN_CLR 0x18 | ||
24 | #define OXU_USBSPHLPWUI 0x00000080 | ||
25 | #define OXU_USBOTGLPWUI 0x00000040 | ||
26 | #define OXU_USBSPHI 0x00000002 | ||
27 | #define OXU_USBOTGI 0x00000001 | ||
28 | |||
29 | #define OXU_CLKCTRL_SET 0x1C | ||
30 | #define OXU_SYSCLKEN 0x00000008 | ||
31 | #define OXU_USBSPHCLKEN 0x00000002 | ||
32 | #define OXU_USBOTGCLKEN 0x00000001 | ||
33 | |||
34 | #define OXU_ASO 0x68 | ||
35 | #define OXU_SPHPOEN 0x00000100 | ||
36 | #define OXU_OVRCCURPUPDEN 0x00000800 | ||
37 | #define OXU_ASO_OP (1 << 10) | ||
38 | #define OXU_COMPARATOR 0x000004000 | ||
39 | |||
40 | #define OXU_USBMODE 0x1A8 | ||
41 | #define OXU_VBPS 0x00000020 | ||
42 | #define OXU_ES_LITTLE 0x00000000 | ||
43 | #define OXU_CM_HOST_ONLY 0x00000003 | ||
44 | |||
45 | /* | ||
46 | * Proper EHCI structs & defines | ||
47 | */ | ||
48 | |||
49 | /* Magic numbers that can affect system performance */ | ||
50 | #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ | ||
51 | #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ | ||
52 | #define EHCI_TUNE_RL_TT 0 | ||
53 | #define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ | ||
54 | #define EHCI_TUNE_MULT_TT 1 | ||
55 | #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ | ||
56 | |||
57 | struct oxu_hcd; | ||
58 | |||
59 | /* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ | ||
60 | |||
61 | /* Section 2.2 Host Controller Capability Registers */ | ||
62 | struct ehci_caps { | ||
63 | /* these fields are specified as 8 and 16 bit registers, | ||
64 | * but some hosts can't perform 8 or 16 bit PCI accesses. | ||
65 | */ | ||
66 | u32 hc_capbase; | ||
67 | #define HC_LENGTH(p) (((p)>>00)&0x00ff) /* bits 7:0 */ | ||
68 | #define HC_VERSION(p) (((p)>>16)&0xffff) /* bits 31:16 */ | ||
69 | u32 hcs_params; /* HCSPARAMS - offset 0x4 */ | ||
70 | #define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ | ||
71 | #define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ | ||
72 | #define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ | ||
73 | #define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ | ||
74 | #define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ | ||
75 | #define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ | ||
76 | #define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ | ||
77 | |||
78 | u32 hcc_params; /* HCCPARAMS - offset 0x8 */ | ||
79 | #define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ | ||
80 | #define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ | ||
81 | #define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ | ||
82 | #define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ | ||
83 | #define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ | ||
84 | #define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ | ||
85 | u8 portroute[8]; /* nibbles for routing - offset 0xC */ | ||
86 | } __attribute__ ((packed)); | ||
87 | |||
88 | |||
89 | /* Section 2.3 Host Controller Operational Registers */ | ||
90 | struct ehci_regs { | ||
91 | /* USBCMD: offset 0x00 */ | ||
92 | u32 command; | ||
93 | /* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ | ||
94 | #define CMD_PARK (1<<11) /* enable "park" on async qh */ | ||
95 | #define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ | ||
96 | #define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ | ||
97 | #define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ | ||
98 | #define CMD_ASE (1<<5) /* async schedule enable */ | ||
99 | #define CMD_PSE (1<<4) /* periodic schedule enable */ | ||
100 | /* 3:2 is periodic frame list size */ | ||
101 | #define CMD_RESET (1<<1) /* reset HC not bus */ | ||
102 | #define CMD_RUN (1<<0) /* start/stop HC */ | ||
103 | |||
104 | /* USBSTS: offset 0x04 */ | ||
105 | u32 status; | ||
106 | #define STS_ASS (1<<15) /* Async Schedule Status */ | ||
107 | #define STS_PSS (1<<14) /* Periodic Schedule Status */ | ||
108 | #define STS_RECL (1<<13) /* Reclamation */ | ||
109 | #define STS_HALT (1<<12) /* Not running (any reason) */ | ||
110 | /* some bits reserved */ | ||
111 | /* these STS_* flags are also intr_enable bits (USBINTR) */ | ||
112 | #define STS_IAA (1<<5) /* Interrupted on async advance */ | ||
113 | #define STS_FATAL (1<<4) /* such as some PCI access errors */ | ||
114 | #define STS_FLR (1<<3) /* frame list rolled over */ | ||
115 | #define STS_PCD (1<<2) /* port change detect */ | ||
116 | #define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ | ||
117 | #define STS_INT (1<<0) /* "normal" completion (short, ...) */ | ||
118 | |||
119 | #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) | ||
120 | |||
121 | /* USBINTR: offset 0x08 */ | ||
122 | u32 intr_enable; | ||
123 | |||
124 | /* FRINDEX: offset 0x0C */ | ||
125 | u32 frame_index; /* current microframe number */ | ||
126 | /* CTRLDSSEGMENT: offset 0x10 */ | ||
127 | u32 segment; /* address bits 63:32 if needed */ | ||
128 | /* PERIODICLISTBASE: offset 0x14 */ | ||
129 | u32 frame_list; /* points to periodic list */ | ||
130 | /* ASYNCLISTADDR: offset 0x18 */ | ||
131 | u32 async_next; /* address of next async queue head */ | ||
132 | |||
133 | u32 reserved[9]; | ||
134 | |||
135 | /* CONFIGFLAG: offset 0x40 */ | ||
136 | u32 configured_flag; | ||
137 | #define FLAG_CF (1<<0) /* true: we'll support "high speed" */ | ||
138 | |||
139 | /* PORTSC: offset 0x44 */ | ||
140 | u32 port_status[0]; /* up to N_PORTS */ | ||
141 | /* 31:23 reserved */ | ||
142 | #define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ | ||
143 | #define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ | ||
144 | #define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ | ||
145 | /* 19:16 for port testing */ | ||
146 | #define PORT_LED_OFF (0<<14) | ||
147 | #define PORT_LED_AMBER (1<<14) | ||
148 | #define PORT_LED_GREEN (2<<14) | ||
149 | #define PORT_LED_MASK (3<<14) | ||
150 | #define PORT_OWNER (1<<13) /* true: companion hc owns this port */ | ||
151 | #define PORT_POWER (1<<12) /* true: has power (see PPC) */ | ||
152 | #define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ | ||
153 | /* 11:10 for detecting lowspeed devices (reset vs release ownership) */ | ||
154 | /* 9 reserved */ | ||
155 | #define PORT_RESET (1<<8) /* reset port */ | ||
156 | #define PORT_SUSPEND (1<<7) /* suspend port */ | ||
157 | #define PORT_RESUME (1<<6) /* resume it */ | ||
158 | #define PORT_OCC (1<<5) /* over current change */ | ||
159 | #define PORT_OC (1<<4) /* over current active */ | ||
160 | #define PORT_PEC (1<<3) /* port enable change */ | ||
161 | #define PORT_PE (1<<2) /* port enable */ | ||
162 | #define PORT_CSC (1<<1) /* connect status change */ | ||
163 | #define PORT_CONNECT (1<<0) /* device connected */ | ||
164 | #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) | ||
165 | } __attribute__ ((packed)); | ||
166 | |||
167 | /* Appendix C, Debug port ... intended for use with special "debug devices" | ||
168 | * that can help if there's no serial console. (nonstandard enumeration.) | ||
169 | */ | ||
170 | struct ehci_dbg_port { | ||
171 | u32 control; | ||
172 | #define DBGP_OWNER (1<<30) | ||
173 | #define DBGP_ENABLED (1<<28) | ||
174 | #define DBGP_DONE (1<<16) | ||
175 | #define DBGP_INUSE (1<<10) | ||
176 | #define DBGP_ERRCODE(x) (((x)>>7)&0x07) | ||
177 | # define DBGP_ERR_BAD 1 | ||
178 | # define DBGP_ERR_SIGNAL 2 | ||
179 | #define DBGP_ERROR (1<<6) | ||
180 | #define DBGP_GO (1<<5) | ||
181 | #define DBGP_OUT (1<<4) | ||
182 | #define DBGP_LEN(x) (((x)>>0)&0x0f) | ||
183 | u32 pids; | ||
184 | #define DBGP_PID_GET(x) (((x)>>16)&0xff) | ||
185 | #define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) | ||
186 | u32 data03; | ||
187 | u32 data47; | ||
188 | u32 address; | ||
189 | #define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) | ||
190 | } __attribute__ ((packed)); | ||
191 | |||
192 | |||
193 | #define QTD_NEXT(dma) cpu_to_le32((u32)dma) | ||
194 | |||
195 | /* | ||
196 | * EHCI Specification 0.95 Section 3.5 | ||
197 | * QTD: describe data transfer components (buffer, direction, ...) | ||
198 | * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". | ||
199 | * | ||
200 | * These are associated only with "QH" (Queue Head) structures, | ||
201 | * used with control, bulk, and interrupt transfers. | ||
202 | */ | ||
203 | struct ehci_qtd { | ||
204 | /* first part defined by EHCI spec */ | ||
205 | __le32 hw_next; /* see EHCI 3.5.1 */ | ||
206 | __le32 hw_alt_next; /* see EHCI 3.5.2 */ | ||
207 | __le32 hw_token; /* see EHCI 3.5.3 */ | ||
208 | #define QTD_TOGGLE (1 << 31) /* data toggle */ | ||
209 | #define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) | ||
210 | #define QTD_IOC (1 << 15) /* interrupt on complete */ | ||
211 | #define QTD_CERR(tok) (((tok)>>10) & 0x3) | ||
212 | #define QTD_PID(tok) (((tok)>>8) & 0x3) | ||
213 | #define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ | ||
214 | #define QTD_STS_HALT (1 << 6) /* halted on error */ | ||
215 | #define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ | ||
216 | #define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ | ||
217 | #define QTD_STS_XACT (1 << 3) /* device gave illegal response */ | ||
218 | #define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ | ||
219 | #define QTD_STS_STS (1 << 1) /* split transaction state */ | ||
220 | #define QTD_STS_PING (1 << 0) /* issue PING? */ | ||
221 | __le32 hw_buf[5]; /* see EHCI 3.5.4 */ | ||
222 | __le32 hw_buf_hi[5]; /* Appendix B */ | ||
223 | |||
224 | /* the rest is HCD-private */ | ||
225 | dma_addr_t qtd_dma; /* qtd address */ | ||
226 | struct list_head qtd_list; /* sw qtd list */ | ||
227 | struct urb *urb; /* qtd's urb */ | ||
228 | size_t length; /* length of buffer */ | ||
229 | |||
230 | u32 qtd_buffer_len; | ||
231 | void *buffer; | ||
232 | dma_addr_t buffer_dma; | ||
233 | void *transfer_buffer; | ||
234 | void *transfer_dma; | ||
235 | } __attribute__ ((aligned(32))); | ||
236 | |||
237 | /* mask NakCnt+T in qh->hw_alt_next */ | ||
238 | #define QTD_MASK __constant_cpu_to_le32 (~0x1f) | ||
239 | |||
240 | #define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) | ||
241 | |||
242 | /* Type tag from {qh, itd, sitd, fstn}->hw_next */ | ||
243 | #define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1)) | ||
244 | |||
245 | /* values for that type tag */ | ||
246 | #define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1) | ||
247 | |||
248 | /* next async queue entry, or pointer to interrupt/periodic QH */ | ||
249 | #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) | ||
250 | |||
251 | /* for periodic/async schedules and qtd lists, mark end of list */ | ||
252 | #define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */ | ||
253 | |||
254 | /* | ||
255 | * Entries in periodic shadow table are pointers to one of four kinds | ||
256 | * of data structure. That's dictated by the hardware; a type tag is | ||
257 | * encoded in the low bits of the hardware's periodic schedule. Use | ||
258 | * Q_NEXT_TYPE to get the tag. | ||
259 | * | ||
260 | * For entries in the async schedule, the type tag always says "qh". | ||
261 | */ | ||
262 | union ehci_shadow { | ||
263 | struct ehci_qh *qh; /* Q_TYPE_QH */ | ||
264 | __le32 *hw_next; /* (all types) */ | ||
265 | void *ptr; | ||
266 | }; | ||
267 | |||
268 | /* | ||
269 | * EHCI Specification 0.95 Section 3.6 | ||
270 | * QH: describes control/bulk/interrupt endpoints | ||
271 | * See Fig 3-7 "Queue Head Structure Layout". | ||
272 | * | ||
273 | * These appear in both the async and (for interrupt) periodic schedules. | ||
274 | */ | ||
275 | |||
276 | struct ehci_qh { | ||
277 | /* first part defined by EHCI spec */ | ||
278 | __le32 hw_next; /* see EHCI 3.6.1 */ | ||
279 | __le32 hw_info1; /* see EHCI 3.6.2 */ | ||
280 | #define QH_HEAD 0x00008000 | ||
281 | __le32 hw_info2; /* see EHCI 3.6.2 */ | ||
282 | #define QH_SMASK 0x000000ff | ||
283 | #define QH_CMASK 0x0000ff00 | ||
284 | #define QH_HUBADDR 0x007f0000 | ||
285 | #define QH_HUBPORT 0x3f800000 | ||
286 | #define QH_MULT 0xc0000000 | ||
287 | __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ | ||
288 | |||
289 | /* qtd overlay (hardware parts of a struct ehci_qtd) */ | ||
290 | __le32 hw_qtd_next; | ||
291 | __le32 hw_alt_next; | ||
292 | __le32 hw_token; | ||
293 | __le32 hw_buf[5]; | ||
294 | __le32 hw_buf_hi[5]; | ||
295 | |||
296 | /* the rest is HCD-private */ | ||
297 | dma_addr_t qh_dma; /* address of qh */ | ||
298 | union ehci_shadow qh_next; /* ptr to qh; or periodic */ | ||
299 | struct list_head qtd_list; /* sw qtd list */ | ||
300 | struct ehci_qtd *dummy; | ||
301 | struct ehci_qh *reclaim; /* next to reclaim */ | ||
302 | |||
303 | struct oxu_hcd *oxu; | ||
304 | struct kref kref; | ||
305 | unsigned stamp; | ||
306 | |||
307 | u8 qh_state; | ||
308 | #define QH_STATE_LINKED 1 /* HC sees this */ | ||
309 | #define QH_STATE_UNLINK 2 /* HC may still see this */ | ||
310 | #define QH_STATE_IDLE 3 /* HC doesn't see this */ | ||
311 | #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ | ||
312 | #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ | ||
313 | |||
314 | /* periodic schedule info */ | ||
315 | u8 usecs; /* intr bandwidth */ | ||
316 | u8 gap_uf; /* uframes split/csplit gap */ | ||
317 | u8 c_usecs; /* ... split completion bw */ | ||
318 | u16 tt_usecs; /* tt downstream bandwidth */ | ||
319 | unsigned short period; /* polling interval */ | ||
320 | unsigned short start; /* where polling starts */ | ||
321 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ | ||
322 | struct usb_device *dev; /* access to TT */ | ||
323 | } __attribute__ ((aligned(32))); | ||
324 | |||
325 | /* | ||
326 | * Proper OXU210HP structs | ||
327 | */ | ||
328 | |||
329 | #define OXU_OTG_CORE_OFFSET 0x00400 | ||
330 | #define OXU_OTG_CAP_OFFSET (OXU_OTG_CORE_OFFSET + 0x100) | ||
331 | #define OXU_SPH_CORE_OFFSET 0x00800 | ||
332 | #define OXU_SPH_CAP_OFFSET (OXU_SPH_CORE_OFFSET + 0x100) | ||
333 | |||
334 | #define OXU_OTG_MEM 0xE000 | ||
335 | #define OXU_SPH_MEM 0x16000 | ||
336 | |||
337 | /* Only how many elements & element structure are specifies here. */ | ||
338 | /* 2 host controllers are enabled - total size <= 28 kbytes */ | ||
339 | #define DEFAULT_I_TDPS 1024 | ||
340 | #define QHEAD_NUM 16 | ||
341 | #define QTD_NUM 32 | ||
342 | #define SITD_NUM 8 | ||
343 | #define MURB_NUM 8 | ||
344 | |||
345 | #define BUFFER_NUM 8 | ||
346 | #define BUFFER_SIZE 512 | ||
347 | |||
348 | struct oxu_info { | ||
349 | struct usb_hcd *hcd[2]; | ||
350 | }; | ||
351 | |||
352 | struct oxu_buf { | ||
353 | u8 buffer[BUFFER_SIZE]; | ||
354 | } __attribute__ ((aligned(BUFFER_SIZE))); | ||
355 | |||
356 | struct oxu_onchip_mem { | ||
357 | struct oxu_buf db_pool[BUFFER_NUM]; | ||
358 | |||
359 | u32 frame_list[DEFAULT_I_TDPS]; | ||
360 | struct ehci_qh qh_pool[QHEAD_NUM]; | ||
361 | struct ehci_qtd qtd_pool[QTD_NUM]; | ||
362 | } __attribute__ ((aligned(4 << 10))); | ||
363 | |||
364 | #define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ | ||
365 | |||
366 | struct oxu_murb { | ||
367 | struct urb urb; | ||
368 | struct urb *main; | ||
369 | u8 last; | ||
370 | }; | ||
371 | |||
372 | struct oxu_hcd { /* one per controller */ | ||
373 | unsigned int is_otg:1; | ||
374 | |||
375 | u8 qh_used[QHEAD_NUM]; | ||
376 | u8 qtd_used[QTD_NUM]; | ||
377 | u8 db_used[BUFFER_NUM]; | ||
378 | u8 murb_used[MURB_NUM]; | ||
379 | |||
380 | struct oxu_onchip_mem __iomem *mem; | ||
381 | spinlock_t mem_lock; | ||
382 | |||
383 | struct timer_list urb_timer; | ||
384 | |||
385 | struct ehci_caps __iomem *caps; | ||
386 | struct ehci_regs __iomem *regs; | ||
387 | |||
388 | __u32 hcs_params; /* cached register copy */ | ||
389 | spinlock_t lock; | ||
390 | |||
391 | /* async schedule support */ | ||
392 | struct ehci_qh *async; | ||
393 | struct ehci_qh *reclaim; | ||
394 | unsigned reclaim_ready:1; | ||
395 | unsigned scanning:1; | ||
396 | |||
397 | /* periodic schedule support */ | ||
398 | unsigned periodic_size; | ||
399 | __le32 *periodic; /* hw periodic table */ | ||
400 | dma_addr_t periodic_dma; | ||
401 | unsigned i_thresh; /* uframes HC might cache */ | ||
402 | |||
403 | union ehci_shadow *pshadow; /* mirror hw periodic table */ | ||
404 | int next_uframe; /* scan periodic, start here */ | ||
405 | unsigned periodic_sched; /* periodic activity count */ | ||
406 | |||
407 | /* per root hub port */ | ||
408 | unsigned long reset_done[EHCI_MAX_ROOT_PORTS]; | ||
409 | /* bit vectors (one bit per port) */ | ||
410 | unsigned long bus_suspended; /* which ports were | ||
411 | * already suspended at the | ||
412 | * start of a bus suspend | ||
413 | */ | ||
414 | unsigned long companion_ports;/* which ports are dedicated | ||
415 | * to the companion controller | ||
416 | */ | ||
417 | |||
418 | struct timer_list watchdog; | ||
419 | unsigned long actions; | ||
420 | unsigned stamp; | ||
421 | unsigned long next_statechange; | ||
422 | u32 command; | ||
423 | |||
424 | /* SILICON QUIRKS */ | ||
425 | struct list_head urb_list; /* this is the head to urb | ||
426 | * queue that didn't get enough | ||
427 | * resources | ||
428 | */ | ||
429 | struct oxu_murb *murb_pool; /* murb per split big urb */ | ||
430 | unsigned urb_len; | ||
431 | |||
432 | u8 sbrn; /* packed release number */ | ||
433 | }; | ||
434 | |||
435 | #define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ | ||
436 | #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ | ||
437 | #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ | ||
438 | #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ | ||
439 | |||
440 | enum ehci_timer_action { | ||
441 | TIMER_IO_WATCHDOG, | ||
442 | TIMER_IAA_WATCHDOG, | ||
443 | TIMER_ASYNC_SHRINK, | ||
444 | TIMER_ASYNC_OFF, | ||
445 | }; | ||
446 | |||
447 | #include <linux/oxu210hp.h> | ||
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index ae6e70edd745..75b69847918e 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -172,9 +172,9 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) | |||
172 | if (!mmio_resource_enabled(pdev, 0)) | 172 | if (!mmio_resource_enabled(pdev, 0)) |
173 | return; | 173 | return; |
174 | 174 | ||
175 | base = ioremap_nocache(pci_resource_start(pdev, 0), | 175 | base = pci_ioremap_bar(pdev, 0); |
176 | pci_resource_len(pdev, 0)); | 176 | if (base == NULL) |
177 | if (base == NULL) return; | 177 | return; |
178 | 178 | ||
179 | /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ | 179 | /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ |
180 | #ifndef __hppa__ | 180 | #ifndef __hppa__ |
@@ -221,9 +221,9 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) | |||
221 | if (!mmio_resource_enabled(pdev, 0)) | 221 | if (!mmio_resource_enabled(pdev, 0)) |
222 | return; | 222 | return; |
223 | 223 | ||
224 | base = ioremap_nocache(pci_resource_start(pdev, 0), | 224 | base = pci_ioremap_bar(pdev, 0); |
225 | pci_resource_len(pdev, 0)); | 225 | if (base == NULL) |
226 | if (base == NULL) return; | 226 | return; |
227 | 227 | ||
228 | cap_length = readb(base); | 228 | cap_length = readb(base); |
229 | op_reg_base = base + cap_length; | 229 | op_reg_base = base + cap_length; |
@@ -271,7 +271,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) | |||
271 | /* if boot firmware now owns EHCI, spin till | 271 | /* if boot firmware now owns EHCI, spin till |
272 | * it hands it over. | 272 | * it hands it over. |
273 | */ | 273 | */ |
274 | msec = 5000; | 274 | msec = 1000; |
275 | while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { | 275 | while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { |
276 | tried_handoff = 1; | 276 | tried_handoff = 1; |
277 | msleep(10); | 277 | msleep(10); |
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index c21f14e0666a..319041205b57 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -2275,7 +2275,6 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev) | |||
2275 | return 0; | 2275 | return 0; |
2276 | } | 2276 | } |
2277 | 2277 | ||
2278 | #define resource_len(r) (((r)->end - (r)->start) + 1) | ||
2279 | static int __init r8a66597_probe(struct platform_device *pdev) | 2278 | static int __init r8a66597_probe(struct platform_device *pdev) |
2280 | { | 2279 | { |
2281 | #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK) | 2280 | #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK) |
@@ -2296,11 +2295,10 @@ static int __init r8a66597_probe(struct platform_device *pdev) | |||
2296 | goto clean_up; | 2295 | goto clean_up; |
2297 | } | 2296 | } |
2298 | 2297 | ||
2299 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 2298 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
2300 | (char *)hcd_name); | ||
2301 | if (!res) { | 2299 | if (!res) { |
2302 | ret = -ENODEV; | 2300 | ret = -ENODEV; |
2303 | dev_err(&pdev->dev, "platform_get_resource_byname error.\n"); | 2301 | dev_err(&pdev->dev, "platform_get_resource error.\n"); |
2304 | goto clean_up; | 2302 | goto clean_up; |
2305 | } | 2303 | } |
2306 | 2304 | ||
@@ -2315,7 +2313,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) | |||
2315 | irq = ires->start; | 2313 | irq = ires->start; |
2316 | irq_trigger = ires->flags & IRQF_TRIGGER_MASK; | 2314 | irq_trigger = ires->flags & IRQF_TRIGGER_MASK; |
2317 | 2315 | ||
2318 | reg = ioremap(res->start, resource_len(res)); | 2316 | reg = ioremap(res->start, resource_size(res)); |
2319 | if (reg == NULL) { | 2317 | if (reg == NULL) { |
2320 | ret = -ENOMEM; | 2318 | ret = -ENOMEM; |
2321 | dev_err(&pdev->dev, "ioremap error.\n"); | 2319 | dev_err(&pdev->dev, "ioremap error.\n"); |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index cf5e4cf7ea42..4e221060f58c 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -942,6 +942,8 @@ static struct pci_driver uhci_pci_driver = { | |||
942 | 942 | ||
943 | #ifdef CONFIG_PM | 943 | #ifdef CONFIG_PM |
944 | .suspend = usb_hcd_pci_suspend, | 944 | .suspend = usb_hcd_pci_suspend, |
945 | .suspend_late = usb_hcd_pci_suspend_late, | ||
946 | .resume_early = usb_hcd_pci_resume_early, | ||
945 | .resume = usb_hcd_pci_resume, | 947 | .resume = usb_hcd_pci_resume, |
946 | #endif /* PM */ | 948 | #endif /* PM */ |
947 | }; | 949 | }; |
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 885867a86de8..4541dfcea88f 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c | |||
@@ -350,17 +350,16 @@ static int mts_scsi_abort(struct scsi_cmnd *srb) | |||
350 | static int mts_scsi_host_reset(struct scsi_cmnd *srb) | 350 | static int mts_scsi_host_reset(struct scsi_cmnd *srb) |
351 | { | 351 | { |
352 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); | 352 | struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]); |
353 | int result, rc; | 353 | int result; |
354 | 354 | ||
355 | MTS_DEBUG_GOT_HERE(); | 355 | MTS_DEBUG_GOT_HERE(); |
356 | mts_debug_dump(desc); | 356 | mts_debug_dump(desc); |
357 | 357 | ||
358 | rc = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf); | 358 | result = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf); |
359 | if (rc < 0) | 359 | if (result == 0) { |
360 | return FAILED; | 360 | result = usb_reset_device(desc->usb_dev); |
361 | result = usb_reset_device(desc->usb_dev); | ||
362 | if (rc) | ||
363 | usb_unlock_device(desc->usb_dev); | 361 | usb_unlock_device(desc->usb_dev); |
362 | } | ||
364 | return result ? FAILED : SUCCESS; | 363 | return result ? FAILED : SUCCESS; |
365 | } | 364 | } |
366 | 365 | ||
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c index 24e2dc3148a4..c05a85bc5925 100644 --- a/drivers/usb/misc/berry_charge.c +++ b/drivers/usb/misc/berry_charge.c | |||
@@ -123,6 +123,11 @@ static int berry_probe(struct usb_interface *intf, | |||
123 | { | 123 | { |
124 | struct usb_device *udev = interface_to_usbdev(intf); | 124 | struct usb_device *udev = interface_to_usbdev(intf); |
125 | 125 | ||
126 | if (udev->bus_mA < 500) { | ||
127 | dbg(&udev->dev, "Not enough power to charge available\n"); | ||
128 | return -ENODEV; | ||
129 | } | ||
130 | |||
126 | dbg(&udev->dev, "Power is set to %dmA\n", | 131 | dbg(&udev->dev, "Power is set to %dmA\n", |
127 | udev->actconfig->desc.bMaxPower * 2); | 132 | udev->actconfig->desc.bMaxPower * 2); |
128 | 133 | ||
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index e762beb5f3c6..879a980ca8c4 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c | |||
@@ -160,7 +160,7 @@ static int emi26_load_firmware (struct usb_device *dev) | |||
160 | err("%s - error loading firmware: error = %d", __func__, err); | 160 | err("%s - error loading firmware: error = %d", __func__, err); |
161 | goto wraperr; | 161 | goto wraperr; |
162 | } | 162 | } |
163 | } while (i > 0); | 163 | } while (rec); |
164 | 164 | ||
165 | /* Assert reset (stop the CPU in the EMI) */ | 165 | /* Assert reset (stop the CPU in the EMI) */ |
166 | err = emi26_set_reset(dev,1); | 166 | err = emi26_set_reset(dev,1); |
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 444c69c447be..5f1a19d1497d 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -192,8 +192,6 @@ static struct urb *simple_alloc_urb ( | |||
192 | { | 192 | { |
193 | struct urb *urb; | 193 | struct urb *urb; |
194 | 194 | ||
195 | if (bytes < 0) | ||
196 | return NULL; | ||
197 | urb = usb_alloc_urb (0, GFP_KERNEL); | 195 | urb = usb_alloc_urb (0, GFP_KERNEL); |
198 | if (!urb) | 196 | if (!urb) |
199 | return urb; | 197 | return urb; |
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig index deb9ddffa402..f28f350cd96a 100644 --- a/drivers/usb/mon/Kconfig +++ b/drivers/usb/mon/Kconfig | |||
@@ -3,14 +3,13 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | config USB_MON | 5 | config USB_MON |
6 | bool "USB Monitor" | 6 | tristate "USB Monitor" |
7 | depends on USB!=n | 7 | depends on USB |
8 | default y | 8 | default y if USB=y |
9 | default m if USB=m | ||
9 | help | 10 | help |
10 | If you say Y here, a component which captures the USB traffic | 11 | If you select this option, a component which captures the USB traffic |
11 | between peripheral-specific drivers and HC drivers will be built. | 12 | between peripheral-specific drivers and HC drivers will be built. |
12 | For more information, see <file:Documentation/usb/usbmon.txt>. | 13 | For more information, see <file:Documentation/usb/usbmon.txt>. |
13 | 14 | ||
14 | This is somewhat experimental at this time, but it should be safe. | 15 | If unsure, say Y (if allowed), otherwise M. |
15 | |||
16 | If unsure, say Y. | ||
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile index 0f76ed5e1617..c6516b566731 100644 --- a/drivers/usb/mon/Makefile +++ b/drivers/usb/mon/Makefile | |||
@@ -4,5 +4,4 @@ | |||
4 | 4 | ||
5 | usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o mon_dma.o | 5 | usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o mon_dma.o |
6 | 6 | ||
7 | # This does not use CONFIG_USB_MON because we want this to use a tristate. | 7 | obj-$(CONFIG_USB_MON) += usbmon.o |
8 | obj-$(CONFIG_USB) += usbmon.o | ||
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 4b9542bbb35c..5af7379cd9a3 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig | |||
@@ -11,7 +11,7 @@ config USB_MUSB_HDRC | |||
11 | depends on (USB || USB_GADGET) && HAVE_CLK | 11 | depends on (USB || USB_GADGET) && HAVE_CLK |
12 | depends on !SUPERH | 12 | depends on !SUPERH |
13 | select TWL4030_USB if MACH_OMAP_3430SDP | 13 | select TWL4030_USB if MACH_OMAP_3430SDP |
14 | tristate 'Inventra Highspeed Dual Role Controller (TI, ...)' | 14 | tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' |
15 | help | 15 | help |
16 | Say Y here if your system has a dual role high speed USB | 16 | Say Y here if your system has a dual role high speed USB |
17 | controller based on the Mentor Graphics silicon IP. Then | 17 | controller based on the Mentor Graphics silicon IP. Then |
@@ -22,6 +22,9 @@ config USB_MUSB_HDRC | |||
22 | Texas Instruments parts using this IP include DaVinci 644x, | 22 | Texas Instruments parts using this IP include DaVinci 644x, |
23 | OMAP 243x, OMAP 343x, and TUSB 6010. | 23 | OMAP 243x, OMAP 343x, and TUSB 6010. |
24 | 24 | ||
25 | Analog Devices parts using this IP include Blackfin BF54x, | ||
26 | BF525 and BF527. | ||
27 | |||
25 | If you do not know what this is, please say N. | 28 | If you do not know what this is, please say N. |
26 | 29 | ||
27 | To compile this driver as a module, choose M here; the | 30 | To compile this driver as a module, choose M here; the |
@@ -33,6 +36,8 @@ config USB_MUSB_SOC | |||
33 | default y if ARCH_DAVINCI | 36 | default y if ARCH_DAVINCI |
34 | default y if ARCH_OMAP2430 | 37 | default y if ARCH_OMAP2430 |
35 | default y if ARCH_OMAP34XX | 38 | default y if ARCH_OMAP34XX |
39 | default y if (BF54x && !BF544) | ||
40 | default y if (BF52x && !BF522 && !BF523) | ||
36 | 41 | ||
37 | comment "DaVinci 644x USB support" | 42 | comment "DaVinci 644x USB support" |
38 | depends on USB_MUSB_HDRC && ARCH_DAVINCI | 43 | depends on USB_MUSB_HDRC && ARCH_DAVINCI |
@@ -43,6 +48,9 @@ comment "OMAP 243x high speed USB support" | |||
43 | comment "OMAP 343x high speed USB support" | 48 | comment "OMAP 343x high speed USB support" |
44 | depends on USB_MUSB_HDRC && ARCH_OMAP34XX | 49 | depends on USB_MUSB_HDRC && ARCH_OMAP34XX |
45 | 50 | ||
51 | comment "Blackfin high speed USB Support" | ||
52 | depends on USB_MUSB_HDRC && (BF54x && !BF544) || (BF52x && !BF522 && !BF523) | ||
53 | |||
46 | config USB_TUSB6010 | 54 | config USB_TUSB6010 |
47 | boolean "TUSB 6010 support" | 55 | boolean "TUSB 6010 support" |
48 | depends on USB_MUSB_HDRC && !USB_MUSB_SOC | 56 | depends on USB_MUSB_HDRC && !USB_MUSB_SOC |
@@ -142,7 +150,7 @@ config MUSB_PIO_ONLY | |||
142 | config USB_INVENTRA_DMA | 150 | config USB_INVENTRA_DMA |
143 | bool | 151 | bool |
144 | depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY | 152 | depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY |
145 | default ARCH_OMAP2430 || ARCH_OMAP34XX | 153 | default ARCH_OMAP2430 || ARCH_OMAP34XX || BLACKFIN |
146 | help | 154 | help |
147 | Enable DMA transfers using Mentor's engine. | 155 | Enable DMA transfers using Mentor's engine. |
148 | 156 | ||
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index b6af0d687a73..85710ccc1887 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile | |||
@@ -22,6 +22,14 @@ ifeq ($(CONFIG_ARCH_OMAP3430),y) | |||
22 | musb_hdrc-objs += omap2430.o | 22 | musb_hdrc-objs += omap2430.o |
23 | endif | 23 | endif |
24 | 24 | ||
25 | ifeq ($(CONFIG_BF54x),y) | ||
26 | musb_hdrc-objs += blackfin.o | ||
27 | endif | ||
28 | |||
29 | ifeq ($(CONFIG_BF52x),y) | ||
30 | musb_hdrc-objs += blackfin.o | ||
31 | endif | ||
32 | |||
25 | ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y) | 33 | ifeq ($(CONFIG_USB_GADGET_MUSB_HDRC),y) |
26 | musb_hdrc-objs += musb_gadget_ep0.o musb_gadget.o | 34 | musb_hdrc-objs += musb_gadget_ep0.o musb_gadget.o |
27 | endif | 35 | endif |
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c new file mode 100644 index 000000000000..786134852092 --- /dev/null +++ b/drivers/usb/musb/blackfin.c | |||
@@ -0,0 +1,320 @@ | |||
1 | /* | ||
2 | * MUSB OTG controller driver for Blackfin Processors | ||
3 | * | ||
4 | * Copyright 2006-2008 Analog Devices Inc. | ||
5 | * | ||
6 | * Enter bugs at http://blackfin.uclinux.org/ | ||
7 | * | ||
8 | * Licensed under the GPL-2 or later. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/clk.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/io.h> | ||
20 | |||
21 | #include <asm/cacheflush.h> | ||
22 | |||
23 | #include "musb_core.h" | ||
24 | #include "blackfin.h" | ||
25 | |||
26 | /* | ||
27 | * Load an endpoint's FIFO | ||
28 | */ | ||
29 | void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) | ||
30 | { | ||
31 | void __iomem *fifo = hw_ep->fifo; | ||
32 | void __iomem *epio = hw_ep->regs; | ||
33 | |||
34 | prefetch((u8 *)src); | ||
35 | |||
36 | musb_writew(epio, MUSB_TXCOUNT, len); | ||
37 | |||
38 | DBG(4, "TX ep%d fifo %p count %d buf %p, epio %p\n", | ||
39 | hw_ep->epnum, fifo, len, src, epio); | ||
40 | |||
41 | dump_fifo_data(src, len); | ||
42 | |||
43 | if (unlikely((unsigned long)src & 0x01)) | ||
44 | outsw_8((unsigned long)fifo, src, | ||
45 | len & 0x01 ? (len >> 1) + 1 : len >> 1); | ||
46 | else | ||
47 | outsw((unsigned long)fifo, src, | ||
48 | len & 0x01 ? (len >> 1) + 1 : len >> 1); | ||
49 | } | ||
50 | |||
51 | /* | ||
52 | * Unload an endpoint's FIFO | ||
53 | */ | ||
54 | void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) | ||
55 | { | ||
56 | void __iomem *fifo = hw_ep->fifo; | ||
57 | u8 epnum = hw_ep->epnum; | ||
58 | u16 dma_reg = 0; | ||
59 | |||
60 | DBG(4, "%cX ep%d fifo %p count %d buf %p\n", | ||
61 | 'R', hw_ep->epnum, fifo, len, dst); | ||
62 | |||
63 | #ifdef CONFIG_BF52x | ||
64 | invalidate_dcache_range((unsigned int)dst, | ||
65 | (unsigned int)(dst + len)); | ||
66 | |||
67 | /* Setup DMA address register */ | ||
68 | dma_reg = (u16) ((u32) dst & 0xFFFF); | ||
69 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); | ||
70 | SSYNC(); | ||
71 | |||
72 | dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF); | ||
73 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); | ||
74 | SSYNC(); | ||
75 | |||
76 | /* Setup DMA count register */ | ||
77 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); | ||
78 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); | ||
79 | SSYNC(); | ||
80 | |||
81 | /* Enable the DMA */ | ||
82 | dma_reg = (epnum << 4) | DMA_ENA | INT_ENA; | ||
83 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); | ||
84 | SSYNC(); | ||
85 | |||
86 | /* Wait for compelete */ | ||
87 | while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) | ||
88 | cpu_relax(); | ||
89 | |||
90 | /* acknowledge dma interrupt */ | ||
91 | bfin_write_USB_DMA_INTERRUPT(1 << epnum); | ||
92 | SSYNC(); | ||
93 | |||
94 | /* Reset DMA */ | ||
95 | bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); | ||
96 | SSYNC(); | ||
97 | #else | ||
98 | if (unlikely((unsigned long)dst & 0x01)) | ||
99 | insw_8((unsigned long)fifo, dst, | ||
100 | len & 0x01 ? (len >> 1) + 1 : len >> 1); | ||
101 | else | ||
102 | insw((unsigned long)fifo, dst, | ||
103 | len & 0x01 ? (len >> 1) + 1 : len >> 1); | ||
104 | #endif | ||
105 | |||
106 | dump_fifo_data(dst, len); | ||
107 | } | ||
108 | |||
109 | static irqreturn_t blackfin_interrupt(int irq, void *__hci) | ||
110 | { | ||
111 | unsigned long flags; | ||
112 | irqreturn_t retval = IRQ_NONE; | ||
113 | struct musb *musb = __hci; | ||
114 | |||
115 | spin_lock_irqsave(&musb->lock, flags); | ||
116 | |||
117 | musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); | ||
118 | musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); | ||
119 | musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); | ||
120 | |||
121 | if (musb->int_usb || musb->int_tx || musb->int_rx) { | ||
122 | musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); | ||
123 | musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); | ||
124 | musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); | ||
125 | retval = musb_interrupt(musb); | ||
126 | } | ||
127 | |||
128 | spin_unlock_irqrestore(&musb->lock, flags); | ||
129 | |||
130 | /* REVISIT we sometimes get spurious IRQs on g_ep0 | ||
131 | * not clear why... fall in BF54x too. | ||
132 | */ | ||
133 | if (retval != IRQ_HANDLED) | ||
134 | DBG(5, "spurious?\n"); | ||
135 | |||
136 | return IRQ_HANDLED; | ||
137 | } | ||
138 | |||
139 | static void musb_conn_timer_handler(unsigned long _musb) | ||
140 | { | ||
141 | struct musb *musb = (void *)_musb; | ||
142 | unsigned long flags; | ||
143 | u16 val; | ||
144 | |||
145 | spin_lock_irqsave(&musb->lock, flags); | ||
146 | switch (musb->xceiv.state) { | ||
147 | case OTG_STATE_A_IDLE: | ||
148 | case OTG_STATE_A_WAIT_BCON: | ||
149 | /* Start a new session */ | ||
150 | val = musb_readw(musb->mregs, MUSB_DEVCTL); | ||
151 | val |= MUSB_DEVCTL_SESSION; | ||
152 | musb_writew(musb->mregs, MUSB_DEVCTL, val); | ||
153 | |||
154 | val = musb_readw(musb->mregs, MUSB_DEVCTL); | ||
155 | if (!(val & MUSB_DEVCTL_BDEVICE)) { | ||
156 | gpio_set_value(musb->config->gpio_vrsel, 1); | ||
157 | musb->xceiv.state = OTG_STATE_A_WAIT_BCON; | ||
158 | } else { | ||
159 | gpio_set_value(musb->config->gpio_vrsel, 0); | ||
160 | |||
161 | /* Ignore VBUSERROR and SUSPEND IRQ */ | ||
162 | val = musb_readb(musb->mregs, MUSB_INTRUSBE); | ||
163 | val &= ~MUSB_INTR_VBUSERROR; | ||
164 | musb_writeb(musb->mregs, MUSB_INTRUSBE, val); | ||
165 | |||
166 | val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR; | ||
167 | musb_writeb(musb->mregs, MUSB_INTRUSB, val); | ||
168 | |||
169 | val = MUSB_POWER_HSENAB; | ||
170 | musb_writeb(musb->mregs, MUSB_POWER, val); | ||
171 | } | ||
172 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); | ||
173 | break; | ||
174 | |||
175 | default: | ||
176 | DBG(1, "%s state not handled\n", otg_state_string(musb)); | ||
177 | break; | ||
178 | } | ||
179 | spin_unlock_irqrestore(&musb->lock, flags); | ||
180 | |||
181 | DBG(4, "state is %s\n", otg_state_string(musb)); | ||
182 | } | ||
183 | |||
184 | void musb_platform_enable(struct musb *musb) | ||
185 | { | ||
186 | if (is_host_enabled(musb)) { | ||
187 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); | ||
188 | musb->a_wait_bcon = TIMER_DELAY; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | void musb_platform_disable(struct musb *musb) | ||
193 | { | ||
194 | } | ||
195 | |||
196 | static void bfin_vbus_power(struct musb *musb, int is_on, int sleeping) | ||
197 | { | ||
198 | } | ||
199 | |||
200 | static void bfin_set_vbus(struct musb *musb, int is_on) | ||
201 | { | ||
202 | if (is_on) | ||
203 | gpio_set_value(musb->config->gpio_vrsel, 1); | ||
204 | else | ||
205 | gpio_set_value(musb->config->gpio_vrsel, 0); | ||
206 | |||
207 | DBG(1, "VBUS %s, devctl %02x " | ||
208 | /* otg %3x conf %08x prcm %08x */ "\n", | ||
209 | otg_state_string(musb), | ||
210 | musb_readb(musb->mregs, MUSB_DEVCTL)); | ||
211 | } | ||
212 | |||
213 | static int bfin_set_power(struct otg_transceiver *x, unsigned mA) | ||
214 | { | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | ||
219 | { | ||
220 | if (is_host_enabled(musb)) | ||
221 | mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); | ||
222 | } | ||
223 | |||
224 | int musb_platform_get_vbus_status(struct musb *musb) | ||
225 | { | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | void musb_platform_set_mode(struct musb *musb, u8 musb_mode) | ||
230 | { | ||
231 | } | ||
232 | |||
233 | int __init musb_platform_init(struct musb *musb) | ||
234 | { | ||
235 | |||
236 | /* | ||
237 | * Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE | ||
238 | * and OTG HOST modes, while rev 1.1 and greater require PE7 to | ||
239 | * be low for DEVICE mode and high for HOST mode. We set it high | ||
240 | * here because we are in host mode | ||
241 | */ | ||
242 | |||
243 | if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) { | ||
244 | printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d \n", | ||
245 | musb->config->gpio_vrsel); | ||
246 | return -ENODEV; | ||
247 | } | ||
248 | gpio_direction_output(musb->config->gpio_vrsel, 0); | ||
249 | |||
250 | if (ANOMALY_05000346) { | ||
251 | bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); | ||
252 | SSYNC(); | ||
253 | } | ||
254 | |||
255 | if (ANOMALY_05000347) { | ||
256 | bfin_write_USB_APHY_CNTRL(0x0); | ||
257 | SSYNC(); | ||
258 | } | ||
259 | |||
260 | /* TODO | ||
261 | * Set SIC-IVG register | ||
262 | */ | ||
263 | |||
264 | /* Configure PLL oscillator register */ | ||
265 | bfin_write_USB_PLLOSC_CTRL(0x30a8); | ||
266 | SSYNC(); | ||
267 | |||
268 | bfin_write_USB_SRP_CLKDIV((get_sclk()/1000) / 32 - 1); | ||
269 | SSYNC(); | ||
270 | |||
271 | bfin_write_USB_EP_NI0_RXMAXP(64); | ||
272 | SSYNC(); | ||
273 | |||
274 | bfin_write_USB_EP_NI0_TXMAXP(64); | ||
275 | SSYNC(); | ||
276 | |||
277 | /* Route INTRUSB/INTR_RX/INTR_TX to USB_INT0*/ | ||
278 | bfin_write_USB_GLOBINTR(0x7); | ||
279 | SSYNC(); | ||
280 | |||
281 | bfin_write_USB_GLOBAL_CTL(GLOBAL_ENA | EP1_TX_ENA | EP2_TX_ENA | | ||
282 | EP3_TX_ENA | EP4_TX_ENA | EP5_TX_ENA | | ||
283 | EP6_TX_ENA | EP7_TX_ENA | EP1_RX_ENA | | ||
284 | EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA | | ||
285 | EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA); | ||
286 | SSYNC(); | ||
287 | |||
288 | if (is_host_enabled(musb)) { | ||
289 | musb->board_set_vbus = bfin_set_vbus; | ||
290 | setup_timer(&musb_conn_timer, | ||
291 | musb_conn_timer_handler, (unsigned long) musb); | ||
292 | } | ||
293 | if (is_peripheral_enabled(musb)) | ||
294 | musb->xceiv.set_power = bfin_set_power; | ||
295 | |||
296 | musb->isr = blackfin_interrupt; | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | int musb_platform_suspend(struct musb *musb) | ||
302 | { | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | int musb_platform_resume(struct musb *musb) | ||
307 | { | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | |||
312 | int musb_platform_exit(struct musb *musb) | ||
313 | { | ||
314 | |||
315 | bfin_vbus_power(musb, 0 /*off*/, 1); | ||
316 | gpio_free(musb->config->gpio_vrsel); | ||
317 | musb_platform_suspend(musb); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
diff --git a/drivers/usb/musb/blackfin.h b/drivers/usb/musb/blackfin.h new file mode 100644 index 000000000000..a240c1e53d16 --- /dev/null +++ b/drivers/usb/musb/blackfin.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 by Analog Devices, Inc. | ||
3 | * | ||
4 | * The Inventra Controller Driver for Linux is free software; you | ||
5 | * can redistribute it and/or modify it under the terms of the GNU | ||
6 | * General Public License version 2 as published by the Free Software | ||
7 | * Foundation. | ||
8 | */ | ||
9 | |||
10 | #ifndef __MUSB_BLACKFIN_H__ | ||
11 | #define __MUSB_BLACKFIN_H__ | ||
12 | |||
13 | /* | ||
14 | * Blackfin specific definitions | ||
15 | */ | ||
16 | |||
17 | #undef DUMP_FIFO_DATA | ||
18 | #ifdef DUMP_FIFO_DATA | ||
19 | static void dump_fifo_data(u8 *buf, u16 len) | ||
20 | { | ||
21 | u8 *tmp = buf; | ||
22 | int i; | ||
23 | |||
24 | for (i = 0; i < len; i++) { | ||
25 | if (!(i % 16) && i) | ||
26 | pr_debug("\n"); | ||
27 | pr_debug("%02x ", *tmp++); | ||
28 | } | ||
29 | pr_debug("\n"); | ||
30 | } | ||
31 | #else | ||
32 | #define dump_fifo_data(buf, len) do {} while (0) | ||
33 | #endif | ||
34 | |||
35 | #ifdef CONFIG_BF52x | ||
36 | |||
37 | #define USB_DMA_BASE USB_DMA_INTERRUPT | ||
38 | #define USB_DMAx_CTRL 0x04 | ||
39 | #define USB_DMAx_ADDR_LOW 0x08 | ||
40 | #define USB_DMAx_ADDR_HIGH 0x0C | ||
41 | #define USB_DMAx_COUNT_LOW 0x10 | ||
42 | #define USB_DMAx_COUNT_HIGH 0x14 | ||
43 | |||
44 | #define USB_DMA_REG(ep, reg) (USB_DMA_BASE + 0x20 * ep + reg) | ||
45 | #endif | ||
46 | |||
47 | /* Almost 1 second */ | ||
48 | #define TIMER_DELAY (1 * HZ) | ||
49 | |||
50 | static struct timer_list musb_conn_timer; | ||
51 | |||
52 | #endif /* __MUSB_BLACKFIN_H__ */ | ||
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index dfb3bcbe00fc..0d566dc5ce06 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c | |||
@@ -32,9 +32,9 @@ | |||
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
34 | 34 | ||
35 | #include <asm/arch/hardware.h> | 35 | #include <mach/arch/hardware.h> |
36 | #include <asm/arch/memory.h> | 36 | #include <mach/arch/memory.h> |
37 | #include <asm/arch/gpio.h> | 37 | #include <mach/arch/gpio.h> |
38 | #include <asm/mach-types.h> | 38 | #include <asm/mach-types.h> |
39 | 39 | ||
40 | #include "musb_core.h" | 40 | #include "musb_core.h" |
@@ -364,6 +364,18 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | |||
364 | return IRQ_HANDLED; | 364 | return IRQ_HANDLED; |
365 | } | 365 | } |
366 | 366 | ||
367 | int musb_platform_set_mode(struct musb *musb, u8 mode) | ||
368 | { | ||
369 | /* EVM can't do this (right?) */ | ||
370 | return -EIO; | ||
371 | } | ||
372 | |||
373 | int musb_platform_set_mode(struct musb *musb, u8 mode) | ||
374 | { | ||
375 | /* EVM can't do this (right?) */ | ||
376 | return -EIO; | ||
377 | } | ||
378 | |||
367 | int __init musb_platform_init(struct musb *musb) | 379 | int __init musb_platform_init(struct musb *musb) |
368 | { | 380 | { |
369 | void __iomem *tibase = musb->ctrl_base; | 381 | void __iomem *tibase = musb->ctrl_base; |
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 5280dba9b1fb..6c7faacfb535 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -148,7 +148,8 @@ static inline struct musb *dev_to_musb(struct device *dev) | |||
148 | 148 | ||
149 | /*-------------------------------------------------------------------------*/ | 149 | /*-------------------------------------------------------------------------*/ |
150 | 150 | ||
151 | #ifndef CONFIG_USB_TUSB6010 | 151 | #if !defined(CONFIG_USB_TUSB6010) && !defined(CONFIG_BLACKFIN) |
152 | |||
152 | /* | 153 | /* |
153 | * Load an endpoint's FIFO | 154 | * Load an endpoint's FIFO |
154 | */ | 155 | */ |
@@ -1124,25 +1125,25 @@ fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, | |||
1124 | #endif | 1125 | #endif |
1125 | switch (cfg->style) { | 1126 | switch (cfg->style) { |
1126 | case FIFO_TX: | 1127 | case FIFO_TX: |
1127 | musb_writeb(mbase, MUSB_TXFIFOSZ, c_size); | 1128 | musb_write_txfifosz(mbase, c_size); |
1128 | musb_writew(mbase, MUSB_TXFIFOADD, c_off); | 1129 | musb_write_txfifoadd(mbase, c_off); |
1129 | hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); | 1130 | hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); |
1130 | hw_ep->max_packet_sz_tx = maxpacket; | 1131 | hw_ep->max_packet_sz_tx = maxpacket; |
1131 | break; | 1132 | break; |
1132 | case FIFO_RX: | 1133 | case FIFO_RX: |
1133 | musb_writeb(mbase, MUSB_RXFIFOSZ, c_size); | 1134 | musb_write_rxfifosz(mbase, c_size); |
1134 | musb_writew(mbase, MUSB_RXFIFOADD, c_off); | 1135 | musb_write_rxfifoadd(mbase, c_off); |
1135 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); | 1136 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); |
1136 | hw_ep->max_packet_sz_rx = maxpacket; | 1137 | hw_ep->max_packet_sz_rx = maxpacket; |
1137 | break; | 1138 | break; |
1138 | case FIFO_RXTX: | 1139 | case FIFO_RXTX: |
1139 | musb_writeb(mbase, MUSB_TXFIFOSZ, c_size); | 1140 | musb_write_txfifosz(mbase, c_size); |
1140 | musb_writew(mbase, MUSB_TXFIFOADD, c_off); | 1141 | musb_write_txfifoadd(mbase, c_off); |
1141 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); | 1142 | hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); |
1142 | hw_ep->max_packet_sz_rx = maxpacket; | 1143 | hw_ep->max_packet_sz_rx = maxpacket; |
1143 | 1144 | ||
1144 | musb_writeb(mbase, MUSB_RXFIFOSZ, c_size); | 1145 | musb_write_rxfifosz(mbase, c_size); |
1145 | musb_writew(mbase, MUSB_RXFIFOADD, c_off); | 1146 | musb_write_rxfifoadd(mbase, c_off); |
1146 | hw_ep->tx_double_buffered = hw_ep->rx_double_buffered; | 1147 | hw_ep->tx_double_buffered = hw_ep->rx_double_buffered; |
1147 | hw_ep->max_packet_sz_tx = maxpacket; | 1148 | hw_ep->max_packet_sz_tx = maxpacket; |
1148 | 1149 | ||
@@ -1212,7 +1213,7 @@ static int __init ep_config_from_table(struct musb *musb) | |||
1212 | if (epn >= musb->config->num_eps) { | 1213 | if (epn >= musb->config->num_eps) { |
1213 | pr_debug("%s: invalid ep %d\n", | 1214 | pr_debug("%s: invalid ep %d\n", |
1214 | musb_driver_name, epn); | 1215 | musb_driver_name, epn); |
1215 | continue; | 1216 | return -EINVAL; |
1216 | } | 1217 | } |
1217 | offset = fifo_setup(musb, hw_ep + epn, cfg++, offset); | 1218 | offset = fifo_setup(musb, hw_ep + epn, cfg++, offset); |
1218 | if (offset < 0) { | 1219 | if (offset < 0) { |
@@ -1246,9 +1247,10 @@ static int __init ep_config_from_table(struct musb *musb) | |||
1246 | */ | 1247 | */ |
1247 | static int __init ep_config_from_hw(struct musb *musb) | 1248 | static int __init ep_config_from_hw(struct musb *musb) |
1248 | { | 1249 | { |
1249 | u8 epnum = 0, reg; | 1250 | u8 epnum = 0; |
1250 | struct musb_hw_ep *hw_ep; | 1251 | struct musb_hw_ep *hw_ep; |
1251 | void *mbase = musb->mregs; | 1252 | void *mbase = musb->mregs; |
1253 | int ret = 0; | ||
1252 | 1254 | ||
1253 | DBG(2, "<== static silicon ep config\n"); | 1255 | DBG(2, "<== static silicon ep config\n"); |
1254 | 1256 | ||
@@ -1258,26 +1260,9 @@ static int __init ep_config_from_hw(struct musb *musb) | |||
1258 | musb_ep_select(mbase, epnum); | 1260 | musb_ep_select(mbase, epnum); |
1259 | hw_ep = musb->endpoints + epnum; | 1261 | hw_ep = musb->endpoints + epnum; |
1260 | 1262 | ||
1261 | /* read from core using indexed model */ | 1263 | ret = musb_read_fifosize(musb, hw_ep, epnum); |
1262 | reg = musb_readb(hw_ep->regs, 0x10 + MUSB_FIFOSIZE); | 1264 | if (ret < 0) |
1263 | if (!reg) { | ||
1264 | /* 0's returned when no more endpoints */ | ||
1265 | break; | 1265 | break; |
1266 | } | ||
1267 | musb->nr_endpoints++; | ||
1268 | musb->epmask |= (1 << epnum); | ||
1269 | |||
1270 | hw_ep->max_packet_sz_tx = 1 << (reg & 0x0f); | ||
1271 | |||
1272 | /* shared TX/RX FIFO? */ | ||
1273 | if ((reg & 0xf0) == 0xf0) { | ||
1274 | hw_ep->max_packet_sz_rx = hw_ep->max_packet_sz_tx; | ||
1275 | hw_ep->is_shared_fifo = true; | ||
1276 | continue; | ||
1277 | } else { | ||
1278 | hw_ep->max_packet_sz_rx = 1 << ((reg & 0xf0) >> 4); | ||
1279 | hw_ep->is_shared_fifo = false; | ||
1280 | } | ||
1281 | 1266 | ||
1282 | /* FIXME set up hw_ep->{rx,tx}_double_buffered */ | 1267 | /* FIXME set up hw_ep->{rx,tx}_double_buffered */ |
1283 | 1268 | ||
@@ -1326,7 +1311,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) | |||
1326 | 1311 | ||
1327 | /* log core options (read using indexed model) */ | 1312 | /* log core options (read using indexed model) */ |
1328 | musb_ep_select(mbase, 0); | 1313 | musb_ep_select(mbase, 0); |
1329 | reg = musb_readb(mbase, 0x10 + MUSB_CONFIGDATA); | 1314 | reg = musb_read_configdata(mbase); |
1330 | 1315 | ||
1331 | strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8"); | 1316 | strcpy(aInfo, (reg & MUSB_CONFIGDATA_UTMIDW) ? "UTMI-16" : "UTMI-8"); |
1332 | if (reg & MUSB_CONFIGDATA_DYNFIFO) | 1317 | if (reg & MUSB_CONFIGDATA_DYNFIFO) |
@@ -1391,7 +1376,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) | |||
1391 | } | 1376 | } |
1392 | 1377 | ||
1393 | /* log release info */ | 1378 | /* log release info */ |
1394 | hwvers = musb_readw(mbase, MUSB_HWVERS); | 1379 | hwvers = musb_read_hwvers(mbase); |
1395 | rev_major = (hwvers >> 10) & 0x1f; | 1380 | rev_major = (hwvers >> 10) & 0x1f; |
1396 | rev_minor = hwvers & 0x3ff; | 1381 | rev_minor = hwvers & 0x3ff; |
1397 | snprintf(aRevision, 32, "%d.%d%s", rev_major, | 1382 | snprintf(aRevision, 32, "%d.%d%s", rev_major, |
@@ -1400,8 +1385,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) | |||
1400 | musb_driver_name, type, aRevision, aDate); | 1385 | musb_driver_name, type, aRevision, aDate); |
1401 | 1386 | ||
1402 | /* configure ep0 */ | 1387 | /* configure ep0 */ |
1403 | musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE; | 1388 | musb_configure_ep0(musb); |
1404 | musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; | ||
1405 | 1389 | ||
1406 | /* discover endpoint configuration */ | 1390 | /* discover endpoint configuration */ |
1407 | musb->nr_endpoints = 1; | 1391 | musb->nr_endpoints = 1; |
@@ -1445,7 +1429,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) | |||
1445 | 1429 | ||
1446 | hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase; | 1430 | hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase; |
1447 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | 1431 | #ifdef CONFIG_USB_MUSB_HDRC_HCD |
1448 | hw_ep->target_regs = MUSB_BUSCTL_OFFSET(i, 0) + mbase; | 1432 | hw_ep->target_regs = musb_read_target_reg_base(i, mbase); |
1449 | hw_ep->rx_reinit = 1; | 1433 | hw_ep->rx_reinit = 1; |
1450 | hw_ep->tx_reinit = 1; | 1434 | hw_ep->tx_reinit = 1; |
1451 | #endif | 1435 | #endif |
@@ -1671,17 +1655,20 @@ musb_mode_store(struct device *dev, struct device_attribute *attr, | |||
1671 | { | 1655 | { |
1672 | struct musb *musb = dev_to_musb(dev); | 1656 | struct musb *musb = dev_to_musb(dev); |
1673 | unsigned long flags; | 1657 | unsigned long flags; |
1658 | int status; | ||
1674 | 1659 | ||
1675 | spin_lock_irqsave(&musb->lock, flags); | 1660 | spin_lock_irqsave(&musb->lock, flags); |
1676 | if (!strncmp(buf, "host", 4)) | 1661 | if (sysfs_streq(buf, "host")) |
1677 | musb_platform_set_mode(musb, MUSB_HOST); | 1662 | status = musb_platform_set_mode(musb, MUSB_HOST); |
1678 | if (!strncmp(buf, "peripheral", 10)) | 1663 | else if (sysfs_streq(buf, "peripheral")) |
1679 | musb_platform_set_mode(musb, MUSB_PERIPHERAL); | 1664 | status = musb_platform_set_mode(musb, MUSB_PERIPHERAL); |
1680 | if (!strncmp(buf, "otg", 3)) | 1665 | else if (sysfs_streq(buf, "otg")) |
1681 | musb_platform_set_mode(musb, MUSB_OTG); | 1666 | status = musb_platform_set_mode(musb, MUSB_OTG); |
1667 | else | ||
1668 | status = -EINVAL; | ||
1682 | spin_unlock_irqrestore(&musb->lock, flags); | 1669 | spin_unlock_irqrestore(&musb->lock, flags); |
1683 | 1670 | ||
1684 | return n; | 1671 | return (status == 0) ? n : status; |
1685 | } | 1672 | } |
1686 | static DEVICE_ATTR(mode, 0644, musb_mode_show, musb_mode_store); | 1673 | static DEVICE_ATTR(mode, 0644, musb_mode_show, musb_mode_store); |
1687 | 1674 | ||
@@ -1781,7 +1768,7 @@ allocate_instance(struct device *dev, | |||
1781 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | 1768 | #ifdef CONFIG_USB_MUSB_HDRC_HCD |
1782 | struct usb_hcd *hcd; | 1769 | struct usb_hcd *hcd; |
1783 | 1770 | ||
1784 | hcd = usb_create_hcd(&musb_hc_driver, dev, dev->bus_id); | 1771 | hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev)); |
1785 | if (!hcd) | 1772 | if (!hcd) |
1786 | return NULL; | 1773 | return NULL; |
1787 | /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ | 1774 | /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ |
@@ -1810,7 +1797,6 @@ allocate_instance(struct device *dev, | |||
1810 | for (epnum = 0, ep = musb->endpoints; | 1797 | for (epnum = 0, ep = musb->endpoints; |
1811 | epnum < musb->config->num_eps; | 1798 | epnum < musb->config->num_eps; |
1812 | epnum++, ep++) { | 1799 | epnum++, ep++) { |
1813 | |||
1814 | ep->musb = musb; | 1800 | ep->musb = musb; |
1815 | ep->epnum = epnum; | 1801 | ep->epnum = epnum; |
1816 | } | 1802 | } |
@@ -1838,7 +1824,7 @@ static void musb_free(struct musb *musb) | |||
1838 | musb_gadget_cleanup(musb); | 1824 | musb_gadget_cleanup(musb); |
1839 | #endif | 1825 | #endif |
1840 | 1826 | ||
1841 | if (musb->nIrq >= 0) { | 1827 | if (musb->nIrq >= 0 && musb->irq_wake) { |
1842 | disable_irq_wake(musb->nIrq); | 1828 | disable_irq_wake(musb->nIrq); |
1843 | free_irq(musb->nIrq, musb); | 1829 | free_irq(musb->nIrq, musb); |
1844 | } | 1830 | } |
@@ -1984,15 +1970,19 @@ bad_config: | |||
1984 | INIT_WORK(&musb->irq_work, musb_irq_work); | 1970 | INIT_WORK(&musb->irq_work, musb_irq_work); |
1985 | 1971 | ||
1986 | /* attach to the IRQ */ | 1972 | /* attach to the IRQ */ |
1987 | if (request_irq(nIrq, musb->isr, 0, dev->bus_id, musb)) { | 1973 | if (request_irq(nIrq, musb->isr, 0, dev_name(dev), musb)) { |
1988 | dev_err(dev, "request_irq %d failed!\n", nIrq); | 1974 | dev_err(dev, "request_irq %d failed!\n", nIrq); |
1989 | status = -ENODEV; | 1975 | status = -ENODEV; |
1990 | goto fail2; | 1976 | goto fail2; |
1991 | } | 1977 | } |
1992 | musb->nIrq = nIrq; | 1978 | musb->nIrq = nIrq; |
1993 | /* FIXME this handles wakeup irqs wrong */ | 1979 | /* FIXME this handles wakeup irqs wrong */ |
1994 | if (enable_irq_wake(nIrq) == 0) | 1980 | if (enable_irq_wake(nIrq) == 0) { |
1981 | musb->irq_wake = 1; | ||
1995 | device_init_wakeup(dev, 1); | 1982 | device_init_wakeup(dev, 1); |
1983 | } else { | ||
1984 | musb->irq_wake = 0; | ||
1985 | } | ||
1996 | 1986 | ||
1997 | pr_info("%s: USB %s mode controller at %p using %s, IRQ %d\n", | 1987 | pr_info("%s: USB %s mode controller at %p using %s, IRQ %d\n", |
1998 | musb_driver_name, | 1988 | musb_driver_name, |
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 82227251931b..630946a2d9fc 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h | |||
@@ -191,7 +191,7 @@ enum musb_g_ep0_state { | |||
191 | */ | 191 | */ |
192 | 192 | ||
193 | #if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_ARCH_OMAP2430) \ | 193 | #if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_ARCH_OMAP2430) \ |
194 | || defined(CONFIG_ARCH_OMAP3430) | 194 | || defined(CONFIG_ARCH_OMAP3430) || defined(CONFIG_BLACKFIN) |
195 | /* REVISIT indexed access seemed to | 195 | /* REVISIT indexed access seemed to |
196 | * misbehave (on DaVinci) for at least peripheral IN ... | 196 | * misbehave (on DaVinci) for at least peripheral IN ... |
197 | */ | 197 | */ |
@@ -359,6 +359,7 @@ struct musb { | |||
359 | struct otg_transceiver xceiv; | 359 | struct otg_transceiver xceiv; |
360 | 360 | ||
361 | int nIrq; | 361 | int nIrq; |
362 | unsigned irq_wake:1; | ||
362 | 363 | ||
363 | struct musb_hw_ep endpoints[MUSB_C_NUM_EPS]; | 364 | struct musb_hw_ep endpoints[MUSB_C_NUM_EPS]; |
364 | #define control_ep endpoints | 365 | #define control_ep endpoints |
@@ -447,6 +448,70 @@ static inline struct musb *gadget_to_musb(struct usb_gadget *g) | |||
447 | } | 448 | } |
448 | #endif | 449 | #endif |
449 | 450 | ||
451 | #ifdef CONFIG_BLACKFIN | ||
452 | static inline int musb_read_fifosize(struct musb *musb, | ||
453 | struct musb_hw_ep *hw_ep, u8 epnum) | ||
454 | { | ||
455 | musb->nr_endpoints++; | ||
456 | musb->epmask |= (1 << epnum); | ||
457 | |||
458 | if (epnum < 5) { | ||
459 | hw_ep->max_packet_sz_tx = 128; | ||
460 | hw_ep->max_packet_sz_rx = 128; | ||
461 | } else { | ||
462 | hw_ep->max_packet_sz_tx = 1024; | ||
463 | hw_ep->max_packet_sz_rx = 1024; | ||
464 | } | ||
465 | hw_ep->is_shared_fifo = false; | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | static inline void musb_configure_ep0(struct musb *musb) | ||
471 | { | ||
472 | musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE; | ||
473 | musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; | ||
474 | musb->endpoints[0].is_shared_fifo = true; | ||
475 | } | ||
476 | |||
477 | #else | ||
478 | |||
479 | static inline int musb_read_fifosize(struct musb *musb, | ||
480 | struct musb_hw_ep *hw_ep, u8 epnum) | ||
481 | { | ||
482 | u8 reg = 0; | ||
483 | |||
484 | /* read from core using indexed model */ | ||
485 | reg = musb_readb(hw_ep->regs, 0x10 + MUSB_FIFOSIZE); | ||
486 | /* 0's returned when no more endpoints */ | ||
487 | if (!reg) | ||
488 | return -ENODEV; | ||
489 | |||
490 | musb->nr_endpoints++; | ||
491 | musb->epmask |= (1 << epnum); | ||
492 | |||
493 | hw_ep->max_packet_sz_tx = 1 << (reg & 0x0f); | ||
494 | |||
495 | /* shared TX/RX FIFO? */ | ||
496 | if ((reg & 0xf0) == 0xf0) { | ||
497 | hw_ep->max_packet_sz_rx = hw_ep->max_packet_sz_tx; | ||
498 | hw_ep->is_shared_fifo = true; | ||
499 | return 0; | ||
500 | } else { | ||
501 | hw_ep->max_packet_sz_rx = 1 << ((reg & 0xf0) >> 4); | ||
502 | hw_ep->is_shared_fifo = false; | ||
503 | } | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static inline void musb_configure_ep0(struct musb *musb) | ||
509 | { | ||
510 | musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE; | ||
511 | musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; | ||
512 | } | ||
513 | #endif /* CONFIG_BLACKFIN */ | ||
514 | |||
450 | 515 | ||
451 | /***************************** Glue it together *****************************/ | 516 | /***************************** Glue it together *****************************/ |
452 | 517 | ||
@@ -467,16 +532,16 @@ extern void musb_platform_disable(struct musb *musb); | |||
467 | 532 | ||
468 | extern void musb_hnp_stop(struct musb *musb); | 533 | extern void musb_hnp_stop(struct musb *musb); |
469 | 534 | ||
470 | extern void musb_platform_set_mode(struct musb *musb, u8 musb_mode); | 535 | extern int musb_platform_set_mode(struct musb *musb, u8 musb_mode); |
471 | 536 | ||
472 | #if defined(CONFIG_USB_TUSB6010) || \ | 537 | #if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) || \ |
473 | defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) | 538 | defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) |
474 | extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout); | 539 | extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout); |
475 | #else | 540 | #else |
476 | #define musb_platform_try_idle(x, y) do {} while (0) | 541 | #define musb_platform_try_idle(x, y) do {} while (0) |
477 | #endif | 542 | #endif |
478 | 543 | ||
479 | #ifdef CONFIG_USB_TUSB6010 | 544 | #if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) |
480 | extern int musb_platform_get_vbus_status(struct musb *musb); | 545 | extern int musb_platform_get_vbus_status(struct musb *musb); |
481 | #else | 546 | #else |
482 | #define musb_platform_get_vbus_status(x) 0 | 547 | #define musb_platform_get_vbus_status(x) 0 |
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d6a802c224fa..6197daeab8f9 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
@@ -1633,7 +1633,7 @@ int __init musb_gadget_setup(struct musb *musb) | |||
1633 | musb->g.speed = USB_SPEED_UNKNOWN; | 1633 | musb->g.speed = USB_SPEED_UNKNOWN; |
1634 | 1634 | ||
1635 | /* this "gadget" abstracts/virtualizes the controller */ | 1635 | /* this "gadget" abstracts/virtualizes the controller */ |
1636 | strcpy(musb->g.dev.bus_id, "gadget"); | 1636 | dev_set_name(&musb->g.dev, "gadget"); |
1637 | musb->g.dev.parent = musb->controller; | 1637 | musb->g.dev.parent = musb->controller; |
1638 | musb->g.dev.dma_mask = musb->controller->dma_mask; | 1638 | musb->g.dev.dma_mask = musb->controller->dma_mask; |
1639 | musb->g.dev.release = musb_gadget_release; | 1639 | musb->g.dev.release = musb_gadget_release; |
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index cc64462d4c4e..99fa61234876 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
@@ -112,18 +112,21 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) | |||
112 | { | 112 | { |
113 | void __iomem *epio = ep->regs; | 113 | void __iomem *epio = ep->regs; |
114 | u16 csr; | 114 | u16 csr; |
115 | u16 lastcsr = 0; | ||
115 | int retries = 1000; | 116 | int retries = 1000; |
116 | 117 | ||
117 | csr = musb_readw(epio, MUSB_TXCSR); | 118 | csr = musb_readw(epio, MUSB_TXCSR); |
118 | while (csr & MUSB_TXCSR_FIFONOTEMPTY) { | 119 | while (csr & MUSB_TXCSR_FIFONOTEMPTY) { |
119 | DBG(5, "Host TX FIFONOTEMPTY csr: %02x\n", csr); | 120 | if (csr != lastcsr) |
121 | DBG(3, "Host TX FIFONOTEMPTY csr: %02x\n", csr); | ||
122 | lastcsr = csr; | ||
120 | csr |= MUSB_TXCSR_FLUSHFIFO; | 123 | csr |= MUSB_TXCSR_FLUSHFIFO; |
121 | musb_writew(epio, MUSB_TXCSR, csr); | 124 | musb_writew(epio, MUSB_TXCSR, csr); |
122 | csr = musb_readw(epio, MUSB_TXCSR); | 125 | csr = musb_readw(epio, MUSB_TXCSR); |
123 | if (retries-- < 1) { | 126 | if (WARN(retries-- < 1, |
124 | ERR("Could not flush host TX fifo: csr: %04x\n", csr); | 127 | "Could not flush host TX%d fifo: csr: %04x\n", |
128 | ep->epnum, csr)) | ||
125 | return; | 129 | return; |
126 | } | ||
127 | mdelay(1); | 130 | mdelay(1); |
128 | } | 131 | } |
129 | } | 132 | } |
@@ -268,7 +271,7 @@ __musb_giveback(struct musb *musb, struct urb *urb, int status) | |||
268 | __releases(musb->lock) | 271 | __releases(musb->lock) |
269 | __acquires(musb->lock) | 272 | __acquires(musb->lock) |
270 | { | 273 | { |
271 | DBG(({ int level; switch (urb->status) { | 274 | DBG(({ int level; switch (status) { |
272 | case 0: | 275 | case 0: |
273 | level = 4; | 276 | level = 4; |
274 | break; | 277 | break; |
@@ -283,8 +286,8 @@ __acquires(musb->lock) | |||
283 | level = 2; | 286 | level = 2; |
284 | break; | 287 | break; |
285 | }; level; }), | 288 | }; level; }), |
286 | "complete %p (%d), dev%d ep%d%s, %d/%d\n", | 289 | "complete %p %pF (%d), dev%d ep%d%s, %d/%d\n", |
287 | urb, urb->status, | 290 | urb, urb->complete, status, |
288 | usb_pipedevice(urb->pipe), | 291 | usb_pipedevice(urb->pipe), |
289 | usb_pipeendpoint(urb->pipe), | 292 | usb_pipeendpoint(urb->pipe), |
290 | usb_pipein(urb->pipe) ? "in" : "out", | 293 | usb_pipein(urb->pipe) ? "in" : "out", |
@@ -593,12 +596,10 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) | |||
593 | 596 | ||
594 | /* target addr and (for multipoint) hub addr/port */ | 597 | /* target addr and (for multipoint) hub addr/port */ |
595 | if (musb->is_multipoint) { | 598 | if (musb->is_multipoint) { |
596 | musb_writeb(ep->target_regs, MUSB_RXFUNCADDR, | 599 | musb_write_rxfunaddr(ep->target_regs, qh->addr_reg); |
597 | qh->addr_reg); | 600 | musb_write_rxhubaddr(ep->target_regs, qh->h_addr_reg); |
598 | musb_writeb(ep->target_regs, MUSB_RXHUBADDR, | 601 | musb_write_rxhubport(ep->target_regs, qh->h_port_reg); |
599 | qh->h_addr_reg); | 602 | |
600 | musb_writeb(ep->target_regs, MUSB_RXHUBPORT, | ||
601 | qh->h_port_reg); | ||
602 | } else | 603 | } else |
603 | musb_writeb(musb->mregs, MUSB_FADDR, qh->addr_reg); | 604 | musb_writeb(musb->mregs, MUSB_FADDR, qh->addr_reg); |
604 | 605 | ||
@@ -712,15 +713,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | |||
712 | 713 | ||
713 | /* target addr and (for multipoint) hub addr/port */ | 714 | /* target addr and (for multipoint) hub addr/port */ |
714 | if (musb->is_multipoint) { | 715 | if (musb->is_multipoint) { |
715 | musb_writeb(mbase, | 716 | musb_write_txfunaddr(mbase, epnum, qh->addr_reg); |
716 | MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR), | 717 | musb_write_txhubaddr(mbase, epnum, qh->h_addr_reg); |
717 | qh->addr_reg); | 718 | musb_write_txhubport(mbase, epnum, qh->h_port_reg); |
718 | musb_writeb(mbase, | ||
719 | MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR), | ||
720 | qh->h_addr_reg); | ||
721 | musb_writeb(mbase, | ||
722 | MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT), | ||
723 | qh->h_port_reg); | ||
724 | /* FIXME if !epnum, do the same for RX ... */ | 719 | /* FIXME if !epnum, do the same for RX ... */ |
725 | } else | 720 | } else |
726 | musb_writeb(mbase, MUSB_FADDR, qh->addr_reg); | 721 | musb_writeb(mbase, MUSB_FADDR, qh->addr_reg); |
@@ -988,8 +983,10 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) | |||
988 | if (fifo_count) { | 983 | if (fifo_count) { |
989 | fifo_dest = (u8 *) (urb->transfer_buffer | 984 | fifo_dest = (u8 *) (urb->transfer_buffer |
990 | + urb->actual_length); | 985 | + urb->actual_length); |
991 | DBG(3, "Sending %d bytes to %p\n", | 986 | DBG(3, "Sending %d byte%s to ep0 fifo %p\n", |
992 | fifo_count, fifo_dest); | 987 | fifo_count, |
988 | (fifo_count == 1) ? "" : "s", | ||
989 | fifo_dest); | ||
993 | musb_write_fifo(hw_ep, fifo_count, fifo_dest); | 990 | musb_write_fifo(hw_ep, fifo_count, fifo_dest); |
994 | 991 | ||
995 | urb->actual_length += fifo_count; | 992 | urb->actual_length += fifo_count; |
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index 223f0a514094..b06e9ef00cfc 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h | |||
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | #if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \ | 40 | #if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \ |
41 | && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \ | 41 | && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \ |
42 | && !defined(CONFIG_PPC64) | 42 | && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) |
43 | static inline void readsl(const void __iomem *addr, void *buf, int len) | 43 | static inline void readsl(const void __iomem *addr, void *buf, int len) |
44 | { insl((unsigned long)addr, buf, len); } | 44 | { insl((unsigned long)addr, buf, len); } |
45 | static inline void readsw(const void __iomem *addr, void *buf, int len) | 45 | static inline void readsw(const void __iomem *addr, void *buf, int len) |
@@ -56,6 +56,8 @@ static inline void writesb(const void __iomem *addr, const void *buf, int len) | |||
56 | 56 | ||
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | #ifndef CONFIG_BLACKFIN | ||
60 | |||
59 | /* NOTE: these offsets are all in bytes */ | 61 | /* NOTE: these offsets are all in bytes */ |
60 | 62 | ||
61 | static inline u16 musb_readw(const void __iomem *addr, unsigned offset) | 63 | static inline u16 musb_readw(const void __iomem *addr, unsigned offset) |
@@ -114,4 +116,26 @@ static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data) | |||
114 | 116 | ||
115 | #endif /* CONFIG_USB_TUSB6010 */ | 117 | #endif /* CONFIG_USB_TUSB6010 */ |
116 | 118 | ||
119 | #else | ||
120 | |||
121 | static inline u8 musb_readb(const void __iomem *addr, unsigned offset) | ||
122 | { return (u8) (bfin_read16(addr + offset)); } | ||
123 | |||
124 | static inline u16 musb_readw(const void __iomem *addr, unsigned offset) | ||
125 | { return bfin_read16(addr + offset); } | ||
126 | |||
127 | static inline u32 musb_readl(const void __iomem *addr, unsigned offset) | ||
128 | { return (u32) (bfin_read16(addr + offset)); } | ||
129 | |||
130 | static inline void musb_writeb(void __iomem *addr, unsigned offset, u8 data) | ||
131 | { bfin_write16(addr + offset, (u16) data); } | ||
132 | |||
133 | static inline void musb_writew(void __iomem *addr, unsigned offset, u16 data) | ||
134 | { bfin_write16(addr + offset, data); } | ||
135 | |||
136 | static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data) | ||
137 | { bfin_write16(addr + offset, (u16) data); } | ||
138 | |||
139 | #endif /* CONFIG_BLACKFIN */ | ||
140 | |||
117 | #endif | 141 | #endif |
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 9c228661aa5a..de3b2f18db44 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h | |||
@@ -38,97 +38,6 @@ | |||
38 | #define MUSB_EP0_FIFOSIZE 64 /* This is non-configurable */ | 38 | #define MUSB_EP0_FIFOSIZE 64 /* This is non-configurable */ |
39 | 39 | ||
40 | /* | 40 | /* |
41 | * Common USB registers | ||
42 | */ | ||
43 | |||
44 | #define MUSB_FADDR 0x00 /* 8-bit */ | ||
45 | #define MUSB_POWER 0x01 /* 8-bit */ | ||
46 | |||
47 | #define MUSB_INTRTX 0x02 /* 16-bit */ | ||
48 | #define MUSB_INTRRX 0x04 | ||
49 | #define MUSB_INTRTXE 0x06 | ||
50 | #define MUSB_INTRRXE 0x08 | ||
51 | #define MUSB_INTRUSB 0x0A /* 8 bit */ | ||
52 | #define MUSB_INTRUSBE 0x0B /* 8 bit */ | ||
53 | #define MUSB_FRAME 0x0C | ||
54 | #define MUSB_INDEX 0x0E /* 8 bit */ | ||
55 | #define MUSB_TESTMODE 0x0F /* 8 bit */ | ||
56 | |||
57 | /* Get offset for a given FIFO from musb->mregs */ | ||
58 | #ifdef CONFIG_USB_TUSB6010 | ||
59 | #define MUSB_FIFO_OFFSET(epnum) (0x200 + ((epnum) * 0x20)) | ||
60 | #else | ||
61 | #define MUSB_FIFO_OFFSET(epnum) (0x20 + ((epnum) * 4)) | ||
62 | #endif | ||
63 | |||
64 | /* | ||
65 | * Additional Control Registers | ||
66 | */ | ||
67 | |||
68 | #define MUSB_DEVCTL 0x60 /* 8 bit */ | ||
69 | |||
70 | /* These are always controlled through the INDEX register */ | ||
71 | #define MUSB_TXFIFOSZ 0x62 /* 8-bit (see masks) */ | ||
72 | #define MUSB_RXFIFOSZ 0x63 /* 8-bit (see masks) */ | ||
73 | #define MUSB_TXFIFOADD 0x64 /* 16-bit offset shifted right 3 */ | ||
74 | #define MUSB_RXFIFOADD 0x66 /* 16-bit offset shifted right 3 */ | ||
75 | |||
76 | /* REVISIT: vctrl/vstatus: optional vendor utmi+phy register at 0x68 */ | ||
77 | #define MUSB_HWVERS 0x6C /* 8 bit */ | ||
78 | |||
79 | #define MUSB_EPINFO 0x78 /* 8 bit */ | ||
80 | #define MUSB_RAMINFO 0x79 /* 8 bit */ | ||
81 | #define MUSB_LINKINFO 0x7a /* 8 bit */ | ||
82 | #define MUSB_VPLEN 0x7b /* 8 bit */ | ||
83 | #define MUSB_HS_EOF1 0x7c /* 8 bit */ | ||
84 | #define MUSB_FS_EOF1 0x7d /* 8 bit */ | ||
85 | #define MUSB_LS_EOF1 0x7e /* 8 bit */ | ||
86 | |||
87 | /* Offsets to endpoint registers */ | ||
88 | #define MUSB_TXMAXP 0x00 | ||
89 | #define MUSB_TXCSR 0x02 | ||
90 | #define MUSB_CSR0 MUSB_TXCSR /* Re-used for EP0 */ | ||
91 | #define MUSB_RXMAXP 0x04 | ||
92 | #define MUSB_RXCSR 0x06 | ||
93 | #define MUSB_RXCOUNT 0x08 | ||
94 | #define MUSB_COUNT0 MUSB_RXCOUNT /* Re-used for EP0 */ | ||
95 | #define MUSB_TXTYPE 0x0A | ||
96 | #define MUSB_TYPE0 MUSB_TXTYPE /* Re-used for EP0 */ | ||
97 | #define MUSB_TXINTERVAL 0x0B | ||
98 | #define MUSB_NAKLIMIT0 MUSB_TXINTERVAL /* Re-used for EP0 */ | ||
99 | #define MUSB_RXTYPE 0x0C | ||
100 | #define MUSB_RXINTERVAL 0x0D | ||
101 | #define MUSB_FIFOSIZE 0x0F | ||
102 | #define MUSB_CONFIGDATA MUSB_FIFOSIZE /* Re-used for EP0 */ | ||
103 | |||
104 | /* Offsets to endpoint registers in indexed model (using INDEX register) */ | ||
105 | #define MUSB_INDEXED_OFFSET(_epnum, _offset) \ | ||
106 | (0x10 + (_offset)) | ||
107 | |||
108 | /* Offsets to endpoint registers in flat models */ | ||
109 | #define MUSB_FLAT_OFFSET(_epnum, _offset) \ | ||
110 | (0x100 + (0x10*(_epnum)) + (_offset)) | ||
111 | |||
112 | #ifdef CONFIG_USB_TUSB6010 | ||
113 | /* TUSB6010 EP0 configuration register is special */ | ||
114 | #define MUSB_TUSB_OFFSET(_epnum, _offset) \ | ||
115 | (0x10 + _offset) | ||
116 | #include "tusb6010.h" /* Needed "only" for TUSB_EP0_CONF */ | ||
117 | #endif | ||
118 | |||
119 | /* "bus control"/target registers, for host side multipoint (external hubs) */ | ||
120 | #define MUSB_TXFUNCADDR 0x00 | ||
121 | #define MUSB_TXHUBADDR 0x02 | ||
122 | #define MUSB_TXHUBPORT 0x03 | ||
123 | |||
124 | #define MUSB_RXFUNCADDR 0x04 | ||
125 | #define MUSB_RXHUBADDR 0x06 | ||
126 | #define MUSB_RXHUBPORT 0x07 | ||
127 | |||
128 | #define MUSB_BUSCTL_OFFSET(_epnum, _offset) \ | ||
129 | (0x80 + (8*(_epnum)) + (_offset)) | ||
130 | |||
131 | /* | ||
132 | * MUSB Register bits | 41 | * MUSB Register bits |
133 | */ | 42 | */ |
134 | 43 | ||
@@ -228,7 +137,6 @@ | |||
228 | 137 | ||
229 | /* TXCSR in Peripheral and Host mode */ | 138 | /* TXCSR in Peripheral and Host mode */ |
230 | #define MUSB_TXCSR_AUTOSET 0x8000 | 139 | #define MUSB_TXCSR_AUTOSET 0x8000 |
231 | #define MUSB_TXCSR_MODE 0x2000 | ||
232 | #define MUSB_TXCSR_DMAENAB 0x1000 | 140 | #define MUSB_TXCSR_DMAENAB 0x1000 |
233 | #define MUSB_TXCSR_FRCDATATOG 0x0800 | 141 | #define MUSB_TXCSR_FRCDATATOG 0x0800 |
234 | #define MUSB_TXCSR_DMAMODE 0x0400 | 142 | #define MUSB_TXCSR_DMAMODE 0x0400 |
@@ -297,4 +205,309 @@ | |||
297 | /* HUBADDR */ | 205 | /* HUBADDR */ |
298 | #define MUSB_HUBADDR_MULTI_TT 0x80 | 206 | #define MUSB_HUBADDR_MULTI_TT 0x80 |
299 | 207 | ||
208 | |||
209 | #ifndef CONFIG_BLACKFIN | ||
210 | |||
211 | /* | ||
212 | * Common USB registers | ||
213 | */ | ||
214 | |||
215 | #define MUSB_FADDR 0x00 /* 8-bit */ | ||
216 | #define MUSB_POWER 0x01 /* 8-bit */ | ||
217 | |||
218 | #define MUSB_INTRTX 0x02 /* 16-bit */ | ||
219 | #define MUSB_INTRRX 0x04 | ||
220 | #define MUSB_INTRTXE 0x06 | ||
221 | #define MUSB_INTRRXE 0x08 | ||
222 | #define MUSB_INTRUSB 0x0A /* 8 bit */ | ||
223 | #define MUSB_INTRUSBE 0x0B /* 8 bit */ | ||
224 | #define MUSB_FRAME 0x0C | ||
225 | #define MUSB_INDEX 0x0E /* 8 bit */ | ||
226 | #define MUSB_TESTMODE 0x0F /* 8 bit */ | ||
227 | |||
228 | /* Get offset for a given FIFO from musb->mregs */ | ||
229 | #ifdef CONFIG_USB_TUSB6010 | ||
230 | #define MUSB_FIFO_OFFSET(epnum) (0x200 + ((epnum) * 0x20)) | ||
231 | #else | ||
232 | #define MUSB_FIFO_OFFSET(epnum) (0x20 + ((epnum) * 4)) | ||
233 | #endif | ||
234 | |||
235 | /* | ||
236 | * Additional Control Registers | ||
237 | */ | ||
238 | |||
239 | #define MUSB_DEVCTL 0x60 /* 8 bit */ | ||
240 | |||
241 | /* These are always controlled through the INDEX register */ | ||
242 | #define MUSB_TXFIFOSZ 0x62 /* 8-bit (see masks) */ | ||
243 | #define MUSB_RXFIFOSZ 0x63 /* 8-bit (see masks) */ | ||
244 | #define MUSB_TXFIFOADD 0x64 /* 16-bit offset shifted right 3 */ | ||
245 | #define MUSB_RXFIFOADD 0x66 /* 16-bit offset shifted right 3 */ | ||
246 | |||
247 | /* REVISIT: vctrl/vstatus: optional vendor utmi+phy register at 0x68 */ | ||
248 | #define MUSB_HWVERS 0x6C /* 8 bit */ | ||
249 | |||
250 | #define MUSB_EPINFO 0x78 /* 8 bit */ | ||
251 | #define MUSB_RAMINFO 0x79 /* 8 bit */ | ||
252 | #define MUSB_LINKINFO 0x7a /* 8 bit */ | ||
253 | #define MUSB_VPLEN 0x7b /* 8 bit */ | ||
254 | #define MUSB_HS_EOF1 0x7c /* 8 bit */ | ||
255 | #define MUSB_FS_EOF1 0x7d /* 8 bit */ | ||
256 | #define MUSB_LS_EOF1 0x7e /* 8 bit */ | ||
257 | |||
258 | /* Offsets to endpoint registers */ | ||
259 | #define MUSB_TXMAXP 0x00 | ||
260 | #define MUSB_TXCSR 0x02 | ||
261 | #define MUSB_CSR0 MUSB_TXCSR /* Re-used for EP0 */ | ||
262 | #define MUSB_RXMAXP 0x04 | ||
263 | #define MUSB_RXCSR 0x06 | ||
264 | #define MUSB_RXCOUNT 0x08 | ||
265 | #define MUSB_COUNT0 MUSB_RXCOUNT /* Re-used for EP0 */ | ||
266 | #define MUSB_TXTYPE 0x0A | ||
267 | #define MUSB_TYPE0 MUSB_TXTYPE /* Re-used for EP0 */ | ||
268 | #define MUSB_TXINTERVAL 0x0B | ||
269 | #define MUSB_NAKLIMIT0 MUSB_TXINTERVAL /* Re-used for EP0 */ | ||
270 | #define MUSB_RXTYPE 0x0C | ||
271 | #define MUSB_RXINTERVAL 0x0D | ||
272 | #define MUSB_FIFOSIZE 0x0F | ||
273 | #define MUSB_CONFIGDATA MUSB_FIFOSIZE /* Re-used for EP0 */ | ||
274 | |||
275 | /* Offsets to endpoint registers in indexed model (using INDEX register) */ | ||
276 | #define MUSB_INDEXED_OFFSET(_epnum, _offset) \ | ||
277 | (0x10 + (_offset)) | ||
278 | |||
279 | /* Offsets to endpoint registers in flat models */ | ||
280 | #define MUSB_FLAT_OFFSET(_epnum, _offset) \ | ||
281 | (0x100 + (0x10*(_epnum)) + (_offset)) | ||
282 | |||
283 | #ifdef CONFIG_USB_TUSB6010 | ||
284 | /* TUSB6010 EP0 configuration register is special */ | ||
285 | #define MUSB_TUSB_OFFSET(_epnum, _offset) \ | ||
286 | (0x10 + _offset) | ||
287 | #include "tusb6010.h" /* Needed "only" for TUSB_EP0_CONF */ | ||
288 | #endif | ||
289 | |||
290 | #define MUSB_TXCSR_MODE 0x2000 | ||
291 | |||
292 | /* "bus control"/target registers, for host side multipoint (external hubs) */ | ||
293 | #define MUSB_TXFUNCADDR 0x00 | ||
294 | #define MUSB_TXHUBADDR 0x02 | ||
295 | #define MUSB_TXHUBPORT 0x03 | ||
296 | |||
297 | #define MUSB_RXFUNCADDR 0x04 | ||
298 | #define MUSB_RXHUBADDR 0x06 | ||
299 | #define MUSB_RXHUBPORT 0x07 | ||
300 | |||
301 | #define MUSB_BUSCTL_OFFSET(_epnum, _offset) \ | ||
302 | (0x80 + (8*(_epnum)) + (_offset)) | ||
303 | |||
304 | static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size) | ||
305 | { | ||
306 | musb_writeb(mbase, MUSB_TXFIFOSZ, c_size); | ||
307 | } | ||
308 | |||
309 | static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off) | ||
310 | { | ||
311 | musb_writew(mbase, MUSB_TXFIFOADD, c_off); | ||
312 | } | ||
313 | |||
314 | static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size) | ||
315 | { | ||
316 | musb_writeb(mbase, MUSB_RXFIFOSZ, c_size); | ||
317 | } | ||
318 | |||
319 | static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) | ||
320 | { | ||
321 | musb_writew(mbase, MUSB_RXFIFOADD, c_off); | ||
322 | } | ||
323 | |||
324 | static inline u8 musb_read_configdata(void __iomem *mbase) | ||
325 | { | ||
326 | return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA); | ||
327 | } | ||
328 | |||
329 | static inline u16 musb_read_hwvers(void __iomem *mbase) | ||
330 | { | ||
331 | return musb_readw(mbase, MUSB_HWVERS); | ||
332 | } | ||
333 | |||
334 | static inline void __iomem *musb_read_target_reg_base(u8 i, void __iomem *mbase) | ||
335 | { | ||
336 | return (MUSB_BUSCTL_OFFSET(i, 0) + mbase); | ||
337 | } | ||
338 | |||
339 | static inline void musb_write_rxfunaddr(void __iomem *ep_target_regs, | ||
340 | u8 qh_addr_reg) | ||
341 | { | ||
342 | musb_writeb(ep_target_regs, MUSB_RXFUNCADDR, qh_addr_reg); | ||
343 | } | ||
344 | |||
345 | static inline void musb_write_rxhubaddr(void __iomem *ep_target_regs, | ||
346 | u8 qh_h_addr_reg) | ||
347 | { | ||
348 | musb_writeb(ep_target_regs, MUSB_RXHUBADDR, qh_h_addr_reg); | ||
349 | } | ||
350 | |||
351 | static inline void musb_write_rxhubport(void __iomem *ep_target_regs, | ||
352 | u8 qh_h_port_reg) | ||
353 | { | ||
354 | musb_writeb(ep_target_regs, MUSB_RXHUBPORT, qh_h_port_reg); | ||
355 | } | ||
356 | |||
357 | static inline void musb_write_txfunaddr(void __iomem *mbase, u8 epnum, | ||
358 | u8 qh_addr_reg) | ||
359 | { | ||
360 | musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXFUNCADDR), | ||
361 | qh_addr_reg); | ||
362 | } | ||
363 | |||
364 | static inline void musb_write_txhubaddr(void __iomem *mbase, u8 epnum, | ||
365 | u8 qh_addr_reg) | ||
366 | { | ||
367 | musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBADDR), | ||
368 | qh_addr_reg); | ||
369 | } | ||
370 | |||
371 | static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum, | ||
372 | u8 qh_h_port_reg) | ||
373 | { | ||
374 | musb_writeb(mbase, MUSB_BUSCTL_OFFSET(epnum, MUSB_TXHUBPORT), | ||
375 | qh_h_port_reg); | ||
376 | } | ||
377 | |||
378 | #else /* CONFIG_BLACKFIN */ | ||
379 | |||
380 | #define USB_BASE USB_FADDR | ||
381 | #define USB_OFFSET(reg) (reg - USB_BASE) | ||
382 | |||
383 | /* | ||
384 | * Common USB registers | ||
385 | */ | ||
386 | #define MUSB_FADDR USB_OFFSET(USB_FADDR) /* 8-bit */ | ||
387 | #define MUSB_POWER USB_OFFSET(USB_POWER) /* 8-bit */ | ||
388 | #define MUSB_INTRTX USB_OFFSET(USB_INTRTX) /* 16-bit */ | ||
389 | #define MUSB_INTRRX USB_OFFSET(USB_INTRRX) | ||
390 | #define MUSB_INTRTXE USB_OFFSET(USB_INTRTXE) | ||
391 | #define MUSB_INTRRXE USB_OFFSET(USB_INTRRXE) | ||
392 | #define MUSB_INTRUSB USB_OFFSET(USB_INTRUSB) /* 8 bit */ | ||
393 | #define MUSB_INTRUSBE USB_OFFSET(USB_INTRUSBE)/* 8 bit */ | ||
394 | #define MUSB_FRAME USB_OFFSET(USB_FRAME) | ||
395 | #define MUSB_INDEX USB_OFFSET(USB_INDEX) /* 8 bit */ | ||
396 | #define MUSB_TESTMODE USB_OFFSET(USB_TESTMODE)/* 8 bit */ | ||
397 | |||
398 | /* Get offset for a given FIFO from musb->mregs */ | ||
399 | #define MUSB_FIFO_OFFSET(epnum) \ | ||
400 | (USB_OFFSET(USB_EP0_FIFO) + ((epnum) * 8)) | ||
401 | |||
402 | /* | ||
403 | * Additional Control Registers | ||
404 | */ | ||
405 | |||
406 | #define MUSB_DEVCTL USB_OFFSET(USB_OTG_DEV_CTL) /* 8 bit */ | ||
407 | |||
408 | #define MUSB_LINKINFO USB_OFFSET(USB_LINKINFO)/* 8 bit */ | ||
409 | #define MUSB_VPLEN USB_OFFSET(USB_VPLEN) /* 8 bit */ | ||
410 | #define MUSB_HS_EOF1 USB_OFFSET(USB_HS_EOF1) /* 8 bit */ | ||
411 | #define MUSB_FS_EOF1 USB_OFFSET(USB_FS_EOF1) /* 8 bit */ | ||
412 | #define MUSB_LS_EOF1 USB_OFFSET(USB_LS_EOF1) /* 8 bit */ | ||
413 | |||
414 | /* Offsets to endpoint registers */ | ||
415 | #define MUSB_TXMAXP 0x00 | ||
416 | #define MUSB_TXCSR 0x04 | ||
417 | #define MUSB_CSR0 MUSB_TXCSR /* Re-used for EP0 */ | ||
418 | #define MUSB_RXMAXP 0x08 | ||
419 | #define MUSB_RXCSR 0x0C | ||
420 | #define MUSB_RXCOUNT 0x10 | ||
421 | #define MUSB_COUNT0 MUSB_RXCOUNT /* Re-used for EP0 */ | ||
422 | #define MUSB_TXTYPE 0x14 | ||
423 | #define MUSB_TYPE0 MUSB_TXTYPE /* Re-used for EP0 */ | ||
424 | #define MUSB_TXINTERVAL 0x18 | ||
425 | #define MUSB_NAKLIMIT0 MUSB_TXINTERVAL /* Re-used for EP0 */ | ||
426 | #define MUSB_RXTYPE 0x1C | ||
427 | #define MUSB_RXINTERVAL 0x20 | ||
428 | #define MUSB_TXCOUNT 0x28 | ||
429 | |||
430 | /* Offsets to endpoint registers in indexed model (using INDEX register) */ | ||
431 | #define MUSB_INDEXED_OFFSET(_epnum, _offset) \ | ||
432 | (0x40 + (_offset)) | ||
433 | |||
434 | /* Offsets to endpoint registers in flat models */ | ||
435 | #define MUSB_FLAT_OFFSET(_epnum, _offset) \ | ||
436 | (USB_OFFSET(USB_EP_NI0_TXMAXP) + (0x40 * (_epnum)) + (_offset)) | ||
437 | |||
438 | /* Not implemented - HW has seperate Tx/Rx FIFO */ | ||
439 | #define MUSB_TXCSR_MODE 0x0000 | ||
440 | |||
441 | /* | ||
442 | * Dummy stub for clk framework, it will be removed | ||
443 | * until Blackfin supports clk framework | ||
444 | */ | ||
445 | #define clk_get(dev, id) NULL | ||
446 | #define clk_put(clock) do {} while (0) | ||
447 | #define clk_enable(clock) do {} while (0) | ||
448 | #define clk_disable(clock) do {} while (0) | ||
449 | |||
450 | static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size) | ||
451 | { | ||
452 | } | ||
453 | |||
454 | static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off) | ||
455 | { | ||
456 | } | ||
457 | |||
458 | static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size) | ||
459 | { | ||
460 | } | ||
461 | |||
462 | static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) | ||
463 | { | ||
464 | } | ||
465 | |||
466 | static inline u8 musb_read_configdata(void __iomem *mbase) | ||
467 | { | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static inline u16 musb_read_hwvers(void __iomem *mbase) | ||
472 | { | ||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static inline u16 musb_read_target_reg_base(u8 i, void __iomem *mbase) | ||
477 | { | ||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static inline void musb_write_rxfunaddr(void __iomem *ep_target_regs, | ||
482 | u8 qh_addr_req) | ||
483 | { | ||
484 | } | ||
485 | |||
486 | static inline void musb_write_rxhubaddr(void __iomem *ep_target_regs, | ||
487 | u8 qh_h_addr_reg) | ||
488 | { | ||
489 | } | ||
490 | |||
491 | static inline void musb_write_rxhubport(void __iomem *ep_target_regs, | ||
492 | u8 qh_h_port_reg) | ||
493 | { | ||
494 | } | ||
495 | |||
496 | static inline void musb_write_txfunaddr(void __iomem *mbase, u8 epnum, | ||
497 | u8 qh_addr_reg) | ||
498 | { | ||
499 | } | ||
500 | |||
501 | static inline void musb_write_txhubaddr(void __iomem *mbase, u8 epnum, | ||
502 | u8 qh_addr_reg) | ||
503 | { | ||
504 | } | ||
505 | |||
506 | static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum, | ||
507 | u8 qh_h_port_reg) | ||
508 | { | ||
509 | } | ||
510 | |||
511 | #endif /* CONFIG_BLACKFIN */ | ||
512 | |||
300 | #endif /* __MUSB_REGS_H__ */ | 513 | #endif /* __MUSB_REGS_H__ */ |
diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 8c734ef2c1ed..8662e9e159c3 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c | |||
@@ -34,58 +34,7 @@ | |||
34 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
35 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
36 | #include "musb_core.h" | 36 | #include "musb_core.h" |
37 | 37 | #include "musbhsdma.h" | |
38 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) | ||
39 | #include "omap2430.h" | ||
40 | #endif | ||
41 | |||
42 | #define MUSB_HSDMA_BASE 0x200 | ||
43 | #define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) | ||
44 | #define MUSB_HSDMA_CONTROL 0x4 | ||
45 | #define MUSB_HSDMA_ADDRESS 0x8 | ||
46 | #define MUSB_HSDMA_COUNT 0xc | ||
47 | |||
48 | #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ | ||
49 | (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) | ||
50 | |||
51 | /* control register (16-bit): */ | ||
52 | #define MUSB_HSDMA_ENABLE_SHIFT 0 | ||
53 | #define MUSB_HSDMA_TRANSMIT_SHIFT 1 | ||
54 | #define MUSB_HSDMA_MODE1_SHIFT 2 | ||
55 | #define MUSB_HSDMA_IRQENABLE_SHIFT 3 | ||
56 | #define MUSB_HSDMA_ENDPOINT_SHIFT 4 | ||
57 | #define MUSB_HSDMA_BUSERROR_SHIFT 8 | ||
58 | #define MUSB_HSDMA_BURSTMODE_SHIFT 9 | ||
59 | #define MUSB_HSDMA_BURSTMODE (3 << MUSB_HSDMA_BURSTMODE_SHIFT) | ||
60 | #define MUSB_HSDMA_BURSTMODE_UNSPEC 0 | ||
61 | #define MUSB_HSDMA_BURSTMODE_INCR4 1 | ||
62 | #define MUSB_HSDMA_BURSTMODE_INCR8 2 | ||
63 | #define MUSB_HSDMA_BURSTMODE_INCR16 3 | ||
64 | |||
65 | #define MUSB_HSDMA_CHANNELS 8 | ||
66 | |||
67 | struct musb_dma_controller; | ||
68 | |||
69 | struct musb_dma_channel { | ||
70 | struct dma_channel channel; | ||
71 | struct musb_dma_controller *controller; | ||
72 | u32 start_addr; | ||
73 | u32 len; | ||
74 | u16 max_packet_sz; | ||
75 | u8 idx; | ||
76 | u8 epnum; | ||
77 | u8 transmit; | ||
78 | }; | ||
79 | |||
80 | struct musb_dma_controller { | ||
81 | struct dma_controller controller; | ||
82 | struct musb_dma_channel channel[MUSB_HSDMA_CHANNELS]; | ||
83 | void *private_data; | ||
84 | void __iomem *base; | ||
85 | u8 channel_count; | ||
86 | u8 used_channels; | ||
87 | u8 irq; | ||
88 | }; | ||
89 | 38 | ||
90 | static int dma_controller_start(struct dma_controller *c) | 39 | static int dma_controller_start(struct dma_controller *c) |
91 | { | 40 | { |
@@ -203,12 +152,8 @@ static void configure_channel(struct dma_channel *channel, | |||
203 | : 0); | 152 | : 0); |
204 | 153 | ||
205 | /* address/count */ | 154 | /* address/count */ |
206 | musb_writel(mbase, | 155 | musb_write_hsdma_addr(mbase, bchannel, dma_addr); |
207 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), | 156 | musb_write_hsdma_count(mbase, bchannel, len); |
208 | dma_addr); | ||
209 | musb_writel(mbase, | ||
210 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), | ||
211 | len); | ||
212 | 157 | ||
213 | /* control (this should start things) */ | 158 | /* control (this should start things) */ |
214 | musb_writew(mbase, | 159 | musb_writew(mbase, |
@@ -279,13 +224,8 @@ static int dma_channel_abort(struct dma_channel *channel) | |||
279 | musb_writew(mbase, | 224 | musb_writew(mbase, |
280 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), | 225 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), |
281 | 0); | 226 | 0); |
282 | musb_writel(mbase, | 227 | musb_write_hsdma_addr(mbase, bchannel, 0); |
283 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), | 228 | musb_write_hsdma_count(mbase, bchannel, 0); |
284 | 0); | ||
285 | musb_writel(mbase, | ||
286 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), | ||
287 | 0); | ||
288 | |||
289 | channel->status = MUSB_DMA_STATUS_FREE; | 229 | channel->status = MUSB_DMA_STATUS_FREE; |
290 | } | 230 | } |
291 | 231 | ||
@@ -333,10 +273,8 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) | |||
333 | } else { | 273 | } else { |
334 | u8 devctl; | 274 | u8 devctl; |
335 | 275 | ||
336 | addr = musb_readl(mbase, | 276 | addr = musb_read_hsdma_addr(mbase, |
337 | MUSB_HSDMA_CHANNEL_OFFSET( | 277 | bchannel); |
338 | bchannel, | ||
339 | MUSB_HSDMA_ADDRESS)); | ||
340 | channel->actual_len = addr | 278 | channel->actual_len = addr |
341 | - musb_channel->start_addr; | 279 | - musb_channel->start_addr; |
342 | 280 | ||
@@ -375,6 +313,12 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) | |||
375 | } | 313 | } |
376 | } | 314 | } |
377 | } | 315 | } |
316 | |||
317 | #ifdef CONFIG_BLACKFIN | ||
318 | /* Clear DMA interrup flags */ | ||
319 | musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma); | ||
320 | #endif | ||
321 | |||
378 | retval = IRQ_HANDLED; | 322 | retval = IRQ_HANDLED; |
379 | done: | 323 | done: |
380 | spin_unlock_irqrestore(&musb->lock, flags); | 324 | spin_unlock_irqrestore(&musb->lock, flags); |
@@ -424,7 +368,7 @@ dma_controller_create(struct musb *musb, void __iomem *base) | |||
424 | controller->controller.channel_abort = dma_channel_abort; | 368 | controller->controller.channel_abort = dma_channel_abort; |
425 | 369 | ||
426 | if (request_irq(irq, dma_controller_irq, IRQF_DISABLED, | 370 | if (request_irq(irq, dma_controller_irq, IRQF_DISABLED, |
427 | musb->controller->bus_id, &controller->controller)) { | 371 | dev_name(musb->controller), &controller->controller)) { |
428 | dev_err(dev, "request_irq %d failed!\n", irq); | 372 | dev_err(dev, "request_irq %d failed!\n", irq); |
429 | dma_controller_destroy(&controller->controller); | 373 | dma_controller_destroy(&controller->controller); |
430 | 374 | ||
diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h new file mode 100644 index 000000000000..1299d92dc83f --- /dev/null +++ b/drivers/usb/musb/musbhsdma.h | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * MUSB OTG driver - support for Mentor's DMA controller | ||
3 | * | ||
4 | * Copyright 2005 Mentor Graphics Corporation | ||
5 | * Copyright (C) 2005-2007 by Texas Instruments | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | * | ||
21 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED | ||
22 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
23 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
24 | * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
27 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
28 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) | ||
35 | #include "omap2430.h" | ||
36 | #endif | ||
37 | |||
38 | #ifndef CONFIG_BLACKFIN | ||
39 | |||
40 | #define MUSB_HSDMA_BASE 0x200 | ||
41 | #define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) | ||
42 | #define MUSB_HSDMA_CONTROL 0x4 | ||
43 | #define MUSB_HSDMA_ADDRESS 0x8 | ||
44 | #define MUSB_HSDMA_COUNT 0xc | ||
45 | |||
46 | #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ | ||
47 | (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) | ||
48 | |||
49 | #define musb_read_hsdma_addr(mbase, bchannel) \ | ||
50 | musb_readl(mbase, \ | ||
51 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS)) | ||
52 | |||
53 | #define musb_write_hsdma_addr(mbase, bchannel, addr) \ | ||
54 | musb_writel(mbase, \ | ||
55 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), \ | ||
56 | addr) | ||
57 | |||
58 | #define musb_write_hsdma_count(mbase, bchannel, len) \ | ||
59 | musb_writel(mbase, \ | ||
60 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \ | ||
61 | len) | ||
62 | #else | ||
63 | |||
64 | #define MUSB_HSDMA_BASE 0x400 | ||
65 | #define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) | ||
66 | #define MUSB_HSDMA_CONTROL 0x04 | ||
67 | #define MUSB_HSDMA_ADDR_LOW 0x08 | ||
68 | #define MUSB_HSDMA_ADDR_HIGH 0x0C | ||
69 | #define MUSB_HSDMA_COUNT_LOW 0x10 | ||
70 | #define MUSB_HSDMA_COUNT_HIGH 0x14 | ||
71 | |||
72 | #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ | ||
73 | (MUSB_HSDMA_BASE + (_bchannel * 0x20) + _offset) | ||
74 | |||
75 | static inline u32 musb_read_hsdma_addr(void __iomem *mbase, u8 bchannel) | ||
76 | { | ||
77 | u32 addr = musb_readw(mbase, | ||
78 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_HIGH)); | ||
79 | |||
80 | addr = addr << 16; | ||
81 | |||
82 | addr |= musb_readw(mbase, | ||
83 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_LOW)); | ||
84 | |||
85 | return addr; | ||
86 | } | ||
87 | |||
88 | static inline void musb_write_hsdma_addr(void __iomem *mbase, | ||
89 | u8 bchannel, dma_addr_t dma_addr) | ||
90 | { | ||
91 | musb_writew(mbase, | ||
92 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_LOW), | ||
93 | ((u16)((u32) dma_addr & 0xFFFF))); | ||
94 | musb_writew(mbase, | ||
95 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDR_HIGH), | ||
96 | ((u16)(((u32) dma_addr >> 16) & 0xFFFF))); | ||
97 | } | ||
98 | |||
99 | static inline void musb_write_hsdma_count(void __iomem *mbase, | ||
100 | u8 bchannel, u32 len) | ||
101 | { | ||
102 | musb_writew(mbase, | ||
103 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_LOW), | ||
104 | ((u16)((u32) len & 0xFFFF))); | ||
105 | musb_writew(mbase, | ||
106 | MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT_HIGH), | ||
107 | ((u16)(((u32) len >> 16) & 0xFFFF))); | ||
108 | } | ||
109 | |||
110 | #endif /* CONFIG_BLACKFIN */ | ||
111 | |||
112 | /* control register (16-bit): */ | ||
113 | #define MUSB_HSDMA_ENABLE_SHIFT 0 | ||
114 | #define MUSB_HSDMA_TRANSMIT_SHIFT 1 | ||
115 | #define MUSB_HSDMA_MODE1_SHIFT 2 | ||
116 | #define MUSB_HSDMA_IRQENABLE_SHIFT 3 | ||
117 | #define MUSB_HSDMA_ENDPOINT_SHIFT 4 | ||
118 | #define MUSB_HSDMA_BUSERROR_SHIFT 8 | ||
119 | #define MUSB_HSDMA_BURSTMODE_SHIFT 9 | ||
120 | #define MUSB_HSDMA_BURSTMODE (3 << MUSB_HSDMA_BURSTMODE_SHIFT) | ||
121 | #define MUSB_HSDMA_BURSTMODE_UNSPEC 0 | ||
122 | #define MUSB_HSDMA_BURSTMODE_INCR4 1 | ||
123 | #define MUSB_HSDMA_BURSTMODE_INCR8 2 | ||
124 | #define MUSB_HSDMA_BURSTMODE_INCR16 3 | ||
125 | |||
126 | #define MUSB_HSDMA_CHANNELS 8 | ||
127 | |||
128 | struct musb_dma_controller; | ||
129 | |||
130 | struct musb_dma_channel { | ||
131 | struct dma_channel channel; | ||
132 | struct musb_dma_controller *controller; | ||
133 | u32 start_addr; | ||
134 | u32 len; | ||
135 | u16 max_packet_sz; | ||
136 | u8 idx; | ||
137 | u8 epnum; | ||
138 | u8 transmit; | ||
139 | }; | ||
140 | |||
141 | struct musb_dma_controller { | ||
142 | struct dma_controller controller; | ||
143 | struct musb_dma_channel channel[MUSB_HSDMA_CHANNELS]; | ||
144 | void *private_data; | ||
145 | void __iomem *base; | ||
146 | u8 channel_count; | ||
147 | u8 used_channels; | ||
148 | u8 irq; | ||
149 | }; | ||
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index ce6c162920f7..901dffdf23b1 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c | |||
@@ -58,10 +58,10 @@ static void musb_do_idle(unsigned long _musb) | |||
58 | #endif | 58 | #endif |
59 | u8 devctl; | 59 | u8 devctl; |
60 | 60 | ||
61 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
62 | |||
63 | spin_lock_irqsave(&musb->lock, flags); | 61 | spin_lock_irqsave(&musb->lock, flags); |
64 | 62 | ||
63 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
64 | |||
65 | switch (musb->xceiv.state) { | 65 | switch (musb->xceiv.state) { |
66 | case OTG_STATE_A_WAIT_BCON: | 66 | case OTG_STATE_A_WAIT_BCON: |
67 | devctl &= ~MUSB_DEVCTL_SESSION; | 67 | devctl &= ~MUSB_DEVCTL_SESSION; |
@@ -196,7 +196,7 @@ static int omap_set_power(struct otg_transceiver *x, unsigned mA) | |||
196 | 196 | ||
197 | static int musb_platform_resume(struct musb *musb); | 197 | static int musb_platform_resume(struct musb *musb); |
198 | 198 | ||
199 | void musb_platform_set_mode(struct musb *musb, u8 musb_mode) | 199 | int musb_platform_set_mode(struct musb *musb, u8 musb_mode) |
200 | { | 200 | { |
201 | u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | 201 | u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL); |
202 | 202 | ||
@@ -204,15 +204,24 @@ void musb_platform_set_mode(struct musb *musb, u8 musb_mode) | |||
204 | musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); | 204 | musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); |
205 | 205 | ||
206 | switch (musb_mode) { | 206 | switch (musb_mode) { |
207 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
207 | case MUSB_HOST: | 208 | case MUSB_HOST: |
208 | otg_set_host(&musb->xceiv, musb->xceiv.host); | 209 | otg_set_host(&musb->xceiv, musb->xceiv.host); |
209 | break; | 210 | break; |
211 | #endif | ||
212 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
210 | case MUSB_PERIPHERAL: | 213 | case MUSB_PERIPHERAL: |
211 | otg_set_peripheral(&musb->xceiv, musb->xceiv.gadget); | 214 | otg_set_peripheral(&musb->xceiv, musb->xceiv.gadget); |
212 | break; | 215 | break; |
216 | #endif | ||
217 | #ifdef CONFIG_USB_MUSB_OTG | ||
213 | case MUSB_OTG: | 218 | case MUSB_OTG: |
214 | break; | 219 | break; |
220 | #endif | ||
221 | default: | ||
222 | return -EINVAL; | ||
215 | } | 223 | } |
224 | return 0; | ||
216 | } | 225 | } |
217 | 226 | ||
218 | int __init musb_platform_init(struct musb *musb) | 227 | int __init musb_platform_init(struct musb *musb) |
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index ee8fca92a4ac..9e20fd070d71 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c | |||
@@ -598,7 +598,7 @@ static void tusb_source_power(struct musb *musb, int is_on) | |||
598 | * and peripheral modes in non-OTG configurations by reconfiguring hardware | 598 | * and peripheral modes in non-OTG configurations by reconfiguring hardware |
599 | * and then setting musb->board_mode. For now, only support OTG mode. | 599 | * and then setting musb->board_mode. For now, only support OTG mode. |
600 | */ | 600 | */ |
601 | void musb_platform_set_mode(struct musb *musb, u8 musb_mode) | 601 | int musb_platform_set_mode(struct musb *musb, u8 musb_mode) |
602 | { | 602 | { |
603 | void __iomem *tbase = musb->ctrl_base; | 603 | void __iomem *tbase = musb->ctrl_base; |
604 | u32 otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf; | 604 | u32 otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf; |
@@ -641,7 +641,8 @@ void musb_platform_set_mode(struct musb *musb, u8 musb_mode) | |||
641 | #endif | 641 | #endif |
642 | 642 | ||
643 | default: | 643 | default: |
644 | DBG(2, "Trying to set unknown mode %i\n", musb_mode); | 644 | DBG(2, "Trying to set mode %i\n", musb_mode); |
645 | return -EINVAL; | ||
645 | } | 646 | } |
646 | 647 | ||
647 | musb_writel(tbase, TUSB_PHY_OTG_CTRL, | 648 | musb_writel(tbase, TUSB_PHY_OTG_CTRL, |
@@ -655,6 +656,8 @@ void musb_platform_set_mode(struct musb *musb, u8 musb_mode) | |||
655 | !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) | 656 | !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) |
656 | INFO("Cannot be peripheral with mini-A cable " | 657 | INFO("Cannot be peripheral with mini-A cable " |
657 | "otg_stat: %08x\n", otg_stat); | 658 | "otg_stat: %08x\n", otg_stat); |
659 | |||
660 | return 0; | ||
658 | } | 661 | } |
659 | 662 | ||
660 | static inline unsigned long | 663 | static inline unsigned long |
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig new file mode 100644 index 000000000000..8e8dbdb9b39b --- /dev/null +++ b/drivers/usb/otg/Kconfig | |||
@@ -0,0 +1,54 @@ | |||
1 | # | ||
2 | # USB OTG infrastructure may be needed for peripheral-only, host-only, | ||
3 | # or OTG-capable configurations when OTG transceivers or controllers | ||
4 | # are used. | ||
5 | # | ||
6 | |||
7 | comment "OTG and related infrastructure" | ||
8 | |||
9 | if USB || USB_GADGET | ||
10 | |||
11 | config USB_OTG_UTILS | ||
12 | bool | ||
13 | help | ||
14 | Select this to make sure the build includes objects from | ||
15 | the OTG infrastructure directory. | ||
16 | |||
17 | # | ||
18 | # USB Transceiver Drivers | ||
19 | # | ||
20 | config USB_GPIO_VBUS | ||
21 | tristate "GPIO based peripheral-only VBUS sensing 'transceiver'" | ||
22 | depends on GENERIC_GPIO | ||
23 | select USB_OTG_UTILS | ||
24 | help | ||
25 | Provides simple GPIO VBUS sensing for controllers with an | ||
26 | internal transceiver via the otg_transceiver interface, and | ||
27 | optionally control of a D+ pullup GPIO as well as a VBUS | ||
28 | current limit regulator. | ||
29 | |||
30 | config ISP1301_OMAP | ||
31 | tristate "Philips ISP1301 with OMAP OTG" | ||
32 | depends on I2C && ARCH_OMAP_OTG | ||
33 | select USB_OTG_UTILS | ||
34 | help | ||
35 | If you say yes here you get support for the Philips ISP1301 | ||
36 | USB-On-The-Go transceiver working with the OMAP OTG controller. | ||
37 | The ISP1301 is a full speed USB transceiver which is used in | ||
38 | products including H2, H3, and H4 development boards for Texas | ||
39 | Instruments OMAP processors. | ||
40 | |||
41 | This driver can also be built as a module. If so, the module | ||
42 | will be called isp1301_omap. | ||
43 | |||
44 | config TWL4030_USB | ||
45 | tristate "TWL4030 USB Transceiver Driver" | ||
46 | depends on TWL4030_CORE | ||
47 | select USB_OTG_UTILS | ||
48 | help | ||
49 | Enable this to support the USB OTG transceiver on TWL4030 | ||
50 | family chips (including the TWL5030 and TPS659x0 devices). | ||
51 | This transceiver supports high and full speed devices plus, | ||
52 | in host mode, low speed. | ||
53 | |||
54 | endif # USB || OTG | ||
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile new file mode 100644 index 000000000000..d73c7cf5e2f7 --- /dev/null +++ b/drivers/usb/otg/Makefile | |||
@@ -0,0 +1,15 @@ | |||
1 | # | ||
2 | # OTG infrastructure and transceiver drivers | ||
3 | # | ||
4 | |||
5 | # infrastructure | ||
6 | obj-$(CONFIG_USB_OTG_UTILS) += otg.o | ||
7 | |||
8 | # transceiver drivers | ||
9 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o | ||
10 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o | ||
11 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o | ||
12 | |||
13 | ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG | ||
14 | ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG | ||
15 | |||
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c new file mode 100644 index 000000000000..63a6036f04be --- /dev/null +++ b/drivers/usb/otg/gpio_vbus.c | |||
@@ -0,0 +1,335 @@ | |||
1 | /* | ||
2 | * gpio-vbus.c - simple GPIO VBUS sensing driver for B peripheral devices | ||
3 | * | ||
4 | * Copyright (c) 2008 Philipp Zabel <philipp.zabel@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/usb.h> | ||
16 | |||
17 | #include <linux/regulator/consumer.h> | ||
18 | |||
19 | #include <linux/usb/gadget.h> | ||
20 | #include <linux/usb/gpio_vbus.h> | ||
21 | #include <linux/usb/otg.h> | ||
22 | |||
23 | |||
24 | /* | ||
25 | * A simple GPIO VBUS sensing driver for B peripheral only devices | ||
26 | * with internal transceivers. It can control a D+ pullup GPIO and | ||
27 | * a regulator to limit the current drawn from VBUS. | ||
28 | * | ||
29 | * Needs to be loaded before the UDC driver that will use it. | ||
30 | */ | ||
31 | struct gpio_vbus_data { | ||
32 | struct otg_transceiver otg; | ||
33 | struct device *dev; | ||
34 | struct regulator *vbus_draw; | ||
35 | int vbus_draw_enabled; | ||
36 | unsigned mA; | ||
37 | }; | ||
38 | |||
39 | |||
40 | /* | ||
41 | * This driver relies on "both edges" triggering. VBUS has 100 msec to | ||
42 | * stabilize, so the peripheral controller driver may need to cope with | ||
43 | * some bouncing due to current surges (e.g. charging local capacitance) | ||
44 | * and contact chatter. | ||
45 | * | ||
46 | * REVISIT in desperate straits, toggling between rising and falling | ||
47 | * edges might be workable. | ||
48 | */ | ||
49 | #define VBUS_IRQ_FLAGS \ | ||
50 | ( IRQF_SAMPLE_RANDOM | IRQF_SHARED \ | ||
51 | | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING ) | ||
52 | |||
53 | |||
54 | /* interface to regulator framework */ | ||
55 | static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA) | ||
56 | { | ||
57 | struct regulator *vbus_draw = gpio_vbus->vbus_draw; | ||
58 | int enabled; | ||
59 | |||
60 | if (!vbus_draw) | ||
61 | return; | ||
62 | |||
63 | enabled = gpio_vbus->vbus_draw_enabled; | ||
64 | if (mA) { | ||
65 | regulator_set_current_limit(vbus_draw, 0, 1000 * mA); | ||
66 | if (!enabled) { | ||
67 | regulator_enable(vbus_draw); | ||
68 | gpio_vbus->vbus_draw_enabled = 1; | ||
69 | } | ||
70 | } else { | ||
71 | if (enabled) { | ||
72 | regulator_disable(vbus_draw); | ||
73 | gpio_vbus->vbus_draw_enabled = 0; | ||
74 | } | ||
75 | } | ||
76 | gpio_vbus->mA = mA; | ||
77 | } | ||
78 | |||
79 | /* VBUS change IRQ handler */ | ||
80 | static irqreturn_t gpio_vbus_irq(int irq, void *data) | ||
81 | { | ||
82 | struct platform_device *pdev = data; | ||
83 | struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; | ||
84 | struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); | ||
85 | int gpio, vbus; | ||
86 | |||
87 | vbus = gpio_get_value(pdata->gpio_vbus); | ||
88 | if (pdata->gpio_vbus_inverted) | ||
89 | vbus = !vbus; | ||
90 | |||
91 | dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", | ||
92 | vbus ? "supplied" : "inactive", | ||
93 | gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); | ||
94 | |||
95 | if (!gpio_vbus->otg.gadget) | ||
96 | return IRQ_HANDLED; | ||
97 | |||
98 | /* Peripheral controllers which manage the pullup themselves won't have | ||
99 | * gpio_pullup configured here. If it's configured here, we'll do what | ||
100 | * isp1301_omap::b_peripheral() does and enable the pullup here... although | ||
101 | * that may complicate usb_gadget_{,dis}connect() support. | ||
102 | */ | ||
103 | gpio = pdata->gpio_pullup; | ||
104 | if (vbus) { | ||
105 | gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL; | ||
106 | usb_gadget_vbus_connect(gpio_vbus->otg.gadget); | ||
107 | |||
108 | /* drawing a "unit load" is *always* OK, except for OTG */ | ||
109 | set_vbus_draw(gpio_vbus, 100); | ||
110 | |||
111 | /* optionally enable D+ pullup */ | ||
112 | if (gpio_is_valid(gpio)) | ||
113 | gpio_set_value(gpio, !pdata->gpio_pullup_inverted); | ||
114 | } else { | ||
115 | /* optionally disable D+ pullup */ | ||
116 | if (gpio_is_valid(gpio)) | ||
117 | gpio_set_value(gpio, pdata->gpio_pullup_inverted); | ||
118 | |||
119 | set_vbus_draw(gpio_vbus, 0); | ||
120 | |||
121 | usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget); | ||
122 | gpio_vbus->otg.state = OTG_STATE_B_IDLE; | ||
123 | } | ||
124 | |||
125 | return IRQ_HANDLED; | ||
126 | } | ||
127 | |||
128 | /* OTG transceiver interface */ | ||
129 | |||
130 | /* bind/unbind the peripheral controller */ | ||
131 | static int gpio_vbus_set_peripheral(struct otg_transceiver *otg, | ||
132 | struct usb_gadget *gadget) | ||
133 | { | ||
134 | struct gpio_vbus_data *gpio_vbus; | ||
135 | struct gpio_vbus_mach_info *pdata; | ||
136 | struct platform_device *pdev; | ||
137 | int gpio, irq; | ||
138 | |||
139 | gpio_vbus = container_of(otg, struct gpio_vbus_data, otg); | ||
140 | pdev = to_platform_device(gpio_vbus->dev); | ||
141 | pdata = gpio_vbus->dev->platform_data; | ||
142 | irq = gpio_to_irq(pdata->gpio_vbus); | ||
143 | gpio = pdata->gpio_pullup; | ||
144 | |||
145 | if (!gadget) { | ||
146 | dev_dbg(&pdev->dev, "unregistering gadget '%s'\n", | ||
147 | otg->gadget->name); | ||
148 | |||
149 | /* optionally disable D+ pullup */ | ||
150 | if (gpio_is_valid(gpio)) | ||
151 | gpio_set_value(gpio, pdata->gpio_pullup_inverted); | ||
152 | |||
153 | set_vbus_draw(gpio_vbus, 0); | ||
154 | |||
155 | usb_gadget_vbus_disconnect(otg->gadget); | ||
156 | otg->state = OTG_STATE_UNDEFINED; | ||
157 | |||
158 | otg->gadget = NULL; | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | otg->gadget = gadget; | ||
163 | dev_dbg(&pdev->dev, "registered gadget '%s'\n", gadget->name); | ||
164 | |||
165 | /* initialize connection state */ | ||
166 | gpio_vbus_irq(irq, pdev); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | /* effective for B devices, ignored for A-peripheral */ | ||
171 | static int gpio_vbus_set_power(struct otg_transceiver *otg, unsigned mA) | ||
172 | { | ||
173 | struct gpio_vbus_data *gpio_vbus; | ||
174 | |||
175 | gpio_vbus = container_of(otg, struct gpio_vbus_data, otg); | ||
176 | |||
177 | if (otg->state == OTG_STATE_B_PERIPHERAL) | ||
178 | set_vbus_draw(gpio_vbus, mA); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | /* for non-OTG B devices: set/clear transceiver suspend mode */ | ||
183 | static int gpio_vbus_set_suspend(struct otg_transceiver *otg, int suspend) | ||
184 | { | ||
185 | struct gpio_vbus_data *gpio_vbus; | ||
186 | |||
187 | gpio_vbus = container_of(otg, struct gpio_vbus_data, otg); | ||
188 | |||
189 | /* draw max 0 mA from vbus in suspend mode; or the previously | ||
190 | * recorded amount of current if not suspended | ||
191 | * | ||
192 | * NOTE: high powered configs (mA > 100) may draw up to 2.5 mA | ||
193 | * if they're wake-enabled ... we don't handle that yet. | ||
194 | */ | ||
195 | return gpio_vbus_set_power(otg, suspend ? 0 : gpio_vbus->mA); | ||
196 | } | ||
197 | |||
198 | /* platform driver interface */ | ||
199 | |||
200 | static int __init gpio_vbus_probe(struct platform_device *pdev) | ||
201 | { | ||
202 | struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; | ||
203 | struct gpio_vbus_data *gpio_vbus; | ||
204 | struct resource *res; | ||
205 | int err, gpio, irq; | ||
206 | |||
207 | if (!pdata || !gpio_is_valid(pdata->gpio_vbus)) | ||
208 | return -EINVAL; | ||
209 | gpio = pdata->gpio_vbus; | ||
210 | |||
211 | gpio_vbus = kzalloc(sizeof(struct gpio_vbus_data), GFP_KERNEL); | ||
212 | if (!gpio_vbus) | ||
213 | return -ENOMEM; | ||
214 | |||
215 | platform_set_drvdata(pdev, gpio_vbus); | ||
216 | gpio_vbus->dev = &pdev->dev; | ||
217 | gpio_vbus->otg.label = "gpio-vbus"; | ||
218 | gpio_vbus->otg.state = OTG_STATE_UNDEFINED; | ||
219 | gpio_vbus->otg.set_peripheral = gpio_vbus_set_peripheral; | ||
220 | gpio_vbus->otg.set_power = gpio_vbus_set_power; | ||
221 | gpio_vbus->otg.set_suspend = gpio_vbus_set_suspend; | ||
222 | |||
223 | err = gpio_request(gpio, "vbus_detect"); | ||
224 | if (err) { | ||
225 | dev_err(&pdev->dev, "can't request vbus gpio %d, err: %d\n", | ||
226 | gpio, err); | ||
227 | goto err_gpio; | ||
228 | } | ||
229 | gpio_direction_input(gpio); | ||
230 | |||
231 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
232 | if (res) { | ||
233 | irq = res->start; | ||
234 | res->flags &= IRQF_TRIGGER_MASK; | ||
235 | res->flags |= IRQF_SAMPLE_RANDOM | IRQF_SHARED; | ||
236 | } else | ||
237 | irq = gpio_to_irq(gpio); | ||
238 | |||
239 | /* if data line pullup is in use, initialize it to "not pulling up" */ | ||
240 | gpio = pdata->gpio_pullup; | ||
241 | if (gpio_is_valid(gpio)) { | ||
242 | err = gpio_request(gpio, "udc_pullup"); | ||
243 | if (err) { | ||
244 | dev_err(&pdev->dev, | ||
245 | "can't request pullup gpio %d, err: %d\n", | ||
246 | gpio, err); | ||
247 | gpio_free(pdata->gpio_vbus); | ||
248 | goto err_gpio; | ||
249 | } | ||
250 | gpio_direction_output(gpio, pdata->gpio_pullup_inverted); | ||
251 | } | ||
252 | |||
253 | err = request_irq(irq, gpio_vbus_irq, VBUS_IRQ_FLAGS, | ||
254 | "vbus_detect", pdev); | ||
255 | if (err) { | ||
256 | dev_err(&pdev->dev, "can't request irq %i, err: %d\n", | ||
257 | irq, err); | ||
258 | goto err_irq; | ||
259 | } | ||
260 | |||
261 | /* only active when a gadget is registered */ | ||
262 | err = otg_set_transceiver(&gpio_vbus->otg); | ||
263 | if (err) { | ||
264 | dev_err(&pdev->dev, "can't register transceiver, err: %d\n", | ||
265 | err); | ||
266 | goto err_otg; | ||
267 | } | ||
268 | |||
269 | gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw"); | ||
270 | if (IS_ERR(gpio_vbus->vbus_draw)) { | ||
271 | dev_dbg(&pdev->dev, "can't get vbus_draw regulator, err: %ld\n", | ||
272 | PTR_ERR(gpio_vbus->vbus_draw)); | ||
273 | gpio_vbus->vbus_draw = NULL; | ||
274 | } | ||
275 | |||
276 | return 0; | ||
277 | err_otg: | ||
278 | free_irq(irq, &pdev->dev); | ||
279 | err_irq: | ||
280 | if (gpio_is_valid(pdata->gpio_pullup)) | ||
281 | gpio_free(pdata->gpio_pullup); | ||
282 | gpio_free(pdata->gpio_vbus); | ||
283 | err_gpio: | ||
284 | platform_set_drvdata(pdev, NULL); | ||
285 | kfree(gpio_vbus); | ||
286 | return err; | ||
287 | } | ||
288 | |||
289 | static int __exit gpio_vbus_remove(struct platform_device *pdev) | ||
290 | { | ||
291 | struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); | ||
292 | struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; | ||
293 | int gpio = pdata->gpio_vbus; | ||
294 | |||
295 | regulator_put(gpio_vbus->vbus_draw); | ||
296 | |||
297 | otg_set_transceiver(NULL); | ||
298 | |||
299 | free_irq(gpio_to_irq(gpio), &pdev->dev); | ||
300 | if (gpio_is_valid(pdata->gpio_pullup)) | ||
301 | gpio_free(pdata->gpio_pullup); | ||
302 | gpio_free(gpio); | ||
303 | platform_set_drvdata(pdev, NULL); | ||
304 | kfree(gpio_vbus); | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | /* NOTE: the gpio-vbus device may *NOT* be hotplugged */ | ||
310 | |||
311 | MODULE_ALIAS("platform:gpio-vbus"); | ||
312 | |||
313 | static struct platform_driver gpio_vbus_driver = { | ||
314 | .driver = { | ||
315 | .name = "gpio-vbus", | ||
316 | .owner = THIS_MODULE, | ||
317 | }, | ||
318 | .remove = __exit_p(gpio_vbus_remove), | ||
319 | }; | ||
320 | |||
321 | static int __init gpio_vbus_init(void) | ||
322 | { | ||
323 | return platform_driver_probe(&gpio_vbus_driver, gpio_vbus_probe); | ||
324 | } | ||
325 | module_init(gpio_vbus_init); | ||
326 | |||
327 | static void __exit gpio_vbus_exit(void) | ||
328 | { | ||
329 | platform_driver_unregister(&gpio_vbus_driver); | ||
330 | } | ||
331 | module_exit(gpio_vbus_exit); | ||
332 | |||
333 | MODULE_DESCRIPTION("simple GPIO controlled OTG transceiver driver"); | ||
334 | MODULE_AUTHOR("Philipp Zabel"); | ||
335 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index e0d56ef2bcb0..e0d56ef2bcb0 100644 --- a/drivers/i2c/chips/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c | |||
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c new file mode 100644 index 000000000000..ff318fae7d4d --- /dev/null +++ b/drivers/usb/otg/otg.c | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * otg.c -- USB OTG utility code | ||
3 | * | ||
4 | * Copyright (C) 2004 Texas Instruments | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/device.h> | ||
14 | |||
15 | #include <linux/usb/otg.h> | ||
16 | |||
17 | static struct otg_transceiver *xceiv; | ||
18 | |||
19 | /** | ||
20 | * otg_get_transceiver - find the (single) OTG transceiver | ||
21 | * | ||
22 | * Returns the transceiver driver, after getting a refcount to it; or | ||
23 | * null if there is no such transceiver. The caller is responsible for | ||
24 | * calling otg_put_transceiver() to release that count. | ||
25 | * | ||
26 | * For use by USB host and peripheral drivers. | ||
27 | */ | ||
28 | struct otg_transceiver *otg_get_transceiver(void) | ||
29 | { | ||
30 | if (xceiv) | ||
31 | get_device(xceiv->dev); | ||
32 | return xceiv; | ||
33 | } | ||
34 | EXPORT_SYMBOL(otg_get_transceiver); | ||
35 | |||
36 | /** | ||
37 | * otg_put_transceiver - release the (single) OTG transceiver | ||
38 | * @x: the transceiver returned by otg_get_transceiver() | ||
39 | * | ||
40 | * Releases a refcount the caller received from otg_get_transceiver(). | ||
41 | * | ||
42 | * For use by USB host and peripheral drivers. | ||
43 | */ | ||
44 | void otg_put_transceiver(struct otg_transceiver *x) | ||
45 | { | ||
46 | put_device(x->dev); | ||
47 | } | ||
48 | EXPORT_SYMBOL(otg_put_transceiver); | ||
49 | |||
50 | /** | ||
51 | * otg_set_transceiver - declare the (single) OTG transceiver | ||
52 | * @x: the USB OTG transceiver to be used; or NULL | ||
53 | * | ||
54 | * This call is exclusively for use by transceiver drivers, which | ||
55 | * coordinate the activities of drivers for host and peripheral | ||
56 | * controllers, and in some cases for VBUS current regulation. | ||
57 | */ | ||
58 | int otg_set_transceiver(struct otg_transceiver *x) | ||
59 | { | ||
60 | if (xceiv && x) | ||
61 | return -EBUSY; | ||
62 | xceiv = x; | ||
63 | return 0; | ||
64 | } | ||
65 | EXPORT_SYMBOL(otg_set_transceiver); | ||
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c new file mode 100644 index 000000000000..416e4410be02 --- /dev/null +++ b/drivers/usb/otg/twl4030-usb.c | |||
@@ -0,0 +1,721 @@ | |||
1 | /* | ||
2 | * twl4030_usb - TWL4030 USB transceiver, talking to OMAP OTG controller | ||
3 | * | ||
4 | * Copyright (C) 2004-2007 Texas Instruments | ||
5 | * Copyright (C) 2008 Nokia Corporation | ||
6 | * Contact: Felipe Balbi <felipe.balbi@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * | ||
22 | * Current status: | ||
23 | * - HS USB ULPI mode works. | ||
24 | * - 3-pin mode support may be added in future. | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | #include <linux/workqueue.h> | ||
33 | #include <linux/io.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/usb/otg.h> | ||
36 | #include <linux/i2c/twl4030.h> | ||
37 | |||
38 | |||
39 | /* Register defines */ | ||
40 | |||
41 | #define VENDOR_ID_LO 0x00 | ||
42 | #define VENDOR_ID_HI 0x01 | ||
43 | #define PRODUCT_ID_LO 0x02 | ||
44 | #define PRODUCT_ID_HI 0x03 | ||
45 | |||
46 | #define FUNC_CTRL 0x04 | ||
47 | #define FUNC_CTRL_SET 0x05 | ||
48 | #define FUNC_CTRL_CLR 0x06 | ||
49 | #define FUNC_CTRL_SUSPENDM (1 << 6) | ||
50 | #define FUNC_CTRL_RESET (1 << 5) | ||
51 | #define FUNC_CTRL_OPMODE_MASK (3 << 3) /* bits 3 and 4 */ | ||
52 | #define FUNC_CTRL_OPMODE_NORMAL (0 << 3) | ||
53 | #define FUNC_CTRL_OPMODE_NONDRIVING (1 << 3) | ||
54 | #define FUNC_CTRL_OPMODE_DISABLE_BIT_NRZI (2 << 3) | ||
55 | #define FUNC_CTRL_TERMSELECT (1 << 2) | ||
56 | #define FUNC_CTRL_XCVRSELECT_MASK (3 << 0) /* bits 0 and 1 */ | ||
57 | #define FUNC_CTRL_XCVRSELECT_HS (0 << 0) | ||
58 | #define FUNC_CTRL_XCVRSELECT_FS (1 << 0) | ||
59 | #define FUNC_CTRL_XCVRSELECT_LS (2 << 0) | ||
60 | #define FUNC_CTRL_XCVRSELECT_FS4LS (3 << 0) | ||
61 | |||
62 | #define IFC_CTRL 0x07 | ||
63 | #define IFC_CTRL_SET 0x08 | ||
64 | #define IFC_CTRL_CLR 0x09 | ||
65 | #define IFC_CTRL_INTERFACE_PROTECT_DISABLE (1 << 7) | ||
66 | #define IFC_CTRL_AUTORESUME (1 << 4) | ||
67 | #define IFC_CTRL_CLOCKSUSPENDM (1 << 3) | ||
68 | #define IFC_CTRL_CARKITMODE (1 << 2) | ||
69 | #define IFC_CTRL_FSLSSERIALMODE_3PIN (1 << 1) | ||
70 | |||
71 | #define TWL4030_OTG_CTRL 0x0A | ||
72 | #define TWL4030_OTG_CTRL_SET 0x0B | ||
73 | #define TWL4030_OTG_CTRL_CLR 0x0C | ||
74 | #define TWL4030_OTG_CTRL_DRVVBUS (1 << 5) | ||
75 | #define TWL4030_OTG_CTRL_CHRGVBUS (1 << 4) | ||
76 | #define TWL4030_OTG_CTRL_DISCHRGVBUS (1 << 3) | ||
77 | #define TWL4030_OTG_CTRL_DMPULLDOWN (1 << 2) | ||
78 | #define TWL4030_OTG_CTRL_DPPULLDOWN (1 << 1) | ||
79 | #define TWL4030_OTG_CTRL_IDPULLUP (1 << 0) | ||
80 | |||
81 | #define USB_INT_EN_RISE 0x0D | ||
82 | #define USB_INT_EN_RISE_SET 0x0E | ||
83 | #define USB_INT_EN_RISE_CLR 0x0F | ||
84 | #define USB_INT_EN_FALL 0x10 | ||
85 | #define USB_INT_EN_FALL_SET 0x11 | ||
86 | #define USB_INT_EN_FALL_CLR 0x12 | ||
87 | #define USB_INT_STS 0x13 | ||
88 | #define USB_INT_LATCH 0x14 | ||
89 | #define USB_INT_IDGND (1 << 4) | ||
90 | #define USB_INT_SESSEND (1 << 3) | ||
91 | #define USB_INT_SESSVALID (1 << 2) | ||
92 | #define USB_INT_VBUSVALID (1 << 1) | ||
93 | #define USB_INT_HOSTDISCONNECT (1 << 0) | ||
94 | |||
95 | #define CARKIT_CTRL 0x19 | ||
96 | #define CARKIT_CTRL_SET 0x1A | ||
97 | #define CARKIT_CTRL_CLR 0x1B | ||
98 | #define CARKIT_CTRL_MICEN (1 << 6) | ||
99 | #define CARKIT_CTRL_SPKRIGHTEN (1 << 5) | ||
100 | #define CARKIT_CTRL_SPKLEFTEN (1 << 4) | ||
101 | #define CARKIT_CTRL_RXDEN (1 << 3) | ||
102 | #define CARKIT_CTRL_TXDEN (1 << 2) | ||
103 | #define CARKIT_CTRL_IDGNDDRV (1 << 1) | ||
104 | #define CARKIT_CTRL_CARKITPWR (1 << 0) | ||
105 | #define CARKIT_PLS_CTRL 0x22 | ||
106 | #define CARKIT_PLS_CTRL_SET 0x23 | ||
107 | #define CARKIT_PLS_CTRL_CLR 0x24 | ||
108 | #define CARKIT_PLS_CTRL_SPKRRIGHT_BIASEN (1 << 3) | ||
109 | #define CARKIT_PLS_CTRL_SPKRLEFT_BIASEN (1 << 2) | ||
110 | #define CARKIT_PLS_CTRL_RXPLSEN (1 << 1) | ||
111 | #define CARKIT_PLS_CTRL_TXPLSEN (1 << 0) | ||
112 | |||
113 | #define MCPC_CTRL 0x30 | ||
114 | #define MCPC_CTRL_SET 0x31 | ||
115 | #define MCPC_CTRL_CLR 0x32 | ||
116 | #define MCPC_CTRL_RTSOL (1 << 7) | ||
117 | #define MCPC_CTRL_EXTSWR (1 << 6) | ||
118 | #define MCPC_CTRL_EXTSWC (1 << 5) | ||
119 | #define MCPC_CTRL_VOICESW (1 << 4) | ||
120 | #define MCPC_CTRL_OUT64K (1 << 3) | ||
121 | #define MCPC_CTRL_RTSCTSSW (1 << 2) | ||
122 | #define MCPC_CTRL_HS_UART (1 << 0) | ||
123 | |||
124 | #define MCPC_IO_CTRL 0x33 | ||
125 | #define MCPC_IO_CTRL_SET 0x34 | ||
126 | #define MCPC_IO_CTRL_CLR 0x35 | ||
127 | #define MCPC_IO_CTRL_MICBIASEN (1 << 5) | ||
128 | #define MCPC_IO_CTRL_CTS_NPU (1 << 4) | ||
129 | #define MCPC_IO_CTRL_RXD_PU (1 << 3) | ||
130 | #define MCPC_IO_CTRL_TXDTYP (1 << 2) | ||
131 | #define MCPC_IO_CTRL_CTSTYP (1 << 1) | ||
132 | #define MCPC_IO_CTRL_RTSTYP (1 << 0) | ||
133 | |||
134 | #define MCPC_CTRL2 0x36 | ||
135 | #define MCPC_CTRL2_SET 0x37 | ||
136 | #define MCPC_CTRL2_CLR 0x38 | ||
137 | #define MCPC_CTRL2_MCPC_CK_EN (1 << 0) | ||
138 | |||
139 | #define OTHER_FUNC_CTRL 0x80 | ||
140 | #define OTHER_FUNC_CTRL_SET 0x81 | ||
141 | #define OTHER_FUNC_CTRL_CLR 0x82 | ||
142 | #define OTHER_FUNC_CTRL_BDIS_ACON_EN (1 << 4) | ||
143 | #define OTHER_FUNC_CTRL_FIVEWIRE_MODE (1 << 2) | ||
144 | |||
145 | #define OTHER_IFC_CTRL 0x83 | ||
146 | #define OTHER_IFC_CTRL_SET 0x84 | ||
147 | #define OTHER_IFC_CTRL_CLR 0x85 | ||
148 | #define OTHER_IFC_CTRL_OE_INT_EN (1 << 6) | ||
149 | #define OTHER_IFC_CTRL_CEA2011_MODE (1 << 5) | ||
150 | #define OTHER_IFC_CTRL_FSLSSERIALMODE_4PIN (1 << 4) | ||
151 | #define OTHER_IFC_CTRL_HIZ_ULPI_60MHZ_OUT (1 << 3) | ||
152 | #define OTHER_IFC_CTRL_HIZ_ULPI (1 << 2) | ||
153 | #define OTHER_IFC_CTRL_ALT_INT_REROUTE (1 << 0) | ||
154 | |||
155 | #define OTHER_INT_EN_RISE 0x86 | ||
156 | #define OTHER_INT_EN_RISE_SET 0x87 | ||
157 | #define OTHER_INT_EN_RISE_CLR 0x88 | ||
158 | #define OTHER_INT_EN_FALL 0x89 | ||
159 | #define OTHER_INT_EN_FALL_SET 0x8A | ||
160 | #define OTHER_INT_EN_FALL_CLR 0x8B | ||
161 | #define OTHER_INT_STS 0x8C | ||
162 | #define OTHER_INT_LATCH 0x8D | ||
163 | #define OTHER_INT_VB_SESS_VLD (1 << 7) | ||
164 | #define OTHER_INT_DM_HI (1 << 6) /* not valid for "latch" reg */ | ||
165 | #define OTHER_INT_DP_HI (1 << 5) /* not valid for "latch" reg */ | ||
166 | #define OTHER_INT_BDIS_ACON (1 << 3) /* not valid for "fall" regs */ | ||
167 | #define OTHER_INT_MANU (1 << 1) | ||
168 | #define OTHER_INT_ABNORMAL_STRESS (1 << 0) | ||
169 | |||
170 | #define ID_STATUS 0x96 | ||
171 | #define ID_RES_FLOAT (1 << 4) | ||
172 | #define ID_RES_440K (1 << 3) | ||
173 | #define ID_RES_200K (1 << 2) | ||
174 | #define ID_RES_102K (1 << 1) | ||
175 | #define ID_RES_GND (1 << 0) | ||
176 | |||
177 | #define POWER_CTRL 0xAC | ||
178 | #define POWER_CTRL_SET 0xAD | ||
179 | #define POWER_CTRL_CLR 0xAE | ||
180 | #define POWER_CTRL_OTG_ENAB (1 << 5) | ||
181 | |||
182 | #define OTHER_IFC_CTRL2 0xAF | ||
183 | #define OTHER_IFC_CTRL2_SET 0xB0 | ||
184 | #define OTHER_IFC_CTRL2_CLR 0xB1 | ||
185 | #define OTHER_IFC_CTRL2_ULPI_STP_LOW (1 << 4) | ||
186 | #define OTHER_IFC_CTRL2_ULPI_TXEN_POL (1 << 3) | ||
187 | #define OTHER_IFC_CTRL2_ULPI_4PIN_2430 (1 << 2) | ||
188 | #define OTHER_IFC_CTRL2_USB_INT_OUTSEL_MASK (3 << 0) /* bits 0 and 1 */ | ||
189 | #define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT1N (0 << 0) | ||
190 | #define OTHER_IFC_CTRL2_USB_INT_OUTSEL_INT2N (1 << 0) | ||
191 | |||
192 | #define REG_CTRL_EN 0xB2 | ||
193 | #define REG_CTRL_EN_SET 0xB3 | ||
194 | #define REG_CTRL_EN_CLR 0xB4 | ||
195 | #define REG_CTRL_ERROR 0xB5 | ||
196 | #define ULPI_I2C_CONFLICT_INTEN (1 << 0) | ||
197 | |||
198 | #define OTHER_FUNC_CTRL2 0xB8 | ||
199 | #define OTHER_FUNC_CTRL2_SET 0xB9 | ||
200 | #define OTHER_FUNC_CTRL2_CLR 0xBA | ||
201 | #define OTHER_FUNC_CTRL2_VBAT_TIMER_EN (1 << 0) | ||
202 | |||
203 | /* following registers do not have separate _clr and _set registers */ | ||
204 | #define VBUS_DEBOUNCE 0xC0 | ||
205 | #define ID_DEBOUNCE 0xC1 | ||
206 | #define VBAT_TIMER 0xD3 | ||
207 | #define PHY_PWR_CTRL 0xFD | ||
208 | #define PHY_PWR_PHYPWD (1 << 0) | ||
209 | #define PHY_CLK_CTRL 0xFE | ||
210 | #define PHY_CLK_CTRL_CLOCKGATING_EN (1 << 2) | ||
211 | #define PHY_CLK_CTRL_CLK32K_EN (1 << 1) | ||
212 | #define REQ_PHY_DPLL_CLK (1 << 0) | ||
213 | #define PHY_CLK_CTRL_STS 0xFF | ||
214 | #define PHY_DPLL_CLK (1 << 0) | ||
215 | |||
216 | /* In module TWL4030_MODULE_PM_MASTER */ | ||
217 | #define PROTECT_KEY 0x0E | ||
218 | |||
219 | /* In module TWL4030_MODULE_PM_RECEIVER */ | ||
220 | #define VUSB_DEDICATED1 0x7D | ||
221 | #define VUSB_DEDICATED2 0x7E | ||
222 | #define VUSB1V5_DEV_GRP 0x71 | ||
223 | #define VUSB1V5_TYPE 0x72 | ||
224 | #define VUSB1V5_REMAP 0x73 | ||
225 | #define VUSB1V8_DEV_GRP 0x74 | ||
226 | #define VUSB1V8_TYPE 0x75 | ||
227 | #define VUSB1V8_REMAP 0x76 | ||
228 | #define VUSB3V1_DEV_GRP 0x77 | ||
229 | #define VUSB3V1_TYPE 0x78 | ||
230 | #define VUSB3V1_REMAP 0x79 | ||
231 | |||
232 | /* In module TWL4030_MODULE_INTBR */ | ||
233 | #define PMBR1 0x0D | ||
234 | #define GPIO_USB_4PIN_ULPI_2430C (3 << 0) | ||
235 | |||
236 | |||
237 | |||
238 | enum linkstat { | ||
239 | USB_LINK_UNKNOWN = 0, | ||
240 | USB_LINK_NONE, | ||
241 | USB_LINK_VBUS, | ||
242 | USB_LINK_ID, | ||
243 | }; | ||
244 | |||
245 | struct twl4030_usb { | ||
246 | struct otg_transceiver otg; | ||
247 | struct device *dev; | ||
248 | |||
249 | /* for vbus reporting with irqs disabled */ | ||
250 | spinlock_t lock; | ||
251 | |||
252 | /* pin configuration */ | ||
253 | enum twl4030_usb_mode usb_mode; | ||
254 | |||
255 | int irq; | ||
256 | u8 linkstat; | ||
257 | u8 asleep; | ||
258 | bool irq_enabled; | ||
259 | }; | ||
260 | |||
261 | /* internal define on top of container_of */ | ||
262 | #define xceiv_to_twl(x) container_of((x), struct twl4030_usb, otg); | ||
263 | |||
264 | /*-------------------------------------------------------------------------*/ | ||
265 | |||
266 | static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl, | ||
267 | u8 module, u8 data, u8 address) | ||
268 | { | ||
269 | u8 check; | ||
270 | |||
271 | if ((twl4030_i2c_write_u8(module, data, address) >= 0) && | ||
272 | (twl4030_i2c_read_u8(module, &check, address) >= 0) && | ||
273 | (check == data)) | ||
274 | return 0; | ||
275 | dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", | ||
276 | 1, module, address, check, data); | ||
277 | |||
278 | /* Failed once: Try again */ | ||
279 | if ((twl4030_i2c_write_u8(module, data, address) >= 0) && | ||
280 | (twl4030_i2c_read_u8(module, &check, address) >= 0) && | ||
281 | (check == data)) | ||
282 | return 0; | ||
283 | dev_dbg(twl->dev, "Write%d[%d,0x%x] wrote %02x but read %02x\n", | ||
284 | 2, module, address, check, data); | ||
285 | |||
286 | /* Failed again: Return error */ | ||
287 | return -EBUSY; | ||
288 | } | ||
289 | |||
290 | #define twl4030_usb_write_verify(twl, address, data) \ | ||
291 | twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_USB, (data), (address)) | ||
292 | |||
293 | static inline int twl4030_usb_write(struct twl4030_usb *twl, | ||
294 | u8 address, u8 data) | ||
295 | { | ||
296 | int ret = 0; | ||
297 | |||
298 | ret = twl4030_i2c_write_u8(TWL4030_MODULE_USB, data, address); | ||
299 | if (ret < 0) | ||
300 | dev_dbg(twl->dev, | ||
301 | "TWL4030:USB:Write[0x%x] Error %d\n", address, ret); | ||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | static inline int twl4030_readb(struct twl4030_usb *twl, u8 module, u8 address) | ||
306 | { | ||
307 | u8 data; | ||
308 | int ret = 0; | ||
309 | |||
310 | ret = twl4030_i2c_read_u8(module, &data, address); | ||
311 | if (ret >= 0) | ||
312 | ret = data; | ||
313 | else | ||
314 | dev_dbg(twl->dev, | ||
315 | "TWL4030:readb[0x%x,0x%x] Error %d\n", | ||
316 | module, address, ret); | ||
317 | |||
318 | return ret; | ||
319 | } | ||
320 | |||
321 | static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address) | ||
322 | { | ||
323 | return twl4030_readb(twl, TWL4030_MODULE_USB, address); | ||
324 | } | ||
325 | |||
326 | /*-------------------------------------------------------------------------*/ | ||
327 | |||
328 | static inline int | ||
329 | twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits) | ||
330 | { | ||
331 | return twl4030_usb_write(twl, reg + 1, bits); | ||
332 | } | ||
333 | |||
334 | static inline int | ||
335 | twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) | ||
336 | { | ||
337 | return twl4030_usb_write(twl, reg + 2, bits); | ||
338 | } | ||
339 | |||
340 | /*-------------------------------------------------------------------------*/ | ||
341 | |||
342 | static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl) | ||
343 | { | ||
344 | int status; | ||
345 | int linkstat = USB_LINK_UNKNOWN; | ||
346 | |||
347 | /* STS_HW_CONDITIONS */ | ||
348 | status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, 0x0f); | ||
349 | if (status < 0) | ||
350 | dev_err(twl->dev, "USB link status err %d\n", status); | ||
351 | else if (status & BIT(7)) | ||
352 | linkstat = USB_LINK_VBUS; | ||
353 | else if (status & BIT(2)) | ||
354 | linkstat = USB_LINK_ID; | ||
355 | else | ||
356 | linkstat = USB_LINK_NONE; | ||
357 | |||
358 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", | ||
359 | status, status, linkstat); | ||
360 | |||
361 | /* REVISIT this assumes host and peripheral controllers | ||
362 | * are registered, and that both are active... | ||
363 | */ | ||
364 | |||
365 | spin_lock_irq(&twl->lock); | ||
366 | twl->linkstat = linkstat; | ||
367 | if (linkstat == USB_LINK_ID) { | ||
368 | twl->otg.default_a = true; | ||
369 | twl->otg.state = OTG_STATE_A_IDLE; | ||
370 | } else { | ||
371 | twl->otg.default_a = false; | ||
372 | twl->otg.state = OTG_STATE_B_IDLE; | ||
373 | } | ||
374 | spin_unlock_irq(&twl->lock); | ||
375 | |||
376 | return linkstat; | ||
377 | } | ||
378 | |||
379 | static void twl4030_usb_set_mode(struct twl4030_usb *twl, int mode) | ||
380 | { | ||
381 | twl->usb_mode = mode; | ||
382 | |||
383 | switch (mode) { | ||
384 | case T2_USB_MODE_ULPI: | ||
385 | twl4030_usb_clear_bits(twl, IFC_CTRL, IFC_CTRL_CARKITMODE); | ||
386 | twl4030_usb_set_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); | ||
387 | twl4030_usb_clear_bits(twl, FUNC_CTRL, | ||
388 | FUNC_CTRL_XCVRSELECT_MASK | | ||
389 | FUNC_CTRL_OPMODE_MASK); | ||
390 | break; | ||
391 | case -1: | ||
392 | /* FIXME: power on defaults */ | ||
393 | break; | ||
394 | default: | ||
395 | dev_err(twl->dev, "unsupported T2 transceiver mode %d\n", | ||
396 | mode); | ||
397 | break; | ||
398 | }; | ||
399 | } | ||
400 | |||
401 | static void twl4030_i2c_access(struct twl4030_usb *twl, int on) | ||
402 | { | ||
403 | unsigned long timeout; | ||
404 | int val = twl4030_usb_read(twl, PHY_CLK_CTRL); | ||
405 | |||
406 | if (val >= 0) { | ||
407 | if (on) { | ||
408 | /* enable DPLL to access PHY registers over I2C */ | ||
409 | val |= REQ_PHY_DPLL_CLK; | ||
410 | WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL, | ||
411 | (u8)val) < 0); | ||
412 | |||
413 | timeout = jiffies + HZ; | ||
414 | while (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) & | ||
415 | PHY_DPLL_CLK) | ||
416 | && time_before(jiffies, timeout)) | ||
417 | udelay(10); | ||
418 | if (!(twl4030_usb_read(twl, PHY_CLK_CTRL_STS) & | ||
419 | PHY_DPLL_CLK)) | ||
420 | dev_err(twl->dev, "Timeout setting T2 HSUSB " | ||
421 | "PHY DPLL clock\n"); | ||
422 | } else { | ||
423 | /* let ULPI control the DPLL clock */ | ||
424 | val &= ~REQ_PHY_DPLL_CLK; | ||
425 | WARN_ON(twl4030_usb_write_verify(twl, PHY_CLK_CTRL, | ||
426 | (u8)val) < 0); | ||
427 | } | ||
428 | } | ||
429 | } | ||
430 | |||
431 | static void twl4030_phy_power(struct twl4030_usb *twl, int on) | ||
432 | { | ||
433 | u8 pwr; | ||
434 | |||
435 | pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); | ||
436 | if (on) { | ||
437 | pwr &= ~PHY_PWR_PHYPWD; | ||
438 | WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); | ||
439 | twl4030_usb_write(twl, PHY_CLK_CTRL, | ||
440 | twl4030_usb_read(twl, PHY_CLK_CTRL) | | ||
441 | (PHY_CLK_CTRL_CLOCKGATING_EN | | ||
442 | PHY_CLK_CTRL_CLK32K_EN)); | ||
443 | } else { | ||
444 | pwr |= PHY_PWR_PHYPWD; | ||
445 | WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off) | ||
450 | { | ||
451 | if (twl->asleep) | ||
452 | return; | ||
453 | |||
454 | twl4030_phy_power(twl, 0); | ||
455 | twl->asleep = 1; | ||
456 | } | ||
457 | |||
458 | static void twl4030_phy_resume(struct twl4030_usb *twl) | ||
459 | { | ||
460 | if (!twl->asleep) | ||
461 | return; | ||
462 | |||
463 | twl4030_phy_power(twl, 1); | ||
464 | twl4030_i2c_access(twl, 1); | ||
465 | twl4030_usb_set_mode(twl, twl->usb_mode); | ||
466 | if (twl->usb_mode == T2_USB_MODE_ULPI) | ||
467 | twl4030_i2c_access(twl, 0); | ||
468 | twl->asleep = 0; | ||
469 | } | ||
470 | |||
471 | static void twl4030_usb_ldo_init(struct twl4030_usb *twl) | ||
472 | { | ||
473 | /* Enable writing to power configuration registers */ | ||
474 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); | ||
475 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0x0C, PROTECT_KEY); | ||
476 | |||
477 | /* put VUSB3V1 LDO in active state */ | ||
478 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); | ||
479 | |||
480 | /* input to VUSB3V1 LDO is from VBAT, not VBUS */ | ||
481 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); | ||
482 | |||
483 | /* turn on 3.1V regulator */ | ||
484 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP); | ||
485 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); | ||
486 | |||
487 | /* turn on 1.5V regulator */ | ||
488 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP); | ||
489 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); | ||
490 | |||
491 | /* turn on 1.8V regulator */ | ||
492 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP); | ||
493 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); | ||
494 | |||
495 | /* disable access to power configuration registers */ | ||
496 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); | ||
497 | } | ||
498 | |||
499 | static ssize_t twl4030_usb_vbus_show(struct device *dev, | ||
500 | struct device_attribute *attr, char *buf) | ||
501 | { | ||
502 | struct twl4030_usb *twl = dev_get_drvdata(dev); | ||
503 | unsigned long flags; | ||
504 | int ret = -EINVAL; | ||
505 | |||
506 | spin_lock_irqsave(&twl->lock, flags); | ||
507 | ret = sprintf(buf, "%s\n", | ||
508 | (twl->linkstat == USB_LINK_VBUS) ? "on" : "off"); | ||
509 | spin_unlock_irqrestore(&twl->lock, flags); | ||
510 | |||
511 | return ret; | ||
512 | } | ||
513 | static DEVICE_ATTR(vbus, 0444, twl4030_usb_vbus_show, NULL); | ||
514 | |||
515 | static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | ||
516 | { | ||
517 | struct twl4030_usb *twl = _twl; | ||
518 | int status; | ||
519 | |||
520 | #ifdef CONFIG_LOCKDEP | ||
521 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | ||
522 | * we don't want and can't tolerate. Although it might be | ||
523 | * friendlier not to borrow this thread context... | ||
524 | */ | ||
525 | local_irq_enable(); | ||
526 | #endif | ||
527 | |||
528 | status = twl4030_usb_linkstat(twl); | ||
529 | if (status != USB_LINK_UNKNOWN) { | ||
530 | |||
531 | /* FIXME add a set_power() method so that B-devices can | ||
532 | * configure the charger appropriately. It's not always | ||
533 | * correct to consume VBUS power, and how much current to | ||
534 | * consume is a function of the USB configuration chosen | ||
535 | * by the host. | ||
536 | * | ||
537 | * REVISIT usb_gadget_vbus_connect(...) as needed, ditto | ||
538 | * its disconnect() sibling, when changing to/from the | ||
539 | * USB_LINK_VBUS state. musb_hdrc won't care until it | ||
540 | * starts to handle softconnect right. | ||
541 | */ | ||
542 | twl4030charger_usb_en(status == USB_LINK_VBUS); | ||
543 | |||
544 | if (status == USB_LINK_NONE) | ||
545 | twl4030_phy_suspend(twl, 0); | ||
546 | else | ||
547 | twl4030_phy_resume(twl); | ||
548 | } | ||
549 | sysfs_notify(&twl->dev->kobj, NULL, "vbus"); | ||
550 | |||
551 | return IRQ_HANDLED; | ||
552 | } | ||
553 | |||
554 | static int twl4030_set_suspend(struct otg_transceiver *x, int suspend) | ||
555 | { | ||
556 | struct twl4030_usb *twl = xceiv_to_twl(x); | ||
557 | |||
558 | if (suspend) | ||
559 | twl4030_phy_suspend(twl, 1); | ||
560 | else | ||
561 | twl4030_phy_resume(twl); | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static int twl4030_set_peripheral(struct otg_transceiver *x, | ||
567 | struct usb_gadget *gadget) | ||
568 | { | ||
569 | struct twl4030_usb *twl; | ||
570 | |||
571 | if (!x) | ||
572 | return -ENODEV; | ||
573 | |||
574 | twl = xceiv_to_twl(x); | ||
575 | twl->otg.gadget = gadget; | ||
576 | if (!gadget) | ||
577 | twl->otg.state = OTG_STATE_UNDEFINED; | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static int twl4030_set_host(struct otg_transceiver *x, struct usb_bus *host) | ||
583 | { | ||
584 | struct twl4030_usb *twl; | ||
585 | |||
586 | if (!x) | ||
587 | return -ENODEV; | ||
588 | |||
589 | twl = xceiv_to_twl(x); | ||
590 | twl->otg.host = host; | ||
591 | if (!host) | ||
592 | twl->otg.state = OTG_STATE_UNDEFINED; | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | static int __init twl4030_usb_probe(struct platform_device *pdev) | ||
598 | { | ||
599 | struct twl4030_usb_data *pdata = pdev->dev.platform_data; | ||
600 | struct twl4030_usb *twl; | ||
601 | int status; | ||
602 | |||
603 | if (!pdata) { | ||
604 | dev_dbg(&pdev->dev, "platform_data not available\n"); | ||
605 | return -EINVAL; | ||
606 | } | ||
607 | |||
608 | twl = kzalloc(sizeof *twl, GFP_KERNEL); | ||
609 | if (!twl) | ||
610 | return -ENOMEM; | ||
611 | |||
612 | twl->dev = &pdev->dev; | ||
613 | twl->irq = platform_get_irq(pdev, 0); | ||
614 | twl->otg.dev = twl->dev; | ||
615 | twl->otg.label = "twl4030"; | ||
616 | twl->otg.set_host = twl4030_set_host; | ||
617 | twl->otg.set_peripheral = twl4030_set_peripheral; | ||
618 | twl->otg.set_suspend = twl4030_set_suspend; | ||
619 | twl->usb_mode = pdata->usb_mode; | ||
620 | twl->asleep = 1; | ||
621 | |||
622 | /* init spinlock for workqueue */ | ||
623 | spin_lock_init(&twl->lock); | ||
624 | |||
625 | twl4030_usb_ldo_init(twl); | ||
626 | otg_set_transceiver(&twl->otg); | ||
627 | |||
628 | platform_set_drvdata(pdev, twl); | ||
629 | if (device_create_file(&pdev->dev, &dev_attr_vbus)) | ||
630 | dev_warn(&pdev->dev, "could not create sysfs file\n"); | ||
631 | |||
632 | /* Our job is to use irqs and status from the power module | ||
633 | * to keep the transceiver disabled when nothing's connected. | ||
634 | * | ||
635 | * FIXME we actually shouldn't start enabling it until the | ||
636 | * USB controller drivers have said they're ready, by calling | ||
637 | * set_host() and/or set_peripheral() ... OTG_capable boards | ||
638 | * need both handles, otherwise just one suffices. | ||
639 | */ | ||
640 | twl->irq_enabled = true; | ||
641 | status = request_irq(twl->irq, twl4030_usb_irq, | ||
642 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
643 | "twl4030_usb", twl); | ||
644 | if (status < 0) { | ||
645 | dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n", | ||
646 | twl->irq, status); | ||
647 | kfree(twl); | ||
648 | return status; | ||
649 | } | ||
650 | |||
651 | /* The IRQ handler just handles changes from the previous states | ||
652 | * of the ID and VBUS pins ... in probe() we must initialize that | ||
653 | * previous state. The easy way: fake an IRQ. | ||
654 | * | ||
655 | * REVISIT: a real IRQ might have happened already, if PREEMPT is | ||
656 | * enabled. Else the IRQ may not yet be configured or enabled, | ||
657 | * because of scheduling delays. | ||
658 | */ | ||
659 | twl4030_usb_irq(twl->irq, twl); | ||
660 | |||
661 | dev_info(&pdev->dev, "Initialized TWL4030 USB module\n"); | ||
662 | return 0; | ||
663 | } | ||
664 | |||
665 | static int __exit twl4030_usb_remove(struct platform_device *pdev) | ||
666 | { | ||
667 | struct twl4030_usb *twl = platform_get_drvdata(pdev); | ||
668 | int val; | ||
669 | |||
670 | free_irq(twl->irq, twl); | ||
671 | device_remove_file(twl->dev, &dev_attr_vbus); | ||
672 | |||
673 | /* set transceiver mode to power on defaults */ | ||
674 | twl4030_usb_set_mode(twl, -1); | ||
675 | |||
676 | /* autogate 60MHz ULPI clock, | ||
677 | * clear dpll clock request for i2c access, | ||
678 | * disable 32KHz | ||
679 | */ | ||
680 | val = twl4030_usb_read(twl, PHY_CLK_CTRL); | ||
681 | if (val >= 0) { | ||
682 | val |= PHY_CLK_CTRL_CLOCKGATING_EN; | ||
683 | val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK); | ||
684 | twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val); | ||
685 | } | ||
686 | |||
687 | /* disable complete OTG block */ | ||
688 | twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); | ||
689 | |||
690 | twl4030_phy_power(twl, 0); | ||
691 | |||
692 | kfree(twl); | ||
693 | |||
694 | return 0; | ||
695 | } | ||
696 | |||
697 | static struct platform_driver twl4030_usb_driver = { | ||
698 | .probe = twl4030_usb_probe, | ||
699 | .remove = __exit_p(twl4030_usb_remove), | ||
700 | .driver = { | ||
701 | .name = "twl4030_usb", | ||
702 | .owner = THIS_MODULE, | ||
703 | }, | ||
704 | }; | ||
705 | |||
706 | static int __init twl4030_usb_init(void) | ||
707 | { | ||
708 | return platform_driver_register(&twl4030_usb_driver); | ||
709 | } | ||
710 | subsys_initcall(twl4030_usb_init); | ||
711 | |||
712 | static void __exit twl4030_usb_exit(void) | ||
713 | { | ||
714 | platform_driver_unregister(&twl4030_usb_driver); | ||
715 | } | ||
716 | module_exit(twl4030_usb_exit); | ||
717 | |||
718 | MODULE_ALIAS("platform:twl4030_usb"); | ||
719 | MODULE_AUTHOR("Texas Instruments, Inc, Nokia Corporation"); | ||
720 | MODULE_DESCRIPTION("TWL4030 USB transceiver driver"); | ||
721 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 70338f4ec918..b361f05cafac 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -496,6 +496,14 @@ config USB_SERIAL_SAFE_PADDED | |||
496 | bool "USB Secure Encapsulated Driver - Padded" | 496 | bool "USB Secure Encapsulated Driver - Padded" |
497 | depends on USB_SERIAL_SAFE | 497 | depends on USB_SERIAL_SAFE |
498 | 498 | ||
499 | config USB_SERIAL_SIEMENS_MPI | ||
500 | tristate "USB Siemens MPI driver" | ||
501 | help | ||
502 | Say M here if you want to use a Siemens USB/MPI adapter. | ||
503 | |||
504 | To compile this driver as a module, choose M here: the | ||
505 | module will be called siemens_mpi. | ||
506 | |||
499 | config USB_SERIAL_SIERRAWIRELESS | 507 | config USB_SERIAL_SIERRAWIRELESS |
500 | tristate "USB Sierra Wireless Driver" | 508 | tristate "USB Sierra Wireless Driver" |
501 | help | 509 | help |
@@ -565,6 +573,15 @@ config USB_SERIAL_OMNINET | |||
565 | To compile this driver as a module, choose M here: the | 573 | To compile this driver as a module, choose M here: the |
566 | module will be called omninet. | 574 | module will be called omninet. |
567 | 575 | ||
576 | config USB_SERIAL_OPTICON | ||
577 | tristate "USB Opticon Barcode driver (serial mode)" | ||
578 | help | ||
579 | Say Y here if you want to use a Opticon USB Barcode device | ||
580 | in serial emulation mode. | ||
581 | |||
582 | To compile this driver as a module, choose M here: the | ||
583 | module will be called opticon. | ||
584 | |||
568 | config USB_SERIAL_DEBUG | 585 | config USB_SERIAL_DEBUG |
569 | tristate "USB Debugging Device" | 586 | tristate "USB Debugging Device" |
570 | help | 587 | help |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 6047f818adfe..b75be91eb8f1 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -41,10 +41,12 @@ obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o | |||
41 | obj-$(CONFIG_USB_SERIAL_MOTOROLA) += moto_modem.o | 41 | obj-$(CONFIG_USB_SERIAL_MOTOROLA) += moto_modem.o |
42 | obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o | 42 | obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o |
43 | obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o | 43 | obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o |
44 | obj-$(CONFIG_USB_SERIAL_OPTICON) += opticon.o | ||
44 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o | 45 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o |
45 | obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o | 46 | obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o |
46 | obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o | 47 | obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o |
47 | obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o | 48 | obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o |
49 | obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o | ||
48 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o | 50 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o |
49 | obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o | 51 | obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o |
50 | obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o | 52 | obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o |
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 69f84f0ea6fe..38ba4ea8b6bf 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
@@ -635,8 +635,7 @@ static int digi_write_oob_command(struct usb_serial_port *port, | |||
635 | 635 | ||
636 | spin_lock_irqsave(&oob_priv->dp_port_lock, flags); | 636 | spin_lock_irqsave(&oob_priv->dp_port_lock, flags); |
637 | while (count > 0) { | 637 | while (count > 0) { |
638 | while (oob_port->write_urb->status == -EINPROGRESS | 638 | while (oob_priv->dp_write_urb_in_use) { |
639 | || oob_priv->dp_write_urb_in_use) { | ||
640 | cond_wait_interruptible_timeout_irqrestore( | 639 | cond_wait_interruptible_timeout_irqrestore( |
641 | &oob_port->write_wait, DIGI_RETRY_TIMEOUT, | 640 | &oob_port->write_wait, DIGI_RETRY_TIMEOUT, |
642 | &oob_priv->dp_port_lock, flags); | 641 | &oob_priv->dp_port_lock, flags); |
@@ -699,9 +698,8 @@ static int digi_write_inb_command(struct usb_serial_port *port, | |||
699 | 698 | ||
700 | spin_lock_irqsave(&priv->dp_port_lock, flags); | 699 | spin_lock_irqsave(&priv->dp_port_lock, flags); |
701 | while (count > 0 && ret == 0) { | 700 | while (count > 0 && ret == 0) { |
702 | while ((port->write_urb->status == -EINPROGRESS | 701 | while (priv->dp_write_urb_in_use && |
703 | || priv->dp_write_urb_in_use) | 702 | time_before(jiffies, timeout)) { |
704 | && time_before(jiffies, timeout)) { | ||
705 | cond_wait_interruptible_timeout_irqrestore( | 703 | cond_wait_interruptible_timeout_irqrestore( |
706 | &port->write_wait, DIGI_RETRY_TIMEOUT, | 704 | &port->write_wait, DIGI_RETRY_TIMEOUT, |
707 | &priv->dp_port_lock, flags); | 705 | &priv->dp_port_lock, flags); |
@@ -779,8 +777,7 @@ static int digi_set_modem_signals(struct usb_serial_port *port, | |||
779 | spin_lock_irqsave(&oob_priv->dp_port_lock, flags); | 777 | spin_lock_irqsave(&oob_priv->dp_port_lock, flags); |
780 | spin_lock(&port_priv->dp_port_lock); | 778 | spin_lock(&port_priv->dp_port_lock); |
781 | 779 | ||
782 | while (oob_port->write_urb->status == -EINPROGRESS || | 780 | while (oob_priv->dp_write_urb_in_use) { |
783 | oob_priv->dp_write_urb_in_use) { | ||
784 | spin_unlock(&port_priv->dp_port_lock); | 781 | spin_unlock(&port_priv->dp_port_lock); |
785 | cond_wait_interruptible_timeout_irqrestore( | 782 | cond_wait_interruptible_timeout_irqrestore( |
786 | &oob_port->write_wait, DIGI_RETRY_TIMEOUT, | 783 | &oob_port->write_wait, DIGI_RETRY_TIMEOUT, |
@@ -1168,12 +1165,10 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1168 | 1165 | ||
1169 | /* be sure only one write proceeds at a time */ | 1166 | /* be sure only one write proceeds at a time */ |
1170 | /* there are races on the port private buffer */ | 1167 | /* there are races on the port private buffer */ |
1171 | /* and races to check write_urb->status */ | ||
1172 | spin_lock_irqsave(&priv->dp_port_lock, flags); | 1168 | spin_lock_irqsave(&priv->dp_port_lock, flags); |
1173 | 1169 | ||
1174 | /* wait for urb status clear to submit another urb */ | 1170 | /* wait for urb status clear to submit another urb */ |
1175 | if (port->write_urb->status == -EINPROGRESS || | 1171 | if (priv->dp_write_urb_in_use) { |
1176 | priv->dp_write_urb_in_use) { | ||
1177 | /* buffer data if count is 1 (probably put_char) if possible */ | 1172 | /* buffer data if count is 1 (probably put_char) if possible */ |
1178 | if (count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE) { | 1173 | if (count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE) { |
1179 | priv->dp_out_buf[priv->dp_out_buf_len++] = *buf; | 1174 | priv->dp_out_buf[priv->dp_out_buf_len++] = *buf; |
@@ -1236,7 +1231,7 @@ static void digi_write_bulk_callback(struct urb *urb) | |||
1236 | int ret = 0; | 1231 | int ret = 0; |
1237 | int status = urb->status; | 1232 | int status = urb->status; |
1238 | 1233 | ||
1239 | dbg("digi_write_bulk_callback: TOP, urb->status=%d", status); | 1234 | dbg("digi_write_bulk_callback: TOP, status=%d", status); |
1240 | 1235 | ||
1241 | /* port and serial sanity check */ | 1236 | /* port and serial sanity check */ |
1242 | if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) { | 1237 | if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) { |
@@ -1266,8 +1261,7 @@ static void digi_write_bulk_callback(struct urb *urb) | |||
1266 | /* try to send any buffered data on this port, if it is open */ | 1261 | /* try to send any buffered data on this port, if it is open */ |
1267 | spin_lock(&priv->dp_port_lock); | 1262 | spin_lock(&priv->dp_port_lock); |
1268 | priv->dp_write_urb_in_use = 0; | 1263 | priv->dp_write_urb_in_use = 0; |
1269 | if (port->port.count && port->write_urb->status != -EINPROGRESS | 1264 | if (port->port.count && priv->dp_out_buf_len > 0) { |
1270 | && priv->dp_out_buf_len > 0) { | ||
1271 | *((unsigned char *)(port->write_urb->transfer_buffer)) | 1265 | *((unsigned char *)(port->write_urb->transfer_buffer)) |
1272 | = (unsigned char)DIGI_CMD_SEND_DATA; | 1266 | = (unsigned char)DIGI_CMD_SEND_DATA; |
1273 | *((unsigned char *)(port->write_urb->transfer_buffer) + 1) | 1267 | *((unsigned char *)(port->write_urb->transfer_buffer) + 1) |
@@ -1305,8 +1299,7 @@ static int digi_write_room(struct tty_struct *tty) | |||
1305 | 1299 | ||
1306 | spin_lock_irqsave(&priv->dp_port_lock, flags); | 1300 | spin_lock_irqsave(&priv->dp_port_lock, flags); |
1307 | 1301 | ||
1308 | if (port->write_urb->status == -EINPROGRESS || | 1302 | if (priv->dp_write_urb_in_use) |
1309 | priv->dp_write_urb_in_use) | ||
1310 | room = 0; | 1303 | room = 0; |
1311 | else | 1304 | else |
1312 | room = port->bulk_out_size - 2 - priv->dp_out_buf_len; | 1305 | room = port->bulk_out_size - 2 - priv->dp_out_buf_len; |
@@ -1322,8 +1315,7 @@ static int digi_chars_in_buffer(struct tty_struct *tty) | |||
1322 | struct usb_serial_port *port = tty->driver_data; | 1315 | struct usb_serial_port *port = tty->driver_data; |
1323 | struct digi_port *priv = usb_get_serial_port_data(port); | 1316 | struct digi_port *priv = usb_get_serial_port_data(port); |
1324 | 1317 | ||
1325 | if (port->write_urb->status == -EINPROGRESS | 1318 | if (priv->dp_write_urb_in_use) { |
1326 | || priv->dp_write_urb_in_use) { | ||
1327 | dbg("digi_chars_in_buffer: port=%d, chars=%d", | 1319 | dbg("digi_chars_in_buffer: port=%d, chars=%d", |
1328 | priv->dp_port_num, port->bulk_out_size - 2); | 1320 | priv->dp_port_num, port->bulk_out_size - 2); |
1329 | /* return(port->bulk_out_size - 2); */ | 1321 | /* return(port->bulk_out_size - 2); */ |
@@ -1702,7 +1694,7 @@ static int digi_read_inb_callback(struct urb *urb) | |||
1702 | /* short/multiple packet check */ | 1694 | /* short/multiple packet check */ |
1703 | if (urb->actual_length != len + 2) { | 1695 | if (urb->actual_length != len + 2) { |
1704 | dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, " | 1696 | dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, " |
1705 | "urb->status=%d, port=%d, opcode=%d, len=%d, " | 1697 | "status=%d, port=%d, opcode=%d, len=%d, " |
1706 | "actual_length=%d, status=%d\n", __func__, status, | 1698 | "actual_length=%d, status=%d\n", __func__, status, |
1707 | priv->dp_port_num, opcode, len, urb->actual_length, | 1699 | priv->dp_port_num, opcode, len, urb->actual_length, |
1708 | port_status); | 1700 | port_status); |
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 8e6a66e38db2..a26a0e2cdb4a 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
@@ -1056,7 +1056,7 @@ static void garmin_write_bulk_callback(struct urb *urb) | |||
1056 | 1056 | ||
1057 | if (status) { | 1057 | if (status) { |
1058 | dbg("%s - nonzero write bulk status received: %d", | 1058 | dbg("%s - nonzero write bulk status received: %d", |
1059 | __func__, urb->status); | 1059 | __func__, status); |
1060 | spin_lock_irqsave(&garmin_data_p->lock, flags); | 1060 | spin_lock_irqsave(&garmin_data_p->lock, flags); |
1061 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; | 1061 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; |
1062 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | 1062 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 3ac59a8a980f..f530032ed93d 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c | |||
@@ -473,7 +473,7 @@ static struct usb_serial_driver ipw_device = { | |||
473 | 473 | ||
474 | 474 | ||
475 | 475 | ||
476 | static int usb_ipw_init(void) | 476 | static int __init usb_ipw_init(void) |
477 | { | 477 | { |
478 | int retval; | 478 | int retval; |
479 | 479 | ||
@@ -490,7 +490,7 @@ static int usb_ipw_init(void) | |||
490 | return 0; | 490 | return 0; |
491 | } | 491 | } |
492 | 492 | ||
493 | static void usb_ipw_exit(void) | 493 | static void __exit usb_ipw_exit(void) |
494 | { | 494 | { |
495 | usb_deregister(&usb_ipw_driver); | 495 | usb_deregister(&usb_ipw_driver); |
496 | usb_serial_deregister(&ipw_device); | 496 | usb_serial_deregister(&ipw_device); |
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index e320972cb227..2314c6ae4fc2 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -190,10 +190,12 @@ static void iuu_rxcmd(struct urb *urb) | |||
190 | { | 190 | { |
191 | struct usb_serial_port *port = urb->context; | 191 | struct usb_serial_port *port = urb->context; |
192 | int result; | 192 | int result; |
193 | int status = urb->status; | ||
194 | |||
193 | dbg("%s - enter", __func__); | 195 | dbg("%s - enter", __func__); |
194 | 196 | ||
195 | if (urb->status) { | 197 | if (status) { |
196 | dbg("%s - urb->status = %d", __func__, urb->status); | 198 | dbg("%s - status = %d", __func__, status); |
197 | /* error stop all */ | 199 | /* error stop all */ |
198 | return; | 200 | return; |
199 | } | 201 | } |
@@ -245,10 +247,12 @@ static void iuu_update_status_callback(struct urb *urb) | |||
245 | struct usb_serial_port *port = urb->context; | 247 | struct usb_serial_port *port = urb->context; |
246 | struct iuu_private *priv = usb_get_serial_port_data(port); | 248 | struct iuu_private *priv = usb_get_serial_port_data(port); |
247 | u8 *st; | 249 | u8 *st; |
250 | int status = urb->status; | ||
251 | |||
248 | dbg("%s - enter", __func__); | 252 | dbg("%s - enter", __func__); |
249 | 253 | ||
250 | if (urb->status) { | 254 | if (status) { |
251 | dbg("%s - urb->status = %d", __func__, urb->status); | 255 | dbg("%s - status = %d", __func__, status); |
252 | /* error stop all */ | 256 | /* error stop all */ |
253 | return; | 257 | return; |
254 | } | 258 | } |
@@ -274,9 +278,9 @@ static void iuu_status_callback(struct urb *urb) | |||
274 | { | 278 | { |
275 | struct usb_serial_port *port = urb->context; | 279 | struct usb_serial_port *port = urb->context; |
276 | int result; | 280 | int result; |
277 | dbg("%s - enter", __func__); | 281 | int status = urb->status; |
278 | 282 | ||
279 | dbg("%s - urb->status = %d", __func__, urb->status); | 283 | dbg("%s - status = %d", __func__, status); |
280 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | 284 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, |
281 | usb_rcvbulkpipe(port->serial->dev, | 285 | usb_rcvbulkpipe(port->serial->dev, |
282 | port->bulk_in_endpointAddress), | 286 | port->bulk_in_endpointAddress), |
@@ -618,11 +622,12 @@ static void read_buf_callback(struct urb *urb) | |||
618 | struct usb_serial_port *port = urb->context; | 622 | struct usb_serial_port *port = urb->context; |
619 | unsigned char *data = urb->transfer_buffer; | 623 | unsigned char *data = urb->transfer_buffer; |
620 | struct tty_struct *tty; | 624 | struct tty_struct *tty; |
621 | dbg("%s - urb->status = %d", __func__, urb->status); | 625 | int status = urb->status; |
622 | 626 | ||
623 | if (urb->status) { | 627 | dbg("%s - status = %d", __func__, status); |
624 | dbg("%s - urb->status = %d", __func__, urb->status); | 628 | |
625 | if (urb->status == -EPROTO) { | 629 | if (status) { |
630 | if (status == -EPROTO) { | ||
626 | /* reschedule needed */ | 631 | /* reschedule needed */ |
627 | } | 632 | } |
628 | return; | 633 | return; |
@@ -695,7 +700,7 @@ static void iuu_uart_read_callback(struct urb *urb) | |||
695 | struct usb_serial_port *port = urb->context; | 700 | struct usb_serial_port *port = urb->context; |
696 | struct iuu_private *priv = usb_get_serial_port_data(port); | 701 | struct iuu_private *priv = usb_get_serial_port_data(port); |
697 | unsigned long flags; | 702 | unsigned long flags; |
698 | int status; | 703 | int status = urb->status; |
699 | int error = 0; | 704 | int error = 0; |
700 | int len = 0; | 705 | int len = 0; |
701 | unsigned char *data = urb->transfer_buffer; | 706 | unsigned char *data = urb->transfer_buffer; |
@@ -703,8 +708,8 @@ static void iuu_uart_read_callback(struct urb *urb) | |||
703 | 708 | ||
704 | dbg("%s - enter", __func__); | 709 | dbg("%s - enter", __func__); |
705 | 710 | ||
706 | if (urb->status) { | 711 | if (status) { |
707 | dbg("%s - urb->status = %d", __func__, urb->status); | 712 | dbg("%s - status = %d", __func__, status); |
708 | /* error stop all */ | 713 | /* error stop all */ |
709 | return; | 714 | return; |
710 | } | 715 | } |
@@ -782,12 +787,11 @@ static void read_rxcmd_callback(struct urb *urb) | |||
782 | { | 787 | { |
783 | struct usb_serial_port *port = urb->context; | 788 | struct usb_serial_port *port = urb->context; |
784 | int result; | 789 | int result; |
785 | dbg("%s - enter", __func__); | 790 | int status = urb->status; |
786 | 791 | ||
787 | dbg("%s - urb->status = %d", __func__, urb->status); | 792 | dbg("%s - status = %d", __func__, status); |
788 | 793 | ||
789 | if (urb->status) { | 794 | if (status) { |
790 | dbg("%s - urb->status = %d", __func__, urb->status); | ||
791 | /* error stop all */ | 795 | /* error stop all */ |
792 | return; | 796 | return; |
793 | } | 797 | } |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 96a8c7713212..2c20e88a91b3 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -214,6 +214,7 @@ struct moschip_port { | |||
214 | spinlock_t pool_lock; | 214 | spinlock_t pool_lock; |
215 | struct urb *write_urb_pool[NUM_URBS]; | 215 | struct urb *write_urb_pool[NUM_URBS]; |
216 | char busy[NUM_URBS]; | 216 | char busy[NUM_URBS]; |
217 | bool read_urb_busy; | ||
217 | }; | 218 | }; |
218 | 219 | ||
219 | 220 | ||
@@ -679,26 +680,30 @@ static void mos7840_bulk_in_callback(struct urb *urb) | |||
679 | struct tty_struct *tty; | 680 | struct tty_struct *tty; |
680 | int status = urb->status; | 681 | int status = urb->status; |
681 | 682 | ||
682 | if (status) { | ||
683 | dbg("nonzero read bulk status received: %d", status); | ||
684 | return; | ||
685 | } | ||
686 | |||
687 | mos7840_port = urb->context; | 683 | mos7840_port = urb->context; |
688 | if (!mos7840_port) { | 684 | if (!mos7840_port) { |
689 | dbg("%s", "NULL mos7840_port pointer \n"); | 685 | dbg("%s", "NULL mos7840_port pointer \n"); |
686 | mos7840_port->read_urb_busy = false; | ||
687 | return; | ||
688 | } | ||
689 | |||
690 | if (status) { | ||
691 | dbg("nonzero read bulk status received: %d", status); | ||
692 | mos7840_port->read_urb_busy = false; | ||
690 | return; | 693 | return; |
691 | } | 694 | } |
692 | 695 | ||
693 | port = (struct usb_serial_port *)mos7840_port->port; | 696 | port = (struct usb_serial_port *)mos7840_port->port; |
694 | if (mos7840_port_paranoia_check(port, __func__)) { | 697 | if (mos7840_port_paranoia_check(port, __func__)) { |
695 | dbg("%s", "Port Paranoia failed \n"); | 698 | dbg("%s", "Port Paranoia failed \n"); |
699 | mos7840_port->read_urb_busy = false; | ||
696 | return; | 700 | return; |
697 | } | 701 | } |
698 | 702 | ||
699 | serial = mos7840_get_usb_serial(port, __func__); | 703 | serial = mos7840_get_usb_serial(port, __func__); |
700 | if (!serial) { | 704 | if (!serial) { |
701 | dbg("%s\n", "Bad serial pointer "); | 705 | dbg("%s\n", "Bad serial pointer "); |
706 | mos7840_port->read_urb_busy = false; | ||
702 | return; | 707 | return; |
703 | } | 708 | } |
704 | 709 | ||
@@ -725,17 +730,19 @@ static void mos7840_bulk_in_callback(struct urb *urb) | |||
725 | 730 | ||
726 | if (!mos7840_port->read_urb) { | 731 | if (!mos7840_port->read_urb) { |
727 | dbg("%s", "URB KILLED !!!\n"); | 732 | dbg("%s", "URB KILLED !!!\n"); |
733 | mos7840_port->read_urb_busy = false; | ||
728 | return; | 734 | return; |
729 | } | 735 | } |
730 | 736 | ||
731 | 737 | ||
732 | mos7840_port->read_urb->dev = serial->dev; | 738 | mos7840_port->read_urb->dev = serial->dev; |
733 | 739 | ||
740 | mos7840_port->read_urb_busy = true; | ||
734 | retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | 741 | retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); |
735 | 742 | ||
736 | if (retval) { | 743 | if (retval) { |
737 | dbg(" usb_submit_urb(read bulk) failed, retval = %d", | 744 | dbg("usb_submit_urb(read bulk) failed, retval = %d", retval); |
738 | retval); | 745 | mos7840_port->read_urb_busy = false; |
739 | } | 746 | } |
740 | } | 747 | } |
741 | 748 | ||
@@ -1055,10 +1062,12 @@ static int mos7840_open(struct tty_struct *tty, | |||
1055 | 1062 | ||
1056 | dbg("mos7840_open: bulkin endpoint is %d\n", | 1063 | dbg("mos7840_open: bulkin endpoint is %d\n", |
1057 | port->bulk_in_endpointAddress); | 1064 | port->bulk_in_endpointAddress); |
1065 | mos7840_port->read_urb_busy = true; | ||
1058 | response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL); | 1066 | response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL); |
1059 | if (response) { | 1067 | if (response) { |
1060 | dev_err(&port->dev, "%s - Error %d submitting control urb\n", | 1068 | dev_err(&port->dev, "%s - Error %d submitting control urb\n", |
1061 | __func__, response); | 1069 | __func__, response); |
1070 | mos7840_port->read_urb_busy = false; | ||
1062 | } | 1071 | } |
1063 | 1072 | ||
1064 | /* initialize our wait queues */ | 1073 | /* initialize our wait queues */ |
@@ -1227,6 +1236,7 @@ static void mos7840_close(struct tty_struct *tty, | |||
1227 | if (mos7840_port->read_urb) { | 1236 | if (mos7840_port->read_urb) { |
1228 | dbg("%s", "Shutdown bulk read\n"); | 1237 | dbg("%s", "Shutdown bulk read\n"); |
1229 | usb_kill_urb(mos7840_port->read_urb); | 1238 | usb_kill_urb(mos7840_port->read_urb); |
1239 | mos7840_port->read_urb_busy = false; | ||
1230 | } | 1240 | } |
1231 | if ((&mos7840_port->control_urb)) { | 1241 | if ((&mos7840_port->control_urb)) { |
1232 | dbg("%s", "Shutdown control read\n"); | 1242 | dbg("%s", "Shutdown control read\n"); |
@@ -2043,14 +2053,14 @@ static void mos7840_change_port_settings(struct tty_struct *tty, | |||
2043 | Data = 0x0c; | 2053 | Data = 0x0c; |
2044 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); | 2054 | mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); |
2045 | 2055 | ||
2046 | if (mos7840_port->read_urb->status != -EINPROGRESS) { | 2056 | if (mos7840_port->read_urb_busy == false) { |
2047 | mos7840_port->read_urb->dev = serial->dev; | 2057 | mos7840_port->read_urb->dev = serial->dev; |
2048 | 2058 | mos7840_port->read_urb_busy = true; | |
2049 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | 2059 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); |
2050 | |||
2051 | if (status) { | 2060 | if (status) { |
2052 | dbg(" usb_submit_urb(read bulk) failed, status = %d", | 2061 | dbg("usb_submit_urb(read bulk) failed, status = %d", |
2053 | status); | 2062 | status); |
2063 | mos7840_port->read_urb_busy = false; | ||
2054 | } | 2064 | } |
2055 | } | 2065 | } |
2056 | wake_up(&mos7840_port->delta_msr_wait); | 2066 | wake_up(&mos7840_port->delta_msr_wait); |
@@ -2117,12 +2127,14 @@ static void mos7840_set_termios(struct tty_struct *tty, | |||
2117 | return; | 2127 | return; |
2118 | } | 2128 | } |
2119 | 2129 | ||
2120 | if (mos7840_port->read_urb->status != -EINPROGRESS) { | 2130 | if (mos7840_port->read_urb_busy == false) { |
2121 | mos7840_port->read_urb->dev = serial->dev; | 2131 | mos7840_port->read_urb->dev = serial->dev; |
2132 | mos7840_port->read_urb_busy = true; | ||
2122 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | 2133 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); |
2123 | if (status) { | 2134 | if (status) { |
2124 | dbg(" usb_submit_urb(read bulk) failed, status = %d", | 2135 | dbg("usb_submit_urb(read bulk) failed, status = %d", |
2125 | status); | 2136 | status); |
2137 | mos7840_port->read_urb_busy = false; | ||
2126 | } | 2138 | } |
2127 | } | 2139 | } |
2128 | return; | 2140 | return; |
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c new file mode 100644 index 000000000000..cea326f1f105 --- /dev/null +++ b/drivers/usb/serial/opticon.c | |||
@@ -0,0 +1,358 @@ | |||
1 | /* | ||
2 | * Opticon USB barcode to serial driver | ||
3 | * | ||
4 | * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de> | ||
5 | * Copyright (C) 2008 Novell Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License version | ||
9 | * 2 as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/tty.h> | ||
15 | #include <linux/tty_driver.h> | ||
16 | #include <linux/tty_flip.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/usb.h> | ||
19 | #include <linux/usb/serial.h> | ||
20 | #include <linux/uaccess.h> | ||
21 | |||
22 | static int debug; | ||
23 | |||
24 | static struct usb_device_id id_table[] = { | ||
25 | { USB_DEVICE(0x065a, 0x0009) }, | ||
26 | { }, | ||
27 | }; | ||
28 | MODULE_DEVICE_TABLE(usb, id_table); | ||
29 | |||
30 | /* This structure holds all of the individual device information */ | ||
31 | struct opticon_private { | ||
32 | struct usb_device *udev; | ||
33 | struct usb_serial *serial; | ||
34 | struct usb_serial_port *port; | ||
35 | unsigned char *bulk_in_buffer; | ||
36 | struct urb *bulk_read_urb; | ||
37 | int buffer_size; | ||
38 | u8 bulk_address; | ||
39 | spinlock_t lock; /* protects the following flags */ | ||
40 | bool throttled; | ||
41 | bool actually_throttled; | ||
42 | bool rts; | ||
43 | }; | ||
44 | |||
45 | static void opticon_bulk_callback(struct urb *urb) | ||
46 | { | ||
47 | struct opticon_private *priv = urb->context; | ||
48 | unsigned char *data = urb->transfer_buffer; | ||
49 | struct usb_serial_port *port = priv->port; | ||
50 | int status = urb->status; | ||
51 | struct tty_struct *tty; | ||
52 | int result; | ||
53 | int available_room = 0; | ||
54 | int data_length; | ||
55 | |||
56 | dbg("%s - port %d", __func__, port->number); | ||
57 | |||
58 | switch (status) { | ||
59 | case 0: | ||
60 | /* success */ | ||
61 | break; | ||
62 | case -ECONNRESET: | ||
63 | case -ENOENT: | ||
64 | case -ESHUTDOWN: | ||
65 | /* this urb is terminated, clean up */ | ||
66 | dbg("%s - urb shutting down with status: %d", | ||
67 | __func__, status); | ||
68 | return; | ||
69 | default: | ||
70 | dbg("%s - nonzero urb status received: %d", | ||
71 | __func__, status); | ||
72 | goto exit; | ||
73 | } | ||
74 | |||
75 | usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, | ||
76 | data); | ||
77 | |||
78 | if (urb->actual_length > 2) { | ||
79 | data_length = urb->actual_length - 2; | ||
80 | |||
81 | /* | ||
82 | * Data from the device comes with a 2 byte header: | ||
83 | * | ||
84 | * <0x00><0x00>data... | ||
85 | * This is real data to be sent to the tty layer | ||
86 | * <0x00><0x01)level | ||
87 | * This is a RTS level change, the third byte is the RTS | ||
88 | * value (0 for low, 1 for high). | ||
89 | */ | ||
90 | if ((data[0] == 0x00) && (data[1] == 0x00)) { | ||
91 | /* real data, send it to the tty layer */ | ||
92 | tty = tty_port_tty_get(&port->port); | ||
93 | if (tty) { | ||
94 | available_room = tty_buffer_request_room(tty, | ||
95 | data_length); | ||
96 | if (available_room) { | ||
97 | tty_insert_flip_string(tty, data, | ||
98 | available_room); | ||
99 | tty_flip_buffer_push(tty); | ||
100 | } | ||
101 | tty_kref_put(tty); | ||
102 | } | ||
103 | } else { | ||
104 | if ((data[0] == 0x00) && (data[1] == 0x01)) { | ||
105 | if (data[2] == 0x00) | ||
106 | priv->rts = false; | ||
107 | else | ||
108 | priv->rts = true; | ||
109 | /* FIXME change the RTS level */ | ||
110 | } else { | ||
111 | dev_dbg(&priv->udev->dev, | ||
112 | "Unknown data packet received from the device:" | ||
113 | " %2x %2x\n", | ||
114 | data[0], data[1]); | ||
115 | } | ||
116 | } | ||
117 | } else { | ||
118 | dev_dbg(&priv->udev->dev, | ||
119 | "Improper ammount of data received from the device, " | ||
120 | "%d bytes", urb->actual_length); | ||
121 | } | ||
122 | |||
123 | exit: | ||
124 | spin_lock(&priv->lock); | ||
125 | |||
126 | /* Continue trying to always read if we should */ | ||
127 | if (!priv->throttled) { | ||
128 | usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev, | ||
129 | usb_rcvbulkpipe(priv->udev, | ||
130 | priv->bulk_address), | ||
131 | priv->bulk_in_buffer, priv->buffer_size, | ||
132 | opticon_bulk_callback, priv); | ||
133 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
134 | if (result) | ||
135 | dev_err(&port->dev, | ||
136 | "%s - failed resubmitting read urb, error %d\n", | ||
137 | __func__, result); | ||
138 | } else | ||
139 | priv->actually_throttled = true; | ||
140 | spin_unlock(&priv->lock); | ||
141 | } | ||
142 | |||
143 | static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port, | ||
144 | struct file *filp) | ||
145 | { | ||
146 | struct opticon_private *priv = usb_get_serial_data(port->serial); | ||
147 | unsigned long flags; | ||
148 | int result = 0; | ||
149 | |||
150 | dbg("%s - port %d", __func__, port->number); | ||
151 | |||
152 | spin_lock_irqsave(&priv->lock, flags); | ||
153 | priv->throttled = false; | ||
154 | priv->actually_throttled = false; | ||
155 | priv->port = port; | ||
156 | spin_unlock_irqrestore(&priv->lock, flags); | ||
157 | |||
158 | /* | ||
159 | * Force low_latency on so that our tty_push actually forces the data | ||
160 | * through, otherwise it is scheduled, and with high data rates (like | ||
161 | * with OHCI) data can get lost. | ||
162 | */ | ||
163 | if (tty) | ||
164 | tty->low_latency = 1; | ||
165 | |||
166 | /* Start reading from the device */ | ||
167 | usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev, | ||
168 | usb_rcvbulkpipe(priv->udev, | ||
169 | priv->bulk_address), | ||
170 | priv->bulk_in_buffer, priv->buffer_size, | ||
171 | opticon_bulk_callback, priv); | ||
172 | result = usb_submit_urb(priv->bulk_read_urb, GFP_KERNEL); | ||
173 | if (result) | ||
174 | dev_err(&port->dev, | ||
175 | "%s - failed resubmitting read urb, error %d\n", | ||
176 | __func__, result); | ||
177 | return result; | ||
178 | } | ||
179 | |||
180 | static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port, | ||
181 | struct file *filp) | ||
182 | { | ||
183 | struct opticon_private *priv = usb_get_serial_data(port->serial); | ||
184 | |||
185 | dbg("%s - port %d", __func__, port->number); | ||
186 | |||
187 | /* shutdown our urbs */ | ||
188 | usb_kill_urb(priv->bulk_read_urb); | ||
189 | } | ||
190 | |||
191 | static void opticon_throttle(struct tty_struct *tty) | ||
192 | { | ||
193 | struct usb_serial_port *port = tty->driver_data; | ||
194 | struct opticon_private *priv = usb_get_serial_data(port->serial); | ||
195 | unsigned long flags; | ||
196 | |||
197 | dbg("%s - port %d", __func__, port->number); | ||
198 | spin_lock_irqsave(&priv->lock, flags); | ||
199 | priv->throttled = true; | ||
200 | spin_unlock_irqrestore(&priv->lock, flags); | ||
201 | } | ||
202 | |||
203 | |||
204 | static void opticon_unthrottle(struct tty_struct *tty) | ||
205 | { | ||
206 | struct usb_serial_port *port = tty->driver_data; | ||
207 | struct opticon_private *priv = usb_get_serial_data(port->serial); | ||
208 | unsigned long flags; | ||
209 | int result; | ||
210 | |||
211 | dbg("%s - port %d", __func__, port->number); | ||
212 | |||
213 | spin_lock_irqsave(&priv->lock, flags); | ||
214 | priv->throttled = false; | ||
215 | priv->actually_throttled = false; | ||
216 | spin_unlock_irqrestore(&priv->lock, flags); | ||
217 | |||
218 | priv->bulk_read_urb->dev = port->serial->dev; | ||
219 | result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC); | ||
220 | if (result) | ||
221 | dev_err(&port->dev, | ||
222 | "%s - failed submitting read urb, error %d\n", | ||
223 | __func__, result); | ||
224 | } | ||
225 | |||
226 | static int opticon_startup(struct usb_serial *serial) | ||
227 | { | ||
228 | struct opticon_private *priv; | ||
229 | struct usb_host_interface *intf; | ||
230 | int i; | ||
231 | int retval = -ENOMEM; | ||
232 | bool bulk_in_found = false; | ||
233 | |||
234 | /* create our private serial structure */ | ||
235 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
236 | if (priv == NULL) { | ||
237 | dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); | ||
238 | return -ENOMEM; | ||
239 | } | ||
240 | spin_lock_init(&priv->lock); | ||
241 | priv->serial = serial; | ||
242 | priv->port = serial->port[0]; | ||
243 | priv->udev = serial->dev; | ||
244 | |||
245 | /* find our bulk endpoint */ | ||
246 | intf = serial->interface->altsetting; | ||
247 | for (i = 0; i < intf->desc.bNumEndpoints; ++i) { | ||
248 | struct usb_endpoint_descriptor *endpoint; | ||
249 | |||
250 | endpoint = &intf->endpoint[i].desc; | ||
251 | if (!usb_endpoint_is_bulk_in(endpoint)) | ||
252 | continue; | ||
253 | |||
254 | priv->bulk_read_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
255 | if (!priv->bulk_read_urb) { | ||
256 | dev_err(&priv->udev->dev, "out of memory\n"); | ||
257 | goto error; | ||
258 | } | ||
259 | |||
260 | priv->buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2; | ||
261 | priv->bulk_in_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); | ||
262 | if (!priv->bulk_in_buffer) { | ||
263 | dev_err(&priv->udev->dev, "out of memory\n"); | ||
264 | goto error; | ||
265 | } | ||
266 | |||
267 | priv->bulk_address = endpoint->bEndpointAddress; | ||
268 | |||
269 | /* set up our bulk urb */ | ||
270 | usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev, | ||
271 | usb_rcvbulkpipe(priv->udev, | ||
272 | endpoint->bEndpointAddress), | ||
273 | priv->bulk_in_buffer, priv->buffer_size, | ||
274 | opticon_bulk_callback, priv); | ||
275 | |||
276 | bulk_in_found = true; | ||
277 | break; | ||
278 | } | ||
279 | |||
280 | if (!bulk_in_found) { | ||
281 | dev_err(&priv->udev->dev, | ||
282 | "Error - the proper endpoints were not found!\n"); | ||
283 | goto error; | ||
284 | } | ||
285 | |||
286 | usb_set_serial_data(serial, priv); | ||
287 | return 0; | ||
288 | |||
289 | error: | ||
290 | usb_free_urb(priv->bulk_read_urb); | ||
291 | kfree(priv->bulk_in_buffer); | ||
292 | kfree(priv); | ||
293 | return retval; | ||
294 | } | ||
295 | |||
296 | static void opticon_shutdown(struct usb_serial *serial) | ||
297 | { | ||
298 | struct opticon_private *priv = usb_get_serial_data(serial); | ||
299 | |||
300 | dbg("%s", __func__); | ||
301 | |||
302 | usb_kill_urb(priv->bulk_read_urb); | ||
303 | usb_free_urb(priv->bulk_read_urb); | ||
304 | kfree(priv->bulk_in_buffer); | ||
305 | kfree(priv); | ||
306 | usb_set_serial_data(serial, NULL); | ||
307 | } | ||
308 | |||
309 | |||
310 | static struct usb_driver opticon_driver = { | ||
311 | .name = "opticon", | ||
312 | .probe = usb_serial_probe, | ||
313 | .disconnect = usb_serial_disconnect, | ||
314 | .id_table = id_table, | ||
315 | .no_dynamic_id = 1, | ||
316 | }; | ||
317 | |||
318 | static struct usb_serial_driver opticon_device = { | ||
319 | .driver = { | ||
320 | .owner = THIS_MODULE, | ||
321 | .name = "opticon", | ||
322 | }, | ||
323 | .id_table = id_table, | ||
324 | .usb_driver = &opticon_driver, | ||
325 | .num_ports = 1, | ||
326 | .attach = opticon_startup, | ||
327 | .open = opticon_open, | ||
328 | .close = opticon_close, | ||
329 | .shutdown = opticon_shutdown, | ||
330 | .throttle = opticon_throttle, | ||
331 | .unthrottle = opticon_unthrottle, | ||
332 | }; | ||
333 | |||
334 | static int __init opticon_init(void) | ||
335 | { | ||
336 | int retval; | ||
337 | |||
338 | retval = usb_serial_register(&opticon_device); | ||
339 | if (retval) | ||
340 | return retval; | ||
341 | retval = usb_register(&opticon_driver); | ||
342 | if (retval) | ||
343 | usb_serial_deregister(&opticon_device); | ||
344 | return retval; | ||
345 | } | ||
346 | |||
347 | static void __exit opticon_exit(void) | ||
348 | { | ||
349 | usb_deregister(&opticon_driver); | ||
350 | usb_serial_deregister(&opticon_device); | ||
351 | } | ||
352 | |||
353 | module_init(opticon_init); | ||
354 | module_exit(opticon_exit); | ||
355 | MODULE_LICENSE("GPL"); | ||
356 | |||
357 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
358 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 809697b3c7fc..5ed183477aaf 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -522,9 +522,9 @@ static int debug; | |||
522 | /* per port private data */ | 522 | /* per port private data */ |
523 | 523 | ||
524 | #define N_IN_URB 4 | 524 | #define N_IN_URB 4 |
525 | #define N_OUT_URB 1 | 525 | #define N_OUT_URB 4 |
526 | #define IN_BUFLEN 4096 | 526 | #define IN_BUFLEN 4096 |
527 | #define OUT_BUFLEN 128 | 527 | #define OUT_BUFLEN 4096 |
528 | 528 | ||
529 | struct option_port_private { | 529 | struct option_port_private { |
530 | /* Input endpoints and buffer for this port */ | 530 | /* Input endpoints and buffer for this port */ |
@@ -654,10 +654,6 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
654 | usb_unlink_urb(this_urb); | 654 | usb_unlink_urb(this_urb); |
655 | continue; | 655 | continue; |
656 | } | 656 | } |
657 | if (this_urb->status != 0) | ||
658 | dbg("usb_write %p failed (err=%d)", | ||
659 | this_urb, this_urb->status); | ||
660 | |||
661 | dbg("%s: endpoint %d buf %d", __func__, | 657 | dbg("%s: endpoint %d buf %d", __func__, |
662 | usb_pipeendpoint(this_urb->pipe), i); | 658 | usb_pipeendpoint(this_urb->pipe), i); |
663 | 659 | ||
@@ -669,8 +665,7 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
669 | err = usb_submit_urb(this_urb, GFP_ATOMIC); | 665 | err = usb_submit_urb(this_urb, GFP_ATOMIC); |
670 | if (err) { | 666 | if (err) { |
671 | dbg("usb_submit_urb %p (write bulk) failed " | 667 | dbg("usb_submit_urb %p (write bulk) failed " |
672 | "(%d, has %d)", this_urb, | 668 | "(%d)", this_urb, err); |
673 | err, this_urb->status); | ||
674 | clear_bit(i, &portdata->out_busy); | 669 | clear_bit(i, &portdata->out_busy); |
675 | continue; | 670 | continue; |
676 | } | 671 | } |
diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c new file mode 100644 index 000000000000..951ea0c6ba77 --- /dev/null +++ b/drivers/usb/serial/siemens_mpi.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * Siemens USB-MPI Serial USB driver | ||
3 | * | ||
4 | * Copyright (C) 2005 Thomas Hergenhahn <thomas.hergenhahn@suse.de> | ||
5 | * Copyright (C) 2005,2008 Greg Kroah-Hartman <gregkh@suse.de> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License version | ||
9 | * 2 as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/tty.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/usb.h> | ||
17 | #include <linux/usb/serial.h> | ||
18 | |||
19 | /* Version Information */ | ||
20 | #define DRIVER_VERSION "Version 0.1 09/26/2005" | ||
21 | #define DRIVER_AUTHOR "Thomas Hergenhahn@web.de http://libnodave.sf.net" | ||
22 | #define DRIVER_DESC "Driver for Siemens USB/MPI adapter" | ||
23 | |||
24 | |||
25 | static struct usb_device_id id_table[] = { | ||
26 | /* Vendor and product id for 6ES7-972-0CB20-0XA0 */ | ||
27 | { USB_DEVICE(0x908, 0x0004) }, | ||
28 | { }, | ||
29 | }; | ||
30 | MODULE_DEVICE_TABLE(usb, id_table); | ||
31 | |||
32 | static struct usb_driver siemens_usb_mpi_driver = { | ||
33 | .name = "siemens_mpi", | ||
34 | .probe = usb_serial_probe, | ||
35 | .disconnect = usb_serial_disconnect, | ||
36 | .id_table = id_table, | ||
37 | }; | ||
38 | |||
39 | static struct usb_serial_driver siemens_usb_mpi_device = { | ||
40 | .driver = { | ||
41 | .owner = THIS_MODULE, | ||
42 | .name = "siemens_mpi", | ||
43 | }, | ||
44 | .id_table = id_table, | ||
45 | .num_ports = 1, | ||
46 | }; | ||
47 | |||
48 | static int __init siemens_usb_mpi_init(void) | ||
49 | { | ||
50 | int retval; | ||
51 | |||
52 | retval = usb_serial_register(&siemens_usb_mpi_device); | ||
53 | if (retval) | ||
54 | goto failed_usb_serial_register; | ||
55 | retval = usb_register(&siemens_usb_mpi_driver); | ||
56 | if (retval) | ||
57 | goto failed_usb_register; | ||
58 | printk(KERN_INFO DRIVER_DESC "\n"); | ||
59 | printk(KERN_INFO DRIVER_VERSION " " DRIVER_AUTHOR "\n"); | ||
60 | return retval; | ||
61 | failed_usb_register: | ||
62 | usb_serial_deregister(&siemens_usb_mpi_device); | ||
63 | failed_usb_serial_register: | ||
64 | return retval; | ||
65 | } | ||
66 | |||
67 | static void __exit siemens_usb_mpi_exit(void) | ||
68 | { | ||
69 | usb_deregister(&siemens_usb_mpi_driver); | ||
70 | usb_serial_deregister(&siemens_usb_mpi_device); | ||
71 | } | ||
72 | |||
73 | module_init(siemens_usb_mpi_init); | ||
74 | module_exit(siemens_usb_mpi_exit); | ||
75 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
76 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
77 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index a65bc2bd8e71..5e7528cc81a8 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c | |||
@@ -709,21 +709,20 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) | |||
709 | unsigned char *data = urb->transfer_buffer; | 709 | unsigned char *data = urb->transfer_buffer; |
710 | unsigned long flags; | 710 | unsigned long flags; |
711 | int i; | 711 | int i; |
712 | int result; | 712 | int result = urb->status; |
713 | u8 status = 0; | 713 | u8 status; |
714 | char tty_flag; | 714 | char tty_flag; |
715 | 715 | ||
716 | dev_dbg(&port->dev, "start, urb->status = %d, " | 716 | dev_dbg(&port->dev, "start, result = %d, urb->actual_length = %d\n,", |
717 | "urb->actual_length = %d\n,", urb->status, urb->actual_length); | 717 | result, urb->actual_length); |
718 | 718 | ||
719 | /* check the urb status */ | 719 | /* check the urb status */ |
720 | if (urb->status) { | 720 | if (result) { |
721 | if (!port->port.count) | 721 | if (!port->port.count) |
722 | return; | 722 | return; |
723 | if (urb->status == -EPROTO) { | 723 | if (result == -EPROTO) { |
724 | /* spcp8x5 mysteriously fails with -EPROTO */ | 724 | /* spcp8x5 mysteriously fails with -EPROTO */ |
725 | /* reschedule the read */ | 725 | /* reschedule the read */ |
726 | urb->status = 0; | ||
727 | urb->dev = port->serial->dev; | 726 | urb->dev = port->serial->dev; |
728 | result = usb_submit_urb(urb , GFP_ATOMIC); | 727 | result = usb_submit_urb(urb , GFP_ATOMIC); |
729 | if (result) | 728 | if (result) |
@@ -833,8 +832,9 @@ static void spcp8x5_write_bulk_callback(struct urb *urb) | |||
833 | struct usb_serial_port *port = urb->context; | 832 | struct usb_serial_port *port = urb->context; |
834 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | 833 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); |
835 | int result; | 834 | int result; |
835 | int status = urb->status; | ||
836 | 836 | ||
837 | switch (urb->status) { | 837 | switch (status) { |
838 | case 0: | 838 | case 0: |
839 | /* success */ | 839 | /* success */ |
840 | break; | 840 | break; |
@@ -843,14 +843,14 @@ static void spcp8x5_write_bulk_callback(struct urb *urb) | |||
843 | case -ESHUTDOWN: | 843 | case -ESHUTDOWN: |
844 | /* this urb is terminated, clean up */ | 844 | /* this urb is terminated, clean up */ |
845 | dev_dbg(&port->dev, "urb shutting down with status: %d\n", | 845 | dev_dbg(&port->dev, "urb shutting down with status: %d\n", |
846 | urb->status); | 846 | status); |
847 | priv->write_urb_in_use = 0; | 847 | priv->write_urb_in_use = 0; |
848 | return; | 848 | return; |
849 | default: | 849 | default: |
850 | /* error in the urb, so we have to resubmit it */ | 850 | /* error in the urb, so we have to resubmit it */ |
851 | dbg("%s - Overflow in write", __func__); | 851 | dbg("%s - Overflow in write", __func__); |
852 | dbg("%s - nonzero write bulk status received: %d", | 852 | dbg("%s - nonzero write bulk status received: %d", |
853 | __func__, urb->status); | 853 | __func__, status); |
854 | port->write_urb->transfer_buffer_length = 1; | 854 | port->write_urb->transfer_buffer_length = 1; |
855 | port->write_urb->dev = port->serial->dev; | 855 | port->write_urb->dev = port->serial->dev; |
856 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 856 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index fc5d9952b03b..6c9cbb59552a 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c | |||
@@ -31,7 +31,7 @@ static struct usb_driver debug_driver = { | |||
31 | .no_dynamic_id = 1, | 31 | .no_dynamic_id = 1, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | int usb_debug_open(struct tty_struct *tty, struct usb_serial_port *port, | 34 | static int usb_debug_open(struct tty_struct *tty, struct usb_serial_port *port, |
35 | struct file *filp) | 35 | struct file *filp) |
36 | { | 36 | { |
37 | port->bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE; | 37 | port->bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE; |
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index c68b738900bd..9df6887b91f6 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig | |||
@@ -61,13 +61,6 @@ config USB_STORAGE_ISD200 | |||
61 | - CyQ've CQ8060A CDRW drive | 61 | - CyQ've CQ8060A CDRW drive |
62 | - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U) | 62 | - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U) |
63 | 63 | ||
64 | config USB_STORAGE_DPCM | ||
65 | bool "Microtech/ZiO! CompactFlash/SmartMedia support" | ||
66 | depends on USB_STORAGE | ||
67 | help | ||
68 | Say Y here to support the Microtech/ZiO! CompactFlash reader. | ||
69 | There is a web page at <http://www.ziocorp.com/products/>. | ||
70 | |||
71 | config USB_STORAGE_USBAT | 64 | config USB_STORAGE_USBAT |
72 | bool "USBAT/USBAT02-based storage support" | 65 | bool "USBAT/USBAT02-based storage support" |
73 | depends on USB_STORAGE | 66 | depends on USB_STORAGE |
@@ -90,12 +83,12 @@ config USB_STORAGE_USBAT | |||
90 | - Sandisk ImageMate SDDR-05b | 83 | - Sandisk ImageMate SDDR-05b |
91 | 84 | ||
92 | config USB_STORAGE_SDDR09 | 85 | config USB_STORAGE_SDDR09 |
93 | bool "SanDisk SDDR-09 (and other SmartMedia) support" | 86 | bool "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support" |
94 | depends on USB_STORAGE | 87 | depends on USB_STORAGE |
95 | help | 88 | help |
96 | Say Y here to include additional code to support the Sandisk SDDR-09 | 89 | Say Y here to include additional code to support the Sandisk SDDR-09 |
97 | SmartMedia reader in the USB Mass Storage driver. | 90 | SmartMedia reader in the USB Mass Storage driver. |
98 | Also works for the Microtech Zio! SmartMedia reader. | 91 | Also works for the Microtech Zio! CompactFlash/SmartMedia reader. |
99 | 92 | ||
100 | config USB_STORAGE_SDDR55 | 93 | config USB_STORAGE_SDDR55 |
101 | bool "SanDisk SDDR-55 SmartMedia support" | 94 | bool "SanDisk SDDR-55 SmartMedia support" |
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 7f8beb5366ae..b32069313390 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile | |||
@@ -14,7 +14,6 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o | |||
14 | usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09) += sddr09.o | 14 | usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09) += sddr09.o |
15 | usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o | 15 | usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o |
16 | usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o | 16 | usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o |
17 | usb-storage-obj-$(CONFIG_USB_STORAGE_DPCM) += dpcm.o | ||
18 | usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o | 17 | usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o |
19 | usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o | 18 | usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o |
20 | usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o | 19 | usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o |
@@ -24,7 +23,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o | |||
24 | usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o | 23 | usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o |
25 | 24 | ||
26 | usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ | 25 | usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ |
27 | initializers.o sierra_ms.o $(usb-storage-obj-y) | 26 | initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) |
28 | 27 | ||
29 | ifneq ($(CONFIG_USB_LIBUSUAL),) | 28 | ifneq ($(CONFIG_USB_LIBUSUAL),) |
30 | obj-$(CONFIG_USB) += libusual.o | 29 | obj-$(CONFIG_USB) += libusual.o |
diff --git a/drivers/usb/storage/dpcm.c b/drivers/usb/storage/dpcm.c deleted file mode 100644 index 939923471af4..000000000000 --- a/drivers/usb/storage/dpcm.c +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
1 | /* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader | ||
2 | * | ||
3 | * DPCM driver v0.1: | ||
4 | * | ||
5 | * First release | ||
6 | * | ||
7 | * Current development and maintenance by: | ||
8 | * (c) 2000 Brian Webb (webbb@earthlink.net) | ||
9 | * | ||
10 | * This device contains both a CompactFlash card reader, which | ||
11 | * uses the Control/Bulk w/o Interrupt protocol and | ||
12 | * a SmartMedia card reader that uses the same protocol | ||
13 | * as the SDDR09. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the | ||
17 | * Free Software Foundation; either version 2, or (at your option) any | ||
18 | * later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, but | ||
21 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
23 | * General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License along | ||
26 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
27 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
28 | */ | ||
29 | |||
30 | #include <scsi/scsi.h> | ||
31 | #include <scsi/scsi_cmnd.h> | ||
32 | #include <scsi/scsi_device.h> | ||
33 | |||
34 | #include "usb.h" | ||
35 | #include "transport.h" | ||
36 | #include "protocol.h" | ||
37 | #include "debug.h" | ||
38 | #include "dpcm.h" | ||
39 | #include "sddr09.h" | ||
40 | |||
41 | /* | ||
42 | * Transport for the Microtech DPCM-USB | ||
43 | * | ||
44 | */ | ||
45 | int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | if (srb == NULL) | ||
50 | return USB_STOR_TRANSPORT_ERROR; | ||
51 | |||
52 | US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun); | ||
53 | |||
54 | switch (srb->device->lun) { | ||
55 | case 0: | ||
56 | |||
57 | /* | ||
58 | * LUN 0 corresponds to the CompactFlash card reader. | ||
59 | */ | ||
60 | ret = usb_stor_CB_transport(srb, us); | ||
61 | break; | ||
62 | |||
63 | #ifdef CONFIG_USB_STORAGE_SDDR09 | ||
64 | case 1: | ||
65 | |||
66 | /* | ||
67 | * LUN 1 corresponds to the SmartMedia card reader. | ||
68 | */ | ||
69 | |||
70 | /* | ||
71 | * Set the LUN to 0 (just in case). | ||
72 | */ | ||
73 | srb->device->lun = 0; us->srb->device->lun = 0; | ||
74 | ret = sddr09_transport(srb, us); | ||
75 | srb->device->lun = 1; us->srb->device->lun = 1; | ||
76 | break; | ||
77 | |||
78 | #endif | ||
79 | |||
80 | default: | ||
81 | US_DEBUGP("dpcm_transport: Invalid LUN %d\n", srb->device->lun); | ||
82 | ret = USB_STOR_TRANSPORT_ERROR; | ||
83 | break; | ||
84 | } | ||
85 | return ret; | ||
86 | } | ||
diff --git a/drivers/usb/storage/dpcm.h b/drivers/usb/storage/dpcm.h deleted file mode 100644 index e7b7b0f120d7..000000000000 --- a/drivers/usb/storage/dpcm.h +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | /* Driver for Microtech DPCM-USB CompactFlash/SmartMedia reader | ||
2 | * | ||
3 | * DPCM driver v0.1: | ||
4 | * | ||
5 | * First release | ||
6 | * | ||
7 | * Current development and maintenance by: | ||
8 | * (c) 2000 Brian Webb (webbb@earthlink.net) | ||
9 | * | ||
10 | * See dpcm.c for more explanation | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2, or (at your option) any | ||
15 | * later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, but | ||
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
20 | * General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License along | ||
23 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
24 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _MICROTECH_DPCM_USB_H | ||
28 | #define _MICROTECH_DPCM_USB_H | ||
29 | |||
30 | extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us); | ||
31 | |||
32 | #endif | ||
diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c index d617e8ae6b00..f970b27ba308 100644 --- a/drivers/usb/storage/libusual.c +++ b/drivers/usb/storage/libusual.c | |||
@@ -46,6 +46,12 @@ static int usu_probe_thread(void *arg); | |||
46 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ | 46 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ |
47 | .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } | 47 | .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } |
48 | 48 | ||
49 | #define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ | ||
50 | vendorName, productName, useProtocol, useTransport, \ | ||
51 | initFunction, flags) \ | ||
52 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ | ||
53 | .driver_info = (flags) } | ||
54 | |||
49 | #define USUAL_DEV(useProto, useTrans, useType) \ | 55 | #define USUAL_DEV(useProto, useTrans, useType) \ |
50 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ | 56 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ |
51 | .driver_info = ((useType)<<24) } | 57 | .driver_info = ((useType)<<24) } |
@@ -57,6 +63,7 @@ struct usb_device_id storage_usb_ids [] = { | |||
57 | 63 | ||
58 | #undef USUAL_DEV | 64 | #undef USUAL_DEV |
59 | #undef UNUSUAL_DEV | 65 | #undef UNUSUAL_DEV |
66 | #undef COMPLIANT_DEV | ||
60 | 67 | ||
61 | MODULE_DEVICE_TABLE(usb, storage_usb_ids); | 68 | MODULE_DEVICE_TABLE(usb, storage_usb_ids); |
62 | EXPORT_SYMBOL_GPL(storage_usb_ids); | 69 | EXPORT_SYMBOL_GPL(storage_usb_ids); |
diff --git a/drivers/usb/storage/option_ms.c b/drivers/usb/storage/option_ms.c new file mode 100644 index 000000000000..353f922939a4 --- /dev/null +++ b/drivers/usb/storage/option_ms.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | * Driver for Option High Speed Mobile Devices. | ||
3 | * | ||
4 | * (c) 2008 Dan Williams <dcbw@redhat.com> | ||
5 | * | ||
6 | * Inspiration taken from sierra_ms.c by Kevin Lloyd <klloyd@sierrawireless.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/usb.h> | ||
24 | |||
25 | #include "usb.h" | ||
26 | #include "transport.h" | ||
27 | #include "option_ms.h" | ||
28 | #include "debug.h" | ||
29 | |||
30 | #define ZCD_FORCE_MODEM 0x01 | ||
31 | #define ZCD_ALLOW_MS 0x02 | ||
32 | |||
33 | static unsigned int option_zero_cd = ZCD_FORCE_MODEM; | ||
34 | module_param(option_zero_cd, uint, S_IRUGO | S_IWUSR); | ||
35 | MODULE_PARM_DESC(option_zero_cd, "ZeroCD mode (1=Force Modem (default)," | ||
36 | " 2=Allow CD-Rom"); | ||
37 | |||
38 | #define RESPONSE_LEN 1024 | ||
39 | |||
40 | static int option_rezero(struct us_data *us, int ep_in, int ep_out) | ||
41 | { | ||
42 | const unsigned char rezero_msg[] = { | ||
43 | 0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12, | ||
44 | 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x01, | ||
45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
47 | }; | ||
48 | char *buffer; | ||
49 | int result; | ||
50 | |||
51 | US_DEBUGP("Option MS: %s", "DEVICE MODE SWITCH\n"); | ||
52 | |||
53 | buffer = kzalloc(RESPONSE_LEN, GFP_KERNEL); | ||
54 | if (buffer == NULL) | ||
55 | return USB_STOR_TRANSPORT_ERROR; | ||
56 | |||
57 | memcpy(buffer, rezero_msg, sizeof (rezero_msg)); | ||
58 | result = usb_stor_bulk_transfer_buf(us, | ||
59 | usb_sndbulkpipe(us->pusb_dev, ep_out), | ||
60 | buffer, sizeof (rezero_msg), NULL); | ||
61 | if (result != USB_STOR_XFER_GOOD) { | ||
62 | result = USB_STOR_XFER_ERROR; | ||
63 | goto out; | ||
64 | } | ||
65 | |||
66 | /* Some of the devices need to be asked for a response, but we don't | ||
67 | * care what that response is. | ||
68 | */ | ||
69 | result = usb_stor_bulk_transfer_buf(us, | ||
70 | usb_sndbulkpipe(us->pusb_dev, ep_out), | ||
71 | buffer, RESPONSE_LEN, NULL); | ||
72 | result = USB_STOR_XFER_GOOD; | ||
73 | |||
74 | out: | ||
75 | kfree(buffer); | ||
76 | return result; | ||
77 | } | ||
78 | |||
79 | int option_ms_init(struct us_data *us) | ||
80 | { | ||
81 | struct usb_device *udev; | ||
82 | struct usb_interface *intf; | ||
83 | struct usb_host_interface *iface_desc; | ||
84 | struct usb_endpoint_descriptor *endpoint = NULL; | ||
85 | u8 ep_in = 0, ep_out = 0; | ||
86 | int ep_in_size = 0, ep_out_size = 0; | ||
87 | int i, result; | ||
88 | |||
89 | udev = us->pusb_dev; | ||
90 | intf = us->pusb_intf; | ||
91 | |||
92 | /* Ensure it's really a ZeroCD device; devices that are already | ||
93 | * in modem mode return 0xFF for class, subclass, and protocol. | ||
94 | */ | ||
95 | if (udev->descriptor.bDeviceClass != 0 || | ||
96 | udev->descriptor.bDeviceSubClass != 0 || | ||
97 | udev->descriptor.bDeviceProtocol != 0) | ||
98 | return USB_STOR_TRANSPORT_GOOD; | ||
99 | |||
100 | US_DEBUGP("Option MS: option_ms_init called\n"); | ||
101 | |||
102 | /* Find the right mass storage interface */ | ||
103 | iface_desc = intf->cur_altsetting; | ||
104 | if (iface_desc->desc.bInterfaceClass != 0x8 || | ||
105 | iface_desc->desc.bInterfaceSubClass != 0x6 || | ||
106 | iface_desc->desc.bInterfaceProtocol != 0x50) { | ||
107 | US_DEBUGP("Option MS: mass storage interface not found, no action " | ||
108 | "required\n"); | ||
109 | return USB_STOR_TRANSPORT_GOOD; | ||
110 | } | ||
111 | |||
112 | /* Find the mass storage bulk endpoints */ | ||
113 | for (i = 0; i < iface_desc->desc.bNumEndpoints && (!ep_in_size || !ep_out_size); ++i) { | ||
114 | endpoint = &iface_desc->endpoint[i].desc; | ||
115 | |||
116 | if (usb_endpoint_is_bulk_in(endpoint)) { | ||
117 | ep_in = usb_endpoint_num(endpoint); | ||
118 | ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize); | ||
119 | } else if (usb_endpoint_is_bulk_out(endpoint)) { | ||
120 | ep_out = usb_endpoint_num(endpoint); | ||
121 | ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | /* Can't find the mass storage endpoints */ | ||
126 | if (!ep_in_size || !ep_out_size) { | ||
127 | US_DEBUGP("Option MS: mass storage endpoints not found, no action " | ||
128 | "required\n"); | ||
129 | return USB_STOR_TRANSPORT_GOOD; | ||
130 | } | ||
131 | |||
132 | /* Force Modem mode */ | ||
133 | if (option_zero_cd == ZCD_FORCE_MODEM) { | ||
134 | US_DEBUGP("Option MS: %s", "Forcing Modem Mode\n"); | ||
135 | result = option_rezero(us, ep_in, ep_out); | ||
136 | if (result != USB_STOR_XFER_GOOD) | ||
137 | US_DEBUGP("Option MS: Failed to switch to modem mode.\n"); | ||
138 | return -EIO; | ||
139 | } else if (option_zero_cd == ZCD_ALLOW_MS) { | ||
140 | /* Allow Mass Storage mode (keep CD-Rom) */ | ||
141 | US_DEBUGP("Option MS: %s", "Allowing Mass Storage Mode if device" | ||
142 | " requests it\n"); | ||
143 | } | ||
144 | |||
145 | return USB_STOR_TRANSPORT_GOOD; | ||
146 | } | ||
147 | |||
diff --git a/drivers/usb/storage/option_ms.h b/drivers/usb/storage/option_ms.h new file mode 100644 index 000000000000..b6e448cab039 --- /dev/null +++ b/drivers/usb/storage/option_ms.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #ifndef _OPTION_MS_H_ | ||
2 | #define _OPTION_MS_H_ | ||
3 | extern int option_ms_init(struct us_data *us); | ||
4 | #endif | ||
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index 3b3357e20ea7..be441d84bc64 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c | |||
@@ -56,9 +56,9 @@ | |||
56 | * Protocol routines | 56 | * Protocol routines |
57 | ***********************************************************************/ | 57 | ***********************************************************************/ |
58 | 58 | ||
59 | void usb_stor_qic157_command(struct scsi_cmnd *srb, struct us_data *us) | 59 | void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us) |
60 | { | 60 | { |
61 | /* Pad the ATAPI command with zeros | 61 | /* Pad the SCSI command with zeros out to 12 bytes |
62 | * | 62 | * |
63 | * NOTE: This only works because a scsi_cmnd struct field contains | 63 | * NOTE: This only works because a scsi_cmnd struct field contains |
64 | * a unsigned char cmnd[16], so we know we have storage available | 64 | * a unsigned char cmnd[16], so we know we have storage available |
@@ -73,26 +73,6 @@ void usb_stor_qic157_command(struct scsi_cmnd *srb, struct us_data *us) | |||
73 | usb_stor_invoke_transport(srb, us); | 73 | usb_stor_invoke_transport(srb, us); |
74 | } | 74 | } |
75 | 75 | ||
76 | void usb_stor_ATAPI_command(struct scsi_cmnd *srb, struct us_data *us) | ||
77 | { | ||
78 | /* Pad the ATAPI command with zeros | ||
79 | * | ||
80 | * NOTE: This only works because a scsi_cmnd struct field contains | ||
81 | * a unsigned char cmnd[16], so we know we have storage available | ||
82 | */ | ||
83 | |||
84 | /* Pad the ATAPI command with zeros */ | ||
85 | for (; srb->cmd_len<12; srb->cmd_len++) | ||
86 | srb->cmnd[srb->cmd_len] = 0; | ||
87 | |||
88 | /* set command length to 12 bytes */ | ||
89 | srb->cmd_len = 12; | ||
90 | |||
91 | /* send the command to the transport layer */ | ||
92 | usb_stor_invoke_transport(srb, us); | ||
93 | } | ||
94 | |||
95 | |||
96 | void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us) | 76 | void usb_stor_ufi_command(struct scsi_cmnd *srb, struct us_data *us) |
97 | { | 77 | { |
98 | /* fix some commands -- this is a form of mode translation | 78 | /* fix some commands -- this is a form of mode translation |
diff --git a/drivers/usb/storage/protocol.h b/drivers/usb/storage/protocol.h index 487056ffb516..ffc3e2af0156 100644 --- a/drivers/usb/storage/protocol.h +++ b/drivers/usb/storage/protocol.h | |||
@@ -40,8 +40,7 @@ | |||
40 | #define _PROTOCOL_H_ | 40 | #define _PROTOCOL_H_ |
41 | 41 | ||
42 | /* Protocol handling routines */ | 42 | /* Protocol handling routines */ |
43 | extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*); | 43 | extern void usb_stor_pad12_command(struct scsi_cmnd*, struct us_data*); |
44 | extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*); | ||
45 | extern void usb_stor_ufi_command(struct scsi_cmnd*, struct us_data*); | 44 | extern void usb_stor_ufi_command(struct scsi_cmnd*, struct us_data*); |
46 | extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*, | 45 | extern void usb_stor_transparent_scsi_command(struct scsi_cmnd*, |
47 | struct us_data*); | 46 | struct us_data*); |
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 09779f6a8179..2a42b862aa9f 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c | |||
@@ -59,6 +59,13 @@ | |||
59 | #include "transport.h" | 59 | #include "transport.h" |
60 | #include "protocol.h" | 60 | #include "protocol.h" |
61 | 61 | ||
62 | /* Vendor IDs for companies that seem to include the READ CAPACITY bug | ||
63 | * in all their devices | ||
64 | */ | ||
65 | #define VENDOR_ID_NOKIA 0x0421 | ||
66 | #define VENDOR_ID_NIKON 0x04b0 | ||
67 | #define VENDOR_ID_MOTOROLA 0x22b8 | ||
68 | |||
62 | /*********************************************************************** | 69 | /*********************************************************************** |
63 | * Host functions | 70 | * Host functions |
64 | ***********************************************************************/ | 71 | ***********************************************************************/ |
@@ -129,11 +136,35 @@ static int slave_configure(struct scsi_device *sdev) | |||
129 | max_sectors); | 136 | max_sectors); |
130 | } | 137 | } |
131 | 138 | ||
139 | /* Some USB host controllers can't do DMA; they have to use PIO. | ||
140 | * They indicate this by setting their dma_mask to NULL. For | ||
141 | * such controllers we need to make sure the block layer sets | ||
142 | * up bounce buffers in addressable memory. | ||
143 | */ | ||
144 | if (!us->pusb_dev->bus->controller->dma_mask) | ||
145 | blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH); | ||
146 | |||
132 | /* We can't put these settings in slave_alloc() because that gets | 147 | /* We can't put these settings in slave_alloc() because that gets |
133 | * called before the device type is known. Consequently these | 148 | * called before the device type is known. Consequently these |
134 | * settings can't be overridden via the scsi devinfo mechanism. */ | 149 | * settings can't be overridden via the scsi devinfo mechanism. */ |
135 | if (sdev->type == TYPE_DISK) { | 150 | if (sdev->type == TYPE_DISK) { |
136 | 151 | ||
152 | /* Some vendors seem to put the READ CAPACITY bug into | ||
153 | * all their devices -- primarily makers of cell phones | ||
154 | * and digital cameras. Since these devices always use | ||
155 | * flash media and can be expected to have an even number | ||
156 | * of sectors, we will always enable the CAPACITY_HEURISTICS | ||
157 | * flag unless told otherwise. */ | ||
158 | switch (le16_to_cpu(us->pusb_dev->descriptor.idVendor)) { | ||
159 | case VENDOR_ID_NOKIA: | ||
160 | case VENDOR_ID_NIKON: | ||
161 | case VENDOR_ID_MOTOROLA: | ||
162 | if (!(us->fflags & (US_FL_FIX_CAPACITY | | ||
163 | US_FL_CAPACITY_OK))) | ||
164 | us->fflags |= US_FL_CAPACITY_HEURISTICS; | ||
165 | break; | ||
166 | } | ||
167 | |||
137 | /* Disk-type devices use MODE SENSE(6) if the protocol | 168 | /* Disk-type devices use MODE SENSE(6) if the protocol |
138 | * (SubClass) is Transparent SCSI, otherwise they use | 169 | * (SubClass) is Transparent SCSI, otherwise they use |
139 | * MODE SENSE(10). */ | 170 | * MODE SENSE(10). */ |
@@ -170,6 +201,10 @@ static int slave_configure(struct scsi_device *sdev) | |||
170 | if (us->fflags & US_FL_CAPACITY_HEURISTICS) | 201 | if (us->fflags & US_FL_CAPACITY_HEURISTICS) |
171 | sdev->guess_capacity = 1; | 202 | sdev->guess_capacity = 1; |
172 | 203 | ||
204 | /* assume SPC3 or latter devices support sense size > 18 */ | ||
205 | if (sdev->scsi_level > SCSI_SPC_2) | ||
206 | us->fflags |= US_FL_SANE_SENSE; | ||
207 | |||
173 | /* Some devices report a SCSI revision level above 2 but are | 208 | /* Some devices report a SCSI revision level above 2 but are |
174 | * unable to handle the REPORT LUNS command (for which | 209 | * unable to handle the REPORT LUNS command (for which |
175 | * support is mandatory at level 3). Since we already have | 210 | * support is mandatory at level 3). Since we already have |
@@ -196,6 +231,14 @@ static int slave_configure(struct scsi_device *sdev) | |||
196 | * sector in a larger then 1 sector read, since the performance | 231 | * sector in a larger then 1 sector read, since the performance |
197 | * impact is negible we set this flag for all USB disks */ | 232 | * impact is negible we set this flag for all USB disks */ |
198 | sdev->last_sector_bug = 1; | 233 | sdev->last_sector_bug = 1; |
234 | |||
235 | /* Enable last-sector hacks for single-target devices using | ||
236 | * the Bulk-only transport, unless we already know the | ||
237 | * capacity will be decremented or is correct. */ | ||
238 | if (!(us->fflags & (US_FL_FIX_CAPACITY | US_FL_CAPACITY_OK | | ||
239 | US_FL_SCM_MULT_TARG)) && | ||
240 | us->protocol == US_PR_BULK) | ||
241 | us->use_last_sector_hacks = 1; | ||
199 | } else { | 242 | } else { |
200 | 243 | ||
201 | /* Non-disk-type devices don't need to blacklist any pages | 244 | /* Non-disk-type devices don't need to blacklist any pages |
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index c5a54b872c24..531ae5c5abf3 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c | |||
@@ -45,6 +45,7 @@ | |||
45 | 45 | ||
46 | #include <scsi/scsi.h> | 46 | #include <scsi/scsi.h> |
47 | #include <scsi/scsi_cmnd.h> | 47 | #include <scsi/scsi_cmnd.h> |
48 | #include <scsi/scsi_device.h> | ||
48 | 49 | ||
49 | #include "usb.h" | 50 | #include "usb.h" |
50 | #include "transport.h" | 51 | #include "transport.h" |
@@ -1446,6 +1447,48 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) { | |||
1446 | } | 1447 | } |
1447 | 1448 | ||
1448 | /* | 1449 | /* |
1450 | * Transport for the Microtech DPCM-USB | ||
1451 | */ | ||
1452 | int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) | ||
1453 | { | ||
1454 | int ret; | ||
1455 | |||
1456 | US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun); | ||
1457 | |||
1458 | switch (srb->device->lun) { | ||
1459 | case 0: | ||
1460 | |||
1461 | /* | ||
1462 | * LUN 0 corresponds to the CompactFlash card reader. | ||
1463 | */ | ||
1464 | ret = usb_stor_CB_transport(srb, us); | ||
1465 | break; | ||
1466 | |||
1467 | case 1: | ||
1468 | |||
1469 | /* | ||
1470 | * LUN 1 corresponds to the SmartMedia card reader. | ||
1471 | */ | ||
1472 | |||
1473 | /* | ||
1474 | * Set the LUN to 0 (just in case). | ||
1475 | */ | ||
1476 | srb->device->lun = 0; | ||
1477 | ret = sddr09_transport(srb, us); | ||
1478 | srb->device->lun = 1; | ||
1479 | break; | ||
1480 | |||
1481 | default: | ||
1482 | US_DEBUGP("dpcm_transport: Invalid LUN %d\n", | ||
1483 | srb->device->lun); | ||
1484 | ret = USB_STOR_TRANSPORT_ERROR; | ||
1485 | break; | ||
1486 | } | ||
1487 | return ret; | ||
1488 | } | ||
1489 | |||
1490 | |||
1491 | /* | ||
1449 | * Transport for the Sandisk SDDR-09 | 1492 | * Transport for the Sandisk SDDR-09 |
1450 | */ | 1493 | */ |
1451 | int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) | 1494 | int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) |
diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h index e50033ad7b19..b701172e12e3 100644 --- a/drivers/usb/storage/sddr09.h +++ b/drivers/usb/storage/sddr09.h | |||
@@ -28,8 +28,11 @@ | |||
28 | /* Sandisk SDDR-09 stuff */ | 28 | /* Sandisk SDDR-09 stuff */ |
29 | 29 | ||
30 | extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); | 30 | extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); |
31 | extern int usb_stor_sddr09_init(struct us_data *us); | ||
32 | |||
33 | /* Microtech DPCM-USB stuff */ | ||
31 | 34 | ||
35 | extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us); | ||
32 | extern int usb_stor_sddr09_dpcm_init(struct us_data *us); | 36 | extern int usb_stor_sddr09_dpcm_init(struct us_data *us); |
33 | extern int usb_stor_sddr09_init(struct us_data *us); | ||
34 | 37 | ||
35 | #endif | 38 | #endif |
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 79108d5d3171..1d5438e6363b 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c | |||
@@ -57,6 +57,9 @@ | |||
57 | #include "scsiglue.h" | 57 | #include "scsiglue.h" |
58 | #include "debug.h" | 58 | #include "debug.h" |
59 | 59 | ||
60 | #include <linux/blkdev.h> | ||
61 | #include "../../scsi/sd.h" | ||
62 | |||
60 | 63 | ||
61 | /*********************************************************************** | 64 | /*********************************************************************** |
62 | * Data transfer routines | 65 | * Data transfer routines |
@@ -511,6 +514,110 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe, | |||
511 | * Transport routines | 514 | * Transport routines |
512 | ***********************************************************************/ | 515 | ***********************************************************************/ |
513 | 516 | ||
517 | /* There are so many devices that report the capacity incorrectly, | ||
518 | * this routine was written to counteract some of the resulting | ||
519 | * problems. | ||
520 | */ | ||
521 | static void last_sector_hacks(struct us_data *us, struct scsi_cmnd *srb) | ||
522 | { | ||
523 | struct gendisk *disk; | ||
524 | struct scsi_disk *sdkp; | ||
525 | u32 sector; | ||
526 | |||
527 | /* To Report "Medium Error: Record Not Found */ | ||
528 | static unsigned char record_not_found[18] = { | ||
529 | [0] = 0x70, /* current error */ | ||
530 | [2] = MEDIUM_ERROR, /* = 0x03 */ | ||
531 | [7] = 0x0a, /* additional length */ | ||
532 | [12] = 0x14 /* Record Not Found */ | ||
533 | }; | ||
534 | |||
535 | /* If last-sector problems can't occur, whether because the | ||
536 | * capacity was already decremented or because the device is | ||
537 | * known to report the correct capacity, then we don't need | ||
538 | * to do anything. | ||
539 | */ | ||
540 | if (!us->use_last_sector_hacks) | ||
541 | return; | ||
542 | |||
543 | /* Was this command a READ(10) or a WRITE(10)? */ | ||
544 | if (srb->cmnd[0] != READ_10 && srb->cmnd[0] != WRITE_10) | ||
545 | goto done; | ||
546 | |||
547 | /* Did this command access the last sector? */ | ||
548 | sector = (srb->cmnd[2] << 24) | (srb->cmnd[3] << 16) | | ||
549 | (srb->cmnd[4] << 8) | (srb->cmnd[5]); | ||
550 | disk = srb->request->rq_disk; | ||
551 | if (!disk) | ||
552 | goto done; | ||
553 | sdkp = scsi_disk(disk); | ||
554 | if (!sdkp) | ||
555 | goto done; | ||
556 | if (sector + 1 != sdkp->capacity) | ||
557 | goto done; | ||
558 | |||
559 | if (srb->result == SAM_STAT_GOOD && scsi_get_resid(srb) == 0) { | ||
560 | |||
561 | /* The command succeeded. If the capacity is odd | ||
562 | * (i.e., if the sector number is even) then the | ||
563 | * "always-even" heuristic would be wrong for this | ||
564 | * device. Issue a WARN() so that the kerneloops.org | ||
565 | * project will be notified and we will then know to | ||
566 | * mark the device with a CAPACITY_OK flag. Hopefully | ||
567 | * this will occur for only a few devices. | ||
568 | * | ||
569 | * Use the sign of us->last_sector_hacks to tell whether | ||
570 | * the warning has already been issued; we don't need | ||
571 | * more than one warning per device. | ||
572 | */ | ||
573 | if (!(sector & 1) && us->use_last_sector_hacks > 0) { | ||
574 | unsigned vid = le16_to_cpu( | ||
575 | us->pusb_dev->descriptor.idVendor); | ||
576 | unsigned pid = le16_to_cpu( | ||
577 | us->pusb_dev->descriptor.idProduct); | ||
578 | unsigned rev = le16_to_cpu( | ||
579 | us->pusb_dev->descriptor.bcdDevice); | ||
580 | |||
581 | WARN(1, "%s: Successful last sector success at %u, " | ||
582 | "device %04x:%04x:%04x\n", | ||
583 | sdkp->disk->disk_name, sector, | ||
584 | vid, pid, rev); | ||
585 | us->use_last_sector_hacks = -1; | ||
586 | } | ||
587 | |||
588 | } else { | ||
589 | /* The command failed. Allow up to 3 retries in case this | ||
590 | * is some normal sort of failure. After that, assume the | ||
591 | * capacity is wrong and we're trying to access the sector | ||
592 | * beyond the end. Replace the result code and sense data | ||
593 | * with values that will cause the SCSI core to fail the | ||
594 | * command immediately, instead of going into an infinite | ||
595 | * (or even just a very long) retry loop. | ||
596 | */ | ||
597 | if (++us->last_sector_retries < 3) | ||
598 | return; | ||
599 | srb->result = SAM_STAT_CHECK_CONDITION; | ||
600 | memcpy(srb->sense_buffer, record_not_found, | ||
601 | sizeof(record_not_found)); | ||
602 | |||
603 | /* In theory we might want to issue a WARN() here if the | ||
604 | * capacity is even, since it could indicate the device | ||
605 | * has the READ CAPACITY bug _and_ the real capacity is | ||
606 | * odd. But it could also indicate that the device | ||
607 | * simply can't access its last sector, a failure mode | ||
608 | * which is surprisingly common. So no warning. | ||
609 | */ | ||
610 | } | ||
611 | |||
612 | done: | ||
613 | /* Don't reset the retry counter for TEST UNIT READY commands, | ||
614 | * because they get issued after device resets which might be | ||
615 | * caused by a failed last-sector access. | ||
616 | */ | ||
617 | if (srb->cmnd[0] != TEST_UNIT_READY) | ||
618 | us->last_sector_retries = 0; | ||
619 | } | ||
620 | |||
514 | /* Invoke the transport and basic error-handling/recovery methods | 621 | /* Invoke the transport and basic error-handling/recovery methods |
515 | * | 622 | * |
516 | * This is used by the protocol layers to actually send the message to | 623 | * This is used by the protocol layers to actually send the message to |
@@ -544,6 +651,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
544 | /* if the transport provided its own sense data, don't auto-sense */ | 651 | /* if the transport provided its own sense data, don't auto-sense */ |
545 | if (result == USB_STOR_TRANSPORT_NO_SENSE) { | 652 | if (result == USB_STOR_TRANSPORT_NO_SENSE) { |
546 | srb->result = SAM_STAT_CHECK_CONDITION; | 653 | srb->result = SAM_STAT_CHECK_CONDITION; |
654 | last_sector_hacks(us, srb); | ||
547 | return; | 655 | return; |
548 | } | 656 | } |
549 | 657 | ||
@@ -579,6 +687,20 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
579 | } | 687 | } |
580 | 688 | ||
581 | /* | 689 | /* |
690 | * Determine if this device is SAT by seeing if the | ||
691 | * command executed successfully. Otherwise we'll have | ||
692 | * to wait for at least one CHECK_CONDITION to determine | ||
693 | * SANE_SENSE support | ||
694 | */ | ||
695 | if ((srb->cmnd[0] == ATA_16 || srb->cmnd[0] == ATA_12) && | ||
696 | result == USB_STOR_TRANSPORT_GOOD && | ||
697 | !(us->fflags & US_FL_SANE_SENSE) && | ||
698 | !(srb->cmnd[2] & 0x20)) { | ||
699 | US_DEBUGP("-- SAT supported, increasing auto-sense\n"); | ||
700 | us->fflags |= US_FL_SANE_SENSE; | ||
701 | } | ||
702 | |||
703 | /* | ||
582 | * A short transfer on a command where we don't expect it | 704 | * A short transfer on a command where we don't expect it |
583 | * is unusual, but it doesn't mean we need to auto-sense. | 705 | * is unusual, but it doesn't mean we need to auto-sense. |
584 | */ | 706 | */ |
@@ -595,10 +717,15 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
595 | if (need_auto_sense) { | 717 | if (need_auto_sense) { |
596 | int temp_result; | 718 | int temp_result; |
597 | struct scsi_eh_save ses; | 719 | struct scsi_eh_save ses; |
720 | int sense_size = US_SENSE_SIZE; | ||
721 | |||
722 | /* device supports and needs bigger sense buffer */ | ||
723 | if (us->fflags & US_FL_SANE_SENSE) | ||
724 | sense_size = ~0; | ||
598 | 725 | ||
599 | US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); | 726 | US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); |
600 | 727 | ||
601 | scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE); | 728 | scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size); |
602 | 729 | ||
603 | /* FIXME: we must do the protocol translation here */ | 730 | /* FIXME: we must do the protocol translation here */ |
604 | if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI || | 731 | if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI || |
@@ -632,6 +759,25 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
632 | return; | 759 | return; |
633 | } | 760 | } |
634 | 761 | ||
762 | /* If the sense data returned is larger than 18-bytes then we | ||
763 | * assume this device supports requesting more in the future. | ||
764 | * The response code must be 70h through 73h inclusive. | ||
765 | */ | ||
766 | if (srb->sense_buffer[7] > (US_SENSE_SIZE - 8) && | ||
767 | !(us->fflags & US_FL_SANE_SENSE) && | ||
768 | (srb->sense_buffer[0] & 0x7C) == 0x70) { | ||
769 | US_DEBUGP("-- SANE_SENSE support enabled\n"); | ||
770 | us->fflags |= US_FL_SANE_SENSE; | ||
771 | |||
772 | /* Indicate to the user that we truncated their sense | ||
773 | * because we didn't know it supported larger sense. | ||
774 | */ | ||
775 | US_DEBUGP("-- Sense data truncated to %i from %i\n", | ||
776 | US_SENSE_SIZE, | ||
777 | srb->sense_buffer[7] + 8); | ||
778 | srb->sense_buffer[7] = (US_SENSE_SIZE - 8); | ||
779 | } | ||
780 | |||
635 | US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); | 781 | US_DEBUGP("-- Result from auto-sense is %d\n", temp_result); |
636 | US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", | 782 | US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n", |
637 | srb->sense_buffer[0], | 783 | srb->sense_buffer[0], |
@@ -667,6 +813,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
667 | scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) | 813 | scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) |
668 | srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24); | 814 | srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24); |
669 | 815 | ||
816 | last_sector_hacks(us, srb); | ||
670 | return; | 817 | return; |
671 | 818 | ||
672 | /* Error and abort processing: try to resynchronize with the device | 819 | /* Error and abort processing: try to resynchronize with the device |
@@ -694,6 +841,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
694 | us->transport_reset(us); | 841 | us->transport_reset(us); |
695 | } | 842 | } |
696 | clear_bit(US_FLIDX_RESETTING, &us->dflags); | 843 | clear_bit(US_FLIDX_RESETTING, &us->dflags); |
844 | last_sector_hacks(us, srb); | ||
697 | } | 845 | } |
698 | 846 | ||
699 | /* Stop the current URB transfer */ | 847 | /* Stop the current URB transfer */ |
@@ -718,10 +866,10 @@ void usb_stor_stop_transport(struct us_data *us) | |||
718 | } | 866 | } |
719 | 867 | ||
720 | /* | 868 | /* |
721 | * Control/Bulk/Interrupt transport | 869 | * Control/Bulk and Control/Bulk/Interrupt transport |
722 | */ | 870 | */ |
723 | 871 | ||
724 | int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us) | 872 | int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) |
725 | { | 873 | { |
726 | unsigned int transfer_length = scsi_bufflen(srb); | 874 | unsigned int transfer_length = scsi_bufflen(srb); |
727 | unsigned int pipe = 0; | 875 | unsigned int pipe = 0; |
@@ -763,6 +911,13 @@ int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
763 | } | 911 | } |
764 | 912 | ||
765 | /* STATUS STAGE */ | 913 | /* STATUS STAGE */ |
914 | |||
915 | /* NOTE: CB does not have a status stage. Silly, I know. So | ||
916 | * we have to catch this at a higher level. | ||
917 | */ | ||
918 | if (us->protocol != US_PR_CBI) | ||
919 | return USB_STOR_TRANSPORT_GOOD; | ||
920 | |||
766 | result = usb_stor_intr_transfer(us, us->iobuf, 2); | 921 | result = usb_stor_intr_transfer(us, us->iobuf, 2); |
767 | US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", | 922 | US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", |
768 | us->iobuf[0], us->iobuf[1]); | 923 | us->iobuf[0], us->iobuf[1]); |
@@ -817,56 +972,6 @@ int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us) | |||
817 | } | 972 | } |
818 | 973 | ||
819 | /* | 974 | /* |
820 | * Control/Bulk transport | ||
821 | */ | ||
822 | int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) | ||
823 | { | ||
824 | unsigned int transfer_length = scsi_bufflen(srb); | ||
825 | int result; | ||
826 | |||
827 | /* COMMAND STAGE */ | ||
828 | /* let's send the command via the control pipe */ | ||
829 | result = usb_stor_ctrl_transfer(us, us->send_ctrl_pipe, | ||
830 | US_CBI_ADSC, | ||
831 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, | ||
832 | us->ifnum, srb->cmnd, srb->cmd_len); | ||
833 | |||
834 | /* check the return code for the command */ | ||
835 | US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result); | ||
836 | |||
837 | /* if we stalled the command, it means command failed */ | ||
838 | if (result == USB_STOR_XFER_STALLED) { | ||
839 | return USB_STOR_TRANSPORT_FAILED; | ||
840 | } | ||
841 | |||
842 | /* Uh oh... serious problem here */ | ||
843 | if (result != USB_STOR_XFER_GOOD) { | ||
844 | return USB_STOR_TRANSPORT_ERROR; | ||
845 | } | ||
846 | |||
847 | /* DATA STAGE */ | ||
848 | /* transfer the data payload for this command, if one exists*/ | ||
849 | if (transfer_length) { | ||
850 | unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? | ||
851 | us->recv_bulk_pipe : us->send_bulk_pipe; | ||
852 | result = usb_stor_bulk_srb(us, pipe, srb); | ||
853 | US_DEBUGP("CB data stage result is 0x%x\n", result); | ||
854 | |||
855 | /* if we stalled the data transfer it means command failed */ | ||
856 | if (result == USB_STOR_XFER_STALLED) | ||
857 | return USB_STOR_TRANSPORT_FAILED; | ||
858 | if (result > USB_STOR_XFER_STALLED) | ||
859 | return USB_STOR_TRANSPORT_ERROR; | ||
860 | } | ||
861 | |||
862 | /* STATUS STAGE */ | ||
863 | /* NOTE: CB does not have a status stage. Silly, I know. So | ||
864 | * we have to catch this at a higher level. | ||
865 | */ | ||
866 | return USB_STOR_TRANSPORT_GOOD; | ||
867 | } | ||
868 | |||
869 | /* | ||
870 | * Bulk only transport | 975 | * Bulk only transport |
871 | */ | 976 | */ |
872 | 977 | ||
@@ -1173,10 +1278,9 @@ int usb_stor_Bulk_reset(struct us_data *us) | |||
1173 | */ | 1278 | */ |
1174 | int usb_stor_port_reset(struct us_data *us) | 1279 | int usb_stor_port_reset(struct us_data *us) |
1175 | { | 1280 | { |
1176 | int result, rc_lock; | 1281 | int result; |
1177 | 1282 | ||
1178 | result = rc_lock = | 1283 | result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); |
1179 | usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); | ||
1180 | if (result < 0) | 1284 | if (result < 0) |
1181 | US_DEBUGP("unable to lock device for reset: %d\n", result); | 1285 | US_DEBUGP("unable to lock device for reset: %d\n", result); |
1182 | else { | 1286 | else { |
@@ -1189,8 +1293,7 @@ int usb_stor_port_reset(struct us_data *us) | |||
1189 | US_DEBUGP("usb_reset_device returns %d\n", | 1293 | US_DEBUGP("usb_reset_device returns %d\n", |
1190 | result); | 1294 | result); |
1191 | } | 1295 | } |
1192 | if (rc_lock) | 1296 | usb_unlock_device(us->pusb_dev); |
1193 | usb_unlock_device(us->pusb_dev); | ||
1194 | } | 1297 | } |
1195 | return result; | 1298 | return result; |
1196 | } | 1299 | } |
diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index e70b88182f0e..242ff5e791a5 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h | |||
@@ -113,8 +113,6 @@ struct bulk_cs_wrap { | |||
113 | 113 | ||
114 | #define US_CBI_ADSC 0 | 114 | #define US_CBI_ADSC 0 |
115 | 115 | ||
116 | extern int usb_stor_CBI_transport(struct scsi_cmnd *, struct us_data*); | ||
117 | |||
118 | extern int usb_stor_CB_transport(struct scsi_cmnd *, struct us_data*); | 116 | extern int usb_stor_CB_transport(struct scsi_cmnd *, struct us_data*); |
119 | extern int usb_stor_CB_reset(struct us_data*); | 117 | extern int usb_stor_CB_reset(struct us_data*); |
120 | 118 | ||
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index bfcc1fe82518..a7f9513fa19d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -27,7 +27,8 @@ | |||
27 | 27 | ||
28 | /* IMPORTANT NOTE: This file must be included in another file which does | 28 | /* IMPORTANT NOTE: This file must be included in another file which does |
29 | * the following thing for it to work: | 29 | * the following thing for it to work: |
30 | * The macro UNUSUAL_DEV() must be defined before this file is included | 30 | * The UNUSUAL_DEV, COMPLIANT_DEV, and USUAL_DEV macros must be defined |
31 | * before this file is included. | ||
31 | */ | 32 | */ |
32 | 33 | ||
33 | /* If you edit this file, please try to keep it sorted first by VendorID, | 34 | /* If you edit this file, please try to keep it sorted first by VendorID, |
@@ -46,6 +47,12 @@ | |||
46 | * <usb-storage@lists.one-eyed-alien.net> | 47 | * <usb-storage@lists.one-eyed-alien.net> |
47 | */ | 48 | */ |
48 | 49 | ||
50 | /* Note: If you add an entry only in order to set the CAPACITY_OK flag, | ||
51 | * use the COMPLIANT_DEV macro instead of UNUSUAL_DEV. This is | ||
52 | * because such entries mark devices which actually work correctly, | ||
53 | * as opposed to devices that do something strangely or wrongly. | ||
54 | */ | ||
55 | |||
49 | /* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr> | 56 | /* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr> |
50 | */ | 57 | */ |
51 | UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, | 58 | UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, |
@@ -85,6 +92,13 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, | |||
85 | US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), | 92 | US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), |
86 | #endif | 93 | #endif |
87 | 94 | ||
95 | /* Reported by Ben Efros <ben@pc-doctor.com> */ | ||
96 | UNUSUAL_DEV( 0x03f0, 0x070c, 0x0000, 0x0000, | ||
97 | "HP", | ||
98 | "Personal Media Drive", | ||
99 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
100 | US_FL_SANE_SENSE ), | ||
101 | |||
88 | /* Reported by Grant Grundler <grundler@parisc-linux.org> | 102 | /* Reported by Grant Grundler <grundler@parisc-linux.org> |
89 | * HP r707 camera in "Disk" mode with 2.00.23 or 2.00.24 firmware. | 103 | * HP r707 camera in "Disk" mode with 2.00.23 or 2.00.24 firmware. |
90 | */ | 104 | */ |
@@ -160,34 +174,6 @@ UNUSUAL_DEV( 0x0421, 0x0019, 0x0592, 0x0592, | |||
160 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 174 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
161 | US_FL_MAX_SECTORS_64 ), | 175 | US_FL_MAX_SECTORS_64 ), |
162 | 176 | ||
163 | /* Reported by Filip Joelsson <filip@blueturtle.nu> */ | ||
164 | UNUSUAL_DEV( 0x0421, 0x005d, 0x0001, 0x0600, | ||
165 | "Nokia", | ||
166 | "Nokia 3110c", | ||
167 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
168 | US_FL_FIX_CAPACITY ), | ||
169 | |||
170 | /* Reported by Ozan Sener <themgzzy@gmail.com> */ | ||
171 | UNUSUAL_DEV( 0x0421, 0x0060, 0x0551, 0x0551, | ||
172 | "Nokia", | ||
173 | "3500c", | ||
174 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
175 | US_FL_FIX_CAPACITY ), | ||
176 | |||
177 | /* Reported by CSECSY Laszlo <boobaa@frugalware.org> */ | ||
178 | UNUSUAL_DEV( 0x0421, 0x0063, 0x0001, 0x0601, | ||
179 | "Nokia", | ||
180 | "Nokia 3109c", | ||
181 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
182 | US_FL_FIX_CAPACITY ), | ||
183 | |||
184 | /* Patch for Nokia 5310 capacity */ | ||
185 | UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0701, | ||
186 | "Nokia", | ||
187 | "5310", | ||
188 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
189 | US_FL_FIX_CAPACITY ), | ||
190 | |||
191 | /* Reported by Mario Rettig <mariorettig@web.de> */ | 177 | /* Reported by Mario Rettig <mariorettig@web.de> */ |
192 | UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, | 178 | UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, |
193 | "Nokia", | 179 | "Nokia", |
@@ -253,35 +239,6 @@ UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370, | |||
253 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 239 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
254 | US_FL_MAX_SECTORS_64 ), | 240 | US_FL_MAX_SECTORS_64 ), |
255 | 241 | ||
256 | /* Reported by Cedric Godin <cedric@belbone.be> */ | ||
257 | UNUSUAL_DEV( 0x0421, 0x04b9, 0x0500, 0x0551, | ||
258 | "Nokia", | ||
259 | "5300", | ||
260 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
261 | US_FL_FIX_CAPACITY ), | ||
262 | |||
263 | /* Reported by Richard Nauber <RichardNauber@web.de> */ | ||
264 | UNUSUAL_DEV( 0x0421, 0x04fa, 0x0550, 0x0660, | ||
265 | "Nokia", | ||
266 | "6300", | ||
267 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
268 | US_FL_FIX_CAPACITY ), | ||
269 | |||
270 | /* Patch for Nokia 5310 capacity */ | ||
271 | UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591, | ||
272 | "Nokia", | ||
273 | "5310", | ||
274 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
275 | US_FL_FIX_CAPACITY ), | ||
276 | |||
277 | /* Submitted by Ricky Wong Yung Fei <evilbladewarrior@gmail.com> */ | ||
278 | /* Nokia 7610 Supernova - Too many sectors reported in usb storage mode */ | ||
279 | UNUSUAL_DEV( 0x0421, 0x00f5, 0x0000, 0x0470, | ||
280 | "Nokia", | ||
281 | "7610 Supernova", | ||
282 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
283 | US_FL_FIX_CAPACITY ), | ||
284 | |||
285 | /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */ | 242 | /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */ |
286 | UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, | 243 | UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, |
287 | "SMSC", | 244 | "SMSC", |
@@ -289,11 +246,17 @@ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, | |||
289 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 246 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
290 | US_FL_SINGLE_LUN ), | 247 | US_FL_SINGLE_LUN ), |
291 | 248 | ||
292 | #ifdef CONFIG_USB_STORAGE_DPCM | 249 | #ifdef CONFIG_USB_STORAGE_SDDR09 |
293 | UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, | 250 | UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, |
294 | "Microtech", | 251 | "Microtech", |
295 | "CameraMate (DPCM_USB)", | 252 | "CameraMate (DPCM_USB)", |
296 | US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), | 253 | US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), |
254 | #else | ||
255 | UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, | ||
256 | "Microtech", | ||
257 | "CameraMate", | ||
258 | US_SC_SCSI, US_PR_CB, NULL, | ||
259 | US_FL_SINGLE_LUN ), | ||
297 | #endif | 260 | #endif |
298 | 261 | ||
299 | /* Patch submitted by Daniel Drake <dsd@gentoo.org> | 262 | /* Patch submitted by Daniel Drake <dsd@gentoo.org> |
@@ -388,6 +351,15 @@ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, | |||
388 | "DVD-CAM DZ-MV100A Camcorder", | 351 | "DVD-CAM DZ-MV100A Camcorder", |
389 | US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN), | 352 | US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN), |
390 | 353 | ||
354 | /* BENQ DC5330 | ||
355 | * Reported by Manuel Fombuena <mfombuena@ya.com> and | ||
356 | * Frank Copeland <fjc@thingy.apana.org.au> */ | ||
357 | UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, | ||
358 | "Tekom Technologies, Inc", | ||
359 | "300_CAMERA", | ||
360 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
361 | US_FL_IGNORE_RESIDUE ), | ||
362 | |||
391 | /* Patch for Nikon coolpix 2000 | 363 | /* Patch for Nikon coolpix 2000 |
392 | * Submitted by Fabien Cosse <fabien.cosse@wanadoo.fr>*/ | 364 | * Submitted by Fabien Cosse <fabien.cosse@wanadoo.fr>*/ |
393 | UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, | 365 | UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, |
@@ -396,83 +368,6 @@ UNUSUAL_DEV( 0x04b0, 0x0301, 0x0010, 0x0010, | |||
396 | US_SC_DEVICE, US_PR_DEVICE,NULL, | 368 | US_SC_DEVICE, US_PR_DEVICE,NULL, |
397 | US_FL_NOT_LOCKABLE ), | 369 | US_FL_NOT_LOCKABLE ), |
398 | 370 | ||
399 | /* Reported by Stefan de Konink <skinkie@xs4all.nl> */ | ||
400 | UNUSUAL_DEV( 0x04b0, 0x0401, 0x0200, 0x0200, | ||
401 | "NIKON", | ||
402 | "NIKON DSC D100", | ||
403 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
404 | US_FL_FIX_CAPACITY), | ||
405 | |||
406 | /* Reported by Tobias Kunze Briseno <t-linux@fictive.com> */ | ||
407 | UNUSUAL_DEV( 0x04b0, 0x0403, 0x0200, 0x0200, | ||
408 | "NIKON", | ||
409 | "NIKON DSC D2H", | ||
410 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
411 | US_FL_FIX_CAPACITY), | ||
412 | |||
413 | /* Reported by Milinevsky Dmitry <niam.niam@gmail.com> */ | ||
414 | UNUSUAL_DEV( 0x04b0, 0x0409, 0x0100, 0x0100, | ||
415 | "NIKON", | ||
416 | "NIKON DSC D50", | ||
417 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
418 | US_FL_FIX_CAPACITY), | ||
419 | |||
420 | /* Reported by Andreas Bockhold <andreas@bockionline.de> */ | ||
421 | UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, | ||
422 | "NIKON", | ||
423 | "NIKON DSC D70", | ||
424 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
425 | US_FL_FIX_CAPACITY), | ||
426 | |||
427 | /* Reported by Jamie Kitson <jamie@staberinde.fsnet.co.uk> */ | ||
428 | UNUSUAL_DEV( 0x04b0, 0x040d, 0x0100, 0x0100, | ||
429 | "NIKON", | ||
430 | "NIKON DSC D70s", | ||
431 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
432 | US_FL_FIX_CAPACITY), | ||
433 | |||
434 | /* Reported by Graber and Mike Pagano <mpagano-kernel@mpagano.com> */ | ||
435 | UNUSUAL_DEV( 0x04b0, 0x040f, 0x0100, 0x0200, | ||
436 | "NIKON", | ||
437 | "NIKON DSC D200", | ||
438 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
439 | US_FL_FIX_CAPACITY), | ||
440 | |||
441 | /* Reported by Emil Larsson <emil@swip.net> */ | ||
442 | UNUSUAL_DEV( 0x04b0, 0x0411, 0x0100, 0x0111, | ||
443 | "NIKON", | ||
444 | "NIKON DSC D80", | ||
445 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
446 | US_FL_FIX_CAPACITY), | ||
447 | |||
448 | /* Reported by Ortwin Glueck <odi@odi.ch> */ | ||
449 | UNUSUAL_DEV( 0x04b0, 0x0413, 0x0110, 0x0111, | ||
450 | "NIKON", | ||
451 | "NIKON DSC D40", | ||
452 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
453 | US_FL_FIX_CAPACITY), | ||
454 | |||
455 | /* Reported by Paul Check <paul@openstreet.com> */ | ||
456 | UNUSUAL_DEV( 0x04b0, 0x0415, 0x0100, 0x0100, | ||
457 | "NIKON", | ||
458 | "NIKON DSC D2Xs", | ||
459 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
460 | US_FL_FIX_CAPACITY), | ||
461 | |||
462 | /* Reported by Shan Destromp (shansan@gmail.com) */ | ||
463 | UNUSUAL_DEV( 0x04b0, 0x0417, 0x0100, 0x0100, | ||
464 | "NIKON", | ||
465 | "NIKON DSC D40X", | ||
466 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
467 | US_FL_FIX_CAPACITY), | ||
468 | |||
469 | /* Reported by paul ready <lxtwin@homecall.co.uk> */ | ||
470 | UNUSUAL_DEV( 0x04b0, 0x0419, 0x0100, 0x0200, | ||
471 | "NIKON", | ||
472 | "NIKON DSC D300", | ||
473 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
474 | US_FL_FIX_CAPACITY), | ||
475 | |||
476 | /* Reported by Doug Maxey (dwm@austin.ibm.com) */ | 371 | /* Reported by Doug Maxey (dwm@austin.ibm.com) */ |
477 | UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, | 372 | UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, |
478 | "IBM", | 373 | "IBM", |
@@ -480,15 +375,6 @@ UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, | |||
480 | US_SC_DEVICE, US_PR_CB, NULL, | 375 | US_SC_DEVICE, US_PR_CB, NULL, |
481 | US_FL_MAX_SECTORS_MIN), | 376 | US_FL_MAX_SECTORS_MIN), |
482 | 377 | ||
483 | /* BENQ DC5330 | ||
484 | * Reported by Manuel Fombuena <mfombuena@ya.com> and | ||
485 | * Frank Copeland <fjc@thingy.apana.org.au> */ | ||
486 | UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, | ||
487 | "Tekom Technologies, Inc", | ||
488 | "300_CAMERA", | ||
489 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
490 | US_FL_IGNORE_RESIDUE ), | ||
491 | |||
492 | #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB | 378 | #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB |
493 | /* CY7C68300 : support atacb */ | 379 | /* CY7C68300 : support atacb */ |
494 | UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, | 380 | UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, |
@@ -594,6 +480,12 @@ UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, | |||
594 | "eUSB SmartMedia / CompactFlash Adapter", | 480 | "eUSB SmartMedia / CompactFlash Adapter", |
595 | US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, | 481 | US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, |
596 | 0), | 482 | 0), |
483 | #else | ||
484 | UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, | ||
485 | "SCM Microsystems", | ||
486 | "eUSB CompactFlash Adapter", | ||
487 | US_SC_SCSI, US_PR_CB, NULL, | ||
488 | US_FL_SINGLE_LUN), | ||
597 | #endif | 489 | #endif |
598 | 490 | ||
599 | /* Reported by Markus Demleitner <msdemlei@cl.uni-heidelberg.de> */ | 491 | /* Reported by Markus Demleitner <msdemlei@cl.uni-heidelberg.de> */ |
@@ -685,6 +577,13 @@ UNUSUAL_DEV( 0x0525, 0xa140, 0x0100, 0x0100, | |||
685 | US_SC_8070, US_PR_DEVICE, NULL, | 577 | US_SC_8070, US_PR_DEVICE, NULL, |
686 | US_FL_FIX_INQUIRY ), | 578 | US_FL_FIX_INQUIRY ), |
687 | 579 | ||
580 | /* Added by Alan Stern <stern@rowland.harvard.edu> */ | ||
581 | COMPLIANT_DEV(0x0525, 0xa4a5, 0x0000, 0x9999, | ||
582 | "Linux", | ||
583 | "File-backed Storage Gadget", | ||
584 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
585 | US_FL_CAPACITY_OK ), | ||
586 | |||
688 | /* Yakumo Mega Image 37 | 587 | /* Yakumo Mega Image 37 |
689 | * Submitted by Stephan Fuhrmann <atomenergie@t-online.de> */ | 588 | * Submitted by Stephan Fuhrmann <atomenergie@t-online.de> */ |
690 | UNUSUAL_DEV( 0x052b, 0x1801, 0x0100, 0x0100, | 589 | UNUSUAL_DEV( 0x052b, 0x1801, 0x0100, 0x0100, |
@@ -807,15 +706,15 @@ UNUSUAL_DEV( 0x054c, 0x006d, 0x0000, 0x9999, | |||
807 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 706 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
808 | US_FL_FIX_INQUIRY ), | 707 | US_FL_FIX_INQUIRY ), |
809 | 708 | ||
810 | /* Submitted by Mike Alborn <malborn@deandra.homeip.net> */ | 709 | /* Submitted by Frank Engel <frankie@cse.unsw.edu.au> */ |
811 | UNUSUAL_DEV( 0x054c, 0x016a, 0x0000, 0x9999, | 710 | UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999, |
812 | "Sony", | 711 | "Sony", |
813 | "PEG Mass Storage", | 712 | "PEG Mass Storage", |
814 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 713 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
815 | US_FL_FIX_INQUIRY ), | 714 | US_FL_FIX_INQUIRY ), |
816 | 715 | ||
817 | /* Submitted by Frank Engel <frankie@cse.unsw.edu.au> */ | 716 | /* Submitted by Mike Alborn <malborn@deandra.homeip.net> */ |
818 | UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999, | 717 | UNUSUAL_DEV( 0x054c, 0x016a, 0x0000, 0x9999, |
819 | "Sony", | 718 | "Sony", |
820 | "PEG Mass Storage", | 719 | "PEG Mass Storage", |
821 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 720 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
@@ -966,6 +865,18 @@ UNUSUAL_DEV( 0x05ac, 0x120a, 0x0000, 0x9999, | |||
966 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 865 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
967 | US_FL_FIX_CAPACITY ), | 866 | US_FL_FIX_CAPACITY ), |
968 | 867 | ||
868 | /* Reported by Dan Williams <dcbw@redhat.com> | ||
869 | * Option N.V. mobile broadband modems | ||
870 | * Ignore driver CD mode and force into modem mode by default. | ||
871 | */ | ||
872 | |||
873 | /* Globetrotter HSDPA; mass storage shows up as Qualcomm for vendor */ | ||
874 | UNUSUAL_DEV( 0x05c6, 0x1000, 0x0000, 0x9999, | ||
875 | "Option N.V.", | ||
876 | "Mass Storage", | ||
877 | US_SC_DEVICE, US_PR_DEVICE, option_ms_init, | ||
878 | 0), | ||
879 | |||
969 | #ifdef CONFIG_USB_STORAGE_JUMPSHOT | 880 | #ifdef CONFIG_USB_STORAGE_JUMPSHOT |
970 | UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, | 881 | UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, |
971 | "Lexar", | 882 | "Lexar", |
@@ -1004,6 +915,13 @@ UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff, | |||
1004 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 915 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1005 | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ), | 916 | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ), |
1006 | 917 | ||
918 | /* Reported by Ben Efros <ben@pc-doctor.com> */ | ||
919 | UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451, | ||
920 | "Genesys Logic", | ||
921 | "USB to SATA", | ||
922 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
923 | US_FL_SANE_SENSE ), | ||
924 | |||
1007 | /* Reported by Hanno Boeck <hanno@gmx.de> | 925 | /* Reported by Hanno Boeck <hanno@gmx.de> |
1008 | * Taken from the Lycoris Kernel */ | 926 | * Taken from the Lycoris Kernel */ |
1009 | UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999, | 927 | UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999, |
@@ -1040,7 +958,7 @@ UNUSUAL_DEV( 0x067b, 0x2507, 0x0100, 0x0100, | |||
1040 | US_FL_FIX_CAPACITY | US_FL_GO_SLOW ), | 958 | US_FL_FIX_CAPACITY | US_FL_GO_SLOW ), |
1041 | 959 | ||
1042 | /* Reported by Alex Butcher <alex.butcher@assursys.co.uk> */ | 960 | /* Reported by Alex Butcher <alex.butcher@assursys.co.uk> */ |
1043 | UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0001, | 961 | UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0101, |
1044 | "Prolific Technology Inc.", | 962 | "Prolific Technology Inc.", |
1045 | "ATAPI-6 Bridge Controller", | 963 | "ATAPI-6 Bridge Controller", |
1046 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 964 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
@@ -1161,11 +1079,17 @@ UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100, | |||
1161 | US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, | 1079 | US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, |
1162 | US_FL_SCM_MULT_TARG ), | 1080 | US_FL_SCM_MULT_TARG ), |
1163 | 1081 | ||
1164 | #ifdef CONFIG_USB_STORAGE_DPCM | 1082 | #ifdef CONFIG_USB_STORAGE_SDDR09 |
1165 | UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, | 1083 | UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, |
1166 | "Microtech", | 1084 | "Microtech", |
1167 | "CameraMate (DPCM_USB)", | 1085 | "CameraMate (DPCM_USB)", |
1168 | US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), | 1086 | US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), |
1087 | #else | ||
1088 | UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, | ||
1089 | "Microtech", | ||
1090 | "CameraMate", | ||
1091 | US_SC_SCSI, US_PR_CB, NULL, | ||
1092 | US_FL_SINGLE_LUN ), | ||
1169 | #endif | 1093 | #endif |
1170 | 1094 | ||
1171 | #ifdef CONFIG_USB_STORAGE_ALAUDA | 1095 | #ifdef CONFIG_USB_STORAGE_ALAUDA |
@@ -1320,6 +1244,13 @@ UNUSUAL_DEV( 0x0840, 0x0082, 0x0001, 0x0001, | |||
1320 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1244 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1321 | US_FL_FIX_CAPACITY), | 1245 | US_FL_FIX_CAPACITY), |
1322 | 1246 | ||
1247 | /* Reported and patched by Nguyen Anh Quynh <aquynh@gmail.com> */ | ||
1248 | UNUSUAL_DEV( 0x0840, 0x0084, 0x0001, 0x0001, | ||
1249 | "Argosy", | ||
1250 | "Storage", | ||
1251 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1252 | US_FL_FIX_CAPACITY), | ||
1253 | |||
1323 | /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>. | 1254 | /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>. |
1324 | * Flag will support Bulk devices which use a standards-violating 32-byte | 1255 | * Flag will support Bulk devices which use a standards-violating 32-byte |
1325 | * Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with | 1256 | * Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with |
@@ -1343,17 +1274,6 @@ UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200, | |||
1343 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1274 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1344 | US_FL_NOT_LOCKABLE), | 1275 | US_FL_NOT_LOCKABLE), |
1345 | 1276 | ||
1346 | /* Andrew Lunn <andrew@lunn.ch> | ||
1347 | * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL | ||
1348 | * on LUN 4. | ||
1349 | * Note: Vend:Prod clash with "Ltd Maxell WS30 Slim Digital Camera" | ||
1350 | */ | ||
1351 | UNUSUAL_DEV( 0x0851, 0x1543, 0x0200, 0x0200, | ||
1352 | "PanDigital", | ||
1353 | "Photo Frame", | ||
1354 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1355 | US_FL_NOT_LOCKABLE), | ||
1356 | |||
1357 | /* Submitted by Jan De Luyck <lkml@kcore.org> */ | 1277 | /* Submitted by Jan De Luyck <lkml@kcore.org> */ |
1358 | UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, | 1278 | UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, |
1359 | "CITIZEN", | 1279 | "CITIZEN", |
@@ -1425,6 +1345,13 @@ UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff, | |||
1425 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1345 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1426 | US_FL_FIX_INQUIRY ), | 1346 | US_FL_FIX_INQUIRY ), |
1427 | 1347 | ||
1348 | /* Reported by Jaak Ristioja <Ristioja@gmail.com> */ | ||
1349 | UNUSUAL_DEV( 0x0a17, 0x006e, 0x0100, 0x0100, | ||
1350 | "Pentax", | ||
1351 | "K10D", | ||
1352 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1353 | US_FL_FIX_CAPACITY ), | ||
1354 | |||
1428 | /* These are virtual windows driver CDs, which the zd1211rw driver | 1355 | /* These are virtual windows driver CDs, which the zd1211rw driver |
1429 | * automatically converts into WLAN devices. */ | 1356 | * automatically converts into WLAN devices. */ |
1430 | UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, | 1357 | UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, |
@@ -1439,6 +1366,18 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, | |||
1439 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1366 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1440 | US_FL_IGNORE_DEVICE ), | 1367 | US_FL_IGNORE_DEVICE ), |
1441 | 1368 | ||
1369 | /* Reported by Dan Williams <dcbw@redhat.com> | ||
1370 | * Option N.V. mobile broadband modems | ||
1371 | * Ignore driver CD mode and force into modem mode by default. | ||
1372 | */ | ||
1373 | |||
1374 | /* iCON 225 */ | ||
1375 | UNUSUAL_DEV( 0x0af0, 0x6971, 0x0000, 0x9999, | ||
1376 | "Option N.V.", | ||
1377 | "Mass Storage", | ||
1378 | US_SC_DEVICE, US_PR_DEVICE, option_ms_init, | ||
1379 | 0), | ||
1380 | |||
1442 | /* Reported by F. Aben <f.aben@option.com> | 1381 | /* Reported by F. Aben <f.aben@option.com> |
1443 | * This device (wrongly) has a vendor-specific device descriptor. | 1382 | * This device (wrongly) has a vendor-specific device descriptor. |
1444 | * The entry is needed so usb-storage can bind to it's mass-storage | 1383 | * The entry is needed so usb-storage can bind to it's mass-storage |
@@ -1449,6 +1388,13 @@ UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000, | |||
1449 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1388 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1450 | 0 ), | 1389 | 0 ), |
1451 | 1390 | ||
1391 | /* Reported by Ben Efros <ben@pc-doctor.com> */ | ||
1392 | UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, | ||
1393 | "Seagate", | ||
1394 | "FreeAgent Pro", | ||
1395 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1396 | US_FL_SANE_SENSE ), | ||
1397 | |||
1452 | #ifdef CONFIG_USB_STORAGE_ISD200 | 1398 | #ifdef CONFIG_USB_STORAGE_ISD200 |
1453 | UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, | 1399 | UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, |
1454 | "ATI", | 1400 | "ATI", |
@@ -1472,6 +1418,22 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, | |||
1472 | US_FL_SINGLE_LUN ), | 1418 | US_FL_SINGLE_LUN ), |
1473 | #endif | 1419 | #endif |
1474 | 1420 | ||
1421 | UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, | ||
1422 | "Maxtor", | ||
1423 | "USB to SATA", | ||
1424 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1425 | US_FL_SANE_SENSE), | ||
1426 | |||
1427 | /* | ||
1428 | * Pete Zaitcev <zaitcev@yahoo.com>, bz#164688. | ||
1429 | * The device blatantly ignores LUN and returns 1 in GetMaxLUN. | ||
1430 | */ | ||
1431 | UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100, | ||
1432 | "Unknown", | ||
1433 | "Unknown", | ||
1434 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1435 | US_FL_SINGLE_LUN ), | ||
1436 | |||
1475 | /* Submitted by: Nick Sillik <n.sillik@temple.edu> | 1437 | /* Submitted by: Nick Sillik <n.sillik@temple.edu> |
1476 | * Needed for OneTouch extension to usb-storage | 1438 | * Needed for OneTouch extension to usb-storage |
1477 | * | 1439 | * |
@@ -1489,16 +1451,6 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, | |||
1489 | 0), | 1451 | 0), |
1490 | #endif | 1452 | #endif |
1491 | 1453 | ||
1492 | /* | ||
1493 | * Pete Zaitcev <zaitcev@yahoo.com>, bz#164688. | ||
1494 | * The device blatantly ignores LUN and returns 1 in GetMaxLUN. | ||
1495 | */ | ||
1496 | UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100, | ||
1497 | "Unknown", | ||
1498 | "Unknown", | ||
1499 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1500 | US_FL_SINGLE_LUN ), | ||
1501 | |||
1502 | /* Submitted by Joris Struyve <joris@struyve.be> */ | 1454 | /* Submitted by Joris Struyve <joris@struyve.be> */ |
1503 | UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, | 1455 | UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, |
1504 | "Medion", | 1456 | "Medion", |
@@ -1516,6 +1468,13 @@ UNUSUAL_DEV( 0x0d96, 0x5200, 0x0001, 0x0200, | |||
1516 | "JD 5200 z3", | 1468 | "JD 5200 z3", |
1517 | US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), | 1469 | US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), |
1518 | 1470 | ||
1471 | /* Reported by Jason Johnston <killean@shaw.ca> */ | ||
1472 | UNUSUAL_DEV( 0x0dc4, 0x0073, 0x0000, 0x0000, | ||
1473 | "Macpower Technology Co.LTD.", | ||
1474 | "USB 2.0 3.5\" DEVICE", | ||
1475 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1476 | US_FL_FIX_CAPACITY), | ||
1477 | |||
1519 | /* Reported by Lubomir Blaha <tritol@trilogic.cz> | 1478 | /* Reported by Lubomir Blaha <tritol@trilogic.cz> |
1520 | * I _REALLY_ don't know what 3rd, 4th number and all defines mean, but this | 1479 | * I _REALLY_ don't know what 3rd, 4th number and all defines mean, but this |
1521 | * works for me. Can anybody correct these values? (I able to test corrected | 1480 | * works for me. Can anybody correct these values? (I able to test corrected |
@@ -1638,13 +1597,6 @@ UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, | |||
1638 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1597 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1639 | US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), | 1598 | US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), |
1640 | 1599 | ||
1641 | /* Reported by Ricardo Barberis <ricardo@dattatec.com> */ | ||
1642 | UNUSUAL_DEV( 0x0fce, 0xe092, 0x0000, 0x0000, | ||
1643 | "Sony Ericsson", | ||
1644 | "P1i", | ||
1645 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1646 | US_FL_IGNORE_RESIDUE ), | ||
1647 | |||
1648 | /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */ | 1600 | /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */ |
1649 | UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, | 1601 | UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, |
1650 | "Sony Ericsson", | 1602 | "Sony Ericsson", |
@@ -1652,6 +1604,13 @@ UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, | |||
1652 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1604 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1653 | US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), | 1605 | US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), |
1654 | 1606 | ||
1607 | /* Reported by Ricardo Barberis <ricardo@dattatec.com> */ | ||
1608 | UNUSUAL_DEV( 0x0fce, 0xe092, 0x0000, 0x0000, | ||
1609 | "Sony Ericsson", | ||
1610 | "P1i", | ||
1611 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1612 | US_FL_IGNORE_RESIDUE ), | ||
1613 | |||
1655 | /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu> | 1614 | /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu> |
1656 | * Tested on hardware version 1.10. | 1615 | * Tested on hardware version 1.10. |
1657 | * Entry is needed only for the initializer function override. | 1616 | * Entry is needed only for the initializer function override. |
@@ -1664,6 +1623,12 @@ UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x0110, | |||
1664 | US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init, | 1623 | US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init, |
1665 | 0 ), | 1624 | 0 ), |
1666 | 1625 | ||
1626 | UNUSUAL_DEV( 0x1058, 0x0704, 0x0000, 0x9999, | ||
1627 | "Western Digital", | ||
1628 | "External HDD", | ||
1629 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
1630 | US_FL_SANE_SENSE), | ||
1631 | |||
1667 | /* Reported by Fabio Venturi <f.venturi@tdnet.it> | 1632 | /* Reported by Fabio Venturi <f.venturi@tdnet.it> |
1668 | * The device reports a vendor-specific bDeviceClass. | 1633 | * The device reports a vendor-specific bDeviceClass. |
1669 | */ | 1634 | */ |
@@ -2053,10 +2018,10 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201, | |||
2053 | * JMicron responds to USN and several other SCSI ioctls with a | 2018 | * JMicron responds to USN and several other SCSI ioctls with a |
2054 | * residue that causes subsequent I/O requests to fail. */ | 2019 | * residue that causes subsequent I/O requests to fail. */ |
2055 | UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100, | 2020 | UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100, |
2056 | "JMicron", | 2021 | "JMicron", |
2057 | "USB to ATA/ATAPI Bridge", | 2022 | "USB to ATA/ATAPI Bridge", |
2058 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 2023 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
2059 | US_FL_IGNORE_RESIDUE ), | 2024 | US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ), |
2060 | 2025 | ||
2061 | /* Reported by Robert Schedel <r.schedel@yahoo.de> | 2026 | /* Reported by Robert Schedel <r.schedel@yahoo.de> |
2062 | * Note: this is a 'super top' device like the above 14cd/6600 device */ | 2027 | * Note: this is a 'super top' device like the above 14cd/6600 device */ |
@@ -2086,27 +2051,6 @@ UNUSUAL_DEV( 0x22b8, 0x3010, 0x0001, 0x0001, | |||
2086 | US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), | 2051 | US_FL_FIX_CAPACITY | US_FL_IGNORE_RESIDUE ), |
2087 | 2052 | ||
2088 | /* | 2053 | /* |
2089 | * Patch by Pete Zaitcev <zaitcev@redhat.com> | ||
2090 | * Report by Mark Patton. Red Hat bz#208928. | ||
2091 | * Added support for rev 0x0002 (Motorola ROKR W5) | ||
2092 | * by Javier Smaldone <javier@smaldone.com.ar> | ||
2093 | */ | ||
2094 | UNUSUAL_DEV( 0x22b8, 0x4810, 0x0001, 0x0002, | ||
2095 | "Motorola", | ||
2096 | "RAZR V3i/ROKR W5", | ||
2097 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
2098 | US_FL_FIX_CAPACITY), | ||
2099 | |||
2100 | /* | ||
2101 | * Patch by Jost Diederichs <jost@qdusa.com> | ||
2102 | */ | ||
2103 | UNUSUAL_DEV(0x22b8, 0x6410, 0x0001, 0x9999, | ||
2104 | "Motorola Inc.", | ||
2105 | "Motorola Phone (RAZRV3xx)", | ||
2106 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
2107 | US_FL_FIX_CAPACITY), | ||
2108 | |||
2109 | /* | ||
2110 | * Patch by Constantin Baranov <const@tltsu.ru> | 2054 | * Patch by Constantin Baranov <const@tltsu.ru> |
2111 | * Report by Andreas Koenecke. | 2055 | * Report by Andreas Koenecke. |
2112 | * Motorola ROKR Z6. | 2056 | * Motorola ROKR Z6. |
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 27016fd2cad1..4becf495ca2d 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -75,9 +75,6 @@ | |||
75 | #ifdef CONFIG_USB_STORAGE_SDDR55 | 75 | #ifdef CONFIG_USB_STORAGE_SDDR55 |
76 | #include "sddr55.h" | 76 | #include "sddr55.h" |
77 | #endif | 77 | #endif |
78 | #ifdef CONFIG_USB_STORAGE_DPCM | ||
79 | #include "dpcm.h" | ||
80 | #endif | ||
81 | #ifdef CONFIG_USB_STORAGE_FREECOM | 78 | #ifdef CONFIG_USB_STORAGE_FREECOM |
82 | #include "freecom.h" | 79 | #include "freecom.h" |
83 | #endif | 80 | #endif |
@@ -103,6 +100,7 @@ | |||
103 | #include "cypress_atacb.h" | 100 | #include "cypress_atacb.h" |
104 | #endif | 101 | #endif |
105 | #include "sierra_ms.h" | 102 | #include "sierra_ms.h" |
103 | #include "option_ms.h" | ||
106 | 104 | ||
107 | /* Some informational data */ | 105 | /* Some informational data */ |
108 | MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); | 106 | MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); |
@@ -113,6 +111,10 @@ static unsigned int delay_use = 5; | |||
113 | module_param(delay_use, uint, S_IRUGO | S_IWUSR); | 111 | module_param(delay_use, uint, S_IRUGO | S_IWUSR); |
114 | MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); | 112 | MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); |
115 | 113 | ||
114 | static char quirks[128]; | ||
115 | module_param_string(quirks, quirks, sizeof(quirks), S_IRUGO | S_IWUSR); | ||
116 | MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); | ||
117 | |||
116 | 118 | ||
117 | /* | 119 | /* |
118 | * The entries in this table correspond, line for line, | 120 | * The entries in this table correspond, line for line, |
@@ -126,6 +128,8 @@ MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); | |||
126 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ | 128 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ |
127 | .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } | 129 | .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } |
128 | 130 | ||
131 | #define COMPLIANT_DEV UNUSUAL_DEV | ||
132 | |||
129 | #define USUAL_DEV(useProto, useTrans, useType) \ | 133 | #define USUAL_DEV(useProto, useTrans, useType) \ |
130 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ | 134 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ |
131 | .driver_info = (USB_US_TYPE_STOR<<24) } | 135 | .driver_info = (USB_US_TYPE_STOR<<24) } |
@@ -134,6 +138,7 @@ static struct usb_device_id storage_usb_ids [] = { | |||
134 | 138 | ||
135 | # include "unusual_devs.h" | 139 | # include "unusual_devs.h" |
136 | #undef UNUSUAL_DEV | 140 | #undef UNUSUAL_DEV |
141 | #undef COMPLIANT_DEV | ||
137 | #undef USUAL_DEV | 142 | #undef USUAL_DEV |
138 | /* Terminating entry */ | 143 | /* Terminating entry */ |
139 | { } | 144 | { } |
@@ -164,6 +169,8 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); | |||
164 | .initFunction = init_function, \ | 169 | .initFunction = init_function, \ |
165 | } | 170 | } |
166 | 171 | ||
172 | #define COMPLIANT_DEV UNUSUAL_DEV | ||
173 | |||
167 | #define USUAL_DEV(use_protocol, use_transport, use_type) \ | 174 | #define USUAL_DEV(use_protocol, use_transport, use_type) \ |
168 | { \ | 175 | { \ |
169 | .useProtocol = use_protocol, \ | 176 | .useProtocol = use_protocol, \ |
@@ -173,6 +180,7 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); | |||
173 | static struct us_unusual_dev us_unusual_dev_list[] = { | 180 | static struct us_unusual_dev us_unusual_dev_list[] = { |
174 | # include "unusual_devs.h" | 181 | # include "unusual_devs.h" |
175 | # undef UNUSUAL_DEV | 182 | # undef UNUSUAL_DEV |
183 | # undef COMPLIANT_DEV | ||
176 | # undef USUAL_DEV | 184 | # undef USUAL_DEV |
177 | 185 | ||
178 | /* Terminating entry */ | 186 | /* Terminating entry */ |
@@ -464,13 +472,83 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf) | |||
464 | US_DEBUGP("I/O buffer allocation failed\n"); | 472 | US_DEBUGP("I/O buffer allocation failed\n"); |
465 | return -ENOMEM; | 473 | return -ENOMEM; |
466 | } | 474 | } |
475 | return 0; | ||
476 | } | ||
467 | 477 | ||
468 | us->sensebuf = kmalloc(US_SENSE_SIZE, GFP_KERNEL); | 478 | /* Works only for digits and letters, but small and fast */ |
469 | if (!us->sensebuf) { | 479 | #define TOLOWER(x) ((x) | 0x20) |
470 | US_DEBUGP("Sense buffer allocation failed\n"); | 480 | |
471 | return -ENOMEM; | 481 | /* Adjust device flags based on the "quirks=" module parameter */ |
482 | static void adjust_quirks(struct us_data *us) | ||
483 | { | ||
484 | char *p; | ||
485 | u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor); | ||
486 | u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct); | ||
487 | unsigned f = 0; | ||
488 | unsigned int mask = (US_FL_SANE_SENSE | US_FL_FIX_CAPACITY | | ||
489 | US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE | | ||
490 | US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 | | ||
491 | US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE | | ||
492 | US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT); | ||
493 | |||
494 | p = quirks; | ||
495 | while (*p) { | ||
496 | /* Each entry consists of VID:PID:flags */ | ||
497 | if (vid == simple_strtoul(p, &p, 16) && | ||
498 | *p == ':' && | ||
499 | pid == simple_strtoul(p+1, &p, 16) && | ||
500 | *p == ':') | ||
501 | break; | ||
502 | |||
503 | /* Move forward to the next entry */ | ||
504 | while (*p) { | ||
505 | if (*p++ == ',') | ||
506 | break; | ||
507 | } | ||
472 | } | 508 | } |
473 | return 0; | 509 | if (!*p) /* No match */ |
510 | return; | ||
511 | |||
512 | /* Collect the flags */ | ||
513 | while (*++p && *p != ',') { | ||
514 | switch (TOLOWER(*p)) { | ||
515 | case 'a': | ||
516 | f |= US_FL_SANE_SENSE; | ||
517 | break; | ||
518 | case 'c': | ||
519 | f |= US_FL_FIX_CAPACITY; | ||
520 | break; | ||
521 | case 'h': | ||
522 | f |= US_FL_CAPACITY_HEURISTICS; | ||
523 | break; | ||
524 | case 'i': | ||
525 | f |= US_FL_IGNORE_DEVICE; | ||
526 | break; | ||
527 | case 'l': | ||
528 | f |= US_FL_NOT_LOCKABLE; | ||
529 | break; | ||
530 | case 'm': | ||
531 | f |= US_FL_MAX_SECTORS_64; | ||
532 | break; | ||
533 | case 'o': | ||
534 | f |= US_FL_CAPACITY_OK; | ||
535 | break; | ||
536 | case 'r': | ||
537 | f |= US_FL_IGNORE_RESIDUE; | ||
538 | break; | ||
539 | case 's': | ||
540 | f |= US_FL_SINGLE_LUN; | ||
541 | break; | ||
542 | case 'w': | ||
543 | f |= US_FL_NO_WP_DETECT; | ||
544 | break; | ||
545 | /* Ignore unrecognized flag characters */ | ||
546 | } | ||
547 | } | ||
548 | us->fflags = (us->fflags & ~mask) | f; | ||
549 | dev_info(&us->pusb_intf->dev, "Quirks match for " | ||
550 | "vid %04x pid %04x: %x\n", | ||
551 | vid, pid, f); | ||
474 | } | 552 | } |
475 | 553 | ||
476 | /* Find an unusual_dev descriptor (always succeeds in the current code) */ | 554 | /* Find an unusual_dev descriptor (always succeeds in the current code) */ |
@@ -497,6 +575,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) | |||
497 | idesc->bInterfaceProtocol : | 575 | idesc->bInterfaceProtocol : |
498 | unusual_dev->useTransport; | 576 | unusual_dev->useTransport; |
499 | us->fflags = USB_US_ORIG_FLAGS(id->driver_info); | 577 | us->fflags = USB_US_ORIG_FLAGS(id->driver_info); |
578 | adjust_quirks(us); | ||
500 | 579 | ||
501 | if (us->fflags & US_FL_IGNORE_DEVICE) { | 580 | if (us->fflags & US_FL_IGNORE_DEVICE) { |
502 | printk(KERN_INFO USB_STORAGE "device ignored\n"); | 581 | printk(KERN_INFO USB_STORAGE "device ignored\n"); |
@@ -562,7 +641,7 @@ static int get_transport(struct us_data *us) | |||
562 | 641 | ||
563 | case US_PR_CBI: | 642 | case US_PR_CBI: |
564 | us->transport_name = "Control/Bulk/Interrupt"; | 643 | us->transport_name = "Control/Bulk/Interrupt"; |
565 | us->transport = usb_stor_CBI_transport; | 644 | us->transport = usb_stor_CB_transport; |
566 | us->transport_reset = usb_stor_CB_reset; | 645 | us->transport_reset = usb_stor_CB_reset; |
567 | us->max_lun = 7; | 646 | us->max_lun = 7; |
568 | break; | 647 | break; |
@@ -675,19 +754,19 @@ static int get_protocol(struct us_data *us) | |||
675 | 754 | ||
676 | case US_SC_8020: | 755 | case US_SC_8020: |
677 | us->protocol_name = "8020i"; | 756 | us->protocol_name = "8020i"; |
678 | us->proto_handler = usb_stor_ATAPI_command; | 757 | us->proto_handler = usb_stor_pad12_command; |
679 | us->max_lun = 0; | 758 | us->max_lun = 0; |
680 | break; | 759 | break; |
681 | 760 | ||
682 | case US_SC_QIC: | 761 | case US_SC_QIC: |
683 | us->protocol_name = "QIC-157"; | 762 | us->protocol_name = "QIC-157"; |
684 | us->proto_handler = usb_stor_qic157_command; | 763 | us->proto_handler = usb_stor_pad12_command; |
685 | us->max_lun = 0; | 764 | us->max_lun = 0; |
686 | break; | 765 | break; |
687 | 766 | ||
688 | case US_SC_8070: | 767 | case US_SC_8070: |
689 | us->protocol_name = "8070i"; | 768 | us->protocol_name = "8070i"; |
690 | us->proto_handler = usb_stor_ATAPI_command; | 769 | us->proto_handler = usb_stor_pad12_command; |
691 | us->max_lun = 0; | 770 | us->max_lun = 0; |
692 | break; | 771 | break; |
693 | 772 | ||
@@ -840,8 +919,6 @@ static void dissociate_dev(struct us_data *us) | |||
840 | { | 919 | { |
841 | US_DEBUGP("-- %s\n", __func__); | 920 | US_DEBUGP("-- %s\n", __func__); |
842 | 921 | ||
843 | kfree(us->sensebuf); | ||
844 | |||
845 | /* Free the device-related DMA-mapped buffers */ | 922 | /* Free the device-related DMA-mapped buffers */ |
846 | if (us->cr) | 923 | if (us->cr) |
847 | usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr, | 924 | usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr, |
@@ -1064,6 +1141,7 @@ static struct usb_driver usb_storage_driver = { | |||
1064 | static int __init usb_stor_init(void) | 1141 | static int __init usb_stor_init(void) |
1065 | { | 1142 | { |
1066 | int retval; | 1143 | int retval; |
1144 | |||
1067 | printk(KERN_INFO "Initializing USB Mass Storage driver...\n"); | 1145 | printk(KERN_INFO "Initializing USB Mass Storage driver...\n"); |
1068 | 1146 | ||
1069 | /* register the driver, return usb_register return code if error */ | 1147 | /* register the driver, return usb_register return code if error */ |
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index a4ad73bd832d..65e674e4be99 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h | |||
@@ -138,7 +138,6 @@ struct us_data { | |||
138 | struct usb_ctrlrequest *cr; /* control requests */ | 138 | struct usb_ctrlrequest *cr; /* control requests */ |
139 | struct usb_sg_request current_sg; /* scatter-gather req. */ | 139 | struct usb_sg_request current_sg; /* scatter-gather req. */ |
140 | unsigned char *iobuf; /* I/O buffer */ | 140 | unsigned char *iobuf; /* I/O buffer */ |
141 | unsigned char *sensebuf; /* sense data buffer */ | ||
142 | dma_addr_t cr_dma; /* buffer DMA addresses */ | 141 | dma_addr_t cr_dma; /* buffer DMA addresses */ |
143 | dma_addr_t iobuf_dma; | 142 | dma_addr_t iobuf_dma; |
144 | struct task_struct *ctl_thread; /* the control thread */ | 143 | struct task_struct *ctl_thread; /* the control thread */ |
@@ -155,6 +154,10 @@ struct us_data { | |||
155 | #ifdef CONFIG_PM | 154 | #ifdef CONFIG_PM |
156 | pm_hook suspend_resume_hook; | 155 | pm_hook suspend_resume_hook; |
157 | #endif | 156 | #endif |
157 | |||
158 | /* hacks for READ CAPACITY bug handling */ | ||
159 | int use_last_sector_hacks; | ||
160 | int last_sector_retries; | ||
158 | }; | 161 | }; |
159 | 162 | ||
160 | /* Convert between us_data and the corresponding Scsi_Host */ | 163 | /* Convert between us_data and the corresponding Scsi_Host */ |
diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c index 95c6fa3bf6b2..3937bf6f8cef 100644 --- a/drivers/usb/wusbcore/rh.c +++ b/drivers/usb/wusbcore/rh.c | |||
@@ -326,7 +326,7 @@ static int wusbhc_rh_clear_port_feat(struct wusbhc *wusbhc, u16 feature, | |||
326 | static int wusbhc_rh_get_port_status(struct wusbhc *wusbhc, u16 port_idx, | 326 | static int wusbhc_rh_get_port_status(struct wusbhc *wusbhc, u16 port_idx, |
327 | u32 *_buf, u16 wLength) | 327 | u32 *_buf, u16 wLength) |
328 | { | 328 | { |
329 | u16 *buf = (u16 *) _buf; | 329 | __le16 *buf = (__le16 *)_buf; |
330 | 330 | ||
331 | if (port_idx > wusbhc->ports_max) | 331 | if (port_idx > wusbhc->ports_max) |
332 | return -EINVAL; | 332 | return -EINVAL; |
diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c index 686795e97195..c7080d497311 100644 --- a/drivers/uwb/i1480/dfu/usb.c +++ b/drivers/uwb/i1480/dfu/usb.c | |||
@@ -387,7 +387,7 @@ int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id) | |||
387 | goto error_create; | 387 | goto error_create; |
388 | } | 388 | } |
389 | 389 | ||
390 | /* setup the fops and upload the firmare */ | 390 | /* setup the fops and upload the firmware */ |
391 | i1480->pre_fw_name = "i1480-pre-phy-0.0.bin"; | 391 | i1480->pre_fw_name = "i1480-pre-phy-0.0.bin"; |
392 | i1480->mac_fw_name = "i1480-usb-0.0.bin"; | 392 | i1480->mac_fw_name = "i1480-usb-0.0.bin"; |
393 | i1480->mac_fw_name_deprecate = "ptc-0.0.bin"; | 393 | i1480->mac_fw_name_deprecate = "ptc-0.0.bin"; |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index e6210725b9ab..d012edda6d11 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -1332,7 +1332,7 @@ static void vgacon_save_screen(struct vc_data *c) | |||
1332 | c->vc_y = screen_info.orig_y; | 1332 | c->vc_y = screen_info.orig_y; |
1333 | } | 1333 | } |
1334 | 1334 | ||
1335 | /* We can't copy in more then the size of the video buffer, | 1335 | /* We can't copy in more than the size of the video buffer, |
1336 | * or we'll be copying in VGA BIOS */ | 1336 | * or we'll be copying in VGA BIOS */ |
1337 | 1337 | ||
1338 | if (!vga_is_gfx) | 1338 | if (!vga_is_gfx) |