Commit bea11f0a authored by Takashi Iwai's avatar Takashi Iwai
Browse files

Merge branch 'topic/firewire' into for-next



Pull FireWire fixes

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parents 81c254a6 39859be8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ properties:
  compatible:
    enum:
      - mediatek,mt8186-mt6366-rt1019-rt5682s-sound
      - mediatek,mt8186-mt6366-rt5682s-max98360-sound

  mediatek,platform:
    $ref: "/schemas/types.yaml#/definitions/phandle"
+3 −1
Original line number Diff line number Diff line
@@ -30,7 +30,9 @@ properties:
    const: 0

  clocks:
    maxItems: 5
    oneOf:
      - maxItems: 3
      - maxItems: 5

  clock-names:
    oneOf:
+47 −11
Original line number Diff line number Diff line
@@ -9,9 +9,6 @@ title: LPASS(Low Power Audio Subsystem) VA Macro audio codec
maintainers:
  - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>

allOf:
  - $ref: dai-common.yaml#

properties:
  compatible:
    enum:
@@ -30,15 +27,12 @@ properties:
    const: 0

  clocks:
    maxItems: 5
    minItems: 5
    maxItems: 6

  clock-names:
    items:
      - const: mclk
      - const: npl
      - const: macro
      - const: dcodec
      - const: fsgen
    minItems: 5
    maxItems: 6

  clock-output-names:
    maxItems: 1
@@ -55,10 +49,51 @@ required:
  - reg
  - "#sound-dai-cells"

allOf:
  - $ref: dai-common.yaml#

  - if:
      properties:
        compatible:
          enum:
            - qcom,sc7280-lpass-wsa-macro
            - qcom,sm8450-lpass-wsa-macro
            - qcom,sc8280xp-lpass-wsa-macro
    then:
      properties:
        clocks:
          maxItems: 5
        clock-names:
          items:
            - const: mclk
            - const: npl
            - const: macro
            - const: dcodec
            - const: fsgen

  - if:
      properties:
        compatible:
          enum:
            - qcom,sm8250-lpass-wsa-macro
    then:
      properties:
        clocks:
          minItems: 6
        clock-names:
          items:
            - const: mclk
            - const: npl
            - const: macro
            - const: dcodec
            - const: va
            - const: fsgen

unevaluatedProperties: false

examples:
  - |
    #include <dt-bindings/clock/qcom,sm8250-lpass-aoncc.h>
    #include <dt-bindings/sound/qcom,q6afe.h>
    codec@3240000 {
      compatible = "qcom,sm8250-lpass-wsa-macro";
@@ -69,7 +104,8 @@ examples:
               <&audiocc 0>,
               <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
               <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
               <&aoncc LPASS_CDC_VA_MCLK>,
               <&vamacro>;
      clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
      clock-names = "mclk", "npl", "macro", "dcodec", "va", "fsgen";
      clock-output-names = "mclk";
    };
+18 −25
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ struct inbound_transaction_resource {
	struct client_resource resource;
	struct fw_card *card;
	struct fw_request *request;
	bool is_fcp;
	void *data;
	size_t length;
};
@@ -643,19 +644,14 @@ static int ioctl_send_request(struct client *client, union ioctl_arg *arg)
			    client->device->max_speed);
}

static inline bool is_fcp_request(struct fw_request *request)
{
	return request == NULL;
}

static void release_request(struct client *client,
			    struct client_resource *resource)
{
	struct inbound_transaction_resource *r = container_of(resource,
			struct inbound_transaction_resource, resource);

	if (is_fcp_request(r->request))
		kfree(r->data);
	if (r->is_fcp)
		fw_request_put(r->request);
	else
		fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR);

