Blame view
drivers/firewire/ohci.c
106 KB
c781c06d1 firewire: Clean u... |
1 2 |
/* * Driver for OHCI 1394 controllers |
ed5689122 firewire: Add dri... |
3 |
* |
ed5689122 firewire: Add dri... |
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
* Copyright (C) 2003-2006 Kristian Hoegsberg <krh@bitplanet.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
dd23736e0 firewire: ohci: r... |
20 |
#include <linux/bitops.h> |
65b2742ac firewire: 'add CS... |
21 |
#include <linux/bug.h> |
e524f616f firewire: fw-ohci... |
22 |
#include <linux/compiler.h> |
ed5689122 firewire: Add dri... |
23 |
#include <linux/delay.h> |
e8ca97021 firewire: clean u... |
24 |
#include <linux/device.h> |
cf3e72fd8 firewire: build fix |
25 |
#include <linux/dma-mapping.h> |
77c9a5daa firewire: reorgan... |
26 |
#include <linux/firewire.h> |
e8ca97021 firewire: clean u... |
27 |
#include <linux/firewire-constants.h> |
a7fb60db7 firewire: fw-ohci... |
28 29 |
#include <linux/init.h> #include <linux/interrupt.h> |
e8ca97021 firewire: clean u... |
30 |
#include <linux/io.h> |
a7fb60db7 firewire: fw-ohci... |
31 |
#include <linux/kernel.h> |
e8ca97021 firewire: clean u... |
32 |
#include <linux/list.h> |
faa2fb4e6 missing mm.h in f... |
33 |
#include <linux/mm.h> |
a7fb60db7 firewire: fw-ohci... |
34 |
#include <linux/module.h> |
ad3c0fe8b firewire: debug i... |
35 |
#include <linux/moduleparam.h> |
02d37bed1 firewire: core: i... |
36 |
#include <linux/mutex.h> |
a7fb60db7 firewire: fw-ohci... |
37 |
#include <linux/pci.h> |
fc383796a firewire: ohci: f... |
38 |
#include <linux/pci_ids.h> |
5a0e3ad6a include cleanup: ... |
39 |
#include <linux/slab.h> |
c26f02340 firewire: fw-ohci... |
40 |
#include <linux/spinlock.h> |
e8ca97021 firewire: clean u... |
41 |
#include <linux/string.h> |
e78483c5a Merge firewire br... |
42 |
#include <linux/time.h> |
7a39d8b82 firewire: ohci: A... |
43 |
#include <linux/vmalloc.h> |
2d7a36e23 firewire: ohci: M... |
44 |
#include <linux/workqueue.h> |
cf3e72fd8 firewire: build fix |
45 |
|
e8ca97021 firewire: clean u... |
46 |
#include <asm/byteorder.h> |
c26f02340 firewire: fw-ohci... |
47 |
#include <asm/page.h> |
ed5689122 firewire: Add dri... |
48 |
|
ea8d006b9 firewire: fw-ohci... |
49 50 51 |
#ifdef CONFIG_PPC_PMAC #include <asm/pmac_feature.h> #endif |
77c9a5daa firewire: reorgan... |
52 53 |
#include "core.h" #include "ohci.h" |
ed5689122 firewire: Add dri... |
54 |
|
de97cb64a firewire: ohci: A... |
55 56 57 |
#define ohci_info(ohci, f, args...) dev_info(ohci->card.device, f, ##args) #define ohci_notice(ohci, f, args...) dev_notice(ohci->card.device, f, ##args) #define ohci_err(ohci, f, args...) dev_err(ohci->card.device, f, ##args) |
a77754a75 firewire: Upperca... |
58 59 60 61 62 63 64 65 66 67 68 69 70 |
#define DESCRIPTOR_OUTPUT_MORE 0 #define DESCRIPTOR_OUTPUT_LAST (1 << 12) #define DESCRIPTOR_INPUT_MORE (2 << 12) #define DESCRIPTOR_INPUT_LAST (3 << 12) #define DESCRIPTOR_STATUS (1 << 11) #define DESCRIPTOR_KEY_IMMEDIATE (2 << 8) #define DESCRIPTOR_PING (1 << 7) #define DESCRIPTOR_YY (1 << 6) #define DESCRIPTOR_NO_IRQ (0 << 4) #define DESCRIPTOR_IRQ_ERROR (1 << 4) #define DESCRIPTOR_IRQ_ALWAYS (3 << 4) #define DESCRIPTOR_BRANCH_ALWAYS (3 << 2) #define DESCRIPTOR_WAIT (3 << 0) |
ed5689122 firewire: Add dri... |
71 |
|
be8dcab94 firewire: ohci: f... |
72 |
#define DESCRIPTOR_CMD (0xf << 12) |
ed5689122 firewire: Add dri... |
73 74 75 76 77 78 79 80 |
struct descriptor { __le16 req_count; __le16 control; __le32 data_address; __le32 branch_address; __le16 res_count; __le16 transfer_status; } __attribute__((aligned(16))); |
a77754a75 firewire: Upperca... |
81 82 83 84 |
#define CONTROL_SET(regs) (regs) #define CONTROL_CLEAR(regs) ((regs) + 4) #define COMMAND_PTR(regs) ((regs) + 12) #define CONTEXT_MATCH(regs) ((regs) + 16) |
72e318e07 firewire: Reduce ... |
85 |
|
7a39d8b82 firewire: ohci: A... |
86 87 88 89 90 91 92 93 |
#define AR_BUFFER_SIZE (32*1024) #define AR_BUFFERS_MIN DIV_ROUND_UP(AR_BUFFER_SIZE, PAGE_SIZE) /* we need at least two pages for proper list management */ #define AR_BUFFERS (AR_BUFFERS_MIN >= 2 ? AR_BUFFERS_MIN : 2) #define MAX_ASYNC_PAYLOAD 4096 #define MAX_AR_PACKET_SIZE (16 + MAX_ASYNC_PAYLOAD + 4) #define AR_WRAPAROUND_PAGES DIV_ROUND_UP(MAX_AR_PACKET_SIZE, PAGE_SIZE) |
ed5689122 firewire: Add dri... |
94 |
|
32b46093a firewire: Rework ... |
95 96 |
struct ar_context { struct fw_ohci *ohci; |
7a39d8b82 firewire: ohci: A... |
97 98 99 100 |
struct page *pages[AR_BUFFERS]; void *buffer; struct descriptor *descriptors; dma_addr_t descriptors_bus; |
32b46093a firewire: Rework ... |
101 |
void *pointer; |
7a39d8b82 firewire: ohci: A... |
102 |
unsigned int last_buffer_index; |
72e318e07 firewire: Reduce ... |
103 |
u32 regs; |
ed5689122 firewire: Add dri... |
104 105 |
struct tasklet_struct tasklet; }; |
30200739e firewire: General... |
106 107 108 109 110 |
struct context; typedef int (*descriptor_callback_t)(struct context *ctx, struct descriptor *d, struct descriptor *last); |
fe5ca6343 firewire: fw-ohci... |
111 112 113 114 115 116 117 118 119 120 121 122 |
/* * A buffer that contains a block of DMA-able coherent memory used for * storing a portion of a DMA descriptor program. */ struct descriptor_buffer { struct list_head list; dma_addr_t buffer_bus; size_t buffer_size; size_t used; struct descriptor buffer[0]; }; |
30200739e firewire: General... |
123 |
struct context { |
373b2edd8 firewire: adjust ... |
124 |
struct fw_ohci *ohci; |
30200739e firewire: General... |
125 |
u32 regs; |
fe5ca6343 firewire: fw-ohci... |
126 |
int total_allocation; |
a572e688c firewire: ohci: f... |
127 |
u32 current_bus; |
386a4153a firewire: ohci: c... |
128 |
bool running; |
82b662dc4 firewire: ohci: f... |
129 |
bool flushing; |
373b2edd8 firewire: adjust ... |
130 |
|
fe5ca6343 firewire: fw-ohci... |
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
/* * List of page-sized buffers for storing DMA descriptors. * Head of list contains buffers in use and tail of list contains * free buffers. */ struct list_head buffer_list; /* * Pointer to a buffer inside buffer_list that contains the tail * end of the current DMA program. */ struct descriptor_buffer *buffer_tail; /* * The descriptor containing the branch address of the first * descriptor that has not yet been filled by the device. */ struct descriptor *last; /* |
be8dcab94 firewire: ohci: f... |
151 |
* The last descriptor block in the DMA program. It contains the branch |
fe5ca6343 firewire: fw-ohci... |
152 153 154 |
* address that must be updated upon appending a new descriptor. */ struct descriptor *prev; |
be8dcab94 firewire: ohci: f... |
155 |
int prev_z; |
30200739e firewire: General... |
156 157 |
descriptor_callback_t callback; |
373b2edd8 firewire: adjust ... |
158 |
struct tasklet_struct tasklet; |
30200739e firewire: General... |
159 |
}; |
30200739e firewire: General... |
160 |
|
a77754a75 firewire: Upperca... |
161 162 163 164 165 166 |
#define IT_HEADER_SY(v) ((v) << 0) #define IT_HEADER_TCODE(v) ((v) << 4) #define IT_HEADER_CHANNEL(v) ((v) << 8) #define IT_HEADER_TAG(v) ((v) << 14) #define IT_HEADER_SPEED(v) ((v) << 16) #define IT_HEADER_DATA_LENGTH(v) ((v) << 16) |
ed5689122 firewire: Add dri... |
167 168 169 |
struct iso_context { struct fw_iso_context base; |
30200739e firewire: General... |
170 |
struct context context; |
9b32d5f30 firewire: Acummul... |
171 172 |
void *header; size_t header_length; |
d1bbd2097 firewire: allow e... |
173 174 175 |
unsigned long flushing_completions; u32 mc_buffer_bus; u16 mc_completed; |
910e76c60 firewire: ohci: f... |
176 |
u16 last_timestamp; |
dd23736e0 firewire: ohci: r... |
177 178 |
u8 sync; u8 tags; |
ed5689122 firewire: Add dri... |
179 180 181 182 183 184 185 186 |
}; #define CONFIG_ROM_SIZE 1024 struct fw_ohci { struct fw_card card; __iomem char *registers; |
e636fe257 firewire: Loop re... |
187 |
int node_id; |
ed5689122 firewire: Add dri... |
188 |
int generation; |
e09770db0 firewire: remove ... |
189 |
int request_generation; /* for timestamping incoming requests */ |
4a635593f firewire: ohci: u... |
190 |
unsigned quirks; |
a1a1132bd firewire: add CSR... |
191 |
unsigned int pri_req_max; |
a48777e03 firewire: add CSR... |
192 |
u32 bus_time; |
9d60ef2bd firewire: ohci: l... |
193 |
bool bus_time_running; |
4ffb7a6a0 firewire: add CSR... |
194 |
bool is_root; |
c8a94ded5 firewire: normali... |
195 |
bool csr_state_setclear_abdicate; |
dd23736e0 firewire: ohci: r... |
196 197 |
int n_ir; int n_it; |
c781c06d1 firewire: Clean u... |
198 199 200 201 |
/* * Spinlock for accessing fw_ohci data. Never call out of * this driver with this lock held. */ |
ed5689122 firewire: Add dri... |
202 |
spinlock_t lock; |
ed5689122 firewire: Add dri... |
203 |
|
02d37bed1 firewire: core: i... |
204 |
struct mutex phy_reg_mutex; |
ec766a797 firewire: ohci: u... |
205 206 |
void *misc_buffer; dma_addr_t misc_buffer_bus; |
ed5689122 firewire: Add dri... |
207 208 |
struct ar_context ar_request_ctx; struct ar_context ar_response_ctx; |
f319b6a02 firewire: Move as... |
209 210 |
struct context at_request_ctx; struct context at_response_ctx; |
ed5689122 firewire: Add dri... |
211 |
|
f117a3e30 firewire: ohci: l... |
212 |
u32 it_context_support; |
872e330e3 firewire: add iso... |
213 |
u32 it_context_mask; /* unoccupied IT contexts */ |
ed5689122 firewire: Add dri... |
214 |
struct iso_context *it_context_list; |
872e330e3 firewire: add iso... |
215 |
u64 ir_context_channels; /* unoccupied channels */ |
f117a3e30 firewire: ohci: l... |
216 |
u32 ir_context_support; |
872e330e3 firewire: add iso... |
217 |
u32 ir_context_mask; /* unoccupied IR contexts */ |
ed5689122 firewire: Add dri... |
218 |
struct iso_context *ir_context_list; |
872e330e3 firewire: add iso... |
219 220 |
u64 mc_channels; /* channels in use by the multichannel IR context */ bool mc_allocated; |
ecb1cf9c4 firewire: ohci: r... |
221 222 223 224 225 226 |
__be32 *config_rom; dma_addr_t config_rom_bus; __be32 *next_config_rom; dma_addr_t next_config_rom_bus; __be32 next_header; |
af53122a2 firewire: ohci: c... |
227 |
__le32 *self_id; |
ecb1cf9c4 firewire: ohci: r... |
228 |
dma_addr_t self_id_bus; |
2d7a36e23 firewire: ohci: M... |
229 |
struct work_struct bus_reset_work; |
ecb1cf9c4 firewire: ohci: r... |
230 231 |
u32 self_id_buffer[512]; |
ed5689122 firewire: Add dri... |
232 |
}; |
db9ae8fec firewire: ohci: F... |
233 |
static struct workqueue_struct *selfid_workqueue; |
95688e97c firewire: cleanups |
234 |
static inline struct fw_ohci *fw_ohci(struct fw_card *card) |
ed5689122 firewire: Add dri... |
235 236 237 |
{ return container_of(card, struct fw_ohci, card); } |
295e3feb9 firewire: Impleme... |
238 239 240 241 242 243 |
#define IT_CONTEXT_CYCLE_MATCH_ENABLE 0x80000000 #define IR_CONTEXT_BUFFER_FILL 0x80000000 #define IR_CONTEXT_ISOCH_HEADER 0x40000000 #define IR_CONTEXT_CYCLE_MATCH_ENABLE 0x20000000 #define IR_CONTEXT_MULTI_CHANNEL_MODE 0x10000000 #define IR_CONTEXT_DUAL_BUFFER_MODE 0x08000000 |
ed5689122 firewire: Add dri... |
244 245 246 247 248 |
#define CONTEXT_RUN 0x8000 #define CONTEXT_WAKE 0x1000 #define CONTEXT_DEAD 0x0800 #define CONTEXT_ACTIVE 0x0400 |
8b7b6afaa firewire: ohci: i... |
249 |
#define OHCI1394_MAX_AT_REQ_RETRIES 0xf |
ed5689122 firewire: Add dri... |
250 251 |
#define OHCI1394_MAX_AT_RESP_RETRIES 0x2 #define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8 |
ed5689122 firewire: Add dri... |
252 |
#define OHCI1394_REGISTER_SIZE 0x800 |
ed5689122 firewire: Add dri... |
253 254 |
#define OHCI1394_PCI_HCI_Control 0x40 #define SELF_ID_BUF_SIZE 0x800 |
32b46093a firewire: Rework ... |
255 |
#define OHCI_TCODE_PHY_PACKET 0x0e |
e364cf4e0 firewire: Store O... |
256 |
#define OHCI_VERSION_1_1 0x010010 |
0edeefd99 firewire: Make su... |
257 |
|
ed5689122 firewire: Add dri... |
258 |
static char ohci_driver_name[] = KBUILD_MODNAME; |
0dbe15f88 firewire: ohci: b... |
259 |
#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd |
9993e0fe0 firewire: ohci: f... |
260 |
#define PCI_DEVICE_ID_AGERE_FW643 0x5901 |
d1bb399ad firewire: ohci: a... |
261 |
#define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001 |
262444eec firewire: ohci: a... |
262 |
#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380 |
8301b91ba firewire: ohci: a... |
263 |
#define PCI_DEVICE_ID_TI_TSB12LV22 0x8009 |
25935ebeb firewire: ohci: A... |
264 265 |
#define PCI_DEVICE_ID_TI_TSB12LV26 0x8020 #define PCI_DEVICE_ID_TI_TSB82AA2 0x8025 |
be8dcab94 firewire: ohci: f... |
266 |
#define PCI_DEVICE_ID_VIA_VT630X 0x3044 |
be8dcab94 firewire: ohci: f... |
267 |
#define PCI_REV_ID_VIA_VT6306 0x46 |
d151f9854 firewire: ohci: e... |
268 |
#define PCI_DEVICE_ID_VIA_VT6315 0x3403 |
8301b91ba firewire: ohci: a... |
269 |
|
0dbe15f88 firewire: ohci: b... |
270 271 272 273 274 275 276 |
#define QUIRK_CYCLE_TIMER 0x1 #define QUIRK_RESET_PACKET 0x2 #define QUIRK_BE_HEADERS 0x4 #define QUIRK_NO_1394A 0x8 #define QUIRK_NO_MSI 0x10 #define QUIRK_TI_SLLZ059 0x20 #define QUIRK_IR_WAKE 0x40 |
4a635593f firewire: ohci: u... |
277 278 279 |
/* In case of multiple matches in ohci_quirks[], only the first one is used. */ static const struct { |
9993e0fe0 firewire: ohci: f... |
280 |
unsigned short vendor, device, revision, flags; |
4a635593f firewire: ohci: u... |
281 |
} ohci_quirks[] = { |
9993e0fe0 firewire: ohci: f... |
282 283 284 285 286 287 288 |
{PCI_VENDOR_ID_AL, PCI_ANY_ID, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, {PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW, PCI_ANY_ID, QUIRK_BE_HEADERS}, {PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6, |
0ca49345b firewire: ohci: f... |
289 |
QUIRK_NO_MSI}, |
9993e0fe0 firewire: ohci: f... |
290 |
|
d1bb399ad firewire: ohci: a... |
291 292 |
{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID, QUIRK_RESET_PACKET}, |
9993e0fe0 firewire: ohci: f... |
293 294 295 296 297 |
{PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID, QUIRK_NO_MSI}, {PCI_VENDOR_ID_NEC, PCI_ANY_ID, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, |
f39aa30d7 firewire: ohci: a... |
298 299 |
{PCI_VENDOR_ID_O2, PCI_ANY_ID, PCI_ANY_ID, QUIRK_NO_MSI}, |
9993e0fe0 firewire: ohci: f... |
300 |
{PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID, |
320cfa6ce firewire: ohci: d... |
301 |
QUIRK_CYCLE_TIMER | QUIRK_NO_MSI}, |
9993e0fe0 firewire: ohci: f... |
302 303 304 |
{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID, QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A}, |
25935ebeb firewire: ohci: A... |
305 306 307 308 309 |
{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV26, PCI_ANY_ID, QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059}, {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB82AA2, PCI_ANY_ID, QUIRK_RESET_PACKET | QUIRK_TI_SLLZ059}, |
9993e0fe0 firewire: ohci: f... |
310 311 |
{PCI_VENDOR_ID_TI, PCI_ANY_ID, PCI_ANY_ID, QUIRK_RESET_PACKET}, |
be8dcab94 firewire: ohci: f... |
312 313 |
{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT630X, PCI_REV_ID_VIA_VT6306, QUIRK_CYCLE_TIMER | QUIRK_IR_WAKE}, |
d151f9854 firewire: ohci: e... |
314 |
{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT6315, 0, |
d584a6627 firewire: ohci: d... |
315 |
QUIRK_CYCLE_TIMER /* FIXME: necessary? */ | QUIRK_NO_MSI}, |
d151f9854 firewire: ohci: e... |
316 317 |
{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT6315, PCI_ANY_ID, |
d584a6627 firewire: ohci: d... |
318 |
QUIRK_NO_MSI}, |
d151f9854 firewire: ohci: e... |
319 |
|
9993e0fe0 firewire: ohci: f... |
320 321 |
{PCI_VENDOR_ID_VIA, PCI_ANY_ID, PCI_ANY_ID, QUIRK_CYCLE_TIMER | QUIRK_NO_MSI}, |
4a635593f firewire: ohci: u... |
322 |
}; |
3e9cc2f3b firewire: ohci: a... |
323 324 325 326 327 328 |
/* This overrides anything that was found in ohci_quirks[]. */ static int param_quirks; module_param_named(quirks, param_quirks, int, 0644); MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" ", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER) ", reset packet generation = " __stringify(QUIRK_RESET_PACKET) |
8a168ca70 treewide: Fix typ... |
329 |
", AR/selfID endianness = " __stringify(QUIRK_BE_HEADERS) |
925e7a650 firewire: ohci: e... |
330 |
", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) |
262444eec firewire: ohci: a... |
331 |
", disable MSI = " __stringify(QUIRK_NO_MSI) |
28897fb73 firewire: ohci: T... |
332 |
", TI SLLZ059 erratum = " __stringify(QUIRK_TI_SLLZ059) |
be8dcab94 firewire: ohci: f... |
333 |
", IR wake unreliable = " __stringify(QUIRK_IR_WAKE) |
3e9cc2f3b firewire: ohci: a... |
334 |
")"); |
a007bb857 firewire: fw-ohci... |
335 |
#define OHCI_PARAM_DEBUG_AT_AR 1 |
ad3c0fe8b firewire: debug i... |
336 |
#define OHCI_PARAM_DEBUG_SELFIDS 2 |
a007bb857 firewire: fw-ohci... |
337 338 |
#define OHCI_PARAM_DEBUG_IRQS 4 #define OHCI_PARAM_DEBUG_BUSRESETS 8 /* only effective before chip init */ |
ad3c0fe8b firewire: debug i... |
339 340 341 342 |
static int param_debug; module_param_named(debug, param_debug, int, 0644); MODULE_PARM_DESC(debug, "Verbose logging (default = 0" |
ad3c0fe8b firewire: debug i... |
343 |
", AT/AR events = " __stringify(OHCI_PARAM_DEBUG_AT_AR) |
a007bb857 firewire: fw-ohci... |
344 345 346 |
", self-IDs = " __stringify(OHCI_PARAM_DEBUG_SELFIDS) ", IRQs = " __stringify(OHCI_PARAM_DEBUG_IRQS) ", busReset events = " __stringify(OHCI_PARAM_DEBUG_BUSRESETS) |
ad3c0fe8b firewire: debug i... |
347 |
", or a combination, or all = -1)"); |
8bc588e0e firewire: ohci: T... |
348 349 350 |
static bool param_remote_dma; module_param_named(remote_dma, param_remote_dma, bool, 0444); MODULE_PARM_DESC(remote_dma, "Enable unfiltered remote DMA (default = N)"); |
64d217201 firewire: ohci: u... |
351 |
static void log_irqs(struct fw_ohci *ohci, u32 evt) |
ad3c0fe8b firewire: debug i... |
352 |
{ |
a007bb857 firewire: fw-ohci... |
353 354 355 356 357 358 |
if (likely(!(param_debug & (OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS)))) return; if (!(param_debug & OHCI_PARAM_DEBUG_IRQS) && !(evt & OHCI1394_busReset)) |
ad3c0fe8b firewire: debug i... |
359 |
return; |
de97cb64a firewire: ohci: A... |
360 361 |
ohci_notice(ohci, "IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s ", evt, |
161b96e78 firewire: fw-ohci... |
362 363 364 365 366 367 368 369 370 |
evt & OHCI1394_selfIDComplete ? " selfID" : "", evt & OHCI1394_RQPkt ? " AR_req" : "", evt & OHCI1394_RSPkt ? " AR_resp" : "", evt & OHCI1394_reqTxComplete ? " AT_req" : "", evt & OHCI1394_respTxComplete ? " AT_resp" : "", evt & OHCI1394_isochRx ? " IR" : "", evt & OHCI1394_isochTx ? " IT" : "", evt & OHCI1394_postedWriteErr ? " postedWriteErr" : "", evt & OHCI1394_cycleTooLong ? " cycleTooLong" : "", |
a48777e03 firewire: add CSR... |
371 |
evt & OHCI1394_cycle64Seconds ? " cycle64Seconds" : "", |
5ed1f321a firewire: ohci: M... |
372 |
evt & OHCI1394_cycleInconsistent ? " cycleInconsistent" : "", |
161b96e78 firewire: fw-ohci... |
373 |
evt & OHCI1394_regAccessFail ? " regAccessFail" : "", |
f117a3e30 firewire: ohci: l... |
374 |
evt & OHCI1394_unrecoverableError ? " unrecoverableError" : "", |
161b96e78 firewire: fw-ohci... |
375 376 377 378 379 |
evt & OHCI1394_busReset ? " busReset" : "", evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt | OHCI1394_RSPkt | OHCI1394_reqTxComplete | OHCI1394_respTxComplete | OHCI1394_isochRx | OHCI1394_isochTx | OHCI1394_postedWriteErr | |
a48777e03 firewire: add CSR... |
380 381 |
OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds | OHCI1394_cycleInconsistent | |
161b96e78 firewire: fw-ohci... |
382 |
OHCI1394_regAccessFail | OHCI1394_busReset) |
ad3c0fe8b firewire: debug i... |
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
? " ?" : ""); } static const char *speed[] = { [0] = "S100", [1] = "S200", [2] = "S400", [3] = "beta", }; static const char *power[] = { [0] = "+0W", [1] = "+15W", [2] = "+30W", [3] = "+45W", [4] = "-3W", [5] = " ?W", [6] = "-3..-6W", [7] = "-3..-10W", }; static const char port[] = { '.', '-', 'p', 'c', }; static char _p(u32 *s, int shift) { return port[*s >> shift & 3]; } |
64d217201 firewire: ohci: u... |
399 |
static void log_selfids(struct fw_ohci *ohci, int generation, int self_id_count) |
ad3c0fe8b firewire: debug i... |
400 |
{ |
64d217201 firewire: ohci: u... |
401 |
u32 *s; |
ad3c0fe8b firewire: debug i... |
402 403 |
if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS))) return; |
de97cb64a firewire: ohci: A... |
404 405 406 |
ohci_notice(ohci, "%d selfIDs, generation %d, local node ID %04x ", self_id_count, generation, ohci->node_id); |
ad3c0fe8b firewire: debug i... |
407 |
|
64d217201 firewire: ohci: u... |
408 |
for (s = ohci->self_id_buffer; self_id_count--; ++s) |
ad3c0fe8b firewire: debug i... |
409 |
if ((*s & 1 << 23) == 0) |
de97cb64a firewire: ohci: A... |
410 411 412 |
ohci_notice(ohci, "selfID 0: %08x, phy %d [%c%c%c] %s gc=%d %s %s%s%s ", |
161b96e78 firewire: fw-ohci... |
413 414 415 416 |
*s, *s >> 24 & 63, _p(s, 6), _p(s, 4), _p(s, 2), speed[*s >> 14 & 3], *s >> 16 & 63, power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "", *s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : ""); |
ad3c0fe8b firewire: debug i... |
417 |
else |
de97cb64a firewire: ohci: A... |
418 |
ohci_notice(ohci, |
64d217201 firewire: ohci: u... |
419 420 |
"selfID n: %08x, phy %d [%c%c%c%c%c%c%c%c] ", |
161b96e78 firewire: fw-ohci... |
421 422 423 |
*s, *s >> 24 & 63, _p(s, 16), _p(s, 14), _p(s, 12), _p(s, 10), _p(s, 8), _p(s, 6), _p(s, 4), _p(s, 2)); |
ad3c0fe8b firewire: debug i... |
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 |
} static const char *evts[] = { [0x00] = "evt_no_status", [0x01] = "-reserved-", [0x02] = "evt_long_packet", [0x03] = "evt_missing_ack", [0x04] = "evt_underrun", [0x05] = "evt_overrun", [0x06] = "evt_descriptor_read", [0x07] = "evt_data_read", [0x08] = "evt_data_write", [0x09] = "evt_bus_reset", [0x0a] = "evt_timeout", [0x0b] = "evt_tcode_err", [0x0c] = "-reserved-", [0x0d] = "-reserved-", [0x0e] = "evt_unknown", [0x0f] = "evt_flushed", [0x10] = "-reserved-", [0x11] = "ack_complete", [0x12] = "ack_pending ", [0x13] = "-reserved-", [0x14] = "ack_busy_X", [0x15] = "ack_busy_A", [0x16] = "ack_busy_B", [0x17] = "-reserved-", [0x18] = "-reserved-", [0x19] = "-reserved-", [0x1a] = "-reserved-", [0x1b] = "ack_tardy", [0x1c] = "-reserved-", [0x1d] = "ack_data_error", [0x1e] = "ack_type_error", [0x1f] = "-reserved-", [0x20] = "pending/cancelled", }; static const char *tcodes[] = { [0x0] = "QW req", [0x1] = "BW req", [0x2] = "W resp", [0x3] = "-reserved-", [0x4] = "QR req", [0x5] = "BR req", [0x6] = "QR resp", [0x7] = "BR resp", [0x8] = "cycle start", [0x9] = "Lk req", [0xa] = "async stream packet", [0xb] = "Lk resp", [0xc] = "-reserved-", [0xd] = "-reserved-", [0xe] = "link internal", [0xf] = "-reserved-", }; |
ad3c0fe8b firewire: debug i... |
455 |
|
64d217201 firewire: ohci: u... |
456 457 |
static void log_ar_at_event(struct fw_ohci *ohci, char dir, int speed, u32 *header, int evt) |
ad3c0fe8b firewire: debug i... |
458 459 460 461 462 463 464 465 466 |
{ int tcode = header[0] >> 4 & 0xf; char specific[12]; if (likely(!(param_debug & OHCI_PARAM_DEBUG_AT_AR))) return; if (unlikely(evt >= ARRAY_SIZE(evts))) evt = 0x1f; |
08ddb2f4c firewire: fw-ohci... |
467 |
if (evt == OHCI1394_evt_bus_reset) { |
de97cb64a firewire: ohci: A... |
468 469 470 |
ohci_notice(ohci, "A%c evt_bus_reset, generation %d ", dir, (header[2] >> 16) & 0xff); |
08ddb2f4c firewire: fw-ohci... |
471 472 |
return; } |
ad3c0fe8b firewire: debug i... |
473 474 475 476 477 478 479 480 481 482 483 484 485 486 |
switch (tcode) { case 0x0: case 0x6: case 0x8: snprintf(specific, sizeof(specific), " = %08x", be32_to_cpu((__force __be32)header[3])); break; case 0x1: case 0x5: case 0x7: case 0x9: case 0xb: snprintf(specific, sizeof(specific), " %x,%x", header[3] >> 16, header[3] & 0xffff); break; default: specific[0] = '\0'; } switch (tcode) { |
5b06db166 firewire: make PH... |
487 |
case 0xa: |
de97cb64a firewire: ohci: A... |
488 489 490 |
ohci_notice(ohci, "A%c %s, %s ", dir, evts[evt], tcodes[tcode]); |
ad3c0fe8b firewire: debug i... |
491 |
break; |
5b06db166 firewire: make PH... |
492 |
case 0xe: |
de97cb64a firewire: ohci: A... |
493 494 495 |
ohci_notice(ohci, "A%c %s, PHY %08x %08x ", dir, evts[evt], header[1], header[2]); |
5b06db166 firewire: make PH... |
496 |
break; |
ad3c0fe8b firewire: debug i... |
497 |
case 0x0: case 0x1: case 0x4: case 0x5: case 0x9: |
de97cb64a firewire: ohci: A... |
498 499 500 501 502 503 |
ohci_notice(ohci, "A%c spd %x tl %02x, %04x -> %04x, %s, %s, %04x%08x%s ", dir, speed, header[0] >> 10 & 0x3f, header[1] >> 16, header[0] >> 16, evts[evt], tcodes[tcode], header[1] & 0xffff, header[2], specific); |
ad3c0fe8b firewire: debug i... |
504 505 |
break; default: |
de97cb64a firewire: ohci: A... |
506 507 508 509 510 511 |
ohci_notice(ohci, "A%c spd %x tl %02x, %04x -> %04x, %s, %s%s ", dir, speed, header[0] >> 10 & 0x3f, header[1] >> 16, header[0] >> 16, evts[evt], tcodes[tcode], specific); |
ad3c0fe8b firewire: debug i... |
512 513 |
} } |
95688e97c firewire: cleanups |
514 |
static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data) |
ed5689122 firewire: Add dri... |
515 516 517 |
{ writel(data, ohci->registers + offset); } |
95688e97c firewire: cleanups |
518 |
static inline u32 reg_read(const struct fw_ohci *ohci, int offset) |
ed5689122 firewire: Add dri... |
519 520 521 |
{ return readl(ohci->registers + offset); } |
95688e97c firewire: cleanups |
522 |
static inline void flush_writes(const struct fw_ohci *ohci) |
ed5689122 firewire: Add dri... |
523 524 525 526 |
{ /* Do a dummy read to flush writes. */ reg_read(ohci, OHCI1394_Version); } |
b14c369d8 firewire: ohci: a... |
527 528 529 530 531 532 |
/* * Beware! read_phy_reg(), write_phy_reg(), update_phy_reg(), and * read_paged_phy_reg() require the caller to hold ohci->phy_reg_mutex. * In other words, only use ohci_read_phy_reg() and ohci_update_phy_reg() * directly. Exceptions are intrinsically serialized contexts like pci_probe. */ |
35d999b12 firewire: ohci: w... |
533 |
static int read_phy_reg(struct fw_ohci *ohci, int addr) |
ed5689122 firewire: Add dri... |
534 |
{ |
4a96b4fcd firewire: ohci: a... |
535 |
u32 val; |
35d999b12 firewire: ohci: w... |
536 |
int i; |
ed5689122 firewire: Add dri... |
537 538 |
reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); |
153e39792 firewire: ohci: s... |
539 |
for (i = 0; i < 3 + 100; i++) { |
35d999b12 firewire: ohci: w... |
540 |
val = reg_read(ohci, OHCI1394_PhyControl); |
215fa444c firewire: ohci: f... |
541 542 |
if (!~val) return -ENODEV; /* Card was ejected. */ |
35d999b12 firewire: ohci: w... |
543 544 |
if (val & OHCI1394_PhyControl_ReadDone) return OHCI1394_PhyControl_ReadData(val); |
153e39792 firewire: ohci: s... |
545 546 547 548 549 550 |
/* * Try a few times without waiting. Sleeping is necessary * only when the link/PHY interface is busy. */ if (i >= 3) msleep(1); |
ed5689122 firewire: Add dri... |
551 |
} |
6fe9efb9c firewire: ohci: d... |
552 553 554 |
ohci_err(ohci, "failed to read phy reg %d ", addr); dump_stack(); |
ed5689122 firewire: Add dri... |
555 |
|
35d999b12 firewire: ohci: w... |
556 557 |
return -EBUSY; } |
4a96b4fcd firewire: ohci: a... |
558 |
|
35d999b12 firewire: ohci: w... |
559 560 561 |
static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val) { int i; |
ed5689122 firewire: Add dri... |
562 |
|
ed5689122 firewire: Add dri... |
563 |
reg_write(ohci, OHCI1394_PhyControl, |
35d999b12 firewire: ohci: w... |
564 |
OHCI1394_PhyControl_Write(addr, val)); |
153e39792 firewire: ohci: s... |
565 |
for (i = 0; i < 3 + 100; i++) { |
35d999b12 firewire: ohci: w... |
566 |
val = reg_read(ohci, OHCI1394_PhyControl); |
215fa444c firewire: ohci: f... |
567 568 |
if (!~val) return -ENODEV; /* Card was ejected. */ |
35d999b12 firewire: ohci: w... |
569 570 |
if (!(val & OHCI1394_PhyControl_WritePending)) return 0; |
ed5689122 firewire: Add dri... |
571 |
|
153e39792 firewire: ohci: s... |
572 573 |
if (i >= 3) msleep(1); |
35d999b12 firewire: ohci: w... |
574 |
} |
6fe9efb9c firewire: ohci: d... |
575 576 577 |
ohci_err(ohci, "failed to write phy reg %d, val %u ", addr, val); dump_stack(); |
35d999b12 firewire: ohci: w... |
578 579 |
return -EBUSY; |
4a96b4fcd firewire: ohci: a... |
580 |
} |
02d37bed1 firewire: core: i... |
581 582 |
static int update_phy_reg(struct fw_ohci *ohci, int addr, int clear_bits, int set_bits) |
4a96b4fcd firewire: ohci: a... |
583 |
{ |
02d37bed1 firewire: core: i... |
584 |
int ret = read_phy_reg(ohci, addr); |
35d999b12 firewire: ohci: w... |
585 586 |
if (ret < 0) return ret; |
4a96b4fcd firewire: ohci: a... |
587 |
|
e7014dada firewire: ohci: d... |
588 589 590 591 592 593 |
/* * The interrupt status bits are cleared by writing a one bit. * Avoid clearing them unless explicitly requested in set_bits. */ if (addr == 5) clear_bits |= PHY_INT_STATUS_BITS; |
35d999b12 firewire: ohci: w... |
594 |
return write_phy_reg(ohci, addr, (ret & ~clear_bits) | set_bits); |
ed5689122 firewire: Add dri... |
595 |
} |
35d999b12 firewire: ohci: w... |
596 |
static int read_paged_phy_reg(struct fw_ohci *ohci, int page, int addr) |
925e7a650 firewire: ohci: e... |
597 |
{ |
35d999b12 firewire: ohci: w... |
598 |
int ret; |
925e7a650 firewire: ohci: e... |
599 |
|
02d37bed1 firewire: core: i... |
600 |
ret = update_phy_reg(ohci, 7, PHY_PAGE_SELECT, page << 5); |
35d999b12 firewire: ohci: w... |
601 602 |
if (ret < 0) return ret; |
925e7a650 firewire: ohci: e... |
603 |
|
35d999b12 firewire: ohci: w... |
604 |
return read_phy_reg(ohci, addr); |
ed5689122 firewire: Add dri... |
605 |
} |
02d37bed1 firewire: core: i... |
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 |
static int ohci_read_phy_reg(struct fw_card *card, int addr) { struct fw_ohci *ohci = fw_ohci(card); int ret; mutex_lock(&ohci->phy_reg_mutex); ret = read_phy_reg(ohci, addr); mutex_unlock(&ohci->phy_reg_mutex); return ret; } static int ohci_update_phy_reg(struct fw_card *card, int addr, int clear_bits, int set_bits) { struct fw_ohci *ohci = fw_ohci(card); int ret; mutex_lock(&ohci->phy_reg_mutex); ret = update_phy_reg(ohci, addr, clear_bits, set_bits); mutex_unlock(&ohci->phy_reg_mutex); return ret; |
ed5689122 firewire: Add dri... |
629 |
} |
7a39d8b82 firewire: ohci: A... |
630 631 632 633 634 635 |
static inline dma_addr_t ar_buffer_bus(struct ar_context *ctx, unsigned int i) { return page_private(ctx->pages[i]); } static void ar_context_link_page(struct ar_context *ctx, unsigned int index) |
ed5689122 firewire: Add dri... |
636 |
{ |
7a39d8b82 firewire: ohci: A... |
637 |
struct descriptor *d; |
32b46093a firewire: Rework ... |
638 |
|
7a39d8b82 firewire: ohci: A... |
639 640 641 642 |
d = &ctx->descriptors[index]; d->branch_address &= cpu_to_le32(~0xf); d->res_count = cpu_to_le16(PAGE_SIZE); d->transfer_status = 0; |
32b46093a firewire: Rework ... |
643 |
|
071595ebd firewire: ohci: u... |
644 |
wmb(); /* finish init of new descriptors before branch_address update */ |
7a39d8b82 firewire: ohci: A... |
645 646 647 648 |
d = &ctx->descriptors[ctx->last_buffer_index]; d->branch_address |= cpu_to_le32(1); ctx->last_buffer_index = index; |
32b46093a firewire: Rework ... |
649 |
|
a77754a75 firewire: Upperca... |
650 |
reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); |
837596a61 firewire: ohci: a... |
651 |
} |
7a39d8b82 firewire: ohci: A... |
652 |
static void ar_context_release(struct ar_context *ctx) |
837596a61 firewire: ohci: a... |
653 |
{ |
7a39d8b82 firewire: ohci: A... |
654 |
unsigned int i; |
837596a61 firewire: ohci: a... |
655 |
|
51b04d59c firewire: ohci: r... |
656 |
vunmap(ctx->buffer); |
32b46093a firewire: Rework ... |
657 |
|
7a39d8b82 firewire: ohci: A... |
658 659 660 661 662 663 664 |
for (i = 0; i < AR_BUFFERS; i++) if (ctx->pages[i]) { dma_unmap_page(ctx->ohci->card.device, ar_buffer_bus(ctx, i), PAGE_SIZE, DMA_FROM_DEVICE); __free_page(ctx->pages[i]); } |
ed5689122 firewire: Add dri... |
665 |
} |
7a39d8b82 firewire: ohci: A... |
666 |
static void ar_context_abort(struct ar_context *ctx, const char *error_msg) |
a55709ba9 firewire: fw-ohci... |
667 |
{ |
64d217201 firewire: ohci: u... |
668 |
struct fw_ohci *ohci = ctx->ohci; |
a55709ba9 firewire: fw-ohci... |
669 |
|
64d217201 firewire: ohci: u... |
670 671 672 |
if (reg_read(ohci, CONTROL_CLEAR(ctx->regs)) & CONTEXT_RUN) { reg_write(ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); flush_writes(ohci); |
a55709ba9 firewire: fw-ohci... |
673 |
|
de97cb64a firewire: ohci: A... |
674 675 |
ohci_err(ohci, "AR error: %s; DMA stopped ", error_msg); |
a55709ba9 firewire: fw-ohci... |
676 |
} |
7a39d8b82 firewire: ohci: A... |
677 678 679 680 681 682 683 |
/* FIXME: restart? */ } static inline unsigned int ar_next_buffer_index(unsigned int index) { return (index + 1) % AR_BUFFERS; } |
7a39d8b82 firewire: ohci: A... |
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 |
static inline unsigned int ar_first_buffer_index(struct ar_context *ctx) { return ar_next_buffer_index(ctx->last_buffer_index); } /* * We search for the buffer that contains the last AR packet DMA data written * by the controller. */ static unsigned int ar_search_last_active_buffer(struct ar_context *ctx, unsigned int *buffer_offset) { unsigned int i, next_i, last = ctx->last_buffer_index; __le16 res_count, next_res_count; i = ar_first_buffer_index(ctx); res_count = ACCESS_ONCE(ctx->descriptors[i].res_count); /* A buffer that is not yet completely filled must be the last one. */ while (i != last && res_count == 0) { /* Peek at the next descriptor. */ next_i = ar_next_buffer_index(i); rmb(); /* read descriptors in order */ next_res_count = ACCESS_ONCE( ctx->descriptors[next_i].res_count); /* * If the next descriptor is still empty, we must stop at this * descriptor. */ if (next_res_count == cpu_to_le16(PAGE_SIZE)) { /* * The exception is when the DMA data for one packet is * split over three buffers; in this case, the middle * buffer's descriptor might be never updated by the * controller and look still empty, and we have to peek * at the third one. */ if (MAX_AR_PACKET_SIZE > PAGE_SIZE && i != last) { next_i = ar_next_buffer_index(next_i); rmb(); next_res_count = ACCESS_ONCE( ctx->descriptors[next_i].res_count); if (next_res_count != cpu_to_le16(PAGE_SIZE)) goto next_buffer_is_active; } break; } next_buffer_is_active: i = next_i; res_count = next_res_count; } rmb(); /* read res_count before the DMA data */ *buffer_offset = PAGE_SIZE - le16_to_cpu(res_count); if (*buffer_offset > PAGE_SIZE) { *buffer_offset = 0; ar_context_abort(ctx, "corrupted descriptor"); } return i; } static void ar_sync_buffers_for_cpu(struct ar_context *ctx, unsigned int end_buffer_index, unsigned int end_buffer_offset) { unsigned int i; i = ar_first_buffer_index(ctx); while (i != end_buffer_index) { dma_sync_single_for_cpu(ctx->ohci->card.device, ar_buffer_bus(ctx, i), PAGE_SIZE, DMA_FROM_DEVICE); i = ar_next_buffer_index(i); } if (end_buffer_offset > 0) dma_sync_single_for_cpu(ctx->ohci->card.device, ar_buffer_bus(ctx, i), end_buffer_offset, DMA_FROM_DEVICE); |
a55709ba9 firewire: fw-ohci... |
767 |
} |
11bf20ad0 firewire: fw-ohci... |
768 769 |
#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) #define cond_le32_to_cpu(v) \ |
4a635593f firewire: ohci: u... |
770 |
(ohci->quirks & QUIRK_BE_HEADERS ? (__force __u32)(v) : le32_to_cpu(v)) |
11bf20ad0 firewire: fw-ohci... |
771 772 773 |
#else #define cond_le32_to_cpu(v) le32_to_cpu(v) #endif |
32b46093a firewire: Rework ... |
774 |
static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) |
ed5689122 firewire: Add dri... |
775 |
{ |
ed5689122 firewire: Add dri... |
776 |
struct fw_ohci *ohci = ctx->ohci; |
2639a6fb2 firewire: Use str... |
777 778 |
struct fw_packet p; u32 status, length, tcode; |
43286568a firewire: fw-ohci... |
779 |
int evt; |
2639a6fb2 firewire: Use str... |
780 |
|
11bf20ad0 firewire: fw-ohci... |
781 782 783 |
p.header[0] = cond_le32_to_cpu(buffer[0]); p.header[1] = cond_le32_to_cpu(buffer[1]); p.header[2] = cond_le32_to_cpu(buffer[2]); |
2639a6fb2 firewire: Use str... |
784 785 786 787 788 |
tcode = (p.header[0] >> 4) & 0x0f; switch (tcode) { case TCODE_WRITE_QUADLET_REQUEST: case TCODE_READ_QUADLET_RESPONSE: |
32b46093a firewire: Rework ... |
789 |
p.header[3] = (__force __u32) buffer[3]; |
2639a6fb2 firewire: Use str... |
790 |
p.header_length = 16; |
32b46093a firewire: Rework ... |
791 |
p.payload_length = 0; |
2639a6fb2 firewire: Use str... |
792 |
break; |
2639a6fb2 firewire: Use str... |
793 |
case TCODE_READ_BLOCK_REQUEST : |
11bf20ad0 firewire: fw-ohci... |
794 |
p.header[3] = cond_le32_to_cpu(buffer[3]); |
32b46093a firewire: Rework ... |
795 796 797 798 799 |
p.header_length = 16; p.payload_length = 0; break; case TCODE_WRITE_BLOCK_REQUEST: |
2639a6fb2 firewire: Use str... |
800 801 802 |
case TCODE_READ_BLOCK_RESPONSE: case TCODE_LOCK_REQUEST: case TCODE_LOCK_RESPONSE: |
11bf20ad0 firewire: fw-ohci... |
803 |
p.header[3] = cond_le32_to_cpu(buffer[3]); |
2639a6fb2 firewire: Use str... |
804 |
p.header_length = 16; |
32b46093a firewire: Rework ... |
805 |
p.payload_length = p.header[3] >> 16; |
7a39d8b82 firewire: ohci: A... |
806 807 808 809 |
if (p.payload_length > MAX_ASYNC_PAYLOAD) { ar_context_abort(ctx, "invalid packet length"); return NULL; } |
2639a6fb2 firewire: Use str... |
810 811 812 813 |
break; case TCODE_WRITE_RESPONSE: case TCODE_READ_QUADLET_REQUEST: |
32b46093a firewire: Rework ... |
814 |
case OHCI_TCODE_PHY_PACKET: |
2639a6fb2 firewire: Use str... |
815 |
p.header_length = 12; |
32b46093a firewire: Rework ... |
816 |
p.payload_length = 0; |
2639a6fb2 firewire: Use str... |
817 |
break; |
ccff96294 firewire: fw-ohci... |
818 819 |
default: |
7a39d8b82 firewire: ohci: A... |
820 821 |
ar_context_abort(ctx, "invalid tcode"); return NULL; |
2639a6fb2 firewire: Use str... |
822 |
} |
ed5689122 firewire: Add dri... |
823 |
|
32b46093a firewire: Rework ... |
824 825 826 827 |
p.payload = (void *) buffer + p.header_length; /* FIXME: What to do about evt_* errors? */ length = (p.header_length + p.payload_length + 3) / 4; |
11bf20ad0 firewire: fw-ohci... |
828 |
status = cond_le32_to_cpu(buffer[length]); |
43286568a firewire: fw-ohci... |
829 |
evt = (status >> 16) & 0x1f; |
32b46093a firewire: Rework ... |
830 |
|
43286568a firewire: fw-ohci... |
831 |
p.ack = evt - 16; |
32b46093a firewire: Rework ... |
832 833 834 |
p.speed = (status >> 21) & 0x7; p.timestamp = status & 0xffff; p.generation = ohci->request_generation; |
ed5689122 firewire: Add dri... |
835 |
|
64d217201 firewire: ohci: u... |
836 |
log_ar_at_event(ohci, 'R', p.speed, p.header, evt); |
ad3c0fe8b firewire: debug i... |
837 |
|
c781c06d1 firewire: Clean u... |
838 |
/* |
a4dc090b6 firewire: ohci: w... |
839 840 841 842 843 844 845 846 847 |
* Several controllers, notably from NEC and VIA, forget to * write ack_complete status at PHY packet reception. */ if (evt == OHCI1394_evt_no_status && (p.header[0] & 0xff) == (OHCI1394_phy_tcode << 4)) p.ack = ACK_COMPLETE; /* * The OHCI bus reset handler synthesizes a PHY packet with |
ed5689122 firewire: Add dri... |
848 849 850 851 852 |
* the new generation number when a bus reset happens (see * section 8.4.2.3). This helps us determine when a request * was received and make sure we send the response in the same * generation. We only need this for requests; for responses * we use the unique tlabel for finding the matching |
c781c06d1 firewire: Clean u... |
853 |
* request. |
d34316a4b firewire: fw-ohci... |
854 855 856 |
* * Alas some chips sometimes emit bus reset packets with a * wrong generation. We set the correct generation for these |
2d7a36e23 firewire: ohci: M... |
857 |
* at a slightly incorrect time (in bus_reset_work). |
c781c06d1 firewire: Clean u... |
858 |
*/ |
d34316a4b firewire: fw-ohci... |
859 |
if (evt == OHCI1394_evt_bus_reset) { |
4a635593f firewire: ohci: u... |
860 |
if (!(ohci->quirks & QUIRK_RESET_PACKET)) |
d34316a4b firewire: fw-ohci... |
861 862 |
ohci->request_generation = (p.header[2] >> 16) & 0xff; } else if (ctx == &ohci->ar_request_ctx) { |
2639a6fb2 firewire: Use str... |
863 |
fw_core_handle_request(&ohci->card, &p); |
d34316a4b firewire: fw-ohci... |
864 |
} else { |
2639a6fb2 firewire: Use str... |
865 |
fw_core_handle_response(&ohci->card, &p); |
d34316a4b firewire: fw-ohci... |
866 |
} |
ed5689122 firewire: Add dri... |
867 |
|
32b46093a firewire: Rework ... |
868 869 |
return buffer + length + 1; } |
ed5689122 firewire: Add dri... |
870 |
|
7a39d8b82 firewire: ohci: A... |
871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 |
static void *handle_ar_packets(struct ar_context *ctx, void *p, void *end) { void *next; while (p < end) { next = handle_ar_packet(ctx, p); if (!next) return p; p = next; } return p; } static void ar_recycle_buffers(struct ar_context *ctx, unsigned int end_buffer) { unsigned int i; i = ar_first_buffer_index(ctx); while (i != end_buffer) { dma_sync_single_for_device(ctx->ohci->card.device, ar_buffer_bus(ctx, i), PAGE_SIZE, DMA_FROM_DEVICE); ar_context_link_page(ctx, i); i = ar_next_buffer_index(i); } } |
32b46093a firewire: Rework ... |
898 899 900 |
static void ar_context_tasklet(unsigned long data) { struct ar_context *ctx = (struct ar_context *)data; |
7a39d8b82 firewire: ohci: A... |
901 902 |
unsigned int end_buffer_index, end_buffer_offset; void *p, *end; |
32b46093a firewire: Rework ... |
903 |
|
7a39d8b82 firewire: ohci: A... |
904 905 906 |
p = ctx->pointer; if (!p) return; |
32b46093a firewire: Rework ... |
907 |
|
7a39d8b82 firewire: ohci: A... |
908 909 910 911 |
end_buffer_index = ar_search_last_active_buffer(ctx, &end_buffer_offset); ar_sync_buffers_for_cpu(ctx, end_buffer_index, end_buffer_offset); end = ctx->buffer + end_buffer_index * PAGE_SIZE + end_buffer_offset; |
32b46093a firewire: Rework ... |
912 |
|
7a39d8b82 firewire: ohci: A... |
913 |
if (end_buffer_index < ar_first_buffer_index(ctx)) { |
c781c06d1 firewire: Clean u... |
914 |
/* |
7a39d8b82 firewire: ohci: A... |
915 916 917 918 |
* The filled part of the overall buffer wraps around; handle * all packets up to the buffer end here. If the last packet * wraps around, its tail will be visible after the buffer end * because the buffer start pages are mapped there again. |
c781c06d1 firewire: Clean u... |
919 |
*/ |
7a39d8b82 firewire: ohci: A... |
920 921 922 923 924 925 926 |
void *buffer_end = ctx->buffer + AR_BUFFERS * PAGE_SIZE; p = handle_ar_packets(ctx, p, buffer_end); if (p < buffer_end) goto error; /* adjust p to point back into the actual buffer */ p -= AR_BUFFERS * PAGE_SIZE; } |
32b46093a firewire: Rework ... |
927 |
|
7a39d8b82 firewire: ohci: A... |
928 929 930 931 932 933 |
p = handle_ar_packets(ctx, p, end); if (p != end) { if (p > end) ar_context_abort(ctx, "inconsistent descriptor"); goto error; } |
32b46093a firewire: Rework ... |
934 |
|
7a39d8b82 firewire: ohci: A... |
935 936 |
ctx->pointer = p; ar_recycle_buffers(ctx, end_buffer_index); |
32b46093a firewire: Rework ... |
937 |
|
7a39d8b82 firewire: ohci: A... |
938 |
return; |
a1f805e5e firewire: ohci: f... |
939 |
|
7a39d8b82 firewire: ohci: A... |
940 941 |
error: ctx->pointer = NULL; |
ed5689122 firewire: Add dri... |
942 |
} |
ec766a797 firewire: ohci: u... |
943 944 |
static int ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, unsigned int descriptors_offset, u32 regs) |
ed5689122 firewire: Add dri... |
945 |
{ |
7a39d8b82 firewire: ohci: A... |
946 947 948 949 |
unsigned int i; dma_addr_t dma_addr; struct page *pages[AR_BUFFERS + AR_WRAPAROUND_PAGES]; struct descriptor *d; |
ed5689122 firewire: Add dri... |
950 |
|
72e318e07 firewire: Reduce ... |
951 952 |
ctx->regs = regs; ctx->ohci = ohci; |
ed5689122 firewire: Add dri... |
953 |
tasklet_init(&ctx->tasklet, ar_context_tasklet, (unsigned long)ctx); |
7a39d8b82 firewire: ohci: A... |
954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 |
for (i = 0; i < AR_BUFFERS; i++) { ctx->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32); if (!ctx->pages[i]) goto out_of_memory; dma_addr = dma_map_page(ohci->card.device, ctx->pages[i], 0, PAGE_SIZE, DMA_FROM_DEVICE); if (dma_mapping_error(ohci->card.device, dma_addr)) { __free_page(ctx->pages[i]); ctx->pages[i] = NULL; goto out_of_memory; } set_page_private(ctx->pages[i], dma_addr); } for (i = 0; i < AR_BUFFERS; i++) pages[i] = ctx->pages[i]; for (i = 0; i < AR_WRAPAROUND_PAGES; i++) pages[AR_BUFFERS + i] = ctx->pages[i]; |
51b04d59c firewire: ohci: r... |
972 |
ctx->buffer = vmap(pages, ARRAY_SIZE(pages), VM_MAP, PAGE_KERNEL); |
7a39d8b82 firewire: ohci: A... |
973 974 |
if (!ctx->buffer) goto out_of_memory; |
ec766a797 firewire: ohci: u... |
975 976 |
ctx->descriptors = ohci->misc_buffer + descriptors_offset; ctx->descriptors_bus = ohci->misc_buffer_bus + descriptors_offset; |
7a39d8b82 firewire: ohci: A... |
977 978 979 980 981 982 983 984 985 986 987 |
for (i = 0; i < AR_BUFFERS; i++) { d = &ctx->descriptors[i]; d->req_count = cpu_to_le16(PAGE_SIZE); d->control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | DESCRIPTOR_STATUS | DESCRIPTOR_BRANCH_ALWAYS); d->data_address = cpu_to_le32(ar_buffer_bus(ctx, i)); d->branch_address = cpu_to_le32(ctx->descriptors_bus + ar_next_buffer_index(i) * sizeof(struct descriptor)); } |
32b46093a firewire: Rework ... |
988 |
|
2aef469a3 firewire: Impleme... |
989 |
return 0; |
7a39d8b82 firewire: ohci: A... |
990 991 992 993 994 |
out_of_memory: ar_context_release(ctx); return -ENOMEM; |
2aef469a3 firewire: Impleme... |
995 996 997 998 |
} static void ar_context_run(struct ar_context *ctx) { |
7a39d8b82 firewire: ohci: A... |
999 1000 1001 1002 |
unsigned int i; for (i = 0; i < AR_BUFFERS; i++) ar_context_link_page(ctx, i); |
2aef469a3 firewire: Impleme... |
1003 |
|
7a39d8b82 firewire: ohci: A... |
1004 |
ctx->pointer = ctx->buffer; |
2aef469a3 firewire: Impleme... |
1005 |
|
7a39d8b82 firewire: ohci: A... |
1006 |
reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ctx->descriptors_bus | 1); |
a77754a75 firewire: Upperca... |
1007 |
reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN); |
ed5689122 firewire: Add dri... |
1008 |
} |
373b2edd8 firewire: adjust ... |
1009 |
|
53dca5117 firewire: remove ... |
1010 |
static struct descriptor *find_branch_descriptor(struct descriptor *d, int z) |
a186b4a6b firewire: OHCI 1.... |
1011 |
{ |
0ff8fbc61 firewire: ohci: o... |
1012 |
__le16 branch; |
a186b4a6b firewire: OHCI 1.... |
1013 |
|
0ff8fbc61 firewire: ohci: o... |
1014 |
branch = d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS); |
a186b4a6b firewire: OHCI 1.... |
1015 1016 |
/* figure out which descriptor the branch address goes in */ |
0ff8fbc61 firewire: ohci: o... |
1017 |
if (z == 2 && branch == cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)) |
a186b4a6b firewire: OHCI 1.... |
1018 1019 1020 1021 |
return d; else return d + z - 1; } |
30200739e firewire: General... |
1022 1023 1024 |
static void context_tasklet(unsigned long data) { struct context *ctx = (struct context *) data; |
30200739e firewire: General... |
1025 1026 1027 |
struct descriptor *d, *last; u32 address; int z; |
fe5ca6343 firewire: fw-ohci... |
1028 |
struct descriptor_buffer *desc; |
30200739e firewire: General... |
1029 |
|
fe5ca6343 firewire: fw-ohci... |
1030 1031 1032 |
desc = list_entry(ctx->buffer_list.next, struct descriptor_buffer, list); last = ctx->last; |
30200739e firewire: General... |
1033 |
while (last->branch_address != 0) { |
fe5ca6343 firewire: fw-ohci... |
1034 |
struct descriptor_buffer *old_desc = desc; |
30200739e firewire: General... |
1035 1036 |
address = le32_to_cpu(last->branch_address); z = address & 0xf; |
fe5ca6343 firewire: fw-ohci... |
1037 |
address &= ~0xf; |
a572e688c firewire: ohci: f... |
1038 |
ctx->current_bus = address; |
fe5ca6343 firewire: fw-ohci... |
1039 1040 1041 1042 1043 1044 1045 1046 |
/* If the branch address points to a buffer outside of the * current buffer, advance to the next buffer. */ if (address < desc->buffer_bus || address >= desc->buffer_bus + desc->used) desc = list_entry(desc->list.next, struct descriptor_buffer, list); d = desc->buffer + (address - desc->buffer_bus) / sizeof(*d); |
a186b4a6b firewire: OHCI 1.... |
1047 |
last = find_branch_descriptor(d, z); |
30200739e firewire: General... |
1048 1049 1050 |
if (!ctx->callback(ctx, d, last)) break; |
fe5ca6343 firewire: fw-ohci... |
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 |
if (old_desc != desc) { /* If we've advanced to the next buffer, move the * previous buffer to the free list. */ unsigned long flags; old_desc->used = 0; spin_lock_irqsave(&ctx->ohci->lock, flags); list_move_tail(&old_desc->list, &ctx->buffer_list); spin_unlock_irqrestore(&ctx->ohci->lock, flags); } ctx->last = last; |
30200739e firewire: General... |
1061 1062 |
} } |
fe5ca6343 firewire: fw-ohci... |
1063 1064 1065 1066 |
/* * Allocate a new buffer and add it to the list of free buffers for this * context. Must be called with ohci->lock held. */ |
53dca5117 firewire: remove ... |
1067 |
static int context_add_buffer(struct context *ctx) |
fe5ca6343 firewire: fw-ohci... |
1068 1069 |
{ struct descriptor_buffer *desc; |
f5101d58a firewire: fw-ohci... |
1070 |
dma_addr_t uninitialized_var(bus_addr); |
fe5ca6343 firewire: fw-ohci... |
1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 |
int offset; /* * 16MB of descriptors should be far more than enough for any DMA * program. This will catch run-away userspace or DoS attacks. */ if (ctx->total_allocation >= 16*1024*1024) return -ENOMEM; desc = dma_alloc_coherent(ctx->ohci->card.device, PAGE_SIZE, &bus_addr, GFP_ATOMIC); if (!desc) return -ENOMEM; offset = (void *)&desc->buffer - (void *)desc; desc->buffer_size = PAGE_SIZE - offset; desc->buffer_bus = bus_addr + offset; desc->used = 0; list_add_tail(&desc->list, &ctx->buffer_list); ctx->total_allocation += PAGE_SIZE; return 0; } |
53dca5117 firewire: remove ... |
1095 1096 |
static int context_init(struct context *ctx, struct fw_ohci *ohci, u32 regs, descriptor_callback_t callback) |
30200739e firewire: General... |
1097 1098 1099 |
{ ctx->ohci = ohci; ctx->regs = regs; |
fe5ca6343 firewire: fw-ohci... |
1100 1101 1102 1103 |
ctx->total_allocation = 0; INIT_LIST_HEAD(&ctx->buffer_list); if (context_add_buffer(ctx) < 0) |
30200739e firewire: General... |
1104 |
return -ENOMEM; |
fe5ca6343 firewire: fw-ohci... |
1105 1106 |
ctx->buffer_tail = list_entry(ctx->buffer_list.next, struct descriptor_buffer, list); |
30200739e firewire: General... |
1107 1108 |
tasklet_init(&ctx->tasklet, context_tasklet, (unsigned long)ctx); ctx->callback = callback; |
c781c06d1 firewire: Clean u... |
1109 1110 |
/* * We put a dummy descriptor in the buffer that has a NULL |
30200739e firewire: General... |
1111 |
* branch address and looks like it's been sent. That way we |
fe5ca6343 firewire: fw-ohci... |
1112 |
* have a descriptor to append DMA programs to. |
c781c06d1 firewire: Clean u... |
1113 |
*/ |
fe5ca6343 firewire: fw-ohci... |
1114 1115 1116 1117 1118 1119 |
memset(ctx->buffer_tail->buffer, 0, sizeof(*ctx->buffer_tail->buffer)); ctx->buffer_tail->buffer->control = cpu_to_le16(DESCRIPTOR_OUTPUT_LAST); ctx->buffer_tail->buffer->transfer_status = cpu_to_le16(0x8011); ctx->buffer_tail->used += sizeof(*ctx->buffer_tail->buffer); ctx->last = ctx->buffer_tail->buffer; ctx->prev = ctx->buffer_tail->buffer; |
be8dcab94 firewire: ohci: f... |
1120 |
ctx->prev_z = 1; |
30200739e firewire: General... |
1121 1122 1123 |
return 0; } |
53dca5117 firewire: remove ... |
1124 |
static void context_release(struct context *ctx) |
30200739e firewire: General... |
1125 1126 |
{ struct fw_card *card = &ctx->ohci->card; |
fe5ca6343 firewire: fw-ohci... |
1127 |
struct descriptor_buffer *desc, *tmp; |
30200739e firewire: General... |
1128 |
|
fe5ca6343 firewire: fw-ohci... |
1129 1130 1131 1132 |
list_for_each_entry_safe(desc, tmp, &ctx->buffer_list, list) dma_free_coherent(card->device, PAGE_SIZE, desc, desc->buffer_bus - ((void *)&desc->buffer - (void *)desc)); |
30200739e firewire: General... |
1133 |
} |
fe5ca6343 firewire: fw-ohci... |
1134 |
/* Must be called with ohci->lock held */ |
53dca5117 firewire: remove ... |
1135 1136 |
static struct descriptor *context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus) |
30200739e firewire: General... |
1137 |
{ |
fe5ca6343 firewire: fw-ohci... |
1138 1139 1140 1141 1142 1143 1144 1145 1146 |
struct descriptor *d = NULL; struct descriptor_buffer *desc = ctx->buffer_tail; if (z * sizeof(*d) > desc->buffer_size) return NULL; if (z * sizeof(*d) > desc->buffer_size - desc->used) { /* No room for the descriptor in this buffer, so advance to the * next one. */ |
30200739e firewire: General... |
1147 |
|
fe5ca6343 firewire: fw-ohci... |
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 |
if (desc->list.next == &ctx->buffer_list) { /* If there is no free buffer next in the list, * allocate one. */ if (context_add_buffer(ctx) < 0) return NULL; } desc = list_entry(desc->list.next, struct descriptor_buffer, list); ctx->buffer_tail = desc; } |
30200739e firewire: General... |
1158 |
|
fe5ca6343 firewire: fw-ohci... |
1159 |
d = desc->buffer + desc->used / sizeof(*d); |
2d826cc5c firewire: Always ... |
1160 |
memset(d, 0, z * sizeof(*d)); |
fe5ca6343 firewire: fw-ohci... |
1161 |
*d_bus = desc->buffer_bus + desc->used; |
30200739e firewire: General... |
1162 1163 1164 |
return d; } |
295e3feb9 firewire: Impleme... |
1165 |
static void context_run(struct context *ctx, u32 extra) |
30200739e firewire: General... |
1166 1167 |
{ struct fw_ohci *ohci = ctx->ohci; |
a77754a75 firewire: Upperca... |
1168 |
reg_write(ohci, COMMAND_PTR(ctx->regs), |
fe5ca6343 firewire: fw-ohci... |
1169 |
le32_to_cpu(ctx->last->branch_address)); |
a77754a75 firewire: Upperca... |
1170 1171 |
reg_write(ohci, CONTROL_CLEAR(ctx->regs), ~0); reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN | extra); |
386a4153a firewire: ohci: c... |
1172 |
ctx->running = true; |
30200739e firewire: General... |
1173 1174 1175 1176 1177 1178 1179 |
flush_writes(ohci); } static void context_append(struct context *ctx, struct descriptor *d, int z, int extra) { dma_addr_t d_bus; |
fe5ca6343 firewire: fw-ohci... |
1180 |
struct descriptor_buffer *desc = ctx->buffer_tail; |
be8dcab94 firewire: ohci: f... |
1181 |
struct descriptor *d_branch; |
30200739e firewire: General... |
1182 |
|
fe5ca6343 firewire: fw-ohci... |
1183 |
d_bus = desc->buffer_bus + (d - desc->buffer) * sizeof(*d); |
30200739e firewire: General... |
1184 |
|
fe5ca6343 firewire: fw-ohci... |
1185 |
desc->used += (z + extra) * sizeof(*d); |
071595ebd firewire: ohci: u... |
1186 1187 |
wmb(); /* finish init of new descriptors before branch_address update */ |
be8dcab94 firewire: ohci: f... |
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 |
d_branch = find_branch_descriptor(ctx->prev, ctx->prev_z); d_branch->branch_address = cpu_to_le32(d_bus | z); /* * VT6306 incorrectly checks only the single descriptor at the * CommandPtr when the wake bit is written, so if it's a * multi-descriptor block starting with an INPUT_MORE, put a copy of * the branch address in the first descriptor. * * Not doing this for transmit contexts since not sure how it interacts * with skip addresses. */ if (unlikely(ctx->ohci->quirks & QUIRK_IR_WAKE) && d_branch != ctx->prev && (ctx->prev->control & cpu_to_le16(DESCRIPTOR_CMD)) == cpu_to_le16(DESCRIPTOR_INPUT_MORE)) { ctx->prev->branch_address = cpu_to_le32(d_bus | z); } ctx->prev = d; ctx->prev_z = z; |
30200739e firewire: General... |
1210 1211 1212 1213 |
} static void context_stop(struct context *ctx) { |
64d217201 firewire: ohci: u... |
1214 |
struct fw_ohci *ohci = ctx->ohci; |
30200739e firewire: General... |
1215 |
u32 reg; |
b82956685 firewire: Impleme... |
1216 |
int i; |
30200739e firewire: General... |
1217 |
|
64d217201 firewire: ohci: u... |
1218 |
reg_write(ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); |
386a4153a firewire: ohci: c... |
1219 |
ctx->running = false; |
30200739e firewire: General... |
1220 |
|
9ef28ccd5 firewire: ohci: r... |
1221 |
for (i = 0; i < 1000; i++) { |
64d217201 firewire: ohci: u... |
1222 |
reg = reg_read(ohci, CONTROL_SET(ctx->regs)); |
b82956685 firewire: Impleme... |
1223 |
if ((reg & CONTEXT_ACTIVE) == 0) |
b00685495 firewire: ohci: c... |
1224 |
return; |
b82956685 firewire: Impleme... |
1225 |
|
9ef28ccd5 firewire: ohci: r... |
1226 1227 |
if (i) udelay(10); |
b82956685 firewire: Impleme... |
1228 |
} |
de97cb64a firewire: ohci: A... |
1229 1230 |
ohci_err(ohci, "DMA context still active (0x%08x) ", reg); |
30200739e firewire: General... |
1231 |
} |
ed5689122 firewire: Add dri... |
1232 |
|
f319b6a02 firewire: Move as... |
1233 |
struct driver_data { |
da28947e7 firewire: ohci: a... |
1234 |
u8 inline_data[8]; |
f319b6a02 firewire: Move as... |
1235 1236 |
struct fw_packet *packet; }; |
ed5689122 firewire: Add dri... |
1237 |
|
c781c06d1 firewire: Clean u... |
1238 1239 |
/* * This function apppends a packet to the DMA queue for transmission. |
f319b6a02 firewire: Move as... |
1240 |
* Must always be called with the ochi->lock held to ensure proper |
c781c06d1 firewire: Clean u... |
1241 1242 |
* generation handling and locking around packet queue manipulation. */ |
53dca5117 firewire: remove ... |
1243 1244 |
static int at_context_queue_packet(struct context *ctx, struct fw_packet *packet) |
ed5689122 firewire: Add dri... |
1245 |
{ |
ed5689122 firewire: Add dri... |
1246 |
struct fw_ohci *ohci = ctx->ohci; |
4b6d51ec6 firewire: fw-ohci... |
1247 |
dma_addr_t d_bus, uninitialized_var(payload_bus); |
f319b6a02 firewire: Move as... |
1248 1249 1250 |
struct driver_data *driver_data; struct descriptor *d, *last; __le32 *header; |
ed5689122 firewire: Add dri... |
1251 |
int z, tcode; |
f319b6a02 firewire: Move as... |
1252 1253 1254 1255 |
d = context_get_descriptors(ctx, 4, &d_bus); if (d == NULL) { packet->ack = RCODE_SEND_ERROR; return -1; |
ed5689122 firewire: Add dri... |
1256 |
} |
a77754a75 firewire: Upperca... |
1257 |
d[0].control = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE); |
f319b6a02 firewire: Move as... |
1258 |
d[0].res_count = cpu_to_le16(packet->timestamp); |
c781c06d1 firewire: Clean u... |
1259 |
/* |
b3834be5c various: Fix spel... |
1260 |
* The DMA format for asynchronous link packets is different |
ed5689122 firewire: Add dri... |
1261 |
* from the IEEE1394 layout, so shift the fields around |
5b06db166 firewire: make PH... |
1262 |
* accordingly. |
c781c06d1 firewire: Clean u... |
1263 |
*/ |
f319b6a02 firewire: Move as... |
1264 |
|
5b06db166 firewire: make PH... |
1265 |
tcode = (packet->header[0] >> 4) & 0x0f; |
f319b6a02 firewire: Move as... |
1266 |
header = (__le32 *) &d[1]; |
5b06db166 firewire: make PH... |
1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 |
switch (tcode) { case TCODE_WRITE_QUADLET_REQUEST: case TCODE_WRITE_BLOCK_REQUEST: case TCODE_WRITE_RESPONSE: case TCODE_READ_QUADLET_REQUEST: case TCODE_READ_BLOCK_REQUEST: case TCODE_READ_QUADLET_RESPONSE: case TCODE_READ_BLOCK_RESPONSE: case TCODE_LOCK_REQUEST: case TCODE_LOCK_RESPONSE: |
f319b6a02 firewire: Move as... |
1277 1278 1279 1280 1281 |
header[0] = cpu_to_le32((packet->header[0] & 0xffff) | (packet->speed << 16)); header[1] = cpu_to_le32((packet->header[1] & 0xffff) | (packet->header[0] & 0xffff0000)); header[2] = cpu_to_le32(packet->header[2]); |
ed5689122 firewire: Add dri... |
1282 |
|
ed5689122 firewire: Add dri... |
1283 |
if (TCODE_IS_BLOCK_PACKET(tcode)) |
f319b6a02 firewire: Move as... |
1284 |
header[3] = cpu_to_le32(packet->header[3]); |
ed5689122 firewire: Add dri... |
1285 |
else |
f319b6a02 firewire: Move as... |
1286 1287 1288 |
header[3] = (__force __le32) packet->header[3]; d[0].req_count = cpu_to_le16(packet->header_length); |
f8c2287c6 firewire: impleme... |
1289 |
break; |
5b06db166 firewire: make PH... |
1290 |
case TCODE_LINK_INTERNAL: |
f319b6a02 firewire: Move as... |
1291 1292 |
header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) | (packet->speed << 16)); |
5b06db166 firewire: make PH... |
1293 1294 |
header[1] = cpu_to_le32(packet->header[1]); header[2] = cpu_to_le32(packet->header[2]); |
f319b6a02 firewire: Move as... |
1295 |
d[0].req_count = cpu_to_le16(12); |
cc550216a firewire: cdev: a... |
1296 |
|
5b06db166 firewire: make PH... |
1297 |
if (is_ping_packet(&packet->header[1])) |
cc550216a firewire: cdev: a... |
1298 |
d[0].control |= cpu_to_le16(DESCRIPTOR_PING); |
f8c2287c6 firewire: impleme... |
1299 |
break; |
5b06db166 firewire: make PH... |
1300 |
case TCODE_STREAM_DATA: |
f8c2287c6 firewire: impleme... |
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 |
header[0] = cpu_to_le32((packet->header[0] & 0xffff) | (packet->speed << 16)); header[1] = cpu_to_le32(packet->header[0] & 0xffff0000); d[0].req_count = cpu_to_le16(8); break; default: /* BUG(); */ packet->ack = RCODE_SEND_ERROR; return -1; |
ed5689122 firewire: Add dri... |
1311 |
} |
da28947e7 firewire: ohci: a... |
1312 |
BUILD_BUG_ON(sizeof(struct driver_data) > sizeof(struct descriptor)); |
f319b6a02 firewire: Move as... |
1313 1314 |
driver_data = (struct driver_data *) &d[3]; driver_data->packet = packet; |
20d116731 firewire: Remembe... |
1315 |
packet->driver_data = driver_data; |
a186b4a6b firewire: OHCI 1.... |
1316 |
|
f319b6a02 firewire: Move as... |
1317 |
if (packet->payload_length > 0) { |
da28947e7 firewire: ohci: a... |
1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 |
if (packet->payload_length > sizeof(driver_data->inline_data)) { payload_bus = dma_map_single(ohci->card.device, packet->payload, packet->payload_length, DMA_TO_DEVICE); if (dma_mapping_error(ohci->card.device, payload_bus)) { packet->ack = RCODE_SEND_ERROR; return -1; } packet->payload_bus = payload_bus; packet->payload_mapped = true; } else { memcpy(driver_data->inline_data, packet->payload, packet->payload_length); payload_bus = d_bus + 3 * sizeof(*d); |
f319b6a02 firewire: Move as... |
1333 1334 1335 1336 1337 1338 |
} d[2].req_count = cpu_to_le16(packet->payload_length); d[2].data_address = cpu_to_le32(payload_bus); last = &d[2]; z = 3; |
ed5689122 firewire: Add dri... |
1339 |
} else { |
f319b6a02 firewire: Move as... |
1340 1341 |
last = &d[0]; z = 2; |
ed5689122 firewire: Add dri... |
1342 |
} |
ed5689122 firewire: Add dri... |
1343 |
|
a77754a75 firewire: Upperca... |
1344 1345 1346 |
last->control |= cpu_to_le16(DESCRIPTOR_OUTPUT_LAST | DESCRIPTOR_IRQ_ALWAYS | DESCRIPTOR_BRANCH_ALWAYS); |
ed5689122 firewire: Add dri... |
1347 |
|
b6258fc1f firewire: ohci: o... |
1348 1349 |
/* FIXME: Document how the locking works. */ if (ohci->generation != packet->generation) { |
19593ffdb firewire: ohci: 0... |
1350 |
if (packet->payload_mapped) |
ab88ca488 firewire: fw-ohci... |
1351 1352 |
dma_unmap_single(ohci->card.device, payload_bus, packet->payload_length, DMA_TO_DEVICE); |
f319b6a02 firewire: Move as... |
1353 1354 1355 1356 1357 |
packet->ack = RCODE_GENERATION; return -1; } context_append(ctx, d, z, 4 - z); |
ed5689122 firewire: Add dri... |
1358 |
|
dd6254e5c firewire: ohci: r... |
1359 |
if (ctx->running) |
13882a82e firewire: optimiz... |
1360 |
reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); |
dd6254e5c firewire: ohci: r... |
1361 |
else |
f319b6a02 firewire: Move as... |
1362 1363 1364 |
context_run(ctx, 0); return 0; |
ed5689122 firewire: Add dri... |
1365 |
} |
82b662dc4 firewire: ohci: f... |
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 |
static void at_context_flush(struct context *ctx) { tasklet_disable(&ctx->tasklet); ctx->flushing = true; context_tasklet((unsigned long)ctx); ctx->flushing = false; tasklet_enable(&ctx->tasklet); } |
f319b6a02 firewire: Move as... |
1376 1377 1378 |
static int handle_at_packet(struct context *context, struct descriptor *d, struct descriptor *last) |
ed5689122 firewire: Add dri... |
1379 |
{ |
f319b6a02 firewire: Move as... |
1380 |
struct driver_data *driver_data; |
ed5689122 firewire: Add dri... |
1381 |
struct fw_packet *packet; |
f319b6a02 firewire: Move as... |
1382 |
struct fw_ohci *ohci = context->ohci; |
ed5689122 firewire: Add dri... |
1383 |
int evt; |
82b662dc4 firewire: ohci: f... |
1384 |
if (last->transfer_status == 0 && !context->flushing) |
f319b6a02 firewire: Move as... |
1385 1386 |
/* This descriptor isn't done yet, stop iteration. */ return 0; |
ed5689122 firewire: Add dri... |
1387 |
|
f319b6a02 firewire: Move as... |
1388 1389 1390 1391 1392 |
driver_data = (struct driver_data *) &d[3]; packet = driver_data->packet; if (packet == NULL) /* This packet was cancelled, just continue. */ return 1; |
730c32f58 firewire: Impleme... |
1393 |
|
19593ffdb firewire: ohci: 0... |
1394 |
if (packet->payload_mapped) |
1d1dc5e83 firewire: fw-ohci... |
1395 |
dma_unmap_single(ohci->card.device, packet->payload_bus, |
ed5689122 firewire: Add dri... |
1396 |
packet->payload_length, DMA_TO_DEVICE); |
ed5689122 firewire: Add dri... |
1397 |
|
f319b6a02 firewire: Move as... |
1398 1399 |
evt = le16_to_cpu(last->transfer_status) & 0x1f; packet->timestamp = le16_to_cpu(last->res_count); |
ed5689122 firewire: Add dri... |
1400 |
|
64d217201 firewire: ohci: u... |
1401 |
log_ar_at_event(ohci, 'T', packet->speed, packet->header, evt); |
ad3c0fe8b firewire: debug i... |
1402 |
|
f319b6a02 firewire: Move as... |
1403 1404 1405 1406 1407 |
switch (evt) { case OHCI1394_evt_timeout: /* Async response transmit timed out. */ packet->ack = RCODE_CANCELLED; break; |
ed5689122 firewire: Add dri... |
1408 |
|
f319b6a02 firewire: Move as... |
1409 |
case OHCI1394_evt_flushed: |
c781c06d1 firewire: Clean u... |
1410 1411 1412 1413 |
/* * The packet was flushed should give same error as * when we try to use a stale generation count. */ |
f319b6a02 firewire: Move as... |
1414 1415 |
packet->ack = RCODE_GENERATION; break; |
ed5689122 firewire: Add dri... |
1416 |
|
f319b6a02 firewire: Move as... |
1417 |
case OHCI1394_evt_missing_ack: |
82b662dc4 firewire: ohci: f... |
1418 1419 1420 1421 1422 1423 1424 1425 1426 |
if (context->flushing) packet->ack = RCODE_GENERATION; else { /* * Using a valid (current) generation count, but the * node is not on the bus or not sending acks. */ packet->ack = RCODE_NO_ACK; } |
f319b6a02 firewire: Move as... |
1427 |
break; |
ed5689122 firewire: Add dri... |
1428 |
|
f319b6a02 firewire: Move as... |
1429 1430 1431 1432 1433 1434 1435 1436 1437 |
case ACK_COMPLETE + 0x10: case ACK_PENDING + 0x10: case ACK_BUSY_X + 0x10: case ACK_BUSY_A + 0x10: case ACK_BUSY_B + 0x10: case ACK_DATA_ERROR + 0x10: case ACK_TYPE_ERROR + 0x10: packet->ack = evt - 0x10; break; |
ed5689122 firewire: Add dri... |
1438 |
|
82b662dc4 firewire: ohci: f... |
1439 1440 1441 1442 1443 1444 |
case OHCI1394_evt_no_status: if (context->flushing) { packet->ack = RCODE_GENERATION; break; } /* fall through */ |
f319b6a02 firewire: Move as... |
1445 1446 1447 1448 |
default: packet->ack = RCODE_SEND_ERROR; break; } |
ed5689122 firewire: Add dri... |
1449 |
|
f319b6a02 firewire: Move as... |
1450 |
packet->callback(packet, &ohci->card, packet->ack); |
ed5689122 firewire: Add dri... |
1451 |
|
f319b6a02 firewire: Move as... |
1452 |
return 1; |
ed5689122 firewire: Add dri... |
1453 |
} |
a77754a75 firewire: Upperca... |
1454 1455 1456 1457 1458 |
#define HEADER_GET_DESTINATION(q) (((q) >> 16) & 0xffff) #define HEADER_GET_TCODE(q) (((q) >> 4) & 0x0f) #define HEADER_GET_OFFSET_HIGH(q) (((q) >> 0) & 0xffff) #define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff) #define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff) |
93c4cceb9 firewire: Handle ... |
1459 |
|
53dca5117 firewire: remove ... |
1460 1461 |
static void handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) |
93c4cceb9 firewire: Handle ... |
1462 1463 1464 |
{ struct fw_packet response; int tcode, length, i; |
a77754a75 firewire: Upperca... |
1465 |
tcode = HEADER_GET_TCODE(packet->header[0]); |
93c4cceb9 firewire: Handle ... |
1466 |
if (TCODE_IS_BLOCK_PACKET(tcode)) |
a77754a75 firewire: Upperca... |
1467 |
length = HEADER_GET_DATA_LENGTH(packet->header[3]); |
93c4cceb9 firewire: Handle ... |
1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 |
else length = 4; i = csr - CSR_CONFIG_ROM; if (i + length > CONFIG_ROM_SIZE) { fw_fill_response(&response, packet->header, RCODE_ADDRESS_ERROR, NULL, 0); } else if (!TCODE_IS_READ_REQUEST(tcode)) { fw_fill_response(&response, packet->header, RCODE_TYPE_ERROR, NULL, 0); } else { fw_fill_response(&response, packet->header, RCODE_COMPLETE, (void *) ohci->config_rom + i, length); } fw_core_handle_response(&ohci->card, &response); } |
53dca5117 firewire: remove ... |
1485 1486 |
static void handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr) |
93c4cceb9 firewire: Handle ... |
1487 1488 |
{ struct fw_packet response; |
e1393667b firewire: ohci: w... |
1489 |
int tcode, length, ext_tcode, sel, try; |
93c4cceb9 firewire: Handle ... |
1490 1491 |
__be32 *payload, lock_old; u32 lock_arg, lock_data; |
a77754a75 firewire: Upperca... |
1492 1493 |
tcode = HEADER_GET_TCODE(packet->header[0]); length = HEADER_GET_DATA_LENGTH(packet->header[3]); |
93c4cceb9 firewire: Handle ... |
1494 |
payload = packet->payload; |
a77754a75 firewire: Upperca... |
1495 |
ext_tcode = HEADER_GET_EXTENDED_TCODE(packet->header[3]); |
93c4cceb9 firewire: Handle ... |
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 |
if (tcode == TCODE_LOCK_REQUEST && ext_tcode == EXTCODE_COMPARE_SWAP && length == 8) { lock_arg = be32_to_cpu(payload[0]); lock_data = be32_to_cpu(payload[1]); } else if (tcode == TCODE_READ_QUADLET_REQUEST) { lock_arg = 0; lock_data = 0; } else { fw_fill_response(&response, packet->header, RCODE_TYPE_ERROR, NULL, 0); goto out; } sel = (csr - CSR_BUS_MANAGER_ID) / 4; reg_write(ohci, OHCI1394_CSRData, lock_data); reg_write(ohci, OHCI1394_CSRCompareData, lock_arg); reg_write(ohci, OHCI1394_CSRControl, sel); |
e1393667b firewire: ohci: w... |
1514 1515 1516 1517 1518 1519 1520 1521 1522 |
for (try = 0; try < 20; try++) if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) { lock_old = cpu_to_be32(reg_read(ohci, OHCI1394_CSRData)); fw_fill_response(&response, packet->header, RCODE_COMPLETE, &lock_old, sizeof(lock_old)); goto out; } |
de97cb64a firewire: ohci: A... |
1523 1524 |
ohci_err(ohci, "swap not done (CSR lock timeout) "); |
e1393667b firewire: ohci: w... |
1525 |
fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0); |
93c4cceb9 firewire: Handle ... |
1526 |
|
93c4cceb9 firewire: Handle ... |
1527 1528 1529 |
out: fw_core_handle_response(&ohci->card, &response); } |
53dca5117 firewire: remove ... |
1530 |
static void handle_local_request(struct context *ctx, struct fw_packet *packet) |
93c4cceb9 firewire: Handle ... |
1531 |
{ |
2608203da firewire: ohci: p... |
1532 |
u64 offset, csr; |
93c4cceb9 firewire: Handle ... |
1533 |
|
473d28c73 firewire: Impleme... |
1534 1535 1536 1537 |
if (ctx == &ctx->ohci->at_request_ctx) { packet->ack = ACK_PENDING; packet->callback(packet, &ctx->ohci->card, packet->ack); } |
93c4cceb9 firewire: Handle ... |
1538 1539 1540 |
offset = ((unsigned long long) |
a77754a75 firewire: Upperca... |
1541 |
HEADER_GET_OFFSET_HIGH(packet->header[1]) << 32) | |
93c4cceb9 firewire: Handle ... |
1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 |
packet->header[2]; csr = offset - CSR_REGISTER_BASE; /* Handle config rom reads. */ if (csr >= CSR_CONFIG_ROM && csr < CSR_CONFIG_ROM_END) handle_local_rom(ctx->ohci, packet, csr); else switch (csr) { case CSR_BUS_MANAGER_ID: case CSR_BANDWIDTH_AVAILABLE: case CSR_CHANNELS_AVAILABLE_HI: case CSR_CHANNELS_AVAILABLE_LO: handle_local_lock(ctx->ohci, packet, csr); break; default: if (ctx == &ctx->ohci->at_request_ctx) fw_core_handle_request(&ctx->ohci->card, packet); else fw_core_handle_response(&ctx->ohci->card, packet); break; } |
473d28c73 firewire: Impleme... |
1562 1563 1564 1565 1566 |
if (ctx == &ctx->ohci->at_response_ctx) { packet->ack = ACK_COMPLETE; packet->callback(packet, &ctx->ohci->card, packet->ack); } |
93c4cceb9 firewire: Handle ... |
1567 |
} |
e636fe257 firewire: Loop re... |
1568 |
|
53dca5117 firewire: remove ... |
1569 |
static void at_context_transmit(struct context *ctx, struct fw_packet *packet) |
ed5689122 firewire: Add dri... |
1570 |
{ |
ed5689122 firewire: Add dri... |
1571 |
unsigned long flags; |
2dbd7d7e2 firewire: standar... |
1572 |
int ret; |
ed5689122 firewire: Add dri... |
1573 1574 |
spin_lock_irqsave(&ctx->ohci->lock, flags); |
a77754a75 firewire: Upperca... |
1575 |
if (HEADER_GET_DESTINATION(packet->header[0]) == ctx->ohci->node_id && |
e636fe257 firewire: Loop re... |
1576 |
ctx->ohci->generation == packet->generation) { |
93c4cceb9 firewire: Handle ... |
1577 1578 1579 |
spin_unlock_irqrestore(&ctx->ohci->lock, flags); handle_local_request(ctx, packet); return; |
e636fe257 firewire: Loop re... |
1580 |
} |
ed5689122 firewire: Add dri... |
1581 |
|
2dbd7d7e2 firewire: standar... |
1582 |
ret = at_context_queue_packet(ctx, packet); |
ed5689122 firewire: Add dri... |
1583 |
spin_unlock_irqrestore(&ctx->ohci->lock, flags); |
2dbd7d7e2 firewire: standar... |
1584 |
if (ret < 0) |
f319b6a02 firewire: Move as... |
1585 |
packet->callback(packet, &ctx->ohci->card, packet->ack); |
a186b4a6b firewire: OHCI 1.... |
1586 |
|
ed5689122 firewire: Add dri... |
1587 |
} |
f117a3e30 firewire: ohci: l... |
1588 1589 1590 1591 1592 1593 |
static void detect_dead_context(struct fw_ohci *ohci, const char *name, unsigned int regs) { u32 ctl; ctl = reg_read(ohci, CONTROL_SET(regs)); |
cfda62baa firewire: ohci: m... |
1594 |
if (ctl & CONTEXT_DEAD) |
de97cb64a firewire: ohci: A... |
1595 1596 |
ohci_err(ohci, "DMA context %s has stopped, error code: %s ", |
64d217201 firewire: ohci: u... |
1597 |
name, evts[ctl & 0x1f]); |
f117a3e30 firewire: ohci: l... |
1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 |
} static void handle_dead_contexts(struct fw_ohci *ohci) { unsigned int i; char name[8]; detect_dead_context(ohci, "ATReq", OHCI1394_AsReqTrContextBase); detect_dead_context(ohci, "ATRsp", OHCI1394_AsRspTrContextBase); detect_dead_context(ohci, "ARReq", OHCI1394_AsReqRcvContextBase); detect_dead_context(ohci, "ARRsp", OHCI1394_AsRspRcvContextBase); for (i = 0; i < 32; ++i) { if (!(ohci->it_context_support & (1 << i))) continue; sprintf(name, "IT%u", i); detect_dead_context(ohci, name, OHCI1394_IsoXmitContextBase(i)); } for (i = 0; i < 32; ++i) { if (!(ohci->ir_context_support & (1 << i))) continue; sprintf(name, "IR%u", i); detect_dead_context(ohci, name, OHCI1394_IsoRcvContextBase(i)); } /* TODO: maybe try to flush and restart the dead contexts */ } |
a48777e03 firewire: add CSR... |
1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 |
static u32 cycle_timer_ticks(u32 cycle_timer) { u32 ticks; ticks = cycle_timer & 0xfff; ticks += 3072 * ((cycle_timer >> 12) & 0x1fff); ticks += (3072 * 8000) * (cycle_timer >> 25); return ticks; } /* * Some controllers exhibit one or more of the following bugs when updating the * iso cycle timer register: * - When the lowest six bits are wrapping around to zero, a read that happens * at the same time will return garbage in the lowest ten bits. * - When the cycleOffset field wraps around to zero, the cycleCount field is * not incremented for about 60 ns. * - Occasionally, the entire register reads zero. * * To catch these, we read the register three times and ensure that the * difference between each two consecutive reads is approximately the same, i.e. * less than twice the other. Furthermore, any negative difference indicates an * error. (A PCI read should take at least 20 ticks of the 24.576 MHz timer to * execute, so we have enough precision to compute the ratio of the differences.) */ static u32 get_cycle_time(struct fw_ohci *ohci) { u32 c0, c1, c2; u32 t0, t1, t2; s32 diff01, diff12; int i; c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); if (ohci->quirks & QUIRK_CYCLE_TIMER) { i = 0; c1 = c2; c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); do { c0 = c1; c1 = c2; c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer); t0 = cycle_timer_ticks(c0); t1 = cycle_timer_ticks(c1); t2 = cycle_timer_ticks(c2); diff01 = t1 - t0; diff12 = t2 - t1; } while ((diff01 <= 0 || diff12 <= 0 || diff01 / diff12 >= 2 || diff12 / diff01 >= 2) && i++ < 20); } return c2; } /* * This function has to be called at least every 64 seconds. The bus_time * field stores not only the upper 25 bits of the BUS_TIME register but also * the most significant bit of the cycle timer in bit 6 so that we can detect * changes in this bit. */ static u32 update_bus_time(struct fw_ohci *ohci) { u32 cycle_time_seconds = get_cycle_time(ohci) >> 25; |
9d60ef2bd firewire: ohci: l... |
1688 1689 1690 1691 1692 1693 |
if (unlikely(!ohci->bus_time_running)) { reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_cycle64Seconds); ohci->bus_time = (lower_32_bits(get_seconds()) & ~0x7f) | (cycle_time_seconds & 0x40); ohci->bus_time_running = true; } |
a48777e03 firewire: add CSR... |
1694 1695 1696 1697 1698 |
if ((ohci->bus_time & 0x40) != (cycle_time_seconds & 0x40)) ohci->bus_time += 0x40; return ohci->bus_time | cycle_time_seconds; } |
25935ebeb firewire: ohci: A... |
1699 1700 1701 1702 1703 1704 |
static int get_status_for_port(struct fw_ohci *ohci, int port_index) { int reg; mutex_lock(&ohci->phy_reg_mutex); reg = write_phy_reg(ohci, 7, port_index); |
28897fb73 firewire: ohci: T... |
1705 1706 |
if (reg >= 0) reg = read_phy_reg(ohci, 8); |
25935ebeb firewire: ohci: A... |
1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 |
mutex_unlock(&ohci->phy_reg_mutex); if (reg < 0) return reg; switch (reg & 0x0f) { case 0x06: return 2; /* is child node (connected to parent node) */ case 0x0e: return 3; /* is parent node (connected to child node) */ } return 1; /* not connected */ } static int get_self_id_pos(struct fw_ohci *ohci, u32 self_id, int self_id_count) { int i; u32 entry; |
28897fb73 firewire: ohci: T... |
1725 |
|
25935ebeb firewire: ohci: A... |
1726 1727 1728 1729 1730 1731 1732 1733 1734 |
for (i = 0; i < self_id_count; i++) { entry = ohci->self_id_buffer[i]; if ((self_id & 0xff000000) == (entry & 0xff000000)) return -1; if ((self_id & 0xff000000) < (entry & 0xff000000)) return i; } return i; } |
52439d605 firewire: ohci: g... |
1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 |
static int initiated_reset(struct fw_ohci *ohci) { int reg; int ret = 0; mutex_lock(&ohci->phy_reg_mutex); reg = write_phy_reg(ohci, 7, 0xe0); /* Select page 7 */ if (reg >= 0) { reg = read_phy_reg(ohci, 8); reg |= 0x40; reg = write_phy_reg(ohci, 8, reg); /* set PMODE bit */ if (reg >= 0) { reg = read_phy_reg(ohci, 12); /* read register 12 */ if (reg >= 0) { if ((reg & 0x08) == 0x08) { /* bit 3 indicates "initiated reset" */ ret = 0x2; } } } } mutex_unlock(&ohci->phy_reg_mutex); return ret; } |
25935ebeb firewire: ohci: A... |
1759 |
/* |
28897fb73 firewire: ohci: T... |
1760 1761 1762 |
* TI TSB82AA2B and TSB12LV26 do not receive the selfID of a locally * attached TSB41BA3D phy; see http://www.ti.com/litv/pdf/sllz059. * Construct the selfID from phy register contents. |
25935ebeb firewire: ohci: A... |
1763 |
*/ |
25935ebeb firewire: ohci: A... |
1764 1765 |
static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count) { |
28897fb73 firewire: ohci: T... |
1766 1767 1768 |
int reg, i, pos, status; /* link active 1, speed 3, bridge 0, contender 1, more packets 0 */ u32 self_id = 0x8040c800; |
25935ebeb firewire: ohci: A... |
1769 1770 1771 |
reg = reg_read(ohci, OHCI1394_NodeID); if (!(reg & OHCI1394_NodeID_idValid)) { |
de97cb64a firewire: ohci: A... |
1772 1773 1774 |
ohci_notice(ohci, "node ID not valid, new bus reset in progress "); |
25935ebeb firewire: ohci: A... |
1775 1776 1777 |
return -EBUSY; } self_id |= ((reg & 0x3f) << 24); /* phy ID */ |
28897fb73 firewire: ohci: T... |
1778 |
reg = ohci_read_phy_reg(&ohci->card, 4); |
25935ebeb firewire: ohci: A... |
1779 1780 1781 |
if (reg < 0) return reg; self_id |= ((reg & 0x07) << 8); /* power class */ |
28897fb73 firewire: ohci: T... |
1782 |
reg = ohci_read_phy_reg(&ohci->card, 1); |
25935ebeb firewire: ohci: A... |
1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 |
if (reg < 0) return reg; self_id |= ((reg & 0x3f) << 16); /* gap count */ for (i = 0; i < 3; i++) { status = get_status_for_port(ohci, i); if (status < 0) return status; self_id |= ((status & 0x3) << (6 - (i * 2))); } |
52439d605 firewire: ohci: g... |
1793 |
self_id |= initiated_reset(ohci); |
25935ebeb firewire: ohci: A... |
1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 |
pos = get_self_id_pos(ohci, self_id, self_id_count); if (pos >= 0) { memmove(&(ohci->self_id_buffer[pos+1]), &(ohci->self_id_buffer[pos]), (self_id_count - pos) * sizeof(*ohci->self_id_buffer)); ohci->self_id_buffer[pos] = self_id; self_id_count++; } return self_id_count; } |
2d7a36e23 firewire: ohci: M... |
1804 |
static void bus_reset_work(struct work_struct *work) |
ed5689122 firewire: Add dri... |
1805 |
{ |
2d7a36e23 firewire: ohci: M... |
1806 1807 |
struct fw_ohci *ohci = container_of(work, struct fw_ohci, bus_reset_work); |
d713dfa70 firewire: ohci: c... |
1808 1809 |
int self_id_count, generation, new_generation, i, j; u32 reg; |
4eaff7d63 firewire: fw-ohci... |
1810 1811 |
void *free_rom = NULL; dma_addr_t free_rom_bus = 0; |
4ffb7a6a0 firewire: add CSR... |
1812 |
bool is_new_root; |
ed5689122 firewire: Add dri... |
1813 1814 1815 |
reg = reg_read(ohci, OHCI1394_NodeID); if (!(reg & OHCI1394_NodeID_idValid)) { |
de97cb64a firewire: ohci: A... |
1816 1817 1818 |
ohci_notice(ohci, "node ID not valid, new bus reset in progress "); |
ed5689122 firewire: Add dri... |
1819 1820 |
return; } |
02ff8f8ee firewire: fw-ohci... |
1821 |
if ((reg & OHCI1394_NodeID_nodeNumber) == 63) { |
de97cb64a firewire: ohci: A... |
1822 1823 |
ohci_notice(ohci, "malconfigured bus "); |
02ff8f8ee firewire: fw-ohci... |
1824 1825 1826 1827 |
return; } ohci->node_id = reg & (OHCI1394_NodeID_busNumber | OHCI1394_NodeID_nodeNumber); |
ed5689122 firewire: Add dri... |
1828 |
|
4ffb7a6a0 firewire: add CSR... |
1829 1830 1831 1832 1833 |
is_new_root = (reg & OHCI1394_NodeID_root) != 0; if (!(ohci->is_root && is_new_root)) reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_cycleMaster); ohci->is_root = is_new_root; |
c8a9a498e firewire: fw-ohci... |
1834 1835 |
reg = reg_read(ohci, OHCI1394_SelfIDCount); if (reg & OHCI1394_SelfIDCount_selfIDError) { |
67672134a firewire: ohci: I... |
1836 1837 |
ohci_notice(ohci, "self ID receive error "); |
c8a9a498e firewire: fw-ohci... |
1838 1839 |
return; } |
c781c06d1 firewire: Clean u... |
1840 1841 |
/* * The count in the SelfIDCount register is the number of |
ed5689122 firewire: Add dri... |
1842 1843 |
* bytes in the self ID receive buffer. Since we also receive * the inverted quadlets and a header quadlet, we shift one |
c781c06d1 firewire: Clean u... |
1844 1845 |
* bit extra to get the actual number of self IDs. */ |
928ec5f14 firewire: ohci: f... |
1846 |
self_id_count = (reg >> 3) & 0xff; |
25935ebeb firewire: ohci: A... |
1847 1848 |
if (self_id_count > 252) { |
67672134a firewire: ohci: I... |
1849 1850 |
ohci_notice(ohci, "bad selfIDSize (%08x) ", reg); |
016bf3dfc firewire: fw-ohci... |
1851 1852 |
return; } |
25935ebeb firewire: ohci: A... |
1853 |
|
af53122a2 firewire: ohci: c... |
1854 |
generation = (cond_le32_to_cpu(ohci->self_id[0]) >> 16) & 0xff; |
ee71c2f9e firewire: fw-ohci... |
1855 |
rmb(); |
ed5689122 firewire: Add dri... |
1856 1857 |
for (i = 1, j = 0; j < self_id_count; i += 2, j++) { |
af53122a2 firewire: ohci: c... |
1858 1859 |
u32 id = cond_le32_to_cpu(ohci->self_id[i]); u32 id2 = cond_le32_to_cpu(ohci->self_id[i + 1]); |
67672134a firewire: ohci: I... |
1860 1861 |
if (id != ~id2) { |
32eaeae17 firewire: ohci: w... |
1862 1863 1864 1865 1866 1867 1868 |
/* * If the invalid data looks like a cycle start packet, * it's likely to be the result of the cycle master * having a wrong gap count. In this case, the self IDs * so far are valid and should be processed so that the * bus manager can then correct the gap count. */ |
67672134a firewire: ohci: I... |
1869 1870 1871 |
if (id == 0xffff008f) { ohci_notice(ohci, "ignoring spurious self IDs "); |
32eaeae17 firewire: ohci: w... |
1872 1873 |
self_id_count = j; break; |
32eaeae17 firewire: ohci: w... |
1874 |
} |
67672134a firewire: ohci: I... |
1875 1876 1877 1878 1879 |
ohci_notice(ohci, "bad self ID %d/%d (%08x != ~%08x) ", j, self_id_count, id, id2); return; |
c8a9a498e firewire: fw-ohci... |
1880 |
} |
67672134a firewire: ohci: I... |
1881 |
ohci->self_id_buffer[j] = id; |
ed5689122 firewire: Add dri... |
1882 |
} |
25935ebeb firewire: ohci: A... |
1883 1884 1885 1886 |
if (ohci->quirks & QUIRK_TI_SLLZ059) { self_id_count = find_and_insert_self_id(ohci, self_id_count); if (self_id_count < 0) { |
de97cb64a firewire: ohci: A... |
1887 1888 1889 |
ohci_notice(ohci, "could not construct local self ID "); |
25935ebeb firewire: ohci: A... |
1890 1891 1892 1893 1894 |
return; } } if (self_id_count == 0) { |
67672134a firewire: ohci: I... |
1895 1896 |
ohci_notice(ohci, "no self IDs "); |
25935ebeb firewire: ohci: A... |
1897 1898 |
return; } |
ee71c2f9e firewire: fw-ohci... |
1899 |
rmb(); |
ed5689122 firewire: Add dri... |
1900 |
|
c781c06d1 firewire: Clean u... |
1901 1902 |
/* * Check the consistency of the self IDs we just read. The |
ed5689122 firewire: Add dri... |
1903 1904 1905 1906 1907 1908 1909 1910 1911 |
* problem we face is that a new bus reset can start while we * read out the self IDs from the DMA buffer. If this happens, * the DMA buffer will be overwritten with new self IDs and we * will read out inconsistent data. The OHCI specification * (section 11.2) recommends a technique similar to * linux/seqlock.h, where we remember the generation of the * self IDs in the buffer before reading them out and compare * it to the current generation after reading them out. If * the two generations match we know we have a consistent set |
c781c06d1 firewire: Clean u... |
1912 1913 |
* of self IDs. */ |
ed5689122 firewire: Add dri... |
1914 1915 1916 |
new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff; if (new_generation != generation) { |
de97cb64a firewire: ohci: A... |
1917 1918 |
ohci_notice(ohci, "new bus reset, discarding self ids "); |
ed5689122 firewire: Add dri... |
1919 1920 1921 1922 |
return; } /* FIXME: Document how the locking works. */ |
8a8c47364 firewire: ohci: o... |
1923 |
spin_lock_irq(&ohci->lock); |
ed5689122 firewire: Add dri... |
1924 |
|
82b662dc4 firewire: ohci: f... |
1925 |
ohci->generation = -1; /* prevent AT packet queueing */ |
f319b6a02 firewire: Move as... |
1926 1927 |
context_stop(&ohci->at_request_ctx); context_stop(&ohci->at_response_ctx); |
82b662dc4 firewire: ohci: f... |
1928 |
|
8a8c47364 firewire: ohci: o... |
1929 |
spin_unlock_irq(&ohci->lock); |
82b662dc4 firewire: ohci: f... |
1930 |
|
78dec56d6 firewire: ohci: f... |
1931 1932 1933 1934 1935 |
/* * Per OHCI 1.2 draft, clause 7.2.3.3, hardware may leave unsent * packets in the AT queues and software needs to drain them. * Some OHCI 1.1 controllers (JMicron) apparently require this too. */ |
82b662dc4 firewire: ohci: f... |
1936 1937 |
at_context_flush(&ohci->at_request_ctx); at_context_flush(&ohci->at_response_ctx); |
8a8c47364 firewire: ohci: o... |
1938 |
spin_lock_irq(&ohci->lock); |
82b662dc4 firewire: ohci: f... |
1939 1940 |
ohci->generation = generation; |
ed5689122 firewire: Add dri... |
1941 |
reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); |
4a635593f firewire: ohci: u... |
1942 |
if (ohci->quirks & QUIRK_RESET_PACKET) |
d34316a4b firewire: fw-ohci... |
1943 |
ohci->request_generation = generation; |
c781c06d1 firewire: Clean u... |
1944 1945 |
/* * This next bit is unrelated to the AT context stuff but we |
ed5689122 firewire: Add dri... |
1946 1947 1948 1949 |
* have to do it under the spinlock also. If a new config rom * was set up before this reset, the old one is now no longer * in use and we can free it. Update the config rom pointers * to point to the current config rom and clear the |
883931612 Fix typos in comm... |
1950 |
* next_config_rom pointer so a new update can take place. |
c781c06d1 firewire: Clean u... |
1951 |
*/ |
ed5689122 firewire: Add dri... |
1952 1953 |
if (ohci->next_config_rom != NULL) { |
0bd243c4d firewire: Fix pci... |
1954 1955 1956 1957 |
if (ohci->next_config_rom != ohci->config_rom) { free_rom = ohci->config_rom; free_rom_bus = ohci->config_rom_bus; } |
ed5689122 firewire: Add dri... |
1958 1959 1960 |
ohci->config_rom = ohci->next_config_rom; ohci->config_rom_bus = ohci->next_config_rom_bus; ohci->next_config_rom = NULL; |
c781c06d1 firewire: Clean u... |
1961 1962 |
/* * Restore config_rom image and manually update |
ed5689122 firewire: Add dri... |
1963 1964 |
* config_rom registers. Writing the header quadlet * will indicate that the config rom is ready, so we |
c781c06d1 firewire: Clean u... |
1965 1966 |
* do that last. */ |
ed5689122 firewire: Add dri... |
1967 1968 |
reg_write(ohci, OHCI1394_BusOptions, be32_to_cpu(ohci->config_rom[2])); |
8e85973ef firewire: optimiz... |
1969 1970 1971 |
ohci->config_rom[0] = ohci->next_header; reg_write(ohci, OHCI1394_ConfigROMhdr, be32_to_cpu(ohci->next_header)); |
ed5689122 firewire: Add dri... |
1972 |
} |
8bc588e0e firewire: ohci: T... |
1973 1974 1975 1976 |
if (param_remote_dma) { reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0); reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0); } |
080de8c2c firewire: fw-ohci... |
1977 |
|
8a8c47364 firewire: ohci: o... |
1978 |
spin_unlock_irq(&ohci->lock); |
ed5689122 firewire: Add dri... |
1979 |
|
4eaff7d63 firewire: fw-ohci... |
1980 1981 1982 |
if (free_rom) dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, free_rom, free_rom_bus); |
64d217201 firewire: ohci: u... |
1983 |
log_selfids(ohci, generation, self_id_count); |
ad3c0fe8b firewire: debug i... |
1984 |
|
e636fe257 firewire: Loop re... |
1985 |
fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation, |
c8a94ded5 firewire: normali... |
1986 1987 1988 |
self_id_count, ohci->self_id_buffer, ohci->csr_state_setclear_abdicate); ohci->csr_state_setclear_abdicate = false; |
ed5689122 firewire: Add dri... |
1989 1990 1991 1992 1993 |
} static irqreturn_t irq_handler(int irq, void *data) { struct fw_ohci *ohci = data; |
168cf9af6 firewire: remove ... |
1994 |
u32 event, iso_event; |
ed5689122 firewire: Add dri... |
1995 1996 1997 |
int i; event = reg_read(ohci, OHCI1394_IntEventClear); |
a515958d6 firewire: fix han... |
1998 |
if (!event || !~event) |
ed5689122 firewire: Add dri... |
1999 |
return IRQ_NONE; |
8327b37b1 firewire: ohci: p... |
2000 2001 2002 2003 2004 2005 |
/* * busReset and postedWriteErr must not be cleared yet * (OHCI 1.1 clauses 7.2.3.2 and 13.2.8.1) */ reg_write(ohci, OHCI1394_IntEventClear, event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr)); |
64d217201 firewire: ohci: u... |
2006 |
log_irqs(ohci, event); |
ed5689122 firewire: Add dri... |
2007 2008 |
if (event & OHCI1394_selfIDComplete) |
db9ae8fec firewire: ohci: F... |
2009 |
queue_work(selfid_workqueue, &ohci->bus_reset_work); |
ed5689122 firewire: Add dri... |
2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 |
if (event & OHCI1394_RQPkt) tasklet_schedule(&ohci->ar_request_ctx.tasklet); if (event & OHCI1394_RSPkt) tasklet_schedule(&ohci->ar_response_ctx.tasklet); if (event & OHCI1394_reqTxComplete) tasklet_schedule(&ohci->at_request_ctx.tasklet); if (event & OHCI1394_respTxComplete) tasklet_schedule(&ohci->at_response_ctx.tasklet); |
2dd5bed59 firewire: ohci: o... |
2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 |
if (event & OHCI1394_isochRx) { iso_event = reg_read(ohci, OHCI1394_IsoRecvIntEventClear); reg_write(ohci, OHCI1394_IsoRecvIntEventClear, iso_event); while (iso_event) { i = ffs(iso_event) - 1; tasklet_schedule( &ohci->ir_context_list[i].context.tasklet); iso_event &= ~(1 << i); } |
ed5689122 firewire: Add dri... |
2032 |
} |
2dd5bed59 firewire: ohci: o... |
2033 2034 2035 |
if (event & OHCI1394_isochTx) { iso_event = reg_read(ohci, OHCI1394_IsoXmitIntEventClear); reg_write(ohci, OHCI1394_IsoXmitIntEventClear, iso_event); |
ed5689122 firewire: Add dri... |
2036 |
|
2dd5bed59 firewire: ohci: o... |
2037 2038 2039 2040 2041 2042 |
while (iso_event) { i = ffs(iso_event) - 1; tasklet_schedule( &ohci->it_context_list[i].context.tasklet); iso_event &= ~(1 << i); } |
ed5689122 firewire: Add dri... |
2043 |
} |
75f7832e3 firewire: fw-ohci... |
2044 |
if (unlikely(event & OHCI1394_regAccessFail)) |
de97cb64a firewire: ohci: A... |
2045 2046 |
ohci_err(ohci, "register access failure "); |
75f7832e3 firewire: fw-ohci... |
2047 |
|
8327b37b1 firewire: ohci: p... |
2048 2049 2050 2051 2052 |
if (unlikely(event & OHCI1394_postedWriteErr)) { reg_read(ohci, OHCI1394_PostedWriteAddressHi); reg_read(ohci, OHCI1394_PostedWriteAddressLo); reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_postedWriteErr); |
a74477db9 firewire: net: Us... |
2053 |
if (printk_ratelimit()) |
de97cb64a firewire: ohci: A... |
2054 2055 |
ohci_err(ohci, "PCI posted write error "); |
8327b37b1 firewire: ohci: p... |
2056 |
} |
e524f616f firewire: fw-ohci... |
2057 |
|
bb9f2206b firewire: fw-ohci... |
2058 2059 |
if (unlikely(event & OHCI1394_cycleTooLong)) { if (printk_ratelimit()) |
de97cb64a firewire: ohci: A... |
2060 2061 |
ohci_notice(ohci, "isochronous cycle too long "); |
bb9f2206b firewire: fw-ohci... |
2062 2063 2064 |
reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_cycleMaster); } |
5ed1f321a firewire: ohci: M... |
2065 2066 2067 2068 2069 2070 2071 2072 |
if (unlikely(event & OHCI1394_cycleInconsistent)) { /* * We need to clear this event bit in order to make * cycleMatch isochronous I/O work. In theory we should * stop active cycleMatch iso contexts now and restart * them at least two cycles later. (FIXME?) */ if (printk_ratelimit()) |
de97cb64a firewire: ohci: A... |
2073 2074 |
ohci_notice(ohci, "isochronous cycle inconsistent "); |
5ed1f321a firewire: ohci: M... |
2075 |
} |
f117a3e30 firewire: ohci: l... |
2076 2077 |
if (unlikely(event & OHCI1394_unrecoverableError)) handle_dead_contexts(ohci); |
a48777e03 firewire: add CSR... |
2078 2079 2080 2081 |
if (event & OHCI1394_cycle64Seconds) { spin_lock(&ohci->lock); update_bus_time(ohci); spin_unlock(&ohci->lock); |
e597e9898 firewire: ohci: f... |
2082 2083 |
} else flush_writes(ohci); |
a48777e03 firewire: add CSR... |
2084 |
|
ed5689122 firewire: Add dri... |
2085 2086 |
return IRQ_HANDLED; } |
2aef469a3 firewire: Impleme... |
2087 2088 |
static int software_reset(struct fw_ohci *ohci) { |
9f426173e firewire: ohci: s... |
2089 |
u32 val; |
2aef469a3 firewire: Impleme... |
2090 2091 2092 |
int i; reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); |
9f426173e firewire: ohci: s... |
2093 2094 2095 2096 |
for (i = 0; i < 500; i++) { val = reg_read(ohci, OHCI1394_HCControlSet); if (!~val) return -ENODEV; /* Card was ejected. */ |
2aef469a3 firewire: Impleme... |
2097 |
|
9f426173e firewire: ohci: s... |
2098 |
if (!(val & OHCI1394_HCControl_softReset)) |
2aef469a3 firewire: Impleme... |
2099 |
return 0; |
9f426173e firewire: ohci: s... |
2100 |
|
2aef469a3 firewire: Impleme... |
2101 2102 2103 2104 2105 |
msleep(1); } return -EBUSY; } |
8e85973ef firewire: optimiz... |
2106 2107 2108 2109 2110 2111 2112 2113 |
static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length) { size_t size = length * 4; memcpy(dest, src, size); if (size < CONFIG_ROM_SIZE) memset(&dest[length], 0, CONFIG_ROM_SIZE - size); } |
925e7a650 firewire: ohci: e... |
2114 2115 2116 |
static int configure_1394a_enhancements(struct fw_ohci *ohci) { bool enable_1394a; |
35d999b12 firewire: ohci: w... |
2117 |
int ret, clear, set, offset; |
925e7a650 firewire: ohci: e... |
2118 2119 2120 2121 2122 2123 2124 2125 |
/* Check if the driver should configure link and PHY. */ if (!(reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_programPhyEnable)) return 0; /* Paranoia: check whether the PHY supports 1394a, too. */ enable_1394a = false; |
35d999b12 firewire: ohci: w... |
2126 2127 2128 2129 2130 2131 2132 2133 |
ret = read_phy_reg(ohci, 2); if (ret < 0) return ret; if ((ret & PHY_EXTENDED_REGISTERS) == PHY_EXTENDED_REGISTERS) { ret = read_paged_phy_reg(ohci, 1, 8); if (ret < 0) return ret; if (ret >= 1) |
925e7a650 firewire: ohci: e... |
2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 |
enable_1394a = true; } if (ohci->quirks & QUIRK_NO_1394A) enable_1394a = false; /* Configure PHY and link consistently. */ if (enable_1394a) { clear = 0; set = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI; } else { clear = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI; set = 0; } |
02d37bed1 firewire: core: i... |
2148 |
ret = update_phy_reg(ohci, 5, clear, set); |
35d999b12 firewire: ohci: w... |
2149 2150 |
if (ret < 0) return ret; |
925e7a650 firewire: ohci: e... |
2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 |
if (enable_1394a) offset = OHCI1394_HCControlSet; else offset = OHCI1394_HCControlClear; reg_write(ohci, offset, OHCI1394_HCControl_aPhyEnhanceEnable); /* Clean up: configuration has been taken care of. */ reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_programPhyEnable); return 0; } |
25935ebeb firewire: ohci: A... |
2164 2165 |
static int probe_tsb41ba3d(struct fw_ohci *ohci) { |
b810e4ae1 firewire: ohci: o... |
2166 2167 2168 |
/* TI vendor ID = 0x080028, TSB41BA3D product ID = 0x833005 (sic) */ static const u8 id[] = { 0x08, 0x00, 0x28, 0x83, 0x30, 0x05, }; int reg, i; |
25935ebeb firewire: ohci: A... |
2169 2170 2171 2172 |
reg = read_phy_reg(ohci, 2); if (reg < 0) return reg; |
b810e4ae1 firewire: ohci: o... |
2173 2174 |
if ((reg & PHY_EXTENDED_REGISTERS) != PHY_EXTENDED_REGISTERS) return 0; |
25935ebeb firewire: ohci: A... |
2175 |
|
b810e4ae1 firewire: ohci: o... |
2176 2177 2178 2179 2180 2181 |
for (i = ARRAY_SIZE(id) - 1; i >= 0; i--) { reg = read_paged_phy_reg(ohci, 1, i + 10); if (reg < 0) return reg; if (reg != id[i]) return 0; |
25935ebeb firewire: ohci: A... |
2182 |
} |
b810e4ae1 firewire: ohci: o... |
2183 |
return 1; |
25935ebeb firewire: ohci: A... |
2184 |
} |
8e85973ef firewire: optimiz... |
2185 2186 |
static int ohci_enable(struct fw_card *card, const __be32 *config_rom, size_t length) |
ed5689122 firewire: Add dri... |
2187 2188 |
{ struct fw_ohci *ohci = fw_ohci(card); |
9d60ef2bd firewire: ohci: l... |
2189 |
u32 lps, version, irqs; |
28897fb73 firewire: ohci: T... |
2190 |
int i, ret; |
ed5689122 firewire: Add dri... |
2191 |
|
a354cf00c firewire: ohci: p... |
2192 2193 |
ret = software_reset(ohci); if (ret < 0) { |
de97cb64a firewire: ohci: A... |
2194 2195 |
ohci_err(ohci, "failed to reset ohci card "); |
a354cf00c firewire: ohci: p... |
2196 |
return ret; |
2aef469a3 firewire: Impleme... |
2197 2198 2199 2200 2201 2202 2203 |
} /* * Now enable LPS, which we need in order to start accessing * most of the registers. In fact, on some cards (ALI M5251), * accessing registers in the SClk domain without LPS enabled * will lock up the machine. Wait 50msec to make sure we have |
022147242 firewire: fw-ohci... |
2204 2205 |
* full link enabled. However, with some cards (well, at least * a JMicron PCIe card), we have to try again sometimes. |
bd972688e firewire: ohci: F... |
2206 2207 2208 2209 |
* * TI TSB82AA2 + TSB81BA3(A) cards signal LPS enabled early but * cannot actually use the phy at that time. These need tens of * millisecods pause between LPS write and first phy access too. |
2aef469a3 firewire: Impleme... |
2210 |
*/ |
bd972688e firewire: ohci: F... |
2211 |
|
2aef469a3 firewire: Impleme... |
2212 2213 2214 2215 |
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS | OHCI1394_HCControl_postedWriteEnable); flush_writes(ohci); |
022147242 firewire: fw-ohci... |
2216 |
|
0ca49345b firewire: ohci: f... |
2217 |
for (lps = 0, i = 0; !lps && i < 3; i++) { |
022147242 firewire: fw-ohci... |
2218 2219 2220 2221 2222 2223 |
msleep(50); lps = reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_LPS; } if (!lps) { |
de97cb64a firewire: ohci: A... |
2224 2225 |
ohci_err(ohci, "failed to set Link Power Status "); |
022147242 firewire: fw-ohci... |
2226 2227 |
return -EIO; } |
2aef469a3 firewire: Impleme... |
2228 |
|
25935ebeb firewire: ohci: A... |
2229 |
if (ohci->quirks & QUIRK_TI_SLLZ059) { |
28897fb73 firewire: ohci: T... |
2230 2231 2232 2233 |
ret = probe_tsb41ba3d(ohci); if (ret < 0) return ret; if (ret) |
de97cb64a firewire: ohci: A... |
2234 2235 |
ohci_notice(ohci, "local TSB41BA3D phy "); |
28897fb73 firewire: ohci: T... |
2236 |
else |
25935ebeb firewire: ohci: A... |
2237 |
ohci->quirks &= ~QUIRK_TI_SLLZ059; |
25935ebeb firewire: ohci: A... |
2238 |
} |
2aef469a3 firewire: Impleme... |
2239 2240 |
reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwapData); |
affc9c24a firewire: fw-ohci... |
2241 |
reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus); |
2aef469a3 firewire: Impleme... |
2242 |
reg_write(ohci, OHCI1394_LinkControlSet, |
2aef469a3 firewire: Impleme... |
2243 2244 2245 2246 2247 2248 |
OHCI1394_LinkControl_cycleTimerEnable | OHCI1394_LinkControl_cycleMaster); reg_write(ohci, OHCI1394_ATRetries, OHCI1394_MAX_AT_REQ_RETRIES | (OHCI1394_MAX_AT_RESP_RETRIES << 4) | |
27a2329f8 firewire: add CSR... |
2249 2250 |
(OHCI1394_MAX_PHYS_RESP_RETRIES << 8) | (200 << 16)); |
2aef469a3 firewire: Impleme... |
2251 |
|
9d60ef2bd firewire: ohci: l... |
2252 |
ohci->bus_time_running = false; |
a48777e03 firewire: add CSR... |
2253 |
|
e18907cc8 firewire: ohci: i... |
2254 2255 2256 2257 |
for (i = 0; i < 32; i++) if (ohci->ir_context_support & (1 << i)) reg_write(ohci, OHCI1394_IsoRcvContextControlClear(i), IR_CONTEXT_MULTI_CHANNEL_MODE); |
e91b2787d firewire: allocat... |
2258 2259 2260 2261 |
version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; if (version >= OHCI_VERSION_1_1) { reg_write(ohci, OHCI1394_InitialChannelsAvailableHi, 0xfffffffe); |
db3c9cc10 firewire: replace... |
2262 |
card->broadcast_channel_auto_allocated = true; |
e91b2787d firewire: allocat... |
2263 |
} |
a1a1132bd firewire: add CSR... |
2264 2265 2266 2267 |
/* Get implemented bits of the priority arbitration request counter. */ reg_write(ohci, OHCI1394_FairnessControl, 0x3f); ohci->pri_req_max = reg_read(ohci, OHCI1394_FairnessControl) & 0x3f; reg_write(ohci, OHCI1394_FairnessControl, 0); |
db3c9cc10 firewire: replace... |
2268 |
card->priority_budget_implemented = ohci->pri_req_max != 0; |
2aef469a3 firewire: Impleme... |
2269 |
|
fcd46b344 firewire: Enable ... |
2270 |
reg_write(ohci, OHCI1394_PhyUpperBound, FW_MAX_PHYSICAL_RANGE >> 16); |
2aef469a3 firewire: Impleme... |
2271 2272 |
reg_write(ohci, OHCI1394_IntEventClear, ~0); reg_write(ohci, OHCI1394_IntMaskClear, ~0); |
2aef469a3 firewire: Impleme... |
2273 |
|
35d999b12 firewire: ohci: w... |
2274 2275 2276 |
ret = configure_1394a_enhancements(ohci); if (ret < 0) return ret; |
925e7a650 firewire: ohci: e... |
2277 |
|
2aef469a3 firewire: Impleme... |
2278 |
/* Activate link_on bit and contender bit in our self ID packets.*/ |
35d999b12 firewire: ohci: w... |
2279 2280 2281 |
ret = ohci_update_phy_reg(card, 4, 0, PHY_LINK_ACTIVE | PHY_CONTENDER); if (ret < 0) return ret; |
2aef469a3 firewire: Impleme... |
2282 |
|
c781c06d1 firewire: Clean u... |
2283 2284 |
/* * When the link is not yet enabled, the atomic config rom |
ed5689122 firewire: Add dri... |
2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 |
* update mechanism described below in ohci_set_config_rom() * is not active. We have to update ConfigRomHeader and * BusOptions manually, and the write to ConfigROMmap takes * effect immediately. We tie this to the enabling of the * link, so we have a valid config rom before enabling - the * OHCI requires that ConfigROMhdr and BusOptions have valid * values before enabling. * * However, when the ConfigROMmap is written, some controllers * always read back quadlets 0 and 2 from the config rom to * the ConfigRomHeader and BusOptions registers on bus reset. * They shouldn't do that in this initial case where the link * isn't enabled. This means we have to use the same * workaround here, setting the bus header to 0 and then write * the right values in the bus reset tasklet. */ |
0bd243c4d firewire: Fix pci... |
2301 2302 2303 2304 2305 2306 2307 |
if (config_rom) { ohci->next_config_rom = dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, &ohci->next_config_rom_bus, GFP_KERNEL); if (ohci->next_config_rom == NULL) return -ENOMEM; |
ed5689122 firewire: Add dri... |
2308 |
|
8e85973ef firewire: optimiz... |
2309 |
copy_config_rom(ohci->next_config_rom, config_rom, length); |
0bd243c4d firewire: Fix pci... |
2310 2311 2312 2313 2314 2315 2316 2317 |
} else { /* * In the suspend case, config_rom is NULL, which * means that we just reuse the old config rom. */ ohci->next_config_rom = ohci->config_rom; ohci->next_config_rom_bus = ohci->config_rom_bus; } |
ed5689122 firewire: Add dri... |
2318 |
|
8e85973ef firewire: optimiz... |
2319 |
ohci->next_header = ohci->next_config_rom[0]; |
ed5689122 firewire: Add dri... |
2320 2321 |
ohci->next_config_rom[0] = 0; reg_write(ohci, OHCI1394_ConfigROMhdr, 0); |
0bd243c4d firewire: Fix pci... |
2322 2323 |
reg_write(ohci, OHCI1394_BusOptions, be32_to_cpu(ohci->next_config_rom[2])); |
ed5689122 firewire: Add dri... |
2324 2325 2326 |
reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus); reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); |
148c7866c firewire: ohci: d... |
2327 2328 2329 2330 2331 2332 |
irqs = OHCI1394_reqTxComplete | OHCI1394_respTxComplete | OHCI1394_RQPkt | OHCI1394_RSPkt | OHCI1394_isochTx | OHCI1394_isochRx | OHCI1394_postedWriteErr | OHCI1394_selfIDComplete | OHCI1394_regAccessFail | |
f117a3e30 firewire: ohci: l... |
2333 2334 2335 |
OHCI1394_cycleInconsistent | OHCI1394_unrecoverableError | OHCI1394_cycleTooLong | |
148c7866c firewire: ohci: d... |
2336 2337 2338 2339 |
OHCI1394_masterIntEnable; if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) irqs |= OHCI1394_busReset; reg_write(ohci, OHCI1394_IntMaskSet, irqs); |
ed5689122 firewire: Add dri... |
2340 2341 2342 |
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable | OHCI1394_HCControl_BIBimageValid); |
ecf8328e5 firewire: ohci: d... |
2343 2344 2345 2346 2347 2348 |
reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_rcvSelfID | OHCI1394_LinkControl_rcvPhyPkt); ar_context_run(&ohci->ar_request_ctx); |
dd6254e5c firewire: ohci: r... |
2349 2350 2351 |
ar_context_run(&ohci->ar_response_ctx); flush_writes(ohci); |
ed5689122 firewire: Add dri... |
2352 |
|
02d37bed1 firewire: core: i... |
2353 2354 |
/* We are ready to go, reset bus to finish initialization. */ fw_schedule_bus_reset(&ohci->card, false, true); |
ed5689122 firewire: Add dri... |
2355 2356 2357 |
return 0; } |
53dca5117 firewire: remove ... |
2358 |
static int ohci_set_config_rom(struct fw_card *card, |
8e85973ef firewire: optimiz... |
2359 |
const __be32 *config_rom, size_t length) |
ed5689122 firewire: Add dri... |
2360 2361 |
{ struct fw_ohci *ohci; |
ed5689122 firewire: Add dri... |
2362 |
__be32 *next_config_rom; |
f5101d58a firewire: fw-ohci... |
2363 |
dma_addr_t uninitialized_var(next_config_rom_bus); |
ed5689122 firewire: Add dri... |
2364 2365 |
ohci = fw_ohci(card); |
c781c06d1 firewire: Clean u... |
2366 2367 |
/* * When the OHCI controller is enabled, the config rom update |
ed5689122 firewire: Add dri... |
2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 |
* mechanism is a bit tricky, but easy enough to use. See * section 5.5.6 in the OHCI specification. * * The OHCI controller caches the new config rom address in a * shadow register (ConfigROMmapNext) and needs a bus reset * for the changes to take place. When the bus reset is * detected, the controller loads the new values for the * ConfigRomHeader and BusOptions registers from the specified * config rom and loads ConfigROMmap from the ConfigROMmapNext * shadow register. All automatically and atomically. * * Now, there's a twist to this story. The automatic load of * ConfigRomHeader and BusOptions doesn't honor the * noByteSwapData bit, so with a be32 config rom, the * controller will load be32 values in to these registers * during the atomic update, even on litte endian * architectures. The workaround we use is to put a 0 in the * header quadlet; 0 is endian agnostic and means that the * config rom isn't ready yet. In the bus reset tasklet we * then set up the real values for the two registers. * * We use ohci->lock to avoid racing with the code that sets |
2d7a36e23 firewire: ohci: M... |
2390 |
* ohci->next_config_rom to NULL (see bus_reset_work). |
ed5689122 firewire: Add dri... |
2391 2392 2393 2394 2395 2396 2397 |
*/ next_config_rom = dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE, &next_config_rom_bus, GFP_KERNEL); if (next_config_rom == NULL) return -ENOMEM; |
8a8c47364 firewire: ohci: o... |
2398 |
spin_lock_irq(&ohci->lock); |
ed5689122 firewire: Add dri... |
2399 |
|
2e053a27d firewire: Fix for... |
2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 |
/* * If there is not an already pending config_rom update, * push our new allocation into the ohci->next_config_rom * and then mark the local variable as null so that we * won't deallocate the new buffer. * * OTOH, if there is a pending config_rom update, just * use that buffer with the new config_rom data, and * let this routine free the unused DMA allocation. */ |
ed5689122 firewire: Add dri... |
2410 2411 2412 |
if (ohci->next_config_rom == NULL) { ohci->next_config_rom = next_config_rom; ohci->next_config_rom_bus = next_config_rom_bus; |
2e053a27d firewire: Fix for... |
2413 2414 |
next_config_rom = NULL; } |
ed5689122 firewire: Add dri... |
2415 |
|
2e053a27d firewire: Fix for... |
2416 |
copy_config_rom(ohci->next_config_rom, config_rom, length); |
ed5689122 firewire: Add dri... |
2417 |
|
2e053a27d firewire: Fix for... |
2418 2419 |
ohci->next_header = config_rom[0]; ohci->next_config_rom[0] = 0; |
ed5689122 firewire: Add dri... |
2420 |
|
2e053a27d firewire: Fix for... |
2421 |
reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus); |
ed5689122 firewire: Add dri... |
2422 |
|
8a8c47364 firewire: ohci: o... |
2423 |
spin_unlock_irq(&ohci->lock); |
ed5689122 firewire: Add dri... |
2424 |
|
2e053a27d firewire: Fix for... |
2425 2426 2427 2428 |
/* If we didn't use the DMA allocation, delete it. */ if (next_config_rom != NULL) dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, next_config_rom, next_config_rom_bus); |
c781c06d1 firewire: Clean u... |
2429 2430 |
/* * Now initiate a bus reset to have the changes take |
ed5689122 firewire: Add dri... |
2431 2432 2433 |
* effect. We clean up the old config rom memory and DMA * mappings in the bus reset tasklet, since the OHCI * controller could need to access it before the bus reset |
c781c06d1 firewire: Clean u... |
2434 2435 |
* takes effect. */ |
ed5689122 firewire: Add dri... |
2436 |
|
2e053a27d firewire: Fix for... |
2437 2438 2439 |
fw_schedule_bus_reset(&ohci->card, true, true); return 0; |
ed5689122 firewire: Add dri... |
2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 |
} static void ohci_send_request(struct fw_card *card, struct fw_packet *packet) { struct fw_ohci *ohci = fw_ohci(card); at_context_transmit(&ohci->at_request_ctx, packet); } static void ohci_send_response(struct fw_card *card, struct fw_packet *packet) { struct fw_ohci *ohci = fw_ohci(card); at_context_transmit(&ohci->at_response_ctx, packet); } |
730c32f58 firewire: Impleme... |
2455 2456 2457 |
static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) { struct fw_ohci *ohci = fw_ohci(card); |
f319b6a02 firewire: Move as... |
2458 2459 |
struct context *ctx = &ohci->at_request_ctx; struct driver_data *driver_data = packet->driver_data; |
2dbd7d7e2 firewire: standar... |
2460 |
int ret = -ENOENT; |
730c32f58 firewire: Impleme... |
2461 |
|
f319b6a02 firewire: Move as... |
2462 |
tasklet_disable(&ctx->tasklet); |
730c32f58 firewire: Impleme... |
2463 |
|
f319b6a02 firewire: Move as... |
2464 2465 |
if (packet->ack != 0) goto out; |
730c32f58 firewire: Impleme... |
2466 |
|
19593ffdb firewire: ohci: 0... |
2467 |
if (packet->payload_mapped) |
1d1dc5e83 firewire: fw-ohci... |
2468 2469 |
dma_unmap_single(ohci->card.device, packet->payload_bus, packet->payload_length, DMA_TO_DEVICE); |
64d217201 firewire: ohci: u... |
2470 |
log_ar_at_event(ohci, 'T', packet->speed, packet->header, 0x20); |
f319b6a02 firewire: Move as... |
2471 2472 2473 |
driver_data->packet = NULL; packet->ack = RCODE_CANCELLED; packet->callback(packet, &ohci->card, packet->ack); |
2dbd7d7e2 firewire: standar... |
2474 |
ret = 0; |
f319b6a02 firewire: Move as... |
2475 2476 |
out: tasklet_enable(&ctx->tasklet); |
730c32f58 firewire: Impleme... |
2477 |
|
2dbd7d7e2 firewire: standar... |
2478 |
return ret; |
730c32f58 firewire: Impleme... |
2479 |
} |
53dca5117 firewire: remove ... |
2480 2481 |
static int ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) |
ed5689122 firewire: Add dri... |
2482 2483 2484 |
{ struct fw_ohci *ohci = fw_ohci(card); unsigned long flags; |
2dbd7d7e2 firewire: standar... |
2485 |
int n, ret = 0; |
ed5689122 firewire: Add dri... |
2486 |
|
8bc588e0e firewire: ohci: T... |
2487 2488 |
if (param_remote_dma) return 0; |
c781c06d1 firewire: Clean u... |
2489 2490 2491 2492 |
/* * FIXME: Make sure this bitmask is cleared when we clear the busReset * interrupt bit. Clear physReqResourceAllBuses on bus reset. */ |
ed5689122 firewire: Add dri... |
2493 2494 2495 2496 |
spin_lock_irqsave(&ohci->lock, flags); if (ohci->generation != generation) { |
2dbd7d7e2 firewire: standar... |
2497 |
ret = -ESTALE; |
ed5689122 firewire: Add dri... |
2498 2499 |
goto out; } |
c781c06d1 firewire: Clean u... |
2500 2501 2502 2503 |
/* * Note, if the node ID contains a non-local bus ID, physical DMA is * enabled for _all_ nodes on remote buses. */ |
907293d78 firewire: consist... |
2504 2505 2506 2507 2508 2509 |
n = (node_id & 0xffc0) == LOCAL_BUS ? node_id & 0x3f : 63; if (n < 32) reg_write(ohci, OHCI1394_PhyReqFilterLoSet, 1 << n); else reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 1 << (n - 32)); |
ed5689122 firewire: Add dri... |
2510 |
flush_writes(ohci); |
ed5689122 firewire: Add dri... |
2511 |
out: |
6cad95fe9 firewire: fix fai... |
2512 |
spin_unlock_irqrestore(&ohci->lock, flags); |
2dbd7d7e2 firewire: standar... |
2513 2514 |
return ret; |
ed5689122 firewire: Add dri... |
2515 |
} |
373b2edd8 firewire: adjust ... |
2516 |
|
0fcff4e39 firewire: rename ... |
2517 |
static u32 ohci_read_csr(struct fw_card *card, int csr_offset) |
b677532b9 firewire: ohci: w... |
2518 |
{ |
60d32970c firewire: add rea... |
2519 |
struct fw_ohci *ohci = fw_ohci(card); |
a48777e03 firewire: add CSR... |
2520 2521 |
unsigned long flags; u32 value; |
60d32970c firewire: add rea... |
2522 2523 |
switch (csr_offset) { |
4ffb7a6a0 firewire: add CSR... |
2524 2525 |
case CSR_STATE_CLEAR: case CSR_STATE_SET: |
4ffb7a6a0 firewire: add CSR... |
2526 2527 2528 |
if (ohci->is_root && (reg_read(ohci, OHCI1394_LinkControlSet) & OHCI1394_LinkControl_cycleMaster)) |
c8a94ded5 firewire: normali... |
2529 |
value = CSR_STATE_BIT_CMSTR; |
4ffb7a6a0 firewire: add CSR... |
2530 |
else |
c8a94ded5 firewire: normali... |
2531 2532 2533 |
value = 0; if (ohci->csr_state_setclear_abdicate) value |= CSR_STATE_BIT_ABDICATE; |
b677532b9 firewire: ohci: w... |
2534 |
|
c8a94ded5 firewire: normali... |
2535 |
return value; |
4a9bde9b8 firewire: get_cyc... |
2536 |
|
506f1a319 firewire: add CSR... |
2537 2538 |
case CSR_NODE_IDS: return reg_read(ohci, OHCI1394_NodeID) << 16; |
60d32970c firewire: add rea... |
2539 2540 |
case CSR_CYCLE_TIME: return get_cycle_time(ohci); |
a48777e03 firewire: add CSR... |
2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 |
case CSR_BUS_TIME: /* * We might be called just after the cycle timer has wrapped * around but just before the cycle64Seconds handler, so we * better check here, too, if the bus time needs to be updated. */ spin_lock_irqsave(&ohci->lock, flags); value = update_bus_time(ohci); spin_unlock_irqrestore(&ohci->lock, flags); return value; |
27a2329f8 firewire: add CSR... |
2551 2552 2553 |
case CSR_BUSY_TIMEOUT: value = reg_read(ohci, OHCI1394_ATRetries); return (value >> 4) & 0x0ffff00f; |
a1a1132bd firewire: add CSR... |
2554 2555 2556 |
case CSR_PRIORITY_BUDGET: return (reg_read(ohci, OHCI1394_FairnessControl) & 0x3f) | (ohci->pri_req_max << 8); |
60d32970c firewire: add rea... |
2557 2558 2559 2560 |
default: WARN_ON(1); return 0; } |
b677532b9 firewire: ohci: w... |
2561 |
} |
0fcff4e39 firewire: rename ... |
2562 |
static void ohci_write_csr(struct fw_card *card, int csr_offset, u32 value) |
d60d7f1d5 firewire: Impleme... |
2563 2564 |
{ struct fw_ohci *ohci = fw_ohci(card); |
a48777e03 firewire: add CSR... |
2565 |
unsigned long flags; |
d60d7f1d5 firewire: Impleme... |
2566 |
|
506f1a319 firewire: add CSR... |
2567 |
switch (csr_offset) { |
4ffb7a6a0 firewire: add CSR... |
2568 |
case CSR_STATE_CLEAR: |
4ffb7a6a0 firewire: add CSR... |
2569 2570 2571 2572 2573 |
if ((value & CSR_STATE_BIT_CMSTR) && ohci->is_root) { reg_write(ohci, OHCI1394_LinkControlClear, OHCI1394_LinkControl_cycleMaster); flush_writes(ohci); } |
c8a94ded5 firewire: normali... |
2574 2575 |
if (value & CSR_STATE_BIT_ABDICATE) ohci->csr_state_setclear_abdicate = false; |
4ffb7a6a0 firewire: add CSR... |
2576 |
break; |
4a9bde9b8 firewire: get_cyc... |
2577 |
|
4ffb7a6a0 firewire: add CSR... |
2578 2579 2580 2581 2582 2583 |
case CSR_STATE_SET: if ((value & CSR_STATE_BIT_CMSTR) && ohci->is_root) { reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_cycleMaster); flush_writes(ohci); } |
c8a94ded5 firewire: normali... |
2584 2585 |
if (value & CSR_STATE_BIT_ABDICATE) ohci->csr_state_setclear_abdicate = true; |
4ffb7a6a0 firewire: add CSR... |
2586 |
break; |
d60d7f1d5 firewire: Impleme... |
2587 |
|
506f1a319 firewire: add CSR... |
2588 2589 2590 2591 |
case CSR_NODE_IDS: reg_write(ohci, OHCI1394_NodeID, value >> 16); flush_writes(ohci); break; |
9ab5071cd firewire: add CSR... |
2592 2593 2594 2595 2596 2597 |
case CSR_CYCLE_TIME: reg_write(ohci, OHCI1394_IsochronousCycleTimer, value); reg_write(ohci, OHCI1394_IntEventSet, OHCI1394_cycleInconsistent); flush_writes(ohci); break; |
a48777e03 firewire: add CSR... |
2598 2599 |
case CSR_BUS_TIME: spin_lock_irqsave(&ohci->lock, flags); |
9d60ef2bd firewire: ohci: l... |
2600 2601 |
ohci->bus_time = (update_bus_time(ohci) & 0x40) | (value & ~0x7f); |
a48777e03 firewire: add CSR... |
2602 2603 |
spin_unlock_irqrestore(&ohci->lock, flags); break; |
27a2329f8 firewire: add CSR... |
2604 2605 2606 2607 2608 2609 |
case CSR_BUSY_TIMEOUT: value = (value & 0xf) | ((value & 0xf) << 4) | ((value & 0xf) << 8) | ((value & 0x0ffff000) << 4); reg_write(ohci, OHCI1394_ATRetries, value); flush_writes(ohci); break; |
a1a1132bd firewire: add CSR... |
2610 2611 2612 2613 |
case CSR_PRIORITY_BUDGET: reg_write(ohci, OHCI1394_FairnessControl, value & 0x3f); flush_writes(ohci); break; |
506f1a319 firewire: add CSR... |
2614 2615 2616 2617 |
default: WARN_ON(1); break; } |
d60d7f1d5 firewire: Impleme... |
2618 |
} |
910e76c60 firewire: ohci: f... |
2619 |
static void flush_iso_completions(struct iso_context *ctx) |
1aa292bb1 firewire: Include... |
2620 |
{ |
910e76c60 firewire: ohci: f... |
2621 2622 2623 2624 2625 |
ctx->base.callback.sc(&ctx->base, ctx->last_timestamp, ctx->header_length, ctx->header, ctx->base.callback_data); ctx->header_length = 0; } |
1aa292bb1 firewire: Include... |
2626 |
|
73864012f firewire: ohci: s... |
2627 |
static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr) |
1aa292bb1 firewire: Include... |
2628 |
{ |
73864012f firewire: ohci: s... |
2629 |
u32 *ctx_hdr; |
1aa292bb1 firewire: Include... |
2630 |
|
0699a73af firewire: fix lib... |
2631 2632 2633 |
if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) { if (ctx->base.drop_overflow_headers) return; |
18d627113 firewire: prevent... |
2634 |
flush_iso_completions(ctx); |
0699a73af firewire: fix lib... |
2635 |
} |
1aa292bb1 firewire: Include... |
2636 |
|
73864012f firewire: ohci: s... |
2637 |
ctx_hdr = ctx->header + ctx->header_length; |
910e76c60 firewire: ohci: f... |
2638 |
ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]); |
1aa292bb1 firewire: Include... |
2639 2640 |
/* |
32c507f7b firewire: ohci: c... |
2641 2642 2643 |
* The two iso header quadlets are byteswapped to little * endian by the controller, but we want to present them * as big endian for consistency with the bus endianness. |
1aa292bb1 firewire: Include... |
2644 2645 |
*/ if (ctx->base.header_size > 0) |
73864012f firewire: ohci: s... |
2646 |
ctx_hdr[0] = swab32(dma_hdr[1]); /* iso packet header */ |
1aa292bb1 firewire: Include... |
2647 |
if (ctx->base.header_size > 4) |
73864012f firewire: ohci: s... |
2648 |
ctx_hdr[1] = swab32(dma_hdr[0]); /* timestamp */ |
1aa292bb1 firewire: Include... |
2649 |
if (ctx->base.header_size > 8) |
73864012f firewire: ohci: s... |
2650 |
memcpy(&ctx_hdr[2], &dma_hdr[2], ctx->base.header_size - 8); |
1aa292bb1 firewire: Include... |
2651 2652 |
ctx->header_length += ctx->base.header_size; } |
a186b4a6b firewire: OHCI 1.... |
2653 2654 2655 2656 2657 2658 |
static int handle_ir_packet_per_buffer(struct context *context, struct descriptor *d, struct descriptor *last) { struct iso_context *ctx = container_of(context, struct iso_context, context); |
bcee893c6 firewire: fw-ohci... |
2659 |
struct descriptor *pd; |
a572e688c firewire: ohci: f... |
2660 |
u32 buffer_dma; |
a186b4a6b firewire: OHCI 1.... |
2661 |
|
872e330e3 firewire: add iso... |
2662 |
for (pd = d; pd <= last; pd++) |
bcee893c6 firewire: fw-ohci... |
2663 2664 |
if (pd->transfer_status) break; |
bcee893c6 firewire: fw-ohci... |
2665 |
if (pd > last) |
a186b4a6b firewire: OHCI 1.... |
2666 2667 |
/* Descriptor(s) not done yet, stop iteration */ return 0; |
a572e688c firewire: ohci: f... |
2668 2669 2670 2671 2672 2673 2674 2675 2676 |
while (!(d->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))) { d++; buffer_dma = le32_to_cpu(d->data_address); dma_sync_single_range_for_cpu(context->ohci->card.device, buffer_dma & PAGE_MASK, buffer_dma & ~PAGE_MASK, le16_to_cpu(d->req_count), DMA_FROM_DEVICE); } |
910e76c60 firewire: ohci: f... |
2677 |
copy_iso_headers(ctx, (u32 *) (last + 1)); |
a186b4a6b firewire: OHCI 1.... |
2678 |
|
910e76c60 firewire: ohci: f... |
2679 2680 |
if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) flush_iso_completions(ctx); |
a186b4a6b firewire: OHCI 1.... |
2681 |
|
a186b4a6b firewire: OHCI 1.... |
2682 2683 |
return 1; } |
872e330e3 firewire: add iso... |
2684 2685 2686 2687 2688 2689 2690 |
/* d == last because each descriptor block is only a single descriptor. */ static int handle_ir_buffer_fill(struct context *context, struct descriptor *d, struct descriptor *last) { struct iso_context *ctx = container_of(context, struct iso_context, context); |
d1bbd2097 firewire: allow e... |
2691 |
unsigned int req_count, res_count, completed; |
a572e688c firewire: ohci: f... |
2692 |
u32 buffer_dma; |
872e330e3 firewire: add iso... |
2693 |
|
d1bbd2097 firewire: allow e... |
2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 |
req_count = le16_to_cpu(last->req_count); res_count = le16_to_cpu(ACCESS_ONCE(last->res_count)); completed = req_count - res_count; buffer_dma = le32_to_cpu(last->data_address); if (completed > 0) { ctx->mc_buffer_bus = buffer_dma; ctx->mc_completed = completed; } if (res_count != 0) |
872e330e3 firewire: add iso... |
2705 2706 |
/* Descriptor(s) not done yet, stop iteration */ return 0; |
a572e688c firewire: ohci: f... |
2707 2708 2709 |
dma_sync_single_range_for_cpu(context->ohci->card.device, buffer_dma & PAGE_MASK, buffer_dma & ~PAGE_MASK, |
d1bbd2097 firewire: allow e... |
2710 |
completed, DMA_FROM_DEVICE); |
a572e688c firewire: ohci: f... |
2711 |
|
d1bbd2097 firewire: allow e... |
2712 |
if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) { |
872e330e3 firewire: add iso... |
2713 |
ctx->base.callback.mc(&ctx->base, |
d1bbd2097 firewire: allow e... |
2714 |
buffer_dma + completed, |
872e330e3 firewire: add iso... |
2715 |
ctx->base.callback_data); |
d1bbd2097 firewire: allow e... |
2716 2717 |
ctx->mc_completed = 0; } |
872e330e3 firewire: add iso... |
2718 2719 2720 |
return 1; } |
d1bbd2097 firewire: allow e... |
2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 |
static void flush_ir_buffer_fill(struct iso_context *ctx) { dma_sync_single_range_for_cpu(ctx->context.ohci->card.device, ctx->mc_buffer_bus & PAGE_MASK, ctx->mc_buffer_bus & ~PAGE_MASK, ctx->mc_completed, DMA_FROM_DEVICE); ctx->base.callback.mc(&ctx->base, ctx->mc_buffer_bus + ctx->mc_completed, ctx->base.callback_data); ctx->mc_completed = 0; } |
a572e688c firewire: ohci: f... |
2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 |
static inline void sync_it_packet_for_cpu(struct context *context, struct descriptor *pd) { __le16 control; u32 buffer_dma; /* only packets beginning with OUTPUT_MORE* have data buffers */ if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)) return; /* skip over the OUTPUT_MORE_IMMEDIATE descriptor */ pd += 2; /* * If the packet has a header, the first OUTPUT_MORE/LAST descriptor's * data buffer is in the context program's coherent page and must not * be synced. */ if ((le32_to_cpu(pd->data_address) & PAGE_MASK) == (context->current_bus & PAGE_MASK)) { if (pd->control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS)) return; pd++; } do { buffer_dma = le32_to_cpu(pd->data_address); dma_sync_single_range_for_cpu(context->ohci->card.device, buffer_dma & PAGE_MASK, buffer_dma & ~PAGE_MASK, le16_to_cpu(pd->req_count), DMA_TO_DEVICE); control = pd->control; pd++; } while (!(control & cpu_to_le16(DESCRIPTOR_BRANCH_ALWAYS))); } |
30200739e firewire: General... |
2769 2770 2771 |
static int handle_it_packet(struct context *context, struct descriptor *d, struct descriptor *last) |
ed5689122 firewire: Add dri... |
2772 |
{ |
30200739e firewire: General... |
2773 2774 |
struct iso_context *ctx = container_of(context, struct iso_context, context); |
31769cef2 firewire: ohci: p... |
2775 |
struct descriptor *pd; |
73864012f firewire: ohci: s... |
2776 |
__be32 *ctx_hdr; |
373b2edd8 firewire: adjust ... |
2777 |
|
31769cef2 firewire: ohci: p... |
2778 2779 2780 2781 2782 |
for (pd = d; pd <= last; pd++) if (pd->transfer_status) break; if (pd > last) /* Descriptor(s) not done yet, stop iteration */ |
30200739e firewire: General... |
2783 |
return 0; |
a572e688c firewire: ohci: f... |
2784 |
sync_it_packet_for_cpu(context, d); |
0699a73af firewire: fix lib... |
2785 2786 2787 |
if (ctx->header_length + 4 > PAGE_SIZE) { if (ctx->base.drop_overflow_headers) return 1; |
18d627113 firewire: prevent... |
2788 |
flush_iso_completions(ctx); |
0699a73af firewire: fix lib... |
2789 |
} |
910e76c60 firewire: ohci: f... |
2790 |
|
18d627113 firewire: prevent... |
2791 |
ctx_hdr = ctx->header + ctx->header_length; |
910e76c60 firewire: ohci: f... |
2792 |
ctx->last_timestamp = le16_to_cpu(last->res_count); |
18d627113 firewire: prevent... |
2793 2794 2795 2796 |
/* Present this value as big-endian to match the receive code */ *ctx_hdr = cpu_to_be32((le16_to_cpu(pd->transfer_status) << 16) | le16_to_cpu(pd->res_count)); ctx->header_length += 4; |
910e76c60 firewire: ohci: f... |
2797 2798 |
if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) flush_iso_completions(ctx); |
30200739e firewire: General... |
2799 |
return 1; |
ed5689122 firewire: Add dri... |
2800 |
} |
872e330e3 firewire: add iso... |
2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 |
static void set_multichannel_mask(struct fw_ohci *ohci, u64 channels) { u32 hi = channels >> 32, lo = channels; reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, ~hi); reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, ~lo); reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet, hi); reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet, lo); mmiowb(); ohci->mc_channels = channels; } |
53dca5117 firewire: remove ... |
2812 |
static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card, |
4817ed240 firewire: prevent... |
2813 |
int type, int channel, size_t header_size) |
ed5689122 firewire: Add dri... |
2814 2815 |
{ struct fw_ohci *ohci = fw_ohci(card); |
872e330e3 firewire: add iso... |
2816 2817 2818 2819 |
struct iso_context *uninitialized_var(ctx); descriptor_callback_t uninitialized_var(callback); u64 *uninitialized_var(channels); u32 *uninitialized_var(mask), uninitialized_var(regs); |
872e330e3 firewire: add iso... |
2820 |
int index, ret = -EBUSY; |
ed5689122 firewire: Add dri... |
2821 |
|
8a8c47364 firewire: ohci: o... |
2822 |
spin_lock_irq(&ohci->lock); |
ed5689122 firewire: Add dri... |
2823 |
|
872e330e3 firewire: add iso... |
2824 2825 2826 |
switch (type) { case FW_ISO_CONTEXT_TRANSMIT: mask = &ohci->it_context_mask; |
30200739e firewire: General... |
2827 |
callback = handle_it_packet; |
872e330e3 firewire: add iso... |
2828 2829 2830 2831 2832 2833 2834 2835 2836 |
index = ffs(*mask) - 1; if (index >= 0) { *mask &= ~(1 << index); regs = OHCI1394_IsoXmitContextBase(index); ctx = &ohci->it_context_list[index]; } break; case FW_ISO_CONTEXT_RECEIVE: |
4817ed240 firewire: prevent... |
2837 |
channels = &ohci->ir_context_channels; |
872e330e3 firewire: add iso... |
2838 |
mask = &ohci->ir_context_mask; |
6498ba04a firewire: ohci: r... |
2839 |
callback = handle_ir_packet_per_buffer; |
872e330e3 firewire: add iso... |
2840 2841 2842 2843 2844 2845 2846 2847 |
index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1; if (index >= 0) { *channels &= ~(1ULL << channel); *mask &= ~(1 << index); regs = OHCI1394_IsoRcvContextBase(index); ctx = &ohci->ir_context_list[index]; } break; |
ed5689122 firewire: Add dri... |
2848 |
|
872e330e3 firewire: add iso... |
2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 |
case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: mask = &ohci->ir_context_mask; callback = handle_ir_buffer_fill; index = !ohci->mc_allocated ? ffs(*mask) - 1 : -1; if (index >= 0) { ohci->mc_allocated = true; *mask &= ~(1 << index); regs = OHCI1394_IsoRcvContextBase(index); ctx = &ohci->ir_context_list[index]; } break; default: index = -1; ret = -ENOSYS; |
4817ed240 firewire: prevent... |
2864 |
} |
872e330e3 firewire: add iso... |
2865 |
|
8a8c47364 firewire: ohci: o... |
2866 |
spin_unlock_irq(&ohci->lock); |
ed5689122 firewire: Add dri... |
2867 2868 |
if (index < 0) |
872e330e3 firewire: add iso... |
2869 |
return ERR_PTR(ret); |
373b2edd8 firewire: adjust ... |
2870 |
|
2d826cc5c firewire: Always ... |
2871 |
memset(ctx, 0, sizeof(*ctx)); |
9b32d5f30 firewire: Acummul... |
2872 2873 |
ctx->header_length = 0; ctx->header = (void *) __get_free_page(GFP_KERNEL); |
872e330e3 firewire: add iso... |
2874 2875 |
if (ctx->header == NULL) { ret = -ENOMEM; |
9b32d5f30 firewire: Acummul... |
2876 |
goto out; |
872e330e3 firewire: add iso... |
2877 |
} |
2dbd7d7e2 firewire: standar... |
2878 2879 |
ret = context_init(&ctx->context, ohci, regs, callback); if (ret < 0) |
9b32d5f30 firewire: Acummul... |
2880 |
goto out_with_header; |
ed5689122 firewire: Add dri... |
2881 |
|
d1bbd2097 firewire: allow e... |
2882 |
if (type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) { |
872e330e3 firewire: add iso... |
2883 |
set_multichannel_mask(ohci, 0); |
d1bbd2097 firewire: allow e... |
2884 2885 |
ctx->mc_completed = 0; } |
872e330e3 firewire: add iso... |
2886 |
|
ed5689122 firewire: Add dri... |
2887 |
return &ctx->base; |
9b32d5f30 firewire: Acummul... |
2888 2889 2890 2891 |
out_with_header: free_page((unsigned long)ctx->header); out: |
8a8c47364 firewire: ohci: o... |
2892 |
spin_lock_irq(&ohci->lock); |
872e330e3 firewire: add iso... |
2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 |
switch (type) { case FW_ISO_CONTEXT_RECEIVE: *channels |= 1ULL << channel; break; case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: ohci->mc_allocated = false; break; } |
9b32d5f30 firewire: Acummul... |
2903 |
*mask |= 1 << index; |
872e330e3 firewire: add iso... |
2904 |
|
8a8c47364 firewire: ohci: o... |
2905 |
spin_unlock_irq(&ohci->lock); |
9b32d5f30 firewire: Acummul... |
2906 |
|
2dbd7d7e2 firewire: standar... |
2907 |
return ERR_PTR(ret); |
ed5689122 firewire: Add dri... |
2908 |
} |
eb0306eac firewire: Move sy... |
2909 2910 |
static int ohci_start_iso(struct fw_iso_context *base, s32 cycle, u32 sync, u32 tags) |
ed5689122 firewire: Add dri... |
2911 |
{ |
373b2edd8 firewire: adjust ... |
2912 |
struct iso_context *ctx = container_of(base, struct iso_context, base); |
30200739e firewire: General... |
2913 |
struct fw_ohci *ohci = ctx->context.ohci; |
872e330e3 firewire: add iso... |
2914 |
u32 control = IR_CONTEXT_ISOCH_HEADER, match; |
ed5689122 firewire: Add dri... |
2915 |
int index; |
44b74d909 firewire: ohci: p... |
2916 2917 2918 |
/* the controller cannot start without any queued packets */ if (ctx->context.last->branch_address == 0) return -ENODATA; |
872e330e3 firewire: add iso... |
2919 2920 |
switch (ctx->base.type) { case FW_ISO_CONTEXT_TRANSMIT: |
295e3feb9 firewire: Impleme... |
2921 |
index = ctx - ohci->it_context_list; |
8a2f7d932 firewire: Fix sta... |
2922 2923 2924 |
match = 0; if (cycle >= 0) match = IT_CONTEXT_CYCLE_MATCH_ENABLE | |
295e3feb9 firewire: Impleme... |
2925 |
(cycle & 0x7fff) << 16; |
21efb3cfc firewire: Configu... |
2926 |
|
295e3feb9 firewire: Impleme... |
2927 2928 |
reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 1 << index); reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << index); |
8a2f7d932 firewire: Fix sta... |
2929 |
context_run(&ctx->context, match); |
872e330e3 firewire: add iso... |
2930 2931 2932 2933 2934 2935 |
break; case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: control |= IR_CONTEXT_BUFFER_FILL|IR_CONTEXT_MULTI_CHANNEL_MODE; /* fall through */ case FW_ISO_CONTEXT_RECEIVE: |
295e3feb9 firewire: Impleme... |
2936 |
index = ctx - ohci->ir_context_list; |
8a2f7d932 firewire: Fix sta... |
2937 2938 2939 2940 2941 |
match = (tags << 28) | (sync << 8) | ctx->base.channel; if (cycle >= 0) { match |= (cycle & 0x07fff) << 12; control |= IR_CONTEXT_CYCLE_MATCH_ENABLE; } |
ed5689122 firewire: Add dri... |
2942 |
|
295e3feb9 firewire: Impleme... |
2943 2944 |
reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); |
a77754a75 firewire: Upperca... |
2945 |
reg_write(ohci, CONTEXT_MATCH(ctx->context.regs), match); |
8a2f7d932 firewire: Fix sta... |
2946 |
context_run(&ctx->context, control); |
dd23736e0 firewire: ohci: r... |
2947 2948 2949 |
ctx->sync = sync; ctx->tags = tags; |
872e330e3 firewire: add iso... |
2950 |
break; |
295e3feb9 firewire: Impleme... |
2951 |
} |
ed5689122 firewire: Add dri... |
2952 2953 2954 |
return 0; } |
b82956685 firewire: Impleme... |
2955 2956 2957 |
static int ohci_stop_iso(struct fw_iso_context *base) { struct fw_ohci *ohci = fw_ohci(base->card); |
373b2edd8 firewire: adjust ... |
2958 |
struct iso_context *ctx = container_of(base, struct iso_context, base); |
b82956685 firewire: Impleme... |
2959 |
int index; |
872e330e3 firewire: add iso... |
2960 2961 |
switch (ctx->base.type) { case FW_ISO_CONTEXT_TRANSMIT: |
b82956685 firewire: Impleme... |
2962 2963 |
index = ctx - ohci->it_context_list; reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index); |
872e330e3 firewire: add iso... |
2964 2965 2966 2967 |
break; case FW_ISO_CONTEXT_RECEIVE: case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: |
b82956685 firewire: Impleme... |
2968 2969 |
index = ctx - ohci->ir_context_list; reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index); |
872e330e3 firewire: add iso... |
2970 |
break; |
b82956685 firewire: Impleme... |
2971 2972 2973 |
} flush_writes(ohci); context_stop(&ctx->context); |
e81cbebdf firewire: ohci: p... |
2974 |
tasklet_kill(&ctx->context.tasklet); |
b82956685 firewire: Impleme... |
2975 2976 2977 |
return 0; } |
ed5689122 firewire: Add dri... |
2978 2979 2980 |
static void ohci_free_iso_context(struct fw_iso_context *base) { struct fw_ohci *ohci = fw_ohci(base->card); |
373b2edd8 firewire: adjust ... |
2981 |
struct iso_context *ctx = container_of(base, struct iso_context, base); |
ed5689122 firewire: Add dri... |
2982 2983 |
unsigned long flags; int index; |
b82956685 firewire: Impleme... |
2984 2985 |
ohci_stop_iso(base); context_release(&ctx->context); |
9b32d5f30 firewire: Acummul... |
2986 |
free_page((unsigned long)ctx->header); |
b82956685 firewire: Impleme... |
2987 |
|
ed5689122 firewire: Add dri... |
2988 |
spin_lock_irqsave(&ohci->lock, flags); |
872e330e3 firewire: add iso... |
2989 2990 |
switch (base->type) { case FW_ISO_CONTEXT_TRANSMIT: |
ed5689122 firewire: Add dri... |
2991 |
index = ctx - ohci->it_context_list; |
ed5689122 firewire: Add dri... |
2992 |
ohci->it_context_mask |= 1 << index; |
872e330e3 firewire: add iso... |
2993 2994 2995 |
break; case FW_ISO_CONTEXT_RECEIVE: |
ed5689122 firewire: Add dri... |
2996 |
index = ctx - ohci->ir_context_list; |
ed5689122 firewire: Add dri... |
2997 |
ohci->ir_context_mask |= 1 << index; |
4817ed240 firewire: prevent... |
2998 |
ohci->ir_context_channels |= 1ULL << base->channel; |
872e330e3 firewire: add iso... |
2999 3000 3001 3002 3003 3004 3005 3006 3007 |
break; case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: index = ctx - ohci->ir_context_list; ohci->ir_context_mask |= 1 << index; ohci->ir_context_channels |= ohci->mc_channels; ohci->mc_channels = 0; ohci->mc_allocated = false; break; |
ed5689122 firewire: Add dri... |
3008 |
} |
ed5689122 firewire: Add dri... |
3009 3010 3011 |
spin_unlock_irqrestore(&ohci->lock, flags); } |
872e330e3 firewire: add iso... |
3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 |
static int ohci_set_iso_channels(struct fw_iso_context *base, u64 *channels) { struct fw_ohci *ohci = fw_ohci(base->card); unsigned long flags; int ret; switch (base->type) { case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: spin_lock_irqsave(&ohci->lock, flags); /* Don't allow multichannel to grab other contexts' channels. */ if (~ohci->ir_context_channels & ~ohci->mc_channels & *channels) { *channels = ohci->ir_context_channels; ret = -EBUSY; } else { set_multichannel_mask(ohci, *channels); ret = 0; } spin_unlock_irqrestore(&ohci->lock, flags); break; default: ret = -EINVAL; } return ret; } |
dd23736e0 firewire: ohci: r... |
3041 3042 3043 3044 3045 3046 3047 3048 |
#ifdef CONFIG_PM static void ohci_resume_iso_dma(struct fw_ohci *ohci) { int i; struct iso_context *ctx; for (i = 0 ; i < ohci->n_ir ; i++) { ctx = &ohci->ir_context_list[i]; |
693a50b51 firewire: ohci: c... |
3049 |
if (ctx->context.running) |
dd23736e0 firewire: ohci: r... |
3050 3051 3052 3053 3054 |
ohci_start_iso(&ctx->base, 0, ctx->sync, ctx->tags); } for (i = 0 ; i < ohci->n_it ; i++) { ctx = &ohci->it_context_list[i]; |
693a50b51 firewire: ohci: c... |
3055 |
if (ctx->context.running) |
dd23736e0 firewire: ohci: r... |
3056 3057 3058 3059 |
ohci_start_iso(&ctx->base, 0, ctx->sync, ctx->tags); } } #endif |
872e330e3 firewire: add iso... |
3060 3061 3062 3063 |
static int queue_iso_transmit(struct iso_context *ctx, struct fw_iso_packet *packet, struct fw_iso_buffer *buffer, unsigned long payload) |
ed5689122 firewire: Add dri... |
3064 |
{ |
30200739e firewire: General... |
3065 |
struct descriptor *d, *last, *pd; |
ed5689122 firewire: Add dri... |
3066 3067 |
struct fw_iso_packet *p; __le32 *header; |
9aad81253 firewire: Split t... |
3068 |
dma_addr_t d_bus, page_bus; |
ed5689122 firewire: Add dri... |
3069 3070 |
u32 z, header_z, payload_z, irq; u32 payload_index, payload_end_index, next_page_index; |
30200739e firewire: General... |
3071 |
int page, end_page, i, length, offset; |
ed5689122 firewire: Add dri... |
3072 |
|
ed5689122 firewire: Add dri... |
3073 |
p = packet; |
9aad81253 firewire: Split t... |
3074 |
payload_index = payload; |
ed5689122 firewire: Add dri... |
3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 |
if (p->skip) z = 1; else z = 2; if (p->header_length > 0) z++; /* Determine the first page the payload isn't contained in. */ end_page = PAGE_ALIGN(payload_index + p->payload_length) >> PAGE_SHIFT; if (p->payload_length > 0) payload_z = end_page - (payload_index >> PAGE_SHIFT); else payload_z = 0; z += payload_z; /* Get header size in number of descriptors. */ |
2d826cc5c firewire: Always ... |
3093 |
header_z = DIV_ROUND_UP(p->header_length, sizeof(*d)); |
ed5689122 firewire: Add dri... |
3094 |
|
30200739e firewire: General... |
3095 3096 3097 |
d = context_get_descriptors(&ctx->context, z + header_z, &d_bus); if (d == NULL) return -ENOMEM; |
ed5689122 firewire: Add dri... |
3098 3099 |
if (!p->skip) { |
a77754a75 firewire: Upperca... |
3100 |
d[0].control = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE); |
ed5689122 firewire: Add dri... |
3101 |
d[0].req_count = cpu_to_le16(8); |
7f51a100b firewire: ohci: r... |
3102 3103 3104 3105 3106 3107 3108 3109 |
/* * Link the skip address to this descriptor itself. This causes * a context to skip a cycle whenever lost cycles or FIFO * overruns occur, without dropping the data. The application * should then decide whether this is an error condition or not. * FIXME: Make the context's cycle-lost behaviour configurable? */ d[0].branch_address = cpu_to_le32(d_bus | z); |
ed5689122 firewire: Add dri... |
3110 3111 |
header = (__le32 *) &d[1]; |
a77754a75 firewire: Upperca... |
3112 3113 3114 3115 3116 |
header[0] = cpu_to_le32(IT_HEADER_SY(p->sy) | IT_HEADER_TAG(p->tag) | IT_HEADER_TCODE(TCODE_STREAM_DATA) | IT_HEADER_CHANNEL(ctx->base.channel) | IT_HEADER_SPEED(ctx->base.speed)); |
ed5689122 firewire: Add dri... |
3117 |
header[1] = |
a77754a75 firewire: Upperca... |
3118 |
cpu_to_le32(IT_HEADER_DATA_LENGTH(p->header_length + |
ed5689122 firewire: Add dri... |
3119 3120 3121 3122 3123 |
p->payload_length)); } if (p->header_length > 0) { d[2].req_count = cpu_to_le16(p->header_length); |
2d826cc5c firewire: Always ... |
3124 |
d[2].data_address = cpu_to_le32(d_bus + z * sizeof(*d)); |
ed5689122 firewire: Add dri... |
3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 |
memcpy(&d[z], p->header, p->header_length); } pd = d + z - payload_z; payload_end_index = payload_index + p->payload_length; for (i = 0; i < payload_z; i++) { page = payload_index >> PAGE_SHIFT; offset = payload_index & ~PAGE_MASK; next_page_index = (page + 1) << PAGE_SHIFT; length = min(next_page_index, payload_end_index) - payload_index; pd[i].req_count = cpu_to_le16(length); |
9aad81253 firewire: Split t... |
3137 3138 3139 |
page_bus = page_private(buffer->pages[page]); pd[i].data_address = cpu_to_le32(page_bus + offset); |
ed5689122 firewire: Add dri... |
3140 |
|
a572e688c firewire: ohci: f... |
3141 3142 3143 |
dma_sync_single_range_for_device(ctx->context.ohci->card.device, page_bus, offset, length, DMA_TO_DEVICE); |
ed5689122 firewire: Add dri... |
3144 3145 |
payload_index += length; } |
ed5689122 firewire: Add dri... |
3146 |
if (p->interrupt) |
a77754a75 firewire: Upperca... |
3147 |
irq = DESCRIPTOR_IRQ_ALWAYS; |
ed5689122 firewire: Add dri... |
3148 |
else |
a77754a75 firewire: Upperca... |
3149 |
irq = DESCRIPTOR_NO_IRQ; |
ed5689122 firewire: Add dri... |
3150 |
|
30200739e firewire: General... |
3151 |
last = z == 2 ? d : d + z - 1; |
a77754a75 firewire: Upperca... |
3152 3153 3154 |
last->control |= cpu_to_le16(DESCRIPTOR_OUTPUT_LAST | DESCRIPTOR_STATUS | DESCRIPTOR_BRANCH_ALWAYS | |
cbb59da71 firewire: Fix ano... |
3155 |
irq); |
ed5689122 firewire: Add dri... |
3156 |
|
30200739e firewire: General... |
3157 |
context_append(&ctx->context, d, z, header_z); |
ed5689122 firewire: Add dri... |
3158 3159 3160 |
return 0; } |
373b2edd8 firewire: adjust ... |
3161 |
|
872e330e3 firewire: add iso... |
3162 3163 3164 3165 |
static int queue_iso_packet_per_buffer(struct iso_context *ctx, struct fw_iso_packet *packet, struct fw_iso_buffer *buffer, unsigned long payload) |
a186b4a6b firewire: OHCI 1.... |
3166 |
{ |
a572e688c firewire: ohci: f... |
3167 |
struct device *device = ctx->context.ohci->card.device; |
8c0c0cc2d firewire: ohci: h... |
3168 |
struct descriptor *d, *pd; |
a186b4a6b firewire: OHCI 1.... |
3169 3170 |
dma_addr_t d_bus, page_bus; u32 z, header_z, rest; |
bcee893c6 firewire: fw-ohci... |
3171 3172 |
int i, j, length; int page, offset, packet_count, header_size, payload_per_buffer; |
a186b4a6b firewire: OHCI 1.... |
3173 3174 |
/* |
1aa292bb1 firewire: Include... |
3175 3176 |
* The OHCI controller puts the isochronous header and trailer in the * buffer, so we need at least 8 bytes. |
a186b4a6b firewire: OHCI 1.... |
3177 |
*/ |
872e330e3 firewire: add iso... |
3178 |
packet_count = packet->header_length / ctx->base.header_size; |
1aa292bb1 firewire: Include... |
3179 |
header_size = max(ctx->base.header_size, (size_t)8); |
a186b4a6b firewire: OHCI 1.... |
3180 3181 3182 3183 3184 |
/* Get header size in number of descriptors. */ header_z = DIV_ROUND_UP(header_size, sizeof(*d)); page = payload >> PAGE_SHIFT; offset = payload & ~PAGE_MASK; |
872e330e3 firewire: add iso... |
3185 |
payload_per_buffer = packet->payload_length / packet_count; |
a186b4a6b firewire: OHCI 1.... |
3186 3187 3188 |
for (i = 0; i < packet_count; i++) { /* d points to the header descriptor */ |
bcee893c6 firewire: fw-ohci... |
3189 |
z = DIV_ROUND_UP(payload_per_buffer + offset, PAGE_SIZE) + 1; |
a186b4a6b firewire: OHCI 1.... |
3190 |
d = context_get_descriptors(&ctx->context, |
bcee893c6 firewire: fw-ohci... |
3191 |
z + header_z, &d_bus); |
a186b4a6b firewire: OHCI 1.... |
3192 3193 |
if (d == NULL) return -ENOMEM; |
bcee893c6 firewire: fw-ohci... |
3194 3195 |
d->control = cpu_to_le16(DESCRIPTOR_STATUS | DESCRIPTOR_INPUT_MORE); |
872e330e3 firewire: add iso... |
3196 |
if (packet->skip && i == 0) |
bcee893c6 firewire: fw-ohci... |
3197 |
d->control |= cpu_to_le16(DESCRIPTOR_WAIT); |
a186b4a6b firewire: OHCI 1.... |
3198 3199 |
d->req_count = cpu_to_le16(header_size); d->res_count = d->req_count; |
bcee893c6 firewire: fw-ohci... |
3200 |
d->transfer_status = 0; |
a186b4a6b firewire: OHCI 1.... |
3201 |
d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d))); |
bcee893c6 firewire: fw-ohci... |
3202 |
rest = payload_per_buffer; |
8c0c0cc2d firewire: ohci: h... |
3203 |
pd = d; |
bcee893c6 firewire: fw-ohci... |
3204 |
for (j = 1; j < z; j++) { |
8c0c0cc2d firewire: ohci: h... |
3205 |
pd++; |
bcee893c6 firewire: fw-ohci... |
3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 |
pd->control = cpu_to_le16(DESCRIPTOR_STATUS | DESCRIPTOR_INPUT_MORE); if (offset + rest < PAGE_SIZE) length = rest; else length = PAGE_SIZE - offset; pd->req_count = cpu_to_le16(length); pd->res_count = pd->req_count; pd->transfer_status = 0; page_bus = page_private(buffer->pages[page]); pd->data_address = cpu_to_le32(page_bus + offset); |
a572e688c firewire: ohci: f... |
3219 3220 3221 |
dma_sync_single_range_for_device(device, page_bus, offset, length, DMA_FROM_DEVICE); |
bcee893c6 firewire: fw-ohci... |
3222 3223 3224 3225 3226 |
offset = (offset + length) & ~PAGE_MASK; rest -= length; if (offset == 0) page++; } |
a186b4a6b firewire: OHCI 1.... |
3227 3228 3229 |
pd->control = cpu_to_le16(DESCRIPTOR_STATUS | DESCRIPTOR_INPUT_LAST | DESCRIPTOR_BRANCH_ALWAYS); |
872e330e3 firewire: add iso... |
3230 |
if (packet->interrupt && i == packet_count - 1) |
a186b4a6b firewire: OHCI 1.... |
3231 |
pd->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS); |
a186b4a6b firewire: OHCI 1.... |
3232 3233 3234 3235 3236 |
context_append(&ctx->context, d, z, header_z); } return 0; } |
872e330e3 firewire: add iso... |
3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 |
static int queue_iso_buffer_fill(struct iso_context *ctx, struct fw_iso_packet *packet, struct fw_iso_buffer *buffer, unsigned long payload) { struct descriptor *d; dma_addr_t d_bus, page_bus; int page, offset, rest, z, i, length; page = payload >> PAGE_SHIFT; offset = payload & ~PAGE_MASK; rest = packet->payload_length; /* We need one descriptor for each page in the buffer. */ z = DIV_ROUND_UP(offset + rest, PAGE_SIZE); if (WARN_ON(offset & 3 || rest & 3 || page + z > buffer->page_count)) return -EFAULT; for (i = 0; i < z; i++) { d = context_get_descriptors(&ctx->context, 1, &d_bus); if (d == NULL) return -ENOMEM; d->control = cpu_to_le16(DESCRIPTOR_INPUT_MORE | DESCRIPTOR_BRANCH_ALWAYS); if (packet->skip && i == 0) d->control |= cpu_to_le16(DESCRIPTOR_WAIT); if (packet->interrupt && i == z - 1) d->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS); if (offset + rest < PAGE_SIZE) length = rest; else length = PAGE_SIZE - offset; d->req_count = cpu_to_le16(length); d->res_count = d->req_count; d->transfer_status = 0; page_bus = page_private(buffer->pages[page]); d->data_address = cpu_to_le32(page_bus + offset); |
a572e688c firewire: ohci: f... |
3278 3279 3280 |
dma_sync_single_range_for_device(ctx->context.ohci->card.device, page_bus, offset, length, DMA_FROM_DEVICE); |
872e330e3 firewire: add iso... |
3281 3282 3283 3284 3285 3286 3287 3288 3289 |
rest -= length; offset = 0; page++; context_append(&ctx->context, d, 1, 0); } return 0; } |
53dca5117 firewire: remove ... |
3290 3291 3292 3293 |
static int ohci_queue_iso(struct fw_iso_context *base, struct fw_iso_packet *packet, struct fw_iso_buffer *buffer, unsigned long payload) |
295e3feb9 firewire: Impleme... |
3294 |
{ |
e364cf4e0 firewire: Store O... |
3295 |
struct iso_context *ctx = container_of(base, struct iso_context, base); |
fe5ca6343 firewire: fw-ohci... |
3296 |
unsigned long flags; |
872e330e3 firewire: add iso... |
3297 |
int ret = -ENOSYS; |
e364cf4e0 firewire: Store O... |
3298 |
|
fe5ca6343 firewire: fw-ohci... |
3299 |
spin_lock_irqsave(&ctx->context.ohci->lock, flags); |
872e330e3 firewire: add iso... |
3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 |
switch (base->type) { case FW_ISO_CONTEXT_TRANSMIT: ret = queue_iso_transmit(ctx, packet, buffer, payload); break; case FW_ISO_CONTEXT_RECEIVE: ret = queue_iso_packet_per_buffer(ctx, packet, buffer, payload); break; case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: ret = queue_iso_buffer_fill(ctx, packet, buffer, payload); break; } |
fe5ca6343 firewire: fw-ohci... |
3311 |
spin_unlock_irqrestore(&ctx->context.ohci->lock, flags); |
2dbd7d7e2 firewire: standar... |
3312 |
return ret; |
295e3feb9 firewire: Impleme... |
3313 |
} |
13882a82e firewire: optimiz... |
3314 3315 3316 3317 3318 3319 |
static void ohci_flush_queue_iso(struct fw_iso_context *base) { struct context *ctx = &container_of(base, struct iso_context, base)->context; reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); |
13882a82e firewire: optimiz... |
3320 |
} |
d1bbd2097 firewire: allow e... |
3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 |
static int ohci_flush_iso_completions(struct fw_iso_context *base) { struct iso_context *ctx = container_of(base, struct iso_context, base); int ret = 0; tasklet_disable(&ctx->context.tasklet); if (!test_and_set_bit_lock(0, &ctx->flushing_completions)) { context_tasklet((unsigned long)&ctx->context); switch (base->type) { case FW_ISO_CONTEXT_TRANSMIT: case FW_ISO_CONTEXT_RECEIVE: if (ctx->header_length != 0) flush_iso_completions(ctx); break; case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: if (ctx->mc_completed != 0) flush_ir_buffer_fill(ctx); break; default: ret = -ENOSYS; } clear_bit_unlock(0, &ctx->flushing_completions); |
4e857c58e arch: Mass conver... |
3346 |
smp_mb__after_atomic(); |
d1bbd2097 firewire: allow e... |
3347 3348 3349 3350 3351 3352 |
} tasklet_enable(&ctx->context.tasklet); return ret; } |
21ebcd122 firewire: mark so... |
3353 |
static const struct fw_card_driver ohci_driver = { |
ed5689122 firewire: Add dri... |
3354 |
.enable = ohci_enable, |
02d37bed1 firewire: core: i... |
3355 |
.read_phy_reg = ohci_read_phy_reg, |
ed5689122 firewire: Add dri... |
3356 3357 3358 3359 |
.update_phy_reg = ohci_update_phy_reg, .set_config_rom = ohci_set_config_rom, .send_request = ohci_send_request, .send_response = ohci_send_response, |
730c32f58 firewire: Impleme... |
3360 |
.cancel_packet = ohci_cancel_packet, |
ed5689122 firewire: Add dri... |
3361 |
.enable_phys_dma = ohci_enable_phys_dma, |
0fcff4e39 firewire: rename ... |
3362 3363 |
.read_csr = ohci_read_csr, .write_csr = ohci_write_csr, |
ed5689122 firewire: Add dri... |
3364 3365 3366 |
.allocate_iso_context = ohci_allocate_iso_context, .free_iso_context = ohci_free_iso_context, |
872e330e3 firewire: add iso... |
3367 |
.set_iso_channels = ohci_set_iso_channels, |
ed5689122 firewire: Add dri... |
3368 |
.queue_iso = ohci_queue_iso, |
13882a82e firewire: optimiz... |
3369 |
.flush_queue_iso = ohci_flush_queue_iso, |
d1bbd2097 firewire: allow e... |
3370 |
.flush_iso_completions = ohci_flush_iso_completions, |
69cdb7268 firewire: Rename ... |
3371 |
.start_iso = ohci_start_iso, |
b82956685 firewire: Impleme... |
3372 |
.stop_iso = ohci_stop_iso, |
ed5689122 firewire: Add dri... |
3373 |
}; |
ea8d006b9 firewire: fw-ohci... |
3374 |
#ifdef CONFIG_PPC_PMAC |
5da3dac8d firewire: ohci: c... |
3375 |
static void pmac_ohci_on(struct pci_dev *dev) |
2ed0f181f firewire: fw-ohci... |
3376 |
{ |
ea8d006b9 firewire: fw-ohci... |
3377 3378 3379 3380 3381 3382 3383 3384 |
if (machine_is(powermac)) { struct device_node *ofn = pci_device_to_OF_node(dev); if (ofn) { pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1); pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1); } } |
2ed0f181f firewire: fw-ohci... |
3385 |
} |
5da3dac8d firewire: ohci: c... |
3386 |
static void pmac_ohci_off(struct pci_dev *dev) |
2ed0f181f firewire: fw-ohci... |
3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 |
{ if (machine_is(powermac)) { struct device_node *ofn = pci_device_to_OF_node(dev); if (ofn) { pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0); pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0); } } } #else |
5da3dac8d firewire: ohci: c... |
3398 3399 |
static inline void pmac_ohci_on(struct pci_dev *dev) {} static inline void pmac_ohci_off(struct pci_dev *dev) {} |
ea8d006b9 firewire: fw-ohci... |
3400 |
#endif /* CONFIG_PPC_PMAC */ |
03f94c0f6 firewire: remove ... |
3401 |
static int pci_probe(struct pci_dev *dev, |
53dca5117 firewire: remove ... |
3402 |
const struct pci_device_id *ent) |
2ed0f181f firewire: fw-ohci... |
3403 3404 |
{ struct fw_ohci *ohci; |
aa0170fff firewire: ohci: f... |
3405 |
u32 bus_options, max_receive, link_speed, version; |
2ed0f181f firewire: fw-ohci... |
3406 |
u64 guid; |
dd23736e0 firewire: ohci: r... |
3407 |
int i, err; |
2ed0f181f firewire: fw-ohci... |
3408 |
size_t size; |
7f7e37115 firewire: ohci: d... |
3409 3410 3411 3412 3413 |
if (dev->vendor == PCI_VENDOR_ID_PINNACLE_SYSTEMS) { dev_err(&dev->dev, "Pinnacle MovieBoard is not yet supported "); return -ENOSYS; } |
2d826cc5c firewire: Always ... |
3414 |
ohci = kzalloc(sizeof(*ohci), GFP_KERNEL); |
ed5689122 firewire: Add dri... |
3415 |
if (ohci == NULL) { |
7007a0765 firewire: fw-ohci... |
3416 3417 |
err = -ENOMEM; goto fail; |
ed5689122 firewire: Add dri... |
3418 3419 3420 |
} fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev); |
5da3dac8d firewire: ohci: c... |
3421 |
pmac_ohci_on(dev); |
130d5496e firewire: fw-ohci... |
3422 |
|
d79406dd1 firewire: Convert... |
3423 3424 |
err = pci_enable_device(dev); if (err) { |
64d217201 firewire: ohci: u... |
3425 3426 |
dev_err(&dev->dev, "failed to enable OHCI hardware "); |
bd7dee631 firewire: remove ... |
3427 |
goto fail_free; |
ed5689122 firewire: Add dri... |
3428 3429 3430 3431 3432 3433 3434 |
} pci_set_master(dev); pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); pci_set_drvdata(dev, ohci); spin_lock_init(&ohci->lock); |
02d37bed1 firewire: core: i... |
3435 |
mutex_init(&ohci->phy_reg_mutex); |
ed5689122 firewire: Add dri... |
3436 |
|
2d7a36e23 firewire: ohci: M... |
3437 |
INIT_WORK(&ohci->bus_reset_work, bus_reset_work); |
ed5689122 firewire: Add dri... |
3438 |
|
7baab9acf firewire: ohci: s... |
3439 3440 |
if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM) || pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE) { |
de97cb64a firewire: ohci: A... |
3441 3442 |
ohci_err(ohci, "invalid MMIO resource "); |
7baab9acf firewire: ohci: s... |
3443 3444 3445 |
err = -ENXIO; goto fail_disable; } |
d79406dd1 firewire: Convert... |
3446 3447 |
err = pci_request_region(dev, 0, ohci_driver_name); if (err) { |
de97cb64a firewire: ohci: A... |
3448 3449 |
ohci_err(ohci, "MMIO resource unavailable "); |
d79406dd1 firewire: Convert... |
3450 |
goto fail_disable; |
ed5689122 firewire: Add dri... |
3451 3452 3453 3454 |
} ohci->registers = pci_iomap(dev, 0, OHCI1394_REGISTER_SIZE); if (ohci->registers == NULL) { |
de97cb64a firewire: ohci: A... |
3455 3456 |
ohci_err(ohci, "failed to remap registers "); |
d79406dd1 firewire: Convert... |
3457 3458 |
err = -ENXIO; goto fail_iomem; |
ed5689122 firewire: Add dri... |
3459 |
} |
4a635593f firewire: ohci: u... |
3460 |
for (i = 0; i < ARRAY_SIZE(ohci_quirks); i++) |
9993e0fe0 firewire: ohci: f... |
3461 3462 3463 3464 3465 |
if ((ohci_quirks[i].vendor == dev->vendor) && (ohci_quirks[i].device == (unsigned short)PCI_ANY_ID || ohci_quirks[i].device == dev->device) && (ohci_quirks[i].revision == (unsigned short)PCI_ANY_ID || ohci_quirks[i].revision >= dev->revision)) { |
4a635593f firewire: ohci: u... |
3466 3467 3468 |
ohci->quirks = ohci_quirks[i].flags; break; } |
3e9cc2f3b firewire: ohci: a... |
3469 3470 |
if (param_quirks) ohci->quirks = param_quirks; |
b677532b9 firewire: ohci: w... |
3471 |
|
ec766a797 firewire: ohci: u... |
3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 |
/* * Because dma_alloc_coherent() allocates at least one page, * we save space by using a common buffer for the AR request/ * response descriptors and the self IDs buffer. */ BUILD_BUG_ON(AR_BUFFERS * sizeof(struct descriptor) > PAGE_SIZE/4); BUILD_BUG_ON(SELF_ID_BUF_SIZE > PAGE_SIZE/2); ohci->misc_buffer = dma_alloc_coherent(ohci->card.device, PAGE_SIZE, &ohci->misc_buffer_bus, GFP_KERNEL); if (!ohci->misc_buffer) { err = -ENOMEM; goto fail_iounmap; } err = ar_context_init(&ohci->ar_request_ctx, ohci, 0, |
7a39d8b82 firewire: ohci: A... |
3489 3490 |
OHCI1394_AsReqRcvContextControlSet); if (err < 0) |
ec766a797 firewire: ohci: u... |
3491 |
goto fail_misc_buf; |
ed5689122 firewire: Add dri... |
3492 |
|
ec766a797 firewire: ohci: u... |
3493 |
err = ar_context_init(&ohci->ar_response_ctx, ohci, PAGE_SIZE/4, |
7a39d8b82 firewire: ohci: A... |
3494 3495 3496 |
OHCI1394_AsRspRcvContextControlSet); if (err < 0) goto fail_arreq_ctx; |
ed5689122 firewire: Add dri... |
3497 |
|
c088ab30e firewire: ohci: f... |
3498 3499 3500 3501 |
err = context_init(&ohci->at_request_ctx, ohci, OHCI1394_AsReqTrContextControlSet, handle_at_packet); if (err < 0) goto fail_arrsp_ctx; |
ed5689122 firewire: Add dri... |
3502 |
|
c088ab30e firewire: ohci: f... |
3503 3504 3505 3506 |
err = context_init(&ohci->at_response_ctx, ohci, OHCI1394_AsRspTrContextControlSet, handle_at_packet); if (err < 0) goto fail_atreq_ctx; |
ed5689122 firewire: Add dri... |
3507 |
|
ed5689122 firewire: Add dri... |
3508 |
reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0); |
4802f16d5 firewire: ohci: f... |
3509 |
ohci->ir_context_channels = ~0ULL; |
f117a3e30 firewire: ohci: l... |
3510 |
ohci->ir_context_support = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); |
ed5689122 firewire: Add dri... |
3511 |
reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0); |
f117a3e30 firewire: ohci: l... |
3512 |
ohci->ir_context_mask = ohci->ir_context_support; |
dd23736e0 firewire: ohci: r... |
3513 3514 |
ohci->n_ir = hweight32(ohci->ir_context_mask); size = sizeof(struct iso_context) * ohci->n_ir; |
4802f16d5 firewire: ohci: f... |
3515 |
ohci->ir_context_list = kzalloc(size, GFP_KERNEL); |
ed5689122 firewire: Add dri... |
3516 3517 |
reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); |
f117a3e30 firewire: ohci: l... |
3518 |
ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); |
100ceb66d firewire: ohci: f... |
3519 3520 3521 3522 3523 3524 |
/* JMicron JMB38x often shows 0 at first read, just ignore it */ if (!ohci->it_context_support) { ohci_notice(ohci, "overriding IsoXmitIntMask "); ohci->it_context_support = 0xf; } |
ed5689122 firewire: Add dri... |
3525 |
reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); |
f117a3e30 firewire: ohci: l... |
3526 |
ohci->it_context_mask = ohci->it_context_support; |
dd23736e0 firewire: ohci: r... |
3527 3528 |
ohci->n_it = hweight32(ohci->it_context_mask); size = sizeof(struct iso_context) * ohci->n_it; |
4802f16d5 firewire: ohci: f... |
3529 |
ohci->it_context_list = kzalloc(size, GFP_KERNEL); |
ed5689122 firewire: Add dri... |
3530 3531 |
if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) { |
d79406dd1 firewire: Convert... |
3532 |
err = -ENOMEM; |
7007a0765 firewire: fw-ohci... |
3533 |
goto fail_contexts; |
ed5689122 firewire: Add dri... |
3534 |
} |
af53122a2 firewire: ohci: c... |
3535 |
ohci->self_id = ohci->misc_buffer + PAGE_SIZE/2; |
ec766a797 firewire: ohci: u... |
3536 |
ohci->self_id_bus = ohci->misc_buffer_bus + PAGE_SIZE/2; |
ed5689122 firewire: Add dri... |
3537 |
|
ed5689122 firewire: Add dri... |
3538 3539 3540 3541 3542 |
bus_options = reg_read(ohci, OHCI1394_BusOptions); max_receive = (bus_options >> 12) & 0xf; link_speed = bus_options & 0x7; guid = ((u64) reg_read(ohci, OHCI1394_GUIDHi) << 32) | reg_read(ohci, OHCI1394_GUIDLo); |
247fd50b5 firewire: ohci: F... |
3543 3544 3545 3546 3547 |
if (!(ohci->quirks & QUIRK_NO_MSI)) pci_enable_msi(dev); if (request_irq(dev->irq, irq_handler, pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED, ohci_driver_name, ohci)) { |
de97cb64a firewire: ohci: A... |
3548 3549 |
ohci_err(ohci, "failed to allocate interrupt %d ", dev->irq); |
247fd50b5 firewire: ohci: F... |
3550 3551 3552 |
err = -EIO; goto fail_msi; } |
d79406dd1 firewire: Convert... |
3553 |
err = fw_card_add(&ohci->card, max_receive, link_speed, guid); |
e1eff7a39 firewire: normali... |
3554 |
if (err) |
247fd50b5 firewire: ohci: F... |
3555 |
goto fail_irq; |
ed5689122 firewire: Add dri... |
3556 |
|
6fdb2ee24 firewire: ohci: e... |
3557 |
version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; |
de97cb64a firewire: ohci: A... |
3558 3559 |
ohci_notice(ohci, "added OHCI v%x.%x device as card %d, " |
fcd46b344 firewire: Enable ... |
3560 3561 |
"%d IR + %d IT contexts, quirks 0x%x%s ", |
de97cb64a firewire: ohci: A... |
3562 |
version >> 16, version & 0xff, ohci->card.index, |
fcd46b344 firewire: Enable ... |
3563 3564 |
ohci->n_ir, ohci->n_it, ohci->quirks, reg_read(ohci, OHCI1394_PhyUpperBound) ? |
2fe2023ad firewire: revert ... |
3565 |
", physUB" : ""); |
e1eff7a39 firewire: normali... |
3566 |
|
ed5689122 firewire: Add dri... |
3567 |
return 0; |
d79406dd1 firewire: Convert... |
3568 |
|
247fd50b5 firewire: ohci: F... |
3569 3570 3571 3572 |
fail_irq: free_irq(dev->irq, ohci); fail_msi: pci_disable_msi(dev); |
7007a0765 firewire: fw-ohci... |
3573 |
fail_contexts: |
d79406dd1 firewire: Convert... |
3574 |
kfree(ohci->ir_context_list); |
7007a0765 firewire: fw-ohci... |
3575 3576 |
kfree(ohci->it_context_list); context_release(&ohci->at_response_ctx); |
c088ab30e firewire: ohci: f... |
3577 |
fail_atreq_ctx: |
7007a0765 firewire: fw-ohci... |
3578 |
context_release(&ohci->at_request_ctx); |
c088ab30e firewire: ohci: f... |
3579 |
fail_arrsp_ctx: |
7007a0765 firewire: fw-ohci... |
3580 |
ar_context_release(&ohci->ar_response_ctx); |
7a39d8b82 firewire: ohci: A... |
3581 |
fail_arreq_ctx: |
7007a0765 firewire: fw-ohci... |
3582 |
ar_context_release(&ohci->ar_request_ctx); |
ec766a797 firewire: ohci: u... |
3583 3584 3585 |
fail_misc_buf: dma_free_coherent(ohci->card.device, PAGE_SIZE, ohci->misc_buffer, ohci->misc_buffer_bus); |
7a39d8b82 firewire: ohci: A... |
3586 |
fail_iounmap: |
d79406dd1 firewire: Convert... |
3587 3588 3589 3590 3591 |
pci_iounmap(dev, ohci->registers); fail_iomem: pci_release_region(dev, 0); fail_disable: pci_disable_device(dev); |
bd7dee631 firewire: remove ... |
3592 |
fail_free: |
d838d2c09 firewire: ohci: M... |
3593 |
kfree(ohci); |
5da3dac8d firewire: ohci: c... |
3594 |
pmac_ohci_off(dev); |
7007a0765 firewire: fw-ohci... |
3595 |
fail: |
d79406dd1 firewire: Convert... |
3596 |
return err; |
ed5689122 firewire: Add dri... |
3597 3598 3599 3600 |
} static void pci_remove(struct pci_dev *dev) { |
8db491490 firewire: ohci: C... |
3601 |
struct fw_ohci *ohci = pci_get_drvdata(dev); |
ed5689122 firewire: Add dri... |
3602 |
|
8db491490 firewire: ohci: C... |
3603 3604 3605 3606 3607 3608 3609 3610 |
/* * If the removal is happening from the suspend state, LPS won't be * enabled and host registers (eg., IntMaskClear) won't be accessible. */ if (reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_LPS) { reg_write(ohci, OHCI1394_IntMaskClear, ~0); flush_writes(ohci); } |
2d7a36e23 firewire: ohci: M... |
3611 |
cancel_work_sync(&ohci->bus_reset_work); |
ed5689122 firewire: Add dri... |
3612 |
fw_core_remove_card(&ohci->card); |
c781c06d1 firewire: Clean u... |
3613 3614 3615 3616 |
/* * FIXME: Fail all pending packets here, now that the upper * layers can't queue any more. */ |
ed5689122 firewire: Add dri... |
3617 3618 3619 |
software_reset(ohci); free_irq(dev->irq, ohci); |
a55709ba9 firewire: fw-ohci... |
3620 3621 3622 3623 3624 3625 3626 |
if (ohci->next_config_rom && ohci->next_config_rom != ohci->config_rom) dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, ohci->next_config_rom, ohci->next_config_rom_bus); if (ohci->config_rom) dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, ohci->config_rom, ohci->config_rom_bus); |
a55709ba9 firewire: fw-ohci... |
3627 3628 |
ar_context_release(&ohci->ar_request_ctx); ar_context_release(&ohci->ar_response_ctx); |
ec766a797 firewire: ohci: u... |
3629 3630 |
dma_free_coherent(ohci->card.device, PAGE_SIZE, ohci->misc_buffer, ohci->misc_buffer_bus); |
a55709ba9 firewire: fw-ohci... |
3631 3632 |
context_release(&ohci->at_request_ctx); context_release(&ohci->at_response_ctx); |
d79406dd1 firewire: Convert... |
3633 3634 |
kfree(ohci->it_context_list); kfree(ohci->ir_context_list); |
262444eec firewire: ohci: a... |
3635 |
pci_disable_msi(dev); |
d79406dd1 firewire: Convert... |
3636 3637 3638 |
pci_iounmap(dev, ohci->registers); pci_release_region(dev, 0); pci_disable_device(dev); |
d838d2c09 firewire: ohci: M... |
3639 |
kfree(ohci); |
5da3dac8d firewire: ohci: c... |
3640 |
pmac_ohci_off(dev); |
ea8d006b9 firewire: fw-ohci... |
3641 |
|
64d217201 firewire: ohci: u... |
3642 3643 |
dev_notice(&dev->dev, "removed fw-ohci device "); |
ed5689122 firewire: Add dri... |
3644 |
} |
2aef469a3 firewire: Impleme... |
3645 |
#ifdef CONFIG_PM |
2ed0f181f firewire: fw-ohci... |
3646 |
static int pci_suspend(struct pci_dev *dev, pm_message_t state) |
2aef469a3 firewire: Impleme... |
3647 |
{ |
2ed0f181f firewire: fw-ohci... |
3648 |
struct fw_ohci *ohci = pci_get_drvdata(dev); |
2aef469a3 firewire: Impleme... |
3649 3650 3651 |
int err; software_reset(ohci); |
2ed0f181f firewire: fw-ohci... |
3652 |
err = pci_save_state(dev); |
2aef469a3 firewire: Impleme... |
3653 |
if (err) { |
de97cb64a firewire: ohci: A... |
3654 3655 |
ohci_err(ohci, "pci_save_state failed "); |
2aef469a3 firewire: Impleme... |
3656 3657 |
return err; } |
2ed0f181f firewire: fw-ohci... |
3658 |
err = pci_set_power_state(dev, pci_choose_state(dev, state)); |
551114287 firewire: fw-ohci... |
3659 |
if (err) |
de97cb64a firewire: ohci: A... |
3660 3661 |
ohci_err(ohci, "pci_set_power_state failed with %d ", err); |
5da3dac8d firewire: ohci: c... |
3662 |
pmac_ohci_off(dev); |
ea8d006b9 firewire: fw-ohci... |
3663 |
|
2aef469a3 firewire: Impleme... |
3664 3665 |
return 0; } |
2ed0f181f firewire: fw-ohci... |
3666 |
static int pci_resume(struct pci_dev *dev) |
2aef469a3 firewire: Impleme... |
3667 |
{ |
2ed0f181f firewire: fw-ohci... |
3668 |
struct fw_ohci *ohci = pci_get_drvdata(dev); |
2aef469a3 firewire: Impleme... |
3669 |
int err; |
5da3dac8d firewire: ohci: c... |
3670 |
pmac_ohci_on(dev); |
2ed0f181f firewire: fw-ohci... |
3671 3672 3673 |
pci_set_power_state(dev, PCI_D0); pci_restore_state(dev); err = pci_enable_device(dev); |
2aef469a3 firewire: Impleme... |
3674 |
if (err) { |
de97cb64a firewire: ohci: A... |
3675 3676 |
ohci_err(ohci, "pci_enable_device failed "); |
2aef469a3 firewire: Impleme... |
3677 3678 |
return err; } |
8662b6b02 firewire: ohci: r... |
3679 3680 3681 3682 3683 3684 |
/* Some systems don't setup GUID register on resume from ram */ if (!reg_read(ohci, OHCI1394_GUIDLo) && !reg_read(ohci, OHCI1394_GUIDHi)) { reg_write(ohci, OHCI1394_GUIDLo, (u32)ohci->card.guid); reg_write(ohci, OHCI1394_GUIDHi, (u32)(ohci->card.guid >> 32)); } |
dd23736e0 firewire: ohci: r... |
3685 |
err = ohci_enable(&ohci->card, NULL, 0); |
dd23736e0 firewire: ohci: r... |
3686 3687 3688 3689 |
if (err) return err; ohci_resume_iso_dma(ohci); |
693a50b51 firewire: ohci: c... |
3690 |
|
dd23736e0 firewire: ohci: r... |
3691 |
return 0; |
2aef469a3 firewire: Impleme... |
3692 3693 |
} #endif |
a67483d2b firewire: make PC... |
3694 |
static const struct pci_device_id pci_table[] = { |
ed5689122 firewire: Add dri... |
3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 |
{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) }, { } }; MODULE_DEVICE_TABLE(pci, pci_table); static struct pci_driver fw_ohci_pci_driver = { .name = ohci_driver_name, .id_table = pci_table, .probe = pci_probe, .remove = pci_remove, |
2aef469a3 firewire: Impleme... |
3706 3707 3708 3709 |
#ifdef CONFIG_PM .resume = pci_resume, .suspend = pci_suspend, #endif |
ed5689122 firewire: Add dri... |
3710 |
}; |
7a723c6ed firewire: ohci: C... |
3711 3712 |
static int __init fw_ohci_init(void) { |
db9ae8fec firewire: ohci: F... |
3713 3714 3715 |
selfid_workqueue = alloc_workqueue(KBUILD_MODNAME, WQ_MEM_RECLAIM, 0); if (!selfid_workqueue) return -ENOMEM; |
7a723c6ed firewire: ohci: C... |
3716 3717 3718 3719 3720 3721 |
return pci_register_driver(&fw_ohci_pci_driver); } static void __exit fw_ohci_cleanup(void) { pci_unregister_driver(&fw_ohci_pci_driver); |
db9ae8fec firewire: ohci: F... |
3722 |
destroy_workqueue(selfid_workqueue); |
7a723c6ed firewire: ohci: C... |
3723 3724 3725 3726 |
} module_init(fw_ohci_init); module_exit(fw_ohci_cleanup); |
fe2af11c2 firewire: use mod... |
3727 |
|
ed5689122 firewire: Add dri... |
3728 3729 3730 |
MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>"); MODULE_DESCRIPTION("Driver for PCI OHCI IEEE1394 controllers"); MODULE_LICENSE("GPL"); |
1e4c7b0da firewire: Provide... |
3731 |
/* Provide a module alias so root-on-sbp2 initrds don't break. */ |
1e4c7b0da firewire: Provide... |
3732 |
MODULE_ALIAS("ohci1394"); |