Skip to content
Closed
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
46 changes: 46 additions & 0 deletions drivers/net/wireless/apple/centauri/centauri_wifi.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ static_assert(DATA_RX_BUFFER + DATA_RX_SLOTS * 4096 <= DATA_TX_BUFFER);
static_assert(DATA_TX_BUFFER + DATA_TX_SLOTS * BUFFER_SIZE <=
CEN_ALPHA_WINDOW_SIZE);

static bool host_setup = true;
module_param(host_setup, bool, 0644);
MODULE_PARM_DESC(host_setup,
"Before a join, tell the firmware the host is awake (command 6) and apply the reference TX defaults (commands 43 and 52); 1 = on (default)");

struct centauri_wifi {
struct centauri *control;
struct cen_alpha_resources a;
Expand Down Expand Up @@ -69,6 +74,9 @@ struct centauri_wifi {
struct net_device_stats station_start;
u8 country[3];
bool country_valid;
/* Sent once per firmware boot, before the first join (host_setup). */
bool host_awake_sent;
u8 tx_defaults_applied;
u32 data_rings_open;
bool data_failed;
struct ieee80211_supported_band bands[2];
Expand Down Expand Up @@ -1084,6 +1092,43 @@ static int wifi_connect(struct wiphy *wiphy, struct net_device *netdev,
return ret;
}

/*
* Without the host power state the firmware treats the host as asleep, powers
* the PHYs down and traps. Called with wifi->lock held.
*/
static void host_setup_commands(struct centauri_wifi *wifi)
{
static const u8 awake[3] = {};
static const u8 control_profile[] = { 0x54, 1, 10, 0, 0, 8, 0, 0,
0xff, 0xff, 0xff, 0xff, 1, 1 };
struct device *dev = &wifi->control->pdev->dev;
u8 lifetime[20] = {};
int ret, i;

if (!host_setup)
return;
if (!wifi->host_awake_sent) {
ret = command(wifi, 6, awake, sizeof(awake));
dev_info(dev, "host power state awake: rc=%d status=%u\n", ret,
wifi->reply_status);
wifi->host_awake_sent = !ret;
}
if (!(wifi->tx_defaults_applied & BIT(0))) {
for (i = 0; i < 4; i++)
put_unaligned_le32(2000000, lifetime + 4 + 4 * i);
ret = command(wifi, 43, lifetime, sizeof(lifetime));
if (!ret)
wifi->tx_defaults_applied |= BIT(0);
dev_info(dev, "TX packet lifetime defaults: rc=%d\n", ret);
}
if (!(wifi->tx_defaults_applied & BIT(1))) {
ret = command(wifi, 52, control_profile, sizeof(control_profile));
if (!ret)
wifi->tx_defaults_applied |= BIT(1);
dev_info(dev, "TX control profile defaults: rc=%d\n", ret);
}
}

static void connect_worker(struct work_struct *work)
{
struct centauri_wifi *wifi =
Expand All @@ -1098,6 +1143,7 @@ static void connect_worker(struct work_struct *work)
mutex_unlock(&wifi->lock);
return;
}
host_setup_commands(wifi);
slot = wifi->command_head;
ret = command(wifi, 131072, wifi->connect_payload, wifi->connect_size);
memzero_explicit(wifi->connect_payload, sizeof(wifi->connect_payload));
Expand Down