@@ -669,15 +665,20 @@ static void handle_request(struct fw_card *card, struct fw_request *request,
			   void *payload, size_t length, void *callback_data)
{
	struct address_handler_resource *handler = callback_data;
	bool is_fcp = is_in_fcp_region(offset, length);
	struct inbound_transaction_resource *r;
	struct inbound_transaction_event *e;
	size_t event_size0;
	void *fcp_frame = NULL;
	int ret;

	/* card may be different from handler->client->device->card */
	fw_card_get(card);

	// Extend the lifetime of data for request so that its payload is safely accessible in
	// the process context for the client.
	if (is_fcp)
		fw_request_get(request);

	r = kmalloc(sizeof(*r), GFP_ATOMIC);
	e = kmalloc(sizeof(*e), GFP_ATOMIC);
	if (r == NULL || e == NULL)
@@ -685,21 +686,10 @@ static void handle_request(struct fw_card *card, struct fw_request *request,

	r->card    = card;
	r->request = request;
	r->is_fcp  = is_fcp;
	r->data    = payload;
	r->length  = length;

	if (is_fcp_request(request)) {
		/*
		 * FIXME: Let core-transaction.c manage a
		 * single reference-counted copy?
		 */
		fcp_frame = kmemdup(payload, length, GFP_ATOMIC);
		if (fcp_frame == NULL)
			goto failed;

		r->data = fcp_frame;
	}

	r->resource.release = release_request;
	ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC);
	if (ret < 0)
@@ -741,10 +731,11 @@ static void handle_request(struct fw_card *card, struct fw_request *request,
 failed:
	kfree(r);
	kfree(e);
	kfree(fcp_frame);

	if (!is_fcp_request(request))
	if (!is_fcp)
		fw_send_response(card, request, RCODE_CONFLICT_ERROR);
	else
		fw_request_put(request);

	fw_card_put(card);
}
@@ -819,17 +810,19 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg)

	r = container_of(resource, struct inbound_transaction_resource,
			 resource);
	if (is_fcp_request(r->request))
	if (r->is_fcp) {
		fw_request_put(r->request);
		goto out;
	}

	if (a->length != fw_get_response_length(r->request)) {
		ret = -EINVAL;
		kfree(r->request);
		fw_request_put(r->request);
		goto out;
	}
	if (copy_from_user(r->data, u64_to_uptr(a->data), a->length)) {
		ret = -EFAULT;
		kfree(r->request);
		fw_request_put(r->request);
		goto out;
	}
	fw_send_response(r->card, r->request, a->rcode);
+39 −14
Original line number Diff line number Diff line
@@ -535,12 +535,6 @@ const struct fw_address_region fw_unit_space_region =
	{ .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, };
#endif  /*  0  */

static bool is_in_fcp_region(u64 offset, size_t length)
{
	return offset >= (CSR_REGISTER_BASE | CSR_FCP_COMMAND) &&
		offset + length <= (CSR_REGISTER_BASE | CSR_FCP_END);
}

/**
 * fw_core_add_address_handler() - register for incoming requests
 * @handler:	callback
@@ -617,6 +611,7 @@ void fw_core_remove_address_handler(struct fw_address_handler *handler)
EXPORT_SYMBOL(fw_core_remove_address_handler);

struct fw_request {
	struct kref kref;
	struct fw_packet response;
	u32 request_header[4];
	int ack;
@@ -625,13 +620,33 @@ struct fw_request {
	u32 data[];
};

void fw_request_get(struct fw_request *request)
{
	kref_get(&request->kref);
}

static void release_request(struct kref *kref)
{
	struct fw_request *request = container_of(kref, struct fw_request, kref);

	kfree(request);
}

void fw_request_put(struct fw_request *request)
{
	kref_put(&request->kref, release_request);
}

static void free_response_callback(struct fw_packet *packet,
				   struct fw_card *card, int status)
{
	struct fw_request *request;
	struct fw_request *request = container_of(packet, struct fw_request, response);

	request = container_of(packet, struct fw_request, response);
	kfree(request);
	// Decrease the reference count since not at in-flight.
	fw_request_put(request);

	// Decrease the reference count to release the object.
	fw_request_put(request);
}

int fw_get_response_length(struct fw_request *r)
@@ -782,6 +797,7 @@ static struct fw_request *allocate_request(struct fw_card *card,
	request = kmalloc(sizeof(*request) + length, GFP_ATOMIC);
	if (request == NULL)
		return NULL;
	kref_init(&request->kref);

	request->response.speed = p->speed;
	request->response.timestamp =
@@ -800,16 +816,22 @@ static struct fw_request *allocate_request(struct fw_card *card,
	return request;
}

/**
 * fw_send_response: - send response packet for asynchronous transaction.
 * @card:	interface to send the response at.
 * @request:	firewire request data for the transaction.
 * @rcode:	response code to send.
 *
 * Submit a response packet into the asynchronous response transmission queue. The @request
 * is going to be released when the transmission successfully finishes later.
 */
void fw_send_response(struct fw_card *card,
		      struct fw_request *request, int rcode)
{
	if (WARN_ONCE(!request, "invalid for FCP address handlers"))
		return;

	/* unified transaction or broadcast transaction: don't respond */
	if (request->ack != ACK_PENDING ||
	    HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) {
		kfree(request);
		fw_request_put(request);
		return;
	}

@@ -821,6 +843,9 @@ void fw_send_response(struct fw_card *card,
		fw_fill_response(&request->response, request->request_header,
				 rcode, NULL, 0);

	// Increase the reference count so that the object is kept during in-flight.
	fw_request_get(request);

	card->driver->send_response(card, &request->response);
}
EXPORT_SYMBOL(fw_send_response);
@@ -910,7 +935,7 @@ static void handle_fcp_region_request(struct fw_card *card,
	rcu_read_lock();
	list_for_each_entry_rcu(handler, &address_handler_list, link) {
		if (is_enclosing_handler(handler, offset, request->length))
			handler->address_callback(card, NULL, tcode,
			handler->address_callback(card, request, tcode,
						  destination, source,
						  p->generation, offset,
						  request->data,
Loading