xref: /OK3568_Linux_fs/kernel/sound/firewire/fcp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Function Control Protocol (IEC 61883-1) helper functions
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/device.h>
9*4882a593Smuzhiyun #include <linux/firewire.h>
10*4882a593Smuzhiyun #include <linux/firewire-constants.h>
11*4882a593Smuzhiyun #include <linux/list.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <linux/sched.h>
15*4882a593Smuzhiyun #include <linux/spinlock.h>
16*4882a593Smuzhiyun #include <linux/wait.h>
17*4882a593Smuzhiyun #include <linux/delay.h>
18*4882a593Smuzhiyun #include "fcp.h"
19*4882a593Smuzhiyun #include "lib.h"
20*4882a593Smuzhiyun #include "amdtp-stream.h"
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define CTS_AVC 0x00
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define ERROR_RETRIES	3
25*4882a593Smuzhiyun #define ERROR_DELAY_MS	5
26*4882a593Smuzhiyun #define FCP_TIMEOUT_MS	125
27*4882a593Smuzhiyun 
avc_general_set_sig_fmt(struct fw_unit * unit,unsigned int rate,enum avc_general_plug_dir dir,unsigned short pid)28*4882a593Smuzhiyun int avc_general_set_sig_fmt(struct fw_unit *unit, unsigned int rate,
29*4882a593Smuzhiyun 			    enum avc_general_plug_dir dir,
30*4882a593Smuzhiyun 			    unsigned short pid)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun 	unsigned int sfc;
33*4882a593Smuzhiyun 	u8 *buf;
34*4882a593Smuzhiyun 	bool flag;
35*4882a593Smuzhiyun 	int err;
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun 	flag = false;
38*4882a593Smuzhiyun 	for (sfc = 0; sfc < CIP_SFC_COUNT; sfc++) {
39*4882a593Smuzhiyun 		if (amdtp_rate_table[sfc] == rate) {
40*4882a593Smuzhiyun 			flag = true;
41*4882a593Smuzhiyun 			break;
42*4882a593Smuzhiyun 		}
43*4882a593Smuzhiyun 	}
44*4882a593Smuzhiyun 	if (!flag)
45*4882a593Smuzhiyun 		return -EINVAL;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	buf = kzalloc(8, GFP_KERNEL);
48*4882a593Smuzhiyun 	if (buf == NULL)
49*4882a593Smuzhiyun 		return -ENOMEM;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	buf[0] = 0x00;		/* AV/C CONTROL */
52*4882a593Smuzhiyun 	buf[1] = 0xff;		/* UNIT */
53*4882a593Smuzhiyun 	if (dir == AVC_GENERAL_PLUG_DIR_IN)
54*4882a593Smuzhiyun 		buf[2] = 0x19;	/* INPUT PLUG SIGNAL FORMAT */
55*4882a593Smuzhiyun 	else
56*4882a593Smuzhiyun 		buf[2] = 0x18;	/* OUTPUT PLUG SIGNAL FORMAT */
57*4882a593Smuzhiyun 	buf[3] = 0xff & pid;	/* plug id */
58*4882a593Smuzhiyun 	buf[4] = 0x90;		/* EOH_1, Form_1, FMT. AM824 */
59*4882a593Smuzhiyun 	buf[5] = 0x07 & sfc;	/* FDF-hi. AM824, frequency */
60*4882a593Smuzhiyun 	buf[6] = 0xff;		/* FDF-mid. AM824, SYT hi (not used)*/
61*4882a593Smuzhiyun 	buf[7] = 0xff;		/* FDF-low. AM824, SYT lo (not used) */
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	/* do transaction and check buf[1-5] are the same against command */
64*4882a593Smuzhiyun 	err = fcp_avc_transaction(unit, buf, 8, buf, 8,
65*4882a593Smuzhiyun 				  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5));
66*4882a593Smuzhiyun 	if (err < 0)
67*4882a593Smuzhiyun 		;
68*4882a593Smuzhiyun 	else if (err < 8)
69*4882a593Smuzhiyun 		err = -EIO;
70*4882a593Smuzhiyun 	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
71*4882a593Smuzhiyun 		err = -ENOSYS;
72*4882a593Smuzhiyun 	else if (buf[0] == 0x0a) /* REJECTED */
73*4882a593Smuzhiyun 		err = -EINVAL;
74*4882a593Smuzhiyun 	if (err < 0)
75*4882a593Smuzhiyun 		goto end;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	err = 0;
78*4882a593Smuzhiyun end:
79*4882a593Smuzhiyun 	kfree(buf);
80*4882a593Smuzhiyun 	return err;
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun EXPORT_SYMBOL(avc_general_set_sig_fmt);
83*4882a593Smuzhiyun 
avc_general_get_sig_fmt(struct fw_unit * unit,unsigned int * rate,enum avc_general_plug_dir dir,unsigned short pid)84*4882a593Smuzhiyun int avc_general_get_sig_fmt(struct fw_unit *unit, unsigned int *rate,
85*4882a593Smuzhiyun 			    enum avc_general_plug_dir dir,
86*4882a593Smuzhiyun 			    unsigned short pid)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	unsigned int sfc;
89*4882a593Smuzhiyun 	u8 *buf;
90*4882a593Smuzhiyun 	int err;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	buf = kzalloc(8, GFP_KERNEL);
93*4882a593Smuzhiyun 	if (buf == NULL)
94*4882a593Smuzhiyun 		return -ENOMEM;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	buf[0] = 0x01;		/* AV/C STATUS */
97*4882a593Smuzhiyun 	buf[1] = 0xff;		/* Unit */
98*4882a593Smuzhiyun 	if (dir == AVC_GENERAL_PLUG_DIR_IN)
99*4882a593Smuzhiyun 		buf[2] = 0x19;	/* INPUT PLUG SIGNAL FORMAT */
100*4882a593Smuzhiyun 	else
101*4882a593Smuzhiyun 		buf[2] = 0x18;	/* OUTPUT PLUG SIGNAL FORMAT */
102*4882a593Smuzhiyun 	buf[3] = 0xff & pid;	/* plug id */
103*4882a593Smuzhiyun 	buf[4] = 0x90;		/* EOH_1, Form_1, FMT. AM824 */
104*4882a593Smuzhiyun 	buf[5] = 0xff;		/* FDF-hi. AM824, frequency */
105*4882a593Smuzhiyun 	buf[6] = 0xff;		/* FDF-mid. AM824, SYT hi (not used) */
106*4882a593Smuzhiyun 	buf[7] = 0xff;		/* FDF-low. AM824, SYT lo (not used) */
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	/* do transaction and check buf[1-4] are the same against command */
109*4882a593Smuzhiyun 	err = fcp_avc_transaction(unit, buf, 8, buf, 8,
110*4882a593Smuzhiyun 				  BIT(1) | BIT(2) | BIT(3) | BIT(4));
111*4882a593Smuzhiyun 	if (err < 0)
112*4882a593Smuzhiyun 		;
113*4882a593Smuzhiyun 	else if (err < 8)
114*4882a593Smuzhiyun 		err = -EIO;
115*4882a593Smuzhiyun 	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
116*4882a593Smuzhiyun 		err = -ENOSYS;
117*4882a593Smuzhiyun 	else if (buf[0] == 0x0a) /* REJECTED */
118*4882a593Smuzhiyun 		err = -EINVAL;
119*4882a593Smuzhiyun 	else if (buf[0] == 0x0b) /* IN TRANSITION */
120*4882a593Smuzhiyun 		err = -EAGAIN;
121*4882a593Smuzhiyun 	if (err < 0)
122*4882a593Smuzhiyun 		goto end;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	/* check sfc field and pick up rate */
125*4882a593Smuzhiyun 	sfc = 0x07 & buf[5];
126*4882a593Smuzhiyun 	if (sfc >= CIP_SFC_COUNT) {
127*4882a593Smuzhiyun 		err = -EAGAIN;	/* also in transition */
128*4882a593Smuzhiyun 		goto end;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	*rate = amdtp_rate_table[sfc];
132*4882a593Smuzhiyun 	err = 0;
133*4882a593Smuzhiyun end:
134*4882a593Smuzhiyun 	kfree(buf);
135*4882a593Smuzhiyun 	return err;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun EXPORT_SYMBOL(avc_general_get_sig_fmt);
138*4882a593Smuzhiyun 
avc_general_get_plug_info(struct fw_unit * unit,unsigned int subunit_type,unsigned int subunit_id,unsigned int subfunction,u8 info[AVC_PLUG_INFO_BUF_BYTES])139*4882a593Smuzhiyun int avc_general_get_plug_info(struct fw_unit *unit, unsigned int subunit_type,
140*4882a593Smuzhiyun 			      unsigned int subunit_id, unsigned int subfunction,
141*4882a593Smuzhiyun 			      u8 info[AVC_PLUG_INFO_BUF_BYTES])
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	u8 *buf;
144*4882a593Smuzhiyun 	int err;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	/* extended subunit in spec.4.2 is not supported */
147*4882a593Smuzhiyun 	if ((subunit_type == 0x1E) || (subunit_id == 5))
148*4882a593Smuzhiyun 		return -EINVAL;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	buf = kzalloc(8, GFP_KERNEL);
151*4882a593Smuzhiyun 	if (buf == NULL)
152*4882a593Smuzhiyun 		return -ENOMEM;
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	buf[0] = 0x01;	/* AV/C STATUS */
155*4882a593Smuzhiyun 	/* UNIT or Subunit, Functionblock */
156*4882a593Smuzhiyun 	buf[1] = ((subunit_type & 0x1f) << 3) | (subunit_id & 0x7);
157*4882a593Smuzhiyun 	buf[2] = 0x02;	/* PLUG INFO */
158*4882a593Smuzhiyun 	buf[3] = 0xff & subfunction;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	err = fcp_avc_transaction(unit, buf, 8, buf, 8, BIT(1) | BIT(2));
161*4882a593Smuzhiyun 	if (err < 0)
162*4882a593Smuzhiyun 		;
163*4882a593Smuzhiyun 	else if (err < 8)
164*4882a593Smuzhiyun 		err = -EIO;
165*4882a593Smuzhiyun 	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
166*4882a593Smuzhiyun 		err = -ENOSYS;
167*4882a593Smuzhiyun 	else if (buf[0] == 0x0a) /* REJECTED */
168*4882a593Smuzhiyun 		err = -EINVAL;
169*4882a593Smuzhiyun 	else if (buf[0] == 0x0b) /* IN TRANSITION */
170*4882a593Smuzhiyun 		err = -EAGAIN;
171*4882a593Smuzhiyun 	if (err < 0)
172*4882a593Smuzhiyun 		goto end;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	info[0] = buf[4];
175*4882a593Smuzhiyun 	info[1] = buf[5];
176*4882a593Smuzhiyun 	info[2] = buf[6];
177*4882a593Smuzhiyun 	info[3] = buf[7];
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	err = 0;
180*4882a593Smuzhiyun end:
181*4882a593Smuzhiyun 	kfree(buf);
182*4882a593Smuzhiyun 	return err;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun EXPORT_SYMBOL(avc_general_get_plug_info);
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun static DEFINE_SPINLOCK(transactions_lock);
187*4882a593Smuzhiyun static LIST_HEAD(transactions);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun enum fcp_state {
190*4882a593Smuzhiyun 	STATE_PENDING,
191*4882a593Smuzhiyun 	STATE_BUS_RESET,
192*4882a593Smuzhiyun 	STATE_COMPLETE,
193*4882a593Smuzhiyun 	STATE_DEFERRED,
194*4882a593Smuzhiyun };
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun struct fcp_transaction {
197*4882a593Smuzhiyun 	struct list_head list;
198*4882a593Smuzhiyun 	struct fw_unit *unit;
199*4882a593Smuzhiyun 	void *response_buffer;
200*4882a593Smuzhiyun 	unsigned int response_size;
201*4882a593Smuzhiyun 	unsigned int response_match_bytes;
202*4882a593Smuzhiyun 	enum fcp_state state;
203*4882a593Smuzhiyun 	wait_queue_head_t wait;
204*4882a593Smuzhiyun 	bool deferrable;
205*4882a593Smuzhiyun };
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun /**
208*4882a593Smuzhiyun  * fcp_avc_transaction - send an AV/C command and wait for its response
209*4882a593Smuzhiyun  * @unit: a unit on the target device
210*4882a593Smuzhiyun  * @command: a buffer containing the command frame; must be DMA-able
211*4882a593Smuzhiyun  * @command_size: the size of @command
212*4882a593Smuzhiyun  * @response: a buffer for the response frame
213*4882a593Smuzhiyun  * @response_size: the maximum size of @response
214*4882a593Smuzhiyun  * @response_match_bytes: a bitmap specifying the bytes used to detect the
215*4882a593Smuzhiyun  *                        correct response frame
216*4882a593Smuzhiyun  *
217*4882a593Smuzhiyun  * This function sends a FCP command frame to the target and waits for the
218*4882a593Smuzhiyun  * corresponding response frame to be returned.
219*4882a593Smuzhiyun  *
220*4882a593Smuzhiyun  * Because it is possible for multiple FCP transactions to be active at the
221*4882a593Smuzhiyun  * same time, the correct response frame is detected by the value of certain
222*4882a593Smuzhiyun  * bytes.  These bytes must be set in @response before calling this function,
223*4882a593Smuzhiyun  * and the corresponding bits must be set in @response_match_bytes.
224*4882a593Smuzhiyun  *
225*4882a593Smuzhiyun  * @command and @response can point to the same buffer.
226*4882a593Smuzhiyun  *
227*4882a593Smuzhiyun  * Returns the actual size of the response frame, or a negative error code.
228*4882a593Smuzhiyun  */
fcp_avc_transaction(struct fw_unit * unit,const void * command,unsigned int command_size,void * response,unsigned int response_size,unsigned int response_match_bytes)229*4882a593Smuzhiyun int fcp_avc_transaction(struct fw_unit *unit,
230*4882a593Smuzhiyun 			const void *command, unsigned int command_size,
231*4882a593Smuzhiyun 			void *response, unsigned int response_size,
232*4882a593Smuzhiyun 			unsigned int response_match_bytes)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun 	struct fcp_transaction t;
235*4882a593Smuzhiyun 	int tcode, ret, tries = 0;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	t.unit = unit;
238*4882a593Smuzhiyun 	t.response_buffer = response;
239*4882a593Smuzhiyun 	t.response_size = response_size;
240*4882a593Smuzhiyun 	t.response_match_bytes = response_match_bytes;
241*4882a593Smuzhiyun 	t.state = STATE_PENDING;
242*4882a593Smuzhiyun 	init_waitqueue_head(&t.wait);
243*4882a593Smuzhiyun 	t.deferrable = (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03);
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	spin_lock_irq(&transactions_lock);
246*4882a593Smuzhiyun 	list_add_tail(&t.list, &transactions);
247*4882a593Smuzhiyun 	spin_unlock_irq(&transactions_lock);
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	for (;;) {
250*4882a593Smuzhiyun 		tcode = command_size == 4 ? TCODE_WRITE_QUADLET_REQUEST
251*4882a593Smuzhiyun 					  : TCODE_WRITE_BLOCK_REQUEST;
252*4882a593Smuzhiyun 		ret = snd_fw_transaction(t.unit, tcode,
253*4882a593Smuzhiyun 					 CSR_REGISTER_BASE + CSR_FCP_COMMAND,
254*4882a593Smuzhiyun 					 (void *)command, command_size, 0);
255*4882a593Smuzhiyun 		if (ret < 0)
256*4882a593Smuzhiyun 			break;
257*4882a593Smuzhiyun deferred:
258*4882a593Smuzhiyun 		wait_event_timeout(t.wait, t.state != STATE_PENDING,
259*4882a593Smuzhiyun 				   msecs_to_jiffies(FCP_TIMEOUT_MS));
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 		if (t.state == STATE_DEFERRED) {
262*4882a593Smuzhiyun 			/*
263*4882a593Smuzhiyun 			 * 'AV/C General Specification' define no time limit
264*4882a593Smuzhiyun 			 * on command completion once an INTERIM response has
265*4882a593Smuzhiyun 			 * been sent. but we promise to finish this function
266*4882a593Smuzhiyun 			 * for a caller. Here we use FCP_TIMEOUT_MS for next
267*4882a593Smuzhiyun 			 * interval. This is not in the specification.
268*4882a593Smuzhiyun 			 */
269*4882a593Smuzhiyun 			t.state = STATE_PENDING;
270*4882a593Smuzhiyun 			goto deferred;
271*4882a593Smuzhiyun 		} else if (t.state == STATE_COMPLETE) {
272*4882a593Smuzhiyun 			ret = t.response_size;
273*4882a593Smuzhiyun 			break;
274*4882a593Smuzhiyun 		} else if (t.state == STATE_BUS_RESET) {
275*4882a593Smuzhiyun 			msleep(ERROR_DELAY_MS);
276*4882a593Smuzhiyun 		} else if (++tries >= ERROR_RETRIES) {
277*4882a593Smuzhiyun 			dev_err(&t.unit->device, "FCP command timed out\n");
278*4882a593Smuzhiyun 			ret = -EIO;
279*4882a593Smuzhiyun 			break;
280*4882a593Smuzhiyun 		}
281*4882a593Smuzhiyun 	}
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	spin_lock_irq(&transactions_lock);
284*4882a593Smuzhiyun 	list_del(&t.list);
285*4882a593Smuzhiyun 	spin_unlock_irq(&transactions_lock);
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	return ret;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun EXPORT_SYMBOL(fcp_avc_transaction);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun /**
292*4882a593Smuzhiyun  * fcp_bus_reset - inform the target handler about a bus reset
293*4882a593Smuzhiyun  * @unit: the unit that might be used by fcp_avc_transaction()
294*4882a593Smuzhiyun  *
295*4882a593Smuzhiyun  * This function must be called from the driver's .update handler to inform
296*4882a593Smuzhiyun  * the FCP transaction handler that a bus reset has happened.  Any pending FCP
297*4882a593Smuzhiyun  * transactions are retried.
298*4882a593Smuzhiyun  */
fcp_bus_reset(struct fw_unit * unit)299*4882a593Smuzhiyun void fcp_bus_reset(struct fw_unit *unit)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun 	struct fcp_transaction *t;
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	spin_lock_irq(&transactions_lock);
304*4882a593Smuzhiyun 	list_for_each_entry(t, &transactions, list) {
305*4882a593Smuzhiyun 		if (t->unit == unit &&
306*4882a593Smuzhiyun 		    (t->state == STATE_PENDING ||
307*4882a593Smuzhiyun 		     t->state == STATE_DEFERRED)) {
308*4882a593Smuzhiyun 			t->state = STATE_BUS_RESET;
309*4882a593Smuzhiyun 			wake_up(&t->wait);
310*4882a593Smuzhiyun 		}
311*4882a593Smuzhiyun 	}
312*4882a593Smuzhiyun 	spin_unlock_irq(&transactions_lock);
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun EXPORT_SYMBOL(fcp_bus_reset);
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun /* checks whether the response matches the masked bytes in response_buffer */
is_matching_response(struct fcp_transaction * transaction,const void * response,size_t length)317*4882a593Smuzhiyun static bool is_matching_response(struct fcp_transaction *transaction,
318*4882a593Smuzhiyun 				 const void *response, size_t length)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	const u8 *p1, *p2;
321*4882a593Smuzhiyun 	unsigned int mask, i;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	p1 = response;
324*4882a593Smuzhiyun 	p2 = transaction->response_buffer;
325*4882a593Smuzhiyun 	mask = transaction->response_match_bytes;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	for (i = 0; ; ++i) {
328*4882a593Smuzhiyun 		if ((mask & 1) && p1[i] != p2[i])
329*4882a593Smuzhiyun 			return false;
330*4882a593Smuzhiyun 		mask >>= 1;
331*4882a593Smuzhiyun 		if (!mask)
332*4882a593Smuzhiyun 			return true;
333*4882a593Smuzhiyun 		if (--length == 0)
334*4882a593Smuzhiyun 			return false;
335*4882a593Smuzhiyun 	}
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun 
fcp_response(struct fw_card * card,struct fw_request * request,int tcode,int destination,int source,int generation,unsigned long long offset,void * data,size_t length,void * callback_data)338*4882a593Smuzhiyun static void fcp_response(struct fw_card *card, struct fw_request *request,
339*4882a593Smuzhiyun 			 int tcode, int destination, int source,
340*4882a593Smuzhiyun 			 int generation, unsigned long long offset,
341*4882a593Smuzhiyun 			 void *data, size_t length, void *callback_data)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun 	struct fcp_transaction *t;
344*4882a593Smuzhiyun 	unsigned long flags;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	if (length < 1 || (*(const u8 *)data & 0xf0) != CTS_AVC)
347*4882a593Smuzhiyun 		return;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	spin_lock_irqsave(&transactions_lock, flags);
350*4882a593Smuzhiyun 	list_for_each_entry(t, &transactions, list) {
351*4882a593Smuzhiyun 		struct fw_device *device = fw_parent_device(t->unit);
352*4882a593Smuzhiyun 		if (device->card != card ||
353*4882a593Smuzhiyun 		    device->generation != generation)
354*4882a593Smuzhiyun 			continue;
355*4882a593Smuzhiyun 		smp_rmb(); /* node_id vs. generation */
356*4882a593Smuzhiyun 		if (device->node_id != source)
357*4882a593Smuzhiyun 			continue;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 		if (t->state == STATE_PENDING &&
360*4882a593Smuzhiyun 		    is_matching_response(t, data, length)) {
361*4882a593Smuzhiyun 			if (t->deferrable && *(const u8 *)data == 0x0f) {
362*4882a593Smuzhiyun 				t->state = STATE_DEFERRED;
363*4882a593Smuzhiyun 			} else {
364*4882a593Smuzhiyun 				t->state = STATE_COMPLETE;
365*4882a593Smuzhiyun 				t->response_size = min_t(unsigned int, length,
366*4882a593Smuzhiyun 							 t->response_size);
367*4882a593Smuzhiyun 				memcpy(t->response_buffer, data,
368*4882a593Smuzhiyun 				       t->response_size);
369*4882a593Smuzhiyun 			}
370*4882a593Smuzhiyun 			wake_up(&t->wait);
371*4882a593Smuzhiyun 		}
372*4882a593Smuzhiyun 	}
373*4882a593Smuzhiyun 	spin_unlock_irqrestore(&transactions_lock, flags);
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun static struct fw_address_handler response_register_handler = {
377*4882a593Smuzhiyun 	.length = 0x200,
378*4882a593Smuzhiyun 	.address_callback = fcp_response,
379*4882a593Smuzhiyun };
380*4882a593Smuzhiyun 
fcp_module_init(void)381*4882a593Smuzhiyun static int __init fcp_module_init(void)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun 	static const struct fw_address_region response_register_region = {
384*4882a593Smuzhiyun 		.start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE,
385*4882a593Smuzhiyun 		.end = CSR_REGISTER_BASE + CSR_FCP_END,
386*4882a593Smuzhiyun 	};
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	fw_core_add_address_handler(&response_register_handler,
389*4882a593Smuzhiyun 				    &response_register_region);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	return 0;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun 
fcp_module_exit(void)394*4882a593Smuzhiyun static void __exit fcp_module_exit(void)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun 	WARN_ON(!list_empty(&transactions));
397*4882a593Smuzhiyun 	fw_core_remove_address_handler(&response_register_handler);
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun module_init(fcp_module_init);
401*4882a593Smuzhiyun module_exit(fcp_module_exit);
402