xref: /linux/sound/firewire/fcp.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*da607e19SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
231ef9134SClemens Ladisch /*
331ef9134SClemens Ladisch  * Function Control Protocol (IEC 61883-1) helper functions
431ef9134SClemens Ladisch  *
531ef9134SClemens Ladisch  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
631ef9134SClemens Ladisch  */
731ef9134SClemens Ladisch 
831ef9134SClemens Ladisch #include <linux/device.h>
931ef9134SClemens Ladisch #include <linux/firewire.h>
1031ef9134SClemens Ladisch #include <linux/firewire-constants.h>
1131ef9134SClemens Ladisch #include <linux/list.h>
1231ef9134SClemens Ladisch #include <linux/module.h>
131017abedSTakashi Sakamoto #include <linux/slab.h>
1431ef9134SClemens Ladisch #include <linux/sched.h>
1531ef9134SClemens Ladisch #include <linux/spinlock.h>
1631ef9134SClemens Ladisch #include <linux/wait.h>
175de0ee57SStephen Rothwell #include <linux/delay.h>
1831ef9134SClemens Ladisch #include "fcp.h"
1931ef9134SClemens Ladisch #include "lib.h"
20d67c46b9STakashi Sakamoto #include "amdtp-stream.h"
2131ef9134SClemens Ladisch 
2231ef9134SClemens Ladisch #define CTS_AVC 0x00
2331ef9134SClemens Ladisch 
2431ef9134SClemens Ladisch #define ERROR_RETRIES	3
2531ef9134SClemens Ladisch #define ERROR_DELAY_MS	5
2631ef9134SClemens Ladisch #define FCP_TIMEOUT_MS	125
2731ef9134SClemens Ladisch 
281017abedSTakashi Sakamoto int avc_general_set_sig_fmt(struct fw_unit *unit, unsigned int rate,
291017abedSTakashi Sakamoto 			    enum avc_general_plug_dir dir,
301017abedSTakashi Sakamoto 			    unsigned short pid)
311017abedSTakashi Sakamoto {
321017abedSTakashi Sakamoto 	unsigned int sfc;
331017abedSTakashi Sakamoto 	u8 *buf;
341017abedSTakashi Sakamoto 	bool flag;
351017abedSTakashi Sakamoto 	int err;
361017abedSTakashi Sakamoto 
371017abedSTakashi Sakamoto 	flag = false;
381017abedSTakashi Sakamoto 	for (sfc = 0; sfc < CIP_SFC_COUNT; sfc++) {
391017abedSTakashi Sakamoto 		if (amdtp_rate_table[sfc] == rate) {
401017abedSTakashi Sakamoto 			flag = true;
411017abedSTakashi Sakamoto 			break;
421017abedSTakashi Sakamoto 		}
431017abedSTakashi Sakamoto 	}
441017abedSTakashi Sakamoto 	if (!flag)
451017abedSTakashi Sakamoto 		return -EINVAL;
461017abedSTakashi Sakamoto 
471017abedSTakashi Sakamoto 	buf = kzalloc(8, GFP_KERNEL);
481017abedSTakashi Sakamoto 	if (buf == NULL)
491017abedSTakashi Sakamoto 		return -ENOMEM;
501017abedSTakashi Sakamoto 
511017abedSTakashi Sakamoto 	buf[0] = 0x00;		/* AV/C CONTROL */
521017abedSTakashi Sakamoto 	buf[1] = 0xff;		/* UNIT */
531017abedSTakashi Sakamoto 	if (dir == AVC_GENERAL_PLUG_DIR_IN)
541017abedSTakashi Sakamoto 		buf[2] = 0x19;	/* INPUT PLUG SIGNAL FORMAT */
551017abedSTakashi Sakamoto 	else
561017abedSTakashi Sakamoto 		buf[2] = 0x18;	/* OUTPUT PLUG SIGNAL FORMAT */
571017abedSTakashi Sakamoto 	buf[3] = 0xff & pid;	/* plug id */
581017abedSTakashi Sakamoto 	buf[4] = 0x90;		/* EOH_1, Form_1, FMT. AM824 */
591017abedSTakashi Sakamoto 	buf[5] = 0x07 & sfc;	/* FDF-hi. AM824, frequency */
601017abedSTakashi Sakamoto 	buf[6] = 0xff;		/* FDF-mid. AM824, SYT hi (not used)*/
611017abedSTakashi Sakamoto 	buf[7] = 0xff;		/* FDF-low. AM824, SYT lo (not used) */
621017abedSTakashi Sakamoto 
631017abedSTakashi Sakamoto 	/* do transaction and check buf[1-5] are the same against command */
641017abedSTakashi Sakamoto 	err = fcp_avc_transaction(unit, buf, 8, buf, 8,
651017abedSTakashi Sakamoto 				  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5));
667e1621deSTakashi Sakamoto 	if (err < 0)
677e1621deSTakashi Sakamoto 		;
687e1621deSTakashi Sakamoto 	else if (err < 8)
691017abedSTakashi Sakamoto 		err = -EIO;
701017abedSTakashi Sakamoto 	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
711017abedSTakashi Sakamoto 		err = -ENOSYS;
721017abedSTakashi Sakamoto 	else if (buf[0] == 0x0a) /* REJECTED */
731017abedSTakashi Sakamoto 		err = -EINVAL;
741017abedSTakashi Sakamoto 	if (err < 0)
751017abedSTakashi Sakamoto 		goto end;
761017abedSTakashi Sakamoto 
771017abedSTakashi Sakamoto 	err = 0;
781017abedSTakashi Sakamoto end:
791017abedSTakashi Sakamoto 	kfree(buf);
801017abedSTakashi Sakamoto 	return err;
811017abedSTakashi Sakamoto }
821017abedSTakashi Sakamoto EXPORT_SYMBOL(avc_general_set_sig_fmt);
831017abedSTakashi Sakamoto 
841017abedSTakashi Sakamoto int avc_general_get_sig_fmt(struct fw_unit *unit, unsigned int *rate,
851017abedSTakashi Sakamoto 			    enum avc_general_plug_dir dir,
861017abedSTakashi Sakamoto 			    unsigned short pid)
871017abedSTakashi Sakamoto {
881017abedSTakashi Sakamoto 	unsigned int sfc;
891017abedSTakashi Sakamoto 	u8 *buf;
901017abedSTakashi Sakamoto 	int err;
911017abedSTakashi Sakamoto 
921017abedSTakashi Sakamoto 	buf = kzalloc(8, GFP_KERNEL);
931017abedSTakashi Sakamoto 	if (buf == NULL)
941017abedSTakashi Sakamoto 		return -ENOMEM;
951017abedSTakashi Sakamoto 
961017abedSTakashi Sakamoto 	buf[0] = 0x01;		/* AV/C STATUS */
971017abedSTakashi Sakamoto 	buf[1] = 0xff;		/* Unit */
981017abedSTakashi Sakamoto 	if (dir == AVC_GENERAL_PLUG_DIR_IN)
991017abedSTakashi Sakamoto 		buf[2] = 0x19;	/* INPUT PLUG SIGNAL FORMAT */
1001017abedSTakashi Sakamoto 	else
1011017abedSTakashi Sakamoto 		buf[2] = 0x18;	/* OUTPUT PLUG SIGNAL FORMAT */
1021017abedSTakashi Sakamoto 	buf[3] = 0xff & pid;	/* plug id */
1031017abedSTakashi Sakamoto 	buf[4] = 0x90;		/* EOH_1, Form_1, FMT. AM824 */
1041017abedSTakashi Sakamoto 	buf[5] = 0xff;		/* FDF-hi. AM824, frequency */
1051017abedSTakashi Sakamoto 	buf[6] = 0xff;		/* FDF-mid. AM824, SYT hi (not used) */
1061017abedSTakashi Sakamoto 	buf[7] = 0xff;		/* FDF-low. AM824, SYT lo (not used) */
1071017abedSTakashi Sakamoto 
1081017abedSTakashi Sakamoto 	/* do transaction and check buf[1-4] are the same against command */
1091017abedSTakashi Sakamoto 	err = fcp_avc_transaction(unit, buf, 8, buf, 8,
1101017abedSTakashi Sakamoto 				  BIT(1) | BIT(2) | BIT(3) | BIT(4));
1117e1621deSTakashi Sakamoto 	if (err < 0)
1127e1621deSTakashi Sakamoto 		;
1137e1621deSTakashi Sakamoto 	else if (err < 8)
1141017abedSTakashi Sakamoto 		err = -EIO;
1151017abedSTakashi Sakamoto 	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
1161017abedSTakashi Sakamoto 		err = -ENOSYS;
1171017abedSTakashi Sakamoto 	else if (buf[0] == 0x0a) /* REJECTED */
1181017abedSTakashi Sakamoto 		err = -EINVAL;
1191017abedSTakashi Sakamoto 	else if (buf[0] == 0x0b) /* IN TRANSITION */
1201017abedSTakashi Sakamoto 		err = -EAGAIN;
1211017abedSTakashi Sakamoto 	if (err < 0)
1221017abedSTakashi Sakamoto 		goto end;
1231017abedSTakashi Sakamoto 
1241017abedSTakashi Sakamoto 	/* check sfc field and pick up rate */
1251017abedSTakashi Sakamoto 	sfc = 0x07 & buf[5];
1261017abedSTakashi Sakamoto 	if (sfc >= CIP_SFC_COUNT) {
1271017abedSTakashi Sakamoto 		err = -EAGAIN;	/* also in transition */
1281017abedSTakashi Sakamoto 		goto end;
1291017abedSTakashi Sakamoto 	}
1301017abedSTakashi Sakamoto 
1311017abedSTakashi Sakamoto 	*rate = amdtp_rate_table[sfc];
1321017abedSTakashi Sakamoto 	err = 0;
1331017abedSTakashi Sakamoto end:
1341017abedSTakashi Sakamoto 	kfree(buf);
1351017abedSTakashi Sakamoto 	return err;
1361017abedSTakashi Sakamoto }
1371017abedSTakashi Sakamoto EXPORT_SYMBOL(avc_general_get_sig_fmt);
1381017abedSTakashi Sakamoto 
1391017abedSTakashi Sakamoto int avc_general_get_plug_info(struct fw_unit *unit, unsigned int subunit_type,
1401017abedSTakashi Sakamoto 			      unsigned int subunit_id, unsigned int subfunction,
1411017abedSTakashi Sakamoto 			      u8 info[AVC_PLUG_INFO_BUF_BYTES])
1421017abedSTakashi Sakamoto {
1431017abedSTakashi Sakamoto 	u8 *buf;
1441017abedSTakashi Sakamoto 	int err;
1451017abedSTakashi Sakamoto 
1461017abedSTakashi Sakamoto 	/* extended subunit in spec.4.2 is not supported */
1471017abedSTakashi Sakamoto 	if ((subunit_type == 0x1E) || (subunit_id == 5))
1481017abedSTakashi Sakamoto 		return -EINVAL;
1491017abedSTakashi Sakamoto 
1501017abedSTakashi Sakamoto 	buf = kzalloc(8, GFP_KERNEL);
1511017abedSTakashi Sakamoto 	if (buf == NULL)
1521017abedSTakashi Sakamoto 		return -ENOMEM;
1531017abedSTakashi Sakamoto 
1541017abedSTakashi Sakamoto 	buf[0] = 0x01;	/* AV/C STATUS */
1551017abedSTakashi Sakamoto 	/* UNIT or Subunit, Functionblock */
1561017abedSTakashi Sakamoto 	buf[1] = ((subunit_type & 0x1f) << 3) | (subunit_id & 0x7);
1571017abedSTakashi Sakamoto 	buf[2] = 0x02;	/* PLUG INFO */
1581017abedSTakashi Sakamoto 	buf[3] = 0xff & subfunction;
1591017abedSTakashi Sakamoto 
1601017abedSTakashi Sakamoto 	err = fcp_avc_transaction(unit, buf, 8, buf, 8, BIT(1) | BIT(2));
1617e1621deSTakashi Sakamoto 	if (err < 0)
1627e1621deSTakashi Sakamoto 		;
1637e1621deSTakashi Sakamoto 	else if (err < 8)
1641017abedSTakashi Sakamoto 		err = -EIO;
1651017abedSTakashi Sakamoto 	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
1661017abedSTakashi Sakamoto 		err = -ENOSYS;
1671017abedSTakashi Sakamoto 	else if (buf[0] == 0x0a) /* REJECTED */
1681017abedSTakashi Sakamoto 		err = -EINVAL;
1691017abedSTakashi Sakamoto 	else if (buf[0] == 0x0b) /* IN TRANSITION */
1701017abedSTakashi Sakamoto 		err = -EAGAIN;
1711017abedSTakashi Sakamoto 	if (err < 0)
1721017abedSTakashi Sakamoto 		goto end;
1731017abedSTakashi Sakamoto 
1741017abedSTakashi Sakamoto 	info[0] = buf[4];
1751017abedSTakashi Sakamoto 	info[1] = buf[5];
1761017abedSTakashi Sakamoto 	info[2] = buf[6];
1771017abedSTakashi Sakamoto 	info[3] = buf[7];
1781017abedSTakashi Sakamoto 
1791017abedSTakashi Sakamoto 	err = 0;
1801017abedSTakashi Sakamoto end:
1811017abedSTakashi Sakamoto 	kfree(buf);
1821017abedSTakashi Sakamoto 	return err;
1831017abedSTakashi Sakamoto }
1841017abedSTakashi Sakamoto EXPORT_SYMBOL(avc_general_get_plug_info);
1851017abedSTakashi Sakamoto 
18631ef9134SClemens Ladisch static DEFINE_SPINLOCK(transactions_lock);
18731ef9134SClemens Ladisch static LIST_HEAD(transactions);
18831ef9134SClemens Ladisch 
18931ef9134SClemens Ladisch enum fcp_state {
19031ef9134SClemens Ladisch 	STATE_PENDING,
19131ef9134SClemens Ladisch 	STATE_BUS_RESET,
19231ef9134SClemens Ladisch 	STATE_COMPLETE,
19300a7bb81STakashi Sakamoto 	STATE_DEFERRED,
19431ef9134SClemens Ladisch };
19531ef9134SClemens Ladisch 
19631ef9134SClemens Ladisch struct fcp_transaction {
19731ef9134SClemens Ladisch 	struct list_head list;
19831ef9134SClemens Ladisch 	struct fw_unit *unit;
19931ef9134SClemens Ladisch 	void *response_buffer;
20031ef9134SClemens Ladisch 	unsigned int response_size;
20131ef9134SClemens Ladisch 	unsigned int response_match_bytes;
20231ef9134SClemens Ladisch 	enum fcp_state state;
20331ef9134SClemens Ladisch 	wait_queue_head_t wait;
20400a7bb81STakashi Sakamoto 	bool deferrable;
20531ef9134SClemens Ladisch };
20631ef9134SClemens Ladisch 
20731ef9134SClemens Ladisch /**
20831ef9134SClemens Ladisch  * fcp_avc_transaction - send an AV/C command and wait for its response
20931ef9134SClemens Ladisch  * @unit: a unit on the target device
21031ef9134SClemens Ladisch  * @command: a buffer containing the command frame; must be DMA-able
21131ef9134SClemens Ladisch  * @command_size: the size of @command
21231ef9134SClemens Ladisch  * @response: a buffer for the response frame
21331ef9134SClemens Ladisch  * @response_size: the maximum size of @response
21431ef9134SClemens Ladisch  * @response_match_bytes: a bitmap specifying the bytes used to detect the
21531ef9134SClemens Ladisch  *                        correct response frame
21631ef9134SClemens Ladisch  *
21731ef9134SClemens Ladisch  * This function sends a FCP command frame to the target and waits for the
21831ef9134SClemens Ladisch  * corresponding response frame to be returned.
21931ef9134SClemens Ladisch  *
22031ef9134SClemens Ladisch  * Because it is possible for multiple FCP transactions to be active at the
22131ef9134SClemens Ladisch  * same time, the correct response frame is detected by the value of certain
22231ef9134SClemens Ladisch  * bytes.  These bytes must be set in @response before calling this function,
22331ef9134SClemens Ladisch  * and the corresponding bits must be set in @response_match_bytes.
22431ef9134SClemens Ladisch  *
22531ef9134SClemens Ladisch  * @command and @response can point to the same buffer.
22631ef9134SClemens Ladisch  *
22731ef9134SClemens Ladisch  * Returns the actual size of the response frame, or a negative error code.
22831ef9134SClemens Ladisch  */
22931ef9134SClemens Ladisch int fcp_avc_transaction(struct fw_unit *unit,
23031ef9134SClemens Ladisch 			const void *command, unsigned int command_size,
23131ef9134SClemens Ladisch 			void *response, unsigned int response_size,
23231ef9134SClemens Ladisch 			unsigned int response_match_bytes)
23331ef9134SClemens Ladisch {
23431ef9134SClemens Ladisch 	struct fcp_transaction t;
23531ef9134SClemens Ladisch 	int tcode, ret, tries = 0;
23631ef9134SClemens Ladisch 
23731ef9134SClemens Ladisch 	t.unit = unit;
23831ef9134SClemens Ladisch 	t.response_buffer = response;
23931ef9134SClemens Ladisch 	t.response_size = response_size;
24031ef9134SClemens Ladisch 	t.response_match_bytes = response_match_bytes;
24131ef9134SClemens Ladisch 	t.state = STATE_PENDING;
24231ef9134SClemens Ladisch 	init_waitqueue_head(&t.wait);
24331ef9134SClemens Ladisch 
24400a7bb81STakashi Sakamoto 	if (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03)
24500a7bb81STakashi Sakamoto 		t.deferrable = true;
24600a7bb81STakashi Sakamoto 
24731ef9134SClemens Ladisch 	spin_lock_irq(&transactions_lock);
24831ef9134SClemens Ladisch 	list_add_tail(&t.list, &transactions);
24931ef9134SClemens Ladisch 	spin_unlock_irq(&transactions_lock);
25031ef9134SClemens Ladisch 
25131ef9134SClemens Ladisch 	for (;;) {
25231ef9134SClemens Ladisch 		tcode = command_size == 4 ? TCODE_WRITE_QUADLET_REQUEST
25331ef9134SClemens Ladisch 					  : TCODE_WRITE_BLOCK_REQUEST;
25431ef9134SClemens Ladisch 		ret = snd_fw_transaction(t.unit, tcode,
25531ef9134SClemens Ladisch 					 CSR_REGISTER_BASE + CSR_FCP_COMMAND,
2561b70485fSClemens Ladisch 					 (void *)command, command_size, 0);
25731ef9134SClemens Ladisch 		if (ret < 0)
25831ef9134SClemens Ladisch 			break;
25900a7bb81STakashi Sakamoto deferred:
26031ef9134SClemens Ladisch 		wait_event_timeout(t.wait, t.state != STATE_PENDING,
26131ef9134SClemens Ladisch 				   msecs_to_jiffies(FCP_TIMEOUT_MS));
26231ef9134SClemens Ladisch 
26300a7bb81STakashi Sakamoto 		if (t.state == STATE_DEFERRED) {
26400a7bb81STakashi Sakamoto 			/*
26500a7bb81STakashi Sakamoto 			 * 'AV/C General Specification' define no time limit
26600a7bb81STakashi Sakamoto 			 * on command completion once an INTERIM response has
26700a7bb81STakashi Sakamoto 			 * been sent. but we promise to finish this function
26800a7bb81STakashi Sakamoto 			 * for a caller. Here we use FCP_TIMEOUT_MS for next
26900a7bb81STakashi Sakamoto 			 * interval. This is not in the specification.
27000a7bb81STakashi Sakamoto 			 */
27100a7bb81STakashi Sakamoto 			t.state = STATE_PENDING;
27200a7bb81STakashi Sakamoto 			goto deferred;
27300a7bb81STakashi Sakamoto 		} else if (t.state == STATE_COMPLETE) {
27431ef9134SClemens Ladisch 			ret = t.response_size;
27531ef9134SClemens Ladisch 			break;
27631ef9134SClemens Ladisch 		} else if (t.state == STATE_BUS_RESET) {
27731ef9134SClemens Ladisch 			msleep(ERROR_DELAY_MS);
27831ef9134SClemens Ladisch 		} else if (++tries >= ERROR_RETRIES) {
27931ef9134SClemens Ladisch 			dev_err(&t.unit->device, "FCP command timed out\n");
28031ef9134SClemens Ladisch 			ret = -EIO;
28131ef9134SClemens Ladisch 			break;
28231ef9134SClemens Ladisch 		}
28331ef9134SClemens Ladisch 	}
28431ef9134SClemens Ladisch 
28531ef9134SClemens Ladisch 	spin_lock_irq(&transactions_lock);
28631ef9134SClemens Ladisch 	list_del(&t.list);
28731ef9134SClemens Ladisch 	spin_unlock_irq(&transactions_lock);
28831ef9134SClemens Ladisch 
28931ef9134SClemens Ladisch 	return ret;
29031ef9134SClemens Ladisch }
29131ef9134SClemens Ladisch EXPORT_SYMBOL(fcp_avc_transaction);
29231ef9134SClemens Ladisch 
29331ef9134SClemens Ladisch /**
29431ef9134SClemens Ladisch  * fcp_bus_reset - inform the target handler about a bus reset
29531ef9134SClemens Ladisch  * @unit: the unit that might be used by fcp_avc_transaction()
29631ef9134SClemens Ladisch  *
29731ef9134SClemens Ladisch  * This function must be called from the driver's .update handler to inform
29831ef9134SClemens Ladisch  * the FCP transaction handler that a bus reset has happened.  Any pending FCP
29931ef9134SClemens Ladisch  * transactions are retried.
30031ef9134SClemens Ladisch  */
30131ef9134SClemens Ladisch void fcp_bus_reset(struct fw_unit *unit)
30231ef9134SClemens Ladisch {
30331ef9134SClemens Ladisch 	struct fcp_transaction *t;
30431ef9134SClemens Ladisch 
30531ef9134SClemens Ladisch 	spin_lock_irq(&transactions_lock);
30631ef9134SClemens Ladisch 	list_for_each_entry(t, &transactions, list) {
30731ef9134SClemens Ladisch 		if (t->unit == unit &&
30800a7bb81STakashi Sakamoto 		    (t->state == STATE_PENDING ||
30900a7bb81STakashi Sakamoto 		     t->state == STATE_DEFERRED)) {
31031ef9134SClemens Ladisch 			t->state = STATE_BUS_RESET;
31131ef9134SClemens Ladisch 			wake_up(&t->wait);
31231ef9134SClemens Ladisch 		}
31331ef9134SClemens Ladisch 	}
31431ef9134SClemens Ladisch 	spin_unlock_irq(&transactions_lock);
31531ef9134SClemens Ladisch }
31631ef9134SClemens Ladisch EXPORT_SYMBOL(fcp_bus_reset);
31731ef9134SClemens Ladisch 
31831ef9134SClemens Ladisch /* checks whether the response matches the masked bytes in response_buffer */
31931ef9134SClemens Ladisch static bool is_matching_response(struct fcp_transaction *transaction,
32031ef9134SClemens Ladisch 				 const void *response, size_t length)
32131ef9134SClemens Ladisch {
32231ef9134SClemens Ladisch 	const u8 *p1, *p2;
32331ef9134SClemens Ladisch 	unsigned int mask, i;
32431ef9134SClemens Ladisch 
32531ef9134SClemens Ladisch 	p1 = response;
32631ef9134SClemens Ladisch 	p2 = transaction->response_buffer;
32731ef9134SClemens Ladisch 	mask = transaction->response_match_bytes;
32831ef9134SClemens Ladisch 
32931ef9134SClemens Ladisch 	for (i = 0; ; ++i) {
33031ef9134SClemens Ladisch 		if ((mask & 1) && p1[i] != p2[i])
33131ef9134SClemens Ladisch 			return false;
33231ef9134SClemens Ladisch 		mask >>= 1;
33331ef9134SClemens Ladisch 		if (!mask)
33431ef9134SClemens Ladisch 			return true;
33531ef9134SClemens Ladisch 		if (--length == 0)
33631ef9134SClemens Ladisch 			return false;
33731ef9134SClemens Ladisch 	}
33831ef9134SClemens Ladisch }
33931ef9134SClemens Ladisch 
34031ef9134SClemens Ladisch static void fcp_response(struct fw_card *card, struct fw_request *request,
34131ef9134SClemens Ladisch 			 int tcode, int destination, int source,
34231ef9134SClemens Ladisch 			 int generation, unsigned long long offset,
34331ef9134SClemens Ladisch 			 void *data, size_t length, void *callback_data)
34431ef9134SClemens Ladisch {
34531ef9134SClemens Ladisch 	struct fcp_transaction *t;
34631ef9134SClemens Ladisch 	unsigned long flags;
34731ef9134SClemens Ladisch 
34831ef9134SClemens Ladisch 	if (length < 1 || (*(const u8 *)data & 0xf0) != CTS_AVC)
34931ef9134SClemens Ladisch 		return;
35031ef9134SClemens Ladisch 
35131ef9134SClemens Ladisch 	spin_lock_irqsave(&transactions_lock, flags);
35231ef9134SClemens Ladisch 	list_for_each_entry(t, &transactions, list) {
35331ef9134SClemens Ladisch 		struct fw_device *device = fw_parent_device(t->unit);
35431ef9134SClemens Ladisch 		if (device->card != card ||
35531ef9134SClemens Ladisch 		    device->generation != generation)
35631ef9134SClemens Ladisch 			continue;
35731ef9134SClemens Ladisch 		smp_rmb(); /* node_id vs. generation */
35831ef9134SClemens Ladisch 		if (device->node_id != source)
35931ef9134SClemens Ladisch 			continue;
36031ef9134SClemens Ladisch 
36131ef9134SClemens Ladisch 		if (t->state == STATE_PENDING &&
36231ef9134SClemens Ladisch 		    is_matching_response(t, data, length)) {
36300a7bb81STakashi Sakamoto 			if (t->deferrable && *(const u8 *)data == 0x0f) {
36400a7bb81STakashi Sakamoto 				t->state = STATE_DEFERRED;
36500a7bb81STakashi Sakamoto 			} else {
36631ef9134SClemens Ladisch 				t->state = STATE_COMPLETE;
36700a7bb81STakashi Sakamoto 				t->response_size = min_t(unsigned int, length,
36831ef9134SClemens Ladisch 							 t->response_size);
36900a7bb81STakashi Sakamoto 				memcpy(t->response_buffer, data,
37000a7bb81STakashi Sakamoto 				       t->response_size);
37100a7bb81STakashi Sakamoto 			}
37231ef9134SClemens Ladisch 			wake_up(&t->wait);
37331ef9134SClemens Ladisch 		}
37431ef9134SClemens Ladisch 	}
37531ef9134SClemens Ladisch 	spin_unlock_irqrestore(&transactions_lock, flags);
37631ef9134SClemens Ladisch }
37731ef9134SClemens Ladisch 
37831ef9134SClemens Ladisch static struct fw_address_handler response_register_handler = {
37931ef9134SClemens Ladisch 	.length = 0x200,
38031ef9134SClemens Ladisch 	.address_callback = fcp_response,
38131ef9134SClemens Ladisch };
38231ef9134SClemens Ladisch 
38331ef9134SClemens Ladisch static int __init fcp_module_init(void)
38431ef9134SClemens Ladisch {
38531ef9134SClemens Ladisch 	static const struct fw_address_region response_register_region = {
38631ef9134SClemens Ladisch 		.start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE,
38731ef9134SClemens Ladisch 		.end = CSR_REGISTER_BASE + CSR_FCP_END,
38831ef9134SClemens Ladisch 	};
38931ef9134SClemens Ladisch 
39031ef9134SClemens Ladisch 	fw_core_add_address_handler(&response_register_handler,
39131ef9134SClemens Ladisch 				    &response_register_region);
39231ef9134SClemens Ladisch 
39331ef9134SClemens Ladisch 	return 0;
39431ef9134SClemens Ladisch }
39531ef9134SClemens Ladisch 
39631ef9134SClemens Ladisch static void __exit fcp_module_exit(void)
39731ef9134SClemens Ladisch {
39831ef9134SClemens Ladisch 	WARN_ON(!list_empty(&transactions));
39931ef9134SClemens Ladisch 	fw_core_remove_address_handler(&response_register_handler);
40031ef9134SClemens Ladisch }
40131ef9134SClemens Ladisch 
40231ef9134SClemens Ladisch module_init(fcp_module_init);
40331ef9134SClemens Ladisch module_exit(fcp_module_exit);
404