Re: [PATCH wireless-next] wifi: rt2x00: Use flexible array for hw_mode_spec channels
From: Rosen Penev
Date: Thu Jul 23 2026 - 15:39:19 EST
On Thu, Jul 23, 2026 at 12:53 AM Stanislaw Gruszka <stf_xl@xxxxx> wrote:
>
> Hi,
>
> On Sun, Jun 28, 2026 at 08:31:56PM -0700, Rosen Penev wrote:
> > struct hw_mode_spec stores channel information that is allocated by the
> > individual rt2x00 drivers during hardware probing. The channel info
> > array has the same lifetime as the hardware mode specification, but it
> > is currently allocated separately and then freed through a separate
> > pointer.
> >
> > Make struct rt2x00_dev hold a pointer to the hardware mode
> > specification, store the channel info as a flexible array member, and
> > allocate both pieces together with kzalloc_flex().
> >
> > Assisted-by: Codex:GPT-5.5
> > Signed-off-by: Rosen Penev <rosenp@xxxxxxxxx>
> > ---
> > .../net/wireless/ralink/rt2x00/rt2400pci.c | 24 +++---
> > .../net/wireless/ralink/rt2x00/rt2500pci.c | 55 ++++++++------
> > .../net/wireless/ralink/rt2x00/rt2500usb.c | 55 ++++++++------
> > .../net/wireless/ralink/rt2x00/rt2800lib.c | 74 ++++++++++---------
> > drivers/net/wireless/ralink/rt2x00/rt2x00.h | 4 +-
> > .../net/wireless/ralink/rt2x00/rt2x00config.c | 12 +--
> > .../net/wireless/ralink/rt2x00/rt2x00dev.c | 4 +-
> > drivers/net/wireless/ralink/rt2x00/rt61pci.c | 42 ++++++-----
> > drivers/net/wireless/ralink/rt2x00/rt73usb.c | 50 +++++++------
> > 9 files changed, 177 insertions(+), 143 deletions(-)
>
> This result in extra code. I do not see benefit of avoiding
> kzalloc calls at cost of adding more lines of code.
On runtime there's extra UBSAN analysis. Reducing allocations is always good.
>
> Regards
> Stanislaw
>
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
> > index cac191304bf5..3fb74dcbee63 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt2400pci.c
> > @@ -1559,7 +1559,7 @@ static const struct rf_channel rf_vals_b[] = {
> >
> > static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > {
> > - struct hw_mode_spec *spec = &rt2x00dev->spec;
> > + struct hw_mode_spec *spec;
> > struct channel_info *info;
> > u8 *tx_power;
> > unsigned int i;
> > @@ -1580,27 +1580,25 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > /*
> > * Initialize hw_mode information.
> > */
> > - spec->supported_bands = SUPPORT_BAND_2GHZ;
> > - spec->supported_rates = SUPPORT_RATE_CCK;
> > + spec = kzalloc_flex(*spec, channels_info, ARRAY_SIZE(rf_vals_b));
> > + if (!spec)
> > + return -ENOMEM;
> >
> > spec->num_channels = ARRAY_SIZE(rf_vals_b);
> > spec->channels = rf_vals_b;
> >
> > - /*
> > - * Create channel information array
> > - */
> > - info = kzalloc_objs(*info, spec->num_channels);
> > - if (!info)
> > - return -ENOMEM;
> > -
> > - spec->channels_info = info;
> > + spec->supported_bands = SUPPORT_BAND_2GHZ;
> > + spec->supported_rates = SUPPORT_RATE_CCK;
> >
> > tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
> > for (i = 0; i < 14; i++) {
> > - info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER);
> > - info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> > + info = &spec->channels_info[i];
> > + info->max_power = TXPOWER_FROM_DEV(MAX_TXPOWER);
> > + info->default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> > }
> >
> > + rt2x00dev->spec = spec;
> > +
> > return 0;
> > }
> >
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
> > index fc35b60e422c..4c85f401c091 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt2500pci.c
> > @@ -1854,7 +1854,10 @@ static const struct rf_channel rf_vals_5222[] = {
> >
> > static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > {
> > - struct hw_mode_spec *spec = &rt2x00dev->spec;
> > + const struct rf_channel *channels;
> > + unsigned int num_channels = 0;
> > + unsigned int supported_bands;
> > + struct hw_mode_spec *spec;
> > struct channel_info *info;
> > u8 *tx_power;
> > unsigned int i;
> > @@ -1880,52 +1883,58 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > /*
> > * Initialize hw_mode information.
> > */
> > - spec->supported_bands = SUPPORT_BAND_2GHZ;
> > - spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
> > + supported_bands = SUPPORT_BAND_2GHZ;
> >
> > if (rt2x00_rf(rt2x00dev, RF2522)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
> > - spec->channels = rf_vals_bg_2522;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2522);
> > + channels = rf_vals_bg_2522;
> > } else if (rt2x00_rf(rt2x00dev, RF2523)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
> > - spec->channels = rf_vals_bg_2523;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2523);
> > + channels = rf_vals_bg_2523;
> > } else if (rt2x00_rf(rt2x00dev, RF2524)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
> > - spec->channels = rf_vals_bg_2524;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2524);
> > + channels = rf_vals_bg_2524;
> > } else if (rt2x00_rf(rt2x00dev, RF2525)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
> > - spec->channels = rf_vals_bg_2525;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2525);
> > + channels = rf_vals_bg_2525;
> > } else if (rt2x00_rf(rt2x00dev, RF2525E)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
> > - spec->channels = rf_vals_bg_2525e;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
> > + channels = rf_vals_bg_2525e;
> > } else if (rt2x00_rf(rt2x00dev, RF5222)) {
> > - spec->supported_bands |= SUPPORT_BAND_5GHZ;
> > - spec->num_channels = ARRAY_SIZE(rf_vals_5222);
> > - spec->channels = rf_vals_5222;
> > + supported_bands |= SUPPORT_BAND_5GHZ;
> > + num_channels = ARRAY_SIZE(rf_vals_5222);
> > + channels = rf_vals_5222;
> > }
> >
> > /*
> > * Create channel information array
> > */
> > - info = kzalloc_objs(*info, spec->num_channels);
> > - if (!info)
> > + spec = kzalloc_flex(*spec, channels_info, num_channels);
> > + if (!spec)
> > return -ENOMEM;
> >
> > - spec->channels_info = info;
> > + spec->num_channels = num_channels;
> > + spec->channels = channels;
> > + spec->supported_bands = supported_bands;
> > + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
> >
> > tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
> > for (i = 0; i < 14; i++) {
> > - info[i].max_power = MAX_TXPOWER;
> > - info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> > + info = &spec->channels_info[i];
> > + info->max_power = MAX_TXPOWER;
> > + info->default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> > }
> >
> > if (spec->num_channels > 14) {
> > for (i = 14; i < spec->num_channels; i++) {
> > - info[i].max_power = MAX_TXPOWER;
> > - info[i].default_power1 = DEFAULT_TXPOWER;
> > + info = &spec->channels_info[i];
> > + info->max_power = MAX_TXPOWER;
> > + info->default_power1 = DEFAULT_TXPOWER;
> > }
> > }
> >
> > + rt2x00dev->spec = spec;
> > +
> > return 0;
> > }
> >
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
> > index 58728df6666c..cbc1c1399cc6 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
> > @@ -1661,7 +1661,10 @@ static const struct rf_channel rf_vals_5222[] = {
> >
> > static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > {
> > - struct hw_mode_spec *spec = &rt2x00dev->spec;
> > + const struct rf_channel *channels;
> > + unsigned int num_channels = 0;
> > + unsigned int supported_bands;
> > + struct hw_mode_spec *spec;
> > struct channel_info *info;
> > u8 *tx_power;
> > unsigned int i;
> > @@ -1693,52 +1696,58 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > /*
> > * Initialize hw_mode information.
> > */
> > - spec->supported_bands = SUPPORT_BAND_2GHZ;
> > - spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
> > + supported_bands = SUPPORT_BAND_2GHZ;
> >
> > if (rt2x00_rf(rt2x00dev, RF2522)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522);
> > - spec->channels = rf_vals_bg_2522;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2522);
> > + channels = rf_vals_bg_2522;
> > } else if (rt2x00_rf(rt2x00dev, RF2523)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523);
> > - spec->channels = rf_vals_bg_2523;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2523);
> > + channels = rf_vals_bg_2523;
> > } else if (rt2x00_rf(rt2x00dev, RF2524)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524);
> > - spec->channels = rf_vals_bg_2524;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2524);
> > + channels = rf_vals_bg_2524;
> > } else if (rt2x00_rf(rt2x00dev, RF2525)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525);
> > - spec->channels = rf_vals_bg_2525;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2525);
> > + channels = rf_vals_bg_2525;
> > } else if (rt2x00_rf(rt2x00dev, RF2525E)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
> > - spec->channels = rf_vals_bg_2525e;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2525e);
> > + channels = rf_vals_bg_2525e;
> > } else if (rt2x00_rf(rt2x00dev, RF5222)) {
> > - spec->supported_bands |= SUPPORT_BAND_5GHZ;
> > - spec->num_channels = ARRAY_SIZE(rf_vals_5222);
> > - spec->channels = rf_vals_5222;
> > + supported_bands |= SUPPORT_BAND_5GHZ;
> > + num_channels = ARRAY_SIZE(rf_vals_5222);
> > + channels = rf_vals_5222;
> > }
> >
> > /*
> > * Create channel information array
> > */
> > - info = kzalloc_objs(*info, spec->num_channels);
> > - if (!info)
> > + spec = kzalloc_flex(*spec, channels_info, num_channels);
> > + if (!spec)
> > return -ENOMEM;
> >
> > - spec->channels_info = info;
> > + spec->num_channels = num_channels;
> > + spec->channels = channels;
> > + spec->supported_bands = supported_bands;
> > + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
> >
> > tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
> > for (i = 0; i < 14; i++) {
> > - info[i].max_power = MAX_TXPOWER;
> > - info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> > + info = &spec->channels_info[i];
> > + info->max_power = MAX_TXPOWER;
> > + info->default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> > }
> >
> > if (spec->num_channels > 14) {
> > for (i = 14; i < spec->num_channels; i++) {
> > - info[i].max_power = MAX_TXPOWER;
> > - info[i].default_power1 = DEFAULT_TXPOWER;
> > + info = &spec->channels_info[i];
> > + info->max_power = MAX_TXPOWER;
> > + info->default_power1 = DEFAULT_TXPOWER;
> > }
> > }
> >
> > + rt2x00dev->spec = spec;
> > +
> > return 0;
> > }
> >
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > index 97290899674e..7b7f6dcc9247 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
> > @@ -11778,7 +11778,9 @@ static const struct rf_channel rf_vals_7620[] = {
> >
> > static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > {
> > - struct hw_mode_spec *spec = &rt2x00dev->spec;
> > + const struct rf_channel *channels;
> > + unsigned int num_channels = 0;
> > + struct hw_mode_spec *spec;
> > struct channel_info *info;
> > s8 *default_power1;
> > s8 *default_power2;
> > @@ -11840,19 +11842,17 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > /*
> > * Initialize hw_mode information.
> > */
> > - spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
> > -
> > switch (rt2x00dev->chip.rf) {
> > case RF2720:
> > case RF2820:
> > - spec->num_channels = 14;
> > - spec->channels = rf_vals;
> > + num_channels = 14;
> > + channels = rf_vals;
> > break;
> >
> > case RF2750:
> > case RF2850:
> > - spec->num_channels = ARRAY_SIZE(rf_vals);
> > - spec->channels = rf_vals;
> > + num_channels = ARRAY_SIZE(rf_vals);
> > + channels = rf_vals;
> > break;
> >
> > case RF2020:
> > @@ -11870,44 +11870,52 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > case RF5372:
> > case RF5390:
> > case RF5392:
> > - spec->num_channels = 14;
> > + num_channels = 14;
> > if (rt2800_clk_is_20mhz(rt2x00dev))
> > - spec->channels = rf_vals_3x_xtal20;
> > + channels = rf_vals_3x_xtal20;
> > else
> > - spec->channels = rf_vals_3x;
> > + channels = rf_vals_3x;
> > break;
> >
> > case RF7620:
> > - spec->num_channels = ARRAY_SIZE(rf_vals_7620);
> > - spec->channels = rf_vals_7620;
> > + num_channels = ARRAY_SIZE(rf_vals_7620);
> > + channels = rf_vals_7620;
> > break;
> >
> > case RF3052:
> > case RF3053:
> > - spec->num_channels = ARRAY_SIZE(rf_vals_3x);
> > - spec->channels = rf_vals_3x;
> > + num_channels = ARRAY_SIZE(rf_vals_3x);
> > + channels = rf_vals_3x;
> > break;
> >
> > case RF3853:
> > - spec->num_channels = ARRAY_SIZE(rf_vals_3853);
> > - spec->channels = rf_vals_3853;
> > + num_channels = ARRAY_SIZE(rf_vals_3853);
> > + channels = rf_vals_3853;
> > break;
> >
> > case RF5592:
> > reg = rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX);
> > if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40);
> > - spec->channels = rf_vals_5592_xtal40;
> > + num_channels = ARRAY_SIZE(rf_vals_5592_xtal40);
> > + channels = rf_vals_5592_xtal40;
> > } else {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20);
> > - spec->channels = rf_vals_5592_xtal20;
> > + num_channels = ARRAY_SIZE(rf_vals_5592_xtal20);
> > + channels = rf_vals_5592_xtal20;
> > }
> > break;
> > }
> >
> > - if (WARN_ON_ONCE(!spec->channels))
> > + if (WARN_ON_ONCE(!channels))
> > return -ENODEV;
> >
> > + spec = kzalloc_flex(*spec, channels_info, num_channels);
> > + if (!spec)
> > + return -ENOMEM;
> > +
> > + spec->num_channels = num_channels;
> > + spec->channels = channels;
> > + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
> > +
> > spec->supported_bands = SUPPORT_BAND_2GHZ;
> > if (spec->num_channels > 14)
> > spec->supported_bands |= SUPPORT_BAND_5GHZ;
> > @@ -11959,19 +11967,13 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > /*
> > * Create channel information and survey arrays
> > */
> > - info = kzalloc_objs(*info, spec->num_channels);
> > - if (!info)
> > - return -ENOMEM;
> > -
> > rt2x00dev->chan_survey =
> > kzalloc_objs(struct rt2x00_chan_survey, spec->num_channels);
> > if (!rt2x00dev->chan_survey) {
> > - kfree(info);
> > + kfree(spec);
> > return -ENOMEM;
> > }
> >
> > - spec->channels_info = info;
> > -
> > default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
> > default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
> >
> > @@ -11982,10 +11984,11 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > default_power3 = NULL;
> >
> > for (i = 0; i < 14; i++) {
> > - info[i].default_power1 = default_power1[i];
> > - info[i].default_power2 = default_power2[i];
> > + info = &spec->channels_info[i];
> > + info->default_power1 = default_power1[i];
> > + info->default_power2 = default_power2[i];
> > if (default_power3)
> > - info[i].default_power3 = default_power3[i];
> > + info->default_power3 = default_power3[i];
> > }
> >
> > if (spec->num_channels > 14) {
> > @@ -12002,10 +12005,11 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > default_power3 = NULL;
> >
> > for (i = 14; i < spec->num_channels; i++) {
> > - info[i].default_power1 = default_power1[i - 14];
> > - info[i].default_power2 = default_power2[i - 14];
> > + info = &spec->channels_info[i];
> > + info->default_power1 = default_power1[i - 14];
> > + info->default_power2 = default_power2[i - 14];
> > if (default_power3)
> > - info[i].default_power3 = default_power3[i - 14];
> > + info->default_power3 = default_power3[i - 14];
> > }
> > }
> >
> > @@ -12033,6 +12037,8 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > break;
> > }
> >
> > + rt2x00dev->spec = spec;
> > +
> > return 0;
> > }
> >
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
> > index 7d313e86d3f2..babc04210a65 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
> > @@ -404,9 +404,9 @@ struct hw_mode_spec {
> >
> > unsigned int num_channels;
> > const struct rf_channel *channels;
> > - const struct channel_info *channels_info;
> >
> > struct ieee80211_sta_ht_cap ht;
> > + struct channel_info channels_info[] __counted_by(num_channels);
> > };
> >
> > /*
> > @@ -802,7 +802,7 @@ struct rt2x00_dev {
> > /*
> > * hw capability specifications.
> > */
> > - struct hw_mode_spec spec;
> > + struct hw_mode_spec *spec;
> >
> > /*
> > * This is the default TX/RX antenna setup as indicated
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
> > index f895f560a185..b97cb67c4361 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00config.c
> > @@ -165,7 +165,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
> > static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
> > struct ieee80211_conf *conf)
> > {
> > - struct hw_mode_spec *spec = &rt2x00dev->spec;
> > + struct hw_mode_spec *spec = rt2x00dev->spec;
> > int center_channel;
> > u16 i;
> >
> > @@ -194,6 +194,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
> > struct ieee80211_conf *conf,
> > unsigned int ieee80211_flags)
> > {
> > + struct hw_mode_spec *spec = rt2x00dev->spec;
> > struct rt2x00lib_conf libconf;
> > u16 hw_value;
> > u16 autowake_timeout;
> > @@ -218,13 +219,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
> > hw_value = conf->chandef.chan->hw_value;
> > }
> >
> > - memcpy(&libconf.rf,
> > - &rt2x00dev->spec.channels[hw_value],
> > - sizeof(libconf.rf));
> > -
> > - memcpy(&libconf.channel,
> > - &rt2x00dev->spec.channels_info[hw_value],
> > - sizeof(libconf.channel));
> > + memcpy(&libconf.rf, &spec->channels[hw_value], sizeof(libconf.rf));
> > + memcpy(&libconf.channel, &spec->channels_info[hw_value], sizeof(libconf.channel));
> >
> > /* Used for VCO periodic calibration */
> > rt2x00dev->rf_channel = libconf.rf.channel;
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
> > index edc1f8eac747..3ffbc8aabbae 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
> > @@ -1097,7 +1097,7 @@ static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev)
> > rt2x00dev->hw->wiphy->bands[NL80211_BAND_5GHZ] = NULL;
> > }
> >
> > - kfree(rt2x00dev->spec.channels_info);
> > + kfree(rt2x00dev->spec);
> > kfree(rt2x00dev->chan_survey);
> > }
> >
> > @@ -1116,7 +1116,7 @@ static const struct ieee80211_tpt_blink rt2x00_tpt_blink[] = {
> >
> > static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
> > {
> > - struct hw_mode_spec *spec = &rt2x00dev->spec;
> > + struct hw_mode_spec *spec = rt2x00dev->spec;
> > int status;
> >
> > if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags))
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt61pci.c b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
> > index 79e1fd0a1fbd..479825f8bba9 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt61pci.c
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt61pci.c
> > @@ -2654,7 +2654,10 @@ static const struct rf_channel rf_vals_seq[] = {
> >
> > static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > {
> > - struct hw_mode_spec *spec = &rt2x00dev->spec;
> > + const struct rf_channel *channels;
> > + unsigned int num_channels = 0;
> > + unsigned int supported_bands;
> > + struct hw_mode_spec *spec;
> > struct channel_info *info;
> > u8 *tx_power;
> > unsigned int i;
> > @@ -2693,46 +2696,51 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > /*
> > * Initialize hw_mode information.
> > */
> > - spec->supported_bands = SUPPORT_BAND_2GHZ;
> > - spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
> > + supported_bands = SUPPORT_BAND_2GHZ;
> >
> > if (!rt2x00_has_cap_rf_sequence(rt2x00dev)) {
> > - spec->num_channels = 14;
> > - spec->channels = rf_vals_noseq;
> > + num_channels = 14;
> > + channels = rf_vals_noseq;
> > } else {
> > - spec->num_channels = 14;
> > - spec->channels = rf_vals_seq;
> > + num_channels = 14;
> > + channels = rf_vals_seq;
> > }
> >
> > if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) {
> > - spec->supported_bands |= SUPPORT_BAND_5GHZ;
> > - spec->num_channels = ARRAY_SIZE(rf_vals_seq);
> > + supported_bands |= SUPPORT_BAND_5GHZ;
> > + num_channels = ARRAY_SIZE(rf_vals_seq);
> > }
> >
> > /*
> > * Create channel information array
> > */
> > - info = kzalloc_objs(*info, spec->num_channels);
> > - if (!info)
> > + spec = kzalloc_flex(*spec, channels_info, num_channels);
> > + if (!spec)
> > return -ENOMEM;
> >
> > - spec->channels_info = info;
> > + spec->num_channels = num_channels;
> > + spec->channels = channels;
> > + spec->supported_bands = supported_bands;
> > + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
> >
> > tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
> > for (i = 0; i < 14; i++) {
> > - info[i].max_power = MAX_TXPOWER;
> > - info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> > + info = &spec->channels_info[i];
> > + info->max_power = MAX_TXPOWER;
> > + info->default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> > }
> >
> > if (spec->num_channels > 14) {
> > tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
> > for (i = 14; i < spec->num_channels; i++) {
> > - info[i].max_power = MAX_TXPOWER;
> > - info[i].default_power1 =
> > - TXPOWER_FROM_DEV(tx_power[i - 14]);
> > + info = &spec->channels_info[i];
> > + info->max_power = MAX_TXPOWER;
> > + info->default_power1 = TXPOWER_FROM_DEV(tx_power[i - 14]);
> > }
> > }
> >
> > + rt2x00dev->spec = spec;
> > +
> > return 0;
> > }
> >
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt73usb.c b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
> > index d6b7174d087a..17338378329b 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt73usb.c
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt73usb.c
> > @@ -2088,7 +2088,10 @@ static const struct rf_channel rf_vals_5225_2527[] = {
> >
> > static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > {
> > - struct hw_mode_spec *spec = &rt2x00dev->spec;
> > + const struct rf_channel *channels;
> > + unsigned int num_channels = 0;
> > + unsigned int supported_bands;
> > + struct hw_mode_spec *spec;
> > struct channel_info *info;
> > u8 *tx_power;
> > unsigned int i;
> > @@ -2114,49 +2117,54 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> > /*
> > * Initialize hw_mode information.
> > */
> > - spec->supported_bands = SUPPORT_BAND_2GHZ;
> > - spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
> > + supported_bands = SUPPORT_BAND_2GHZ;
> >
> > if (rt2x00_rf(rt2x00dev, RF2528)) {
> > - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528);
> > - spec->channels = rf_vals_bg_2528;
> > + num_channels = ARRAY_SIZE(rf_vals_bg_2528);
> > + channels = rf_vals_bg_2528;
> > } else if (rt2x00_rf(rt2x00dev, RF5226)) {
> > - spec->supported_bands |= SUPPORT_BAND_5GHZ;
> > - spec->num_channels = ARRAY_SIZE(rf_vals_5226);
> > - spec->channels = rf_vals_5226;
> > + supported_bands |= SUPPORT_BAND_5GHZ;
> > + num_channels = ARRAY_SIZE(rf_vals_5226);
> > + channels = rf_vals_5226;
> > } else if (rt2x00_rf(rt2x00dev, RF2527)) {
> > - spec->num_channels = 14;
> > - spec->channels = rf_vals_5225_2527;
> > + num_channels = 14;
> > + channels = rf_vals_5225_2527;
> > } else if (rt2x00_rf(rt2x00dev, RF5225)) {
> > - spec->supported_bands |= SUPPORT_BAND_5GHZ;
> > - spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527);
> > - spec->channels = rf_vals_5225_2527;
> > + supported_bands |= SUPPORT_BAND_5GHZ;
> > + num_channels = ARRAY_SIZE(rf_vals_5225_2527);
> > + channels = rf_vals_5225_2527;
> > }
> >
> > /*
> > * Create channel information array
> > */
> > - info = kzalloc_objs(*info, spec->num_channels);
> > - if (!info)
> > + spec = kzalloc_flex(*spec, channels_info, num_channels);
> > + if (!spec)
> > return -ENOMEM;
> >
> > - spec->channels_info = info;
> > + spec->num_channels = num_channels;
> > + spec->channels = channels;
> > + spec->supported_bands = supported_bands;
> > + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
> >
> > tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
> > for (i = 0; i < 14; i++) {
> > - info[i].max_power = MAX_TXPOWER;
> > - info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> > + info = &spec->channels_info[i];
> > + info->max_power = MAX_TXPOWER;
> > + info->default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> > }
> >
> > if (spec->num_channels > 14) {
> > tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
> > for (i = 14; i < spec->num_channels; i++) {
> > - info[i].max_power = MAX_TXPOWER;
> > - info[i].default_power1 =
> > - TXPOWER_FROM_DEV(tx_power[i - 14]);
> > + info = &spec->channels_info[i];
> > + info->max_power = MAX_TXPOWER;
> > + info->default_power1 = TXPOWER_FROM_DEV(tx_power[i - 14]);
> > }
> > }
> >
> > + rt2x00dev->spec = spec;
> > +
> > return 0;
> > }
> >
> > --
> > 2.54.0
> >