Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 2 additions & 94 deletions drivers/soc/apple/mailbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include <linux/bits.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/hrtimer.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/iopoll.h>
Expand Down Expand Up @@ -211,15 +210,6 @@ static_assert(APPLE_ASCWRAP_V6_MBOX_OFFSET + APPLE_ASC_MBOX_I2A_RECV0 ==
#define APPLE_MBOX_TX_RECHECK_MS 2
#define APPLE_G17_MBOX_RX_BUDGET 64
#define APPLE_G17_MBOX_ATOMIC_TX_US 1000
/*
* T6050 poll-only receive: every send arms an hrtimer that polls the receive
* FIFO at this period, kept for this long after the last message or send. A
* GPU reply lands within one 0.22 ms frame; polling every 25 us bounds the
* added receive latency to ~11% of a frame instead of one 4 ms jiffy, while
* idle receive stays on the jiffy poller.
*/
#define APPLE_MBOX_RX_FAST_POLL_US 25
#define APPLE_MBOX_RX_FAST_GRACE_US 1000

/* One firmware role of an ASCWrap v6 provider, at its fixed CPU-physical windows. */
struct apple_mbox_ascwrap_v6_role_desc {
Expand All @@ -236,8 +226,6 @@ struct apple_mbox_hw {
unsigned int num_ascwrap_v6_roles;
/* T8152 GPU ASCWrap v8: wrapper + iop-vbar + post-office window + PSD. */
bool is_ascwrap_v8;
/* The mailbox interrupt never reaches the AIC: receive by polling. */
bool rx_poll_only;
/* Status word counts RX occupancy and free TX slots; paired transfers. */
bool counted_fifo;
bool ap_initializes_mailboxes;
Expand Down Expand Up @@ -280,9 +268,6 @@ struct apple_mbox_priv {
/* rx_lock: an unpowered-PSD receive skip was logged this activation. */
bool rx_psd_skip_logged;
struct delayed_work rx_poll_work;
/* Kick and fast tick write this lock-free; reads use READ_ONCE. */
ktime_t rx_fast_until;
struct hrtimer rx_fast_timer;
};

static struct apple_mbox_priv *apple_mbox_to_priv(struct apple_mbox *mbox)
Expand All @@ -293,7 +278,7 @@ static struct apple_mbox_priv *apple_mbox_to_priv(struct apple_mbox *mbox)
/* Only providers allocated by apple_mbox_probe() have a receive poller. */
static bool apple_mbox_has_rx_poller(const struct apple_mbox *mbox)
{
return mbox->hw->is_ascwrap_v8 || mbox->hw->rx_poll_only;
return mbox->hw->is_ascwrap_v8;
}

/* Both ASCWrap generations share the consumer lifecycle API below. */
Expand Down Expand Up @@ -663,65 +648,6 @@ static struct apple_mbox_msg apple_mbox_read_msg(struct apple_mbox *mbox)
return msg;
}

static int apple_mbox_poll_locked(struct apple_mbox *mbox);

/*
* Fast receive tick for rx_poll_only mailboxes (T6050): the same receive
* step apple_mbox_v8_rx_poll_work() runs, under the same rx_lock, with
* apple_mbox_poll_locked() doing the same PSD and removal checks. The v8
* storm guard does not apply: it guards the recv-not-empty IRQ line, which
* rx_poll_only hardware never enables. Runs in hardirq context.
*/
static enum hrtimer_restart apple_mbox_fast_rx_poll(struct hrtimer *timer)
{
struct apple_mbox_priv *priv = container_of(timer, struct apple_mbox_priv,
rx_fast_timer);
struct apple_mbox *mbox = &priv->mbox;
unsigned long flags;
ktime_t now;
int consumed = 0;

if (!READ_ONCE(mbox->active) || READ_ONCE(mbox->removing))
return HRTIMER_NORESTART;

spin_lock_irqsave(&mbox->rx_lock, flags);
if (likely(!READ_ONCE(mbox->removing)))
consumed = apple_mbox_poll_locked(mbox);
spin_unlock_irqrestore(&mbox->rx_lock, flags);

now = ktime_get();
if (consumed > 0) {
/* Traffic arrived: keep polling as if a send just happened. */
WRITE_ONCE(priv->rx_fast_until,
ktime_add_us(now, APPLE_MBOX_RX_FAST_GRACE_US));
} else if (!ktime_before(now, READ_ONCE(priv->rx_fast_until))) {
return HRTIMER_NORESTART;
}

hrtimer_forward_now(timer, us_to_ktime(APPLE_MBOX_RX_FAST_POLL_US));
return HRTIMER_RESTART;
}

/*
* tx_lock held. Lock-free on purpose: apple_mbox_poll_locked() invokes the
* rx callback with rx_lock held, and a callback that sends would then take
* tx_lock under rx_lock. Kick never touches rx_lock, so no ordering exists
* to invert. A kick that loses a race with the timer's final no-restart
* decision leaves the fast poller disarmed once; the next jiffy poll or
* send recovers it.
*/
static void apple_mbox_fast_rx_kick(struct apple_mbox_priv *priv)
{
WRITE_ONCE(priv->rx_fast_until,
ktime_add_us(ktime_get(), APPLE_MBOX_RX_FAST_GRACE_US));
/* Publish the deadline before deciding to arm. */
smp_mb();
if (!hrtimer_active(&priv->rx_fast_timer))
hrtimer_start(&priv->rx_fast_timer,
us_to_ktime(APPLE_MBOX_RX_FAST_POLL_US),
HRTIMER_MODE_REL);
}

int apple_mbox_send(struct apple_mbox *mbox, const struct apple_mbox_msg msg,
bool atomic)
{
Expand Down Expand Up @@ -845,10 +771,6 @@ int apple_mbox_send(struct apple_mbox *mbox, const struct apple_mbox_msg msg,

apple_mbox_write_msg(mbox, msg);

/* The reply may be back well within a jiffy: fast-poll for it. */
if (mbox->hw->rx_poll_only)
apple_mbox_fast_rx_kick(apple_mbox_to_priv(mbox));

spin_unlock_irqrestore(&mbox->tx_lock, flags);

return 0;
Expand Down Expand Up @@ -1137,9 +1059,6 @@ static void apple_mbox_v8_rx_stop(struct apple_mbox *mbox)

if (live)
disable_irq(mbox->irq_recv_not_empty);
/* Same cancel-and-drain guarantee for the fast poller as below. */
if (mbox->hw->rx_poll_only)
hrtimer_cancel(&priv->rx_fast_timer);
cancel_delayed_work_sync(&priv->rx_poll_work);
}

Expand Down Expand Up @@ -1326,11 +1245,8 @@ static void apple_mbox_quiesce(void *data)
pm_runtime_put_autosuspend(mbox->dev);
}
/* The v8 poller also stops on the removal fence; make sure it is gone. */
if (apple_mbox_has_rx_poller(mbox)) {
if (mbox->hw->rx_poll_only)
hrtimer_cancel(&apple_mbox_to_priv(mbox)->rx_fast_timer);
if (apple_mbox_has_rx_poller(mbox))
cancel_delayed_work_sync(&apple_mbox_to_priv(mbox)->rx_poll_work);
}

/* Serialize once-only masking with the IRQ and send-error paths. */
spin_lock_irqsave(&mbox->tx_lock, flags);
Expand Down Expand Up @@ -1546,12 +1462,6 @@ static int apple_mbox_probe(struct platform_device *pdev)
return -EINVAL;
if (mbox->hw->counted_fifo && !IS_ENABLED(CONFIG_ARM64))
return -EOPNOTSUPP;
if (mbox->hw->rx_poll_only) {
priv->rx_poll_only = true;
hrtimer_setup(&priv->rx_fast_timer, apple_mbox_fast_rx_poll,
CLOCK_MONOTONIC, HRTIMER_MODE_REL);
INIT_DELAYED_WORK(&priv->rx_poll_work, apple_mbox_v8_rx_poll_work);
}

if (mbox->hw->is_ascwrap_v6) {
/*
Expand Down Expand Up @@ -1942,7 +1852,6 @@ static const struct apple_mbox_hw apple_mbox_t6050_ascwrap_v6_hw = {
.i2a_recv0 = APPLE_ASC_MBOX_I2A_RECV0,
.i2a_recv1 = APPLE_ASC_MBOX_I2A_RECV1,
.has_irq_controls = false,
.rx_poll_only = true,
};

static const struct apple_mbox_hw apple_mbox_t6050_j775d_ascwrap_v6_hw = {
Expand All @@ -1959,7 +1868,6 @@ static const struct apple_mbox_hw apple_mbox_t6050_j775d_ascwrap_v6_hw = {
.i2a_recv0 = APPLE_ASC_MBOX_I2A_RECV0,
.i2a_recv1 = APPLE_ASC_MBOX_I2A_RECV1,
.has_irq_controls = false,
.rx_poll_only = true,
};

/*
Expand Down
Loading