aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxim Levitsky <maximlevitsky@gmail.com>2010-11-28 21:09:50 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2010-12-13 14:39:15 -0500
commitdd23736e092035b71df1117482b71fdfb5634239 (patch)
tree82e5ca95a4065f57e6c0e6504b3458d592a7c7f0
parent8662b6b029636c35e5876e184d90daf6b0072667 (diff)
firewire: ohci: restart iso DMA contexts on resume from low power mode
Restore iso channels DMA so that iso channels could continue to work after resume from RAM/disk. Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r--drivers/firewire/ohci.c54
1 files changed, 46 insertions, 8 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 3a908038ff62..5e5d5d3d43d1 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -18,6 +18,7 @@
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */ 19 */
20 20
21#include <linux/bitops.h>
21#include <linux/bug.h> 22#include <linux/bug.h>
22#include <linux/compiler.h> 23#include <linux/compiler.h>
23#include <linux/delay.h> 24#include <linux/delay.h>
@@ -153,6 +154,7 @@ struct context {
153 descriptor_callback_t callback; 154 descriptor_callback_t callback;
154 155
155 struct tasklet_struct tasklet; 156 struct tasklet_struct tasklet;
157 bool active;
156}; 158};
157 159
158#define IT_HEADER_SY(v) ((v) << 0) 160#define IT_HEADER_SY(v) ((v) << 0)
@@ -168,6 +170,9 @@ struct iso_context {
168 int excess_bytes; 170 int excess_bytes;
169 void *header; 171 void *header;
170 size_t header_length; 172 size_t header_length;
173
174 u8 sync;
175 u8 tags;
171}; 176};
172 177
173#define CONFIG_ROM_SIZE 1024 178#define CONFIG_ROM_SIZE 1024
@@ -184,7 +189,8 @@ struct fw_ohci {
184 u32 bus_time; 189 u32 bus_time;
185 bool is_root; 190 bool is_root;
186 bool csr_state_setclear_abdicate; 191 bool csr_state_setclear_abdicate;
187 192 int n_ir;
193 int n_it;
188 /* 194 /*
189 * Spinlock for accessing fw_ohci data. Never call out of 195 * Spinlock for accessing fw_ohci data. Never call out of
190 * this driver with this lock held. 196 * this driver with this lock held.
@@ -1161,6 +1167,7 @@ static struct descriptor *context_get_descriptors(struct context *ctx,
1161static void context_run(struct context *ctx, u32 extra) 1167static void context_run(struct context *ctx, u32 extra)
1162{ 1168{
1163 struct fw_ohci *ohci = ctx->ohci; 1169 struct fw_ohci *ohci = ctx->ohci;
1170 ctx->active = true;
1164 1171
1165 reg_write(ohci, COMMAND_PTR(ctx->regs), 1172 reg_write(ohci, COMMAND_PTR(ctx->regs),
1166 le32_to_cpu(ctx->last->branch_address)); 1173 le32_to_cpu(ctx->last->branch_address));
@@ -1192,6 +1199,7 @@ static void context_stop(struct context *ctx)
1192 u32 reg; 1199 u32 reg;
1193 int i; 1200 int i;
1194 1201
1202 ctx->active = false;
1195 reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); 1203 reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
1196 flush_writes(ctx->ohci); 1204 flush_writes(ctx->ohci);
1197 1205
@@ -2641,6 +2649,10 @@ static int ohci_start_iso(struct fw_iso_context *base,
2641 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); 2649 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index);
2642 reg_write(ohci, CONTEXT_MATCH(ctx->context.regs), match); 2650 reg_write(ohci, CONTEXT_MATCH(ctx->context.regs), match);
2643 context_run(&ctx->context, control); 2651 context_run(&ctx->context, control);
2652
2653 ctx->sync = sync;
2654 ctx->tags = tags;
2655
2644 break; 2656 break;
2645 } 2657 }
2646 2658
@@ -2738,6 +2750,26 @@ static int ohci_set_iso_channels(struct fw_iso_context *base, u64 *channels)
2738 return ret; 2750 return ret;
2739} 2751}
2740 2752
2753#ifdef CONFIG_PM
2754static void ohci_resume_iso_dma(struct fw_ohci *ohci)
2755{
2756 int i;
2757 struct iso_context *ctx;
2758
2759 for (i = 0 ; i < ohci->n_ir ; i++) {
2760 ctx = &ohci->ir_context_list[i];
2761 if (ctx->context.active)
2762 ohci_start_iso(&ctx->base, 0, ctx->sync, ctx->tags);
2763 }
2764
2765 for (i = 0 ; i < ohci->n_it ; i++) {
2766 ctx = &ohci->it_context_list[i];
2767 if (ctx->context.active)
2768 ohci_start_iso(&ctx->base, 0, ctx->sync, ctx->tags);
2769 }
2770}
2771#endif
2772
2741static int queue_iso_transmit(struct iso_context *ctx, 2773static int queue_iso_transmit(struct iso_context *ctx,
2742 struct fw_iso_packet *packet, 2774 struct fw_iso_packet *packet,
2743 struct fw_iso_buffer *buffer, 2775 struct fw_iso_buffer *buffer,
@@ -3047,7 +3079,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
3047 struct fw_ohci *ohci; 3079 struct fw_ohci *ohci;
3048 u32 bus_options, max_receive, link_speed, version; 3080 u32 bus_options, max_receive, link_speed, version;
3049 u64 guid; 3081 u64 guid;
3050 int i, err, n_ir, n_it; 3082 int i, err;
3051 size_t size; 3083 size_t size;
3052 3084
3053 ohci = kzalloc(sizeof(*ohci), GFP_KERNEL); 3085 ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
@@ -3141,15 +3173,15 @@ static int __devinit pci_probe(struct pci_dev *dev,
3141 ohci->ir_context_channels = ~0ULL; 3173 ohci->ir_context_channels = ~0ULL;
3142 ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); 3174 ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
3143 reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0); 3175 reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
3144 n_ir = hweight32(ohci->ir_context_mask); 3176 ohci->n_ir = hweight32(ohci->ir_context_mask);
3145 size = sizeof(struct iso_context) * n_ir; 3177 size = sizeof(struct iso_context) * ohci->n_ir;
3146 ohci->ir_context_list = kzalloc(size, GFP_KERNEL); 3178 ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
3147 3179
3148 reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); 3180 reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
3149 ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); 3181 ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
3150 reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); 3182 reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
3151 n_it = hweight32(ohci->it_context_mask); 3183 ohci->n_it = hweight32(ohci->it_context_mask);
3152 size = sizeof(struct iso_context) * n_it; 3184 size = sizeof(struct iso_context) * ohci->n_it;
3153 ohci->it_context_list = kzalloc(size, GFP_KERNEL); 3185 ohci->it_context_list = kzalloc(size, GFP_KERNEL);
3154 3186
3155 if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) { 3187 if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) {
@@ -3174,7 +3206,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
3174 fw_notify("Added fw-ohci device %s, OHCI v%x.%x, " 3206 fw_notify("Added fw-ohci device %s, OHCI v%x.%x, "
3175 "%d IR + %d IT contexts, quirks 0x%x\n", 3207 "%d IR + %d IT contexts, quirks 0x%x\n",
3176 dev_name(&dev->dev), version >> 16, version & 0xff, 3208 dev_name(&dev->dev), version >> 16, version & 0xff,
3177 n_ir, n_it, ohci->quirks); 3209 ohci->n_ir, ohci->n_it, ohci->quirks);
3178 3210
3179 return 0; 3211 return 0;
3180 3212
@@ -3291,7 +3323,13 @@ static int pci_resume(struct pci_dev *dev)
3291 reg_write(ohci, OHCI1394_GUIDHi, (u32)(ohci->card.guid >> 32)); 3323 reg_write(ohci, OHCI1394_GUIDHi, (u32)(ohci->card.guid >> 32));
3292 } 3324 }
3293 3325
3294 return ohci_enable(&ohci->card, NULL, 0); 3326 err = ohci_enable(&ohci->card, NULL, 0);
3327
3328 if (err)
3329 return err;
3330
3331 ohci_resume_iso_dma(ohci);
3332 return 0;
3295} 3333}
3296#endif 3334#endif
3297 3335