1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Firmware I/O code for mac80211 Prism54 drivers 4 * 5 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net> 6 * Copyright (c) 2007-2009, Christian Lamparter <chunkeey@web.de> 7 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> 8 * 9 * Based on: 10 * - the islsm (softmac prism54) driver, which is: 11 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al. 12 * - stlc45xx driver 13 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). 14 */ 15 16 #include <linux/slab.h> 17 #include <linux/firmware.h> 18 #include <linux/etherdevice.h> 19 #include <linux/export.h> 20 21 #include <net/mac80211.h> 22 23 #include "p54.h" 24 #include "eeprom.h" 25 #include "lmac.h" 26 27 int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) 28 { 29 struct p54_common *priv = dev->priv; 30 struct exp_if *exp_if; 31 struct bootrec *bootrec; 32 u32 *data = (u32 *)fw->data; 33 u32 *end_data = (u32 *)fw->data + (fw->size >> 2); 34 u8 *fw_version = NULL; 35 size_t len; 36 int i; 37 int maxlen; 38 39 if (priv->rx_start) 40 return 0; 41 42 while (data < end_data && *data) 43 data++; 44 45 while (data < end_data && !*data) 46 data++; 47 48 bootrec = (struct bootrec *) data; 49 50 while (bootrec->data <= end_data && (bootrec->data + 51 (len = le32_to_cpu(bootrec->len))) <= end_data) { 52 u32 code = le32_to_cpu(bootrec->code); 53 switch (code) { 54 case BR_CODE_COMPONENT_ID: 55 priv->fw_interface = be32_to_cpup((__be32 *) 56 bootrec->data); 57 switch (priv->fw_interface) { 58 case FW_LM86: 59 case FW_LM20: 60 case FW_LM87: { 61 char *iftype = (char *)bootrec->data; 62 wiphy_info(priv->hw->wiphy, 63 "p54 detected a LM%c%c firmware\n", 64 iftype[2], iftype[3]); 65 break; 66 } 67 case FW_FMAC: 68 default: 69 wiphy_err(priv->hw->wiphy, 70 "unsupported firmware\n"); 71 return -ENODEV; 72 } 73 break; 74 case BR_CODE_COMPONENT_VERSION: 75 /* 24 bytes should be enough for all firmwares */ 76 if (strnlen((unsigned char *) bootrec->data, 24) < 24) 77 fw_version = (unsigned char *) bootrec->data; 78 break; 79 case BR_CODE_DESCR: { 80 struct bootrec_desc *desc = 81 (struct bootrec_desc *)bootrec->data; 82 priv->rx_start = le32_to_cpu(desc->rx_start); 83 /* FIXME add sanity checking */ 84 priv->rx_end = le32_to_cpu(desc->rx_end) - 0x3500; 85 priv->headroom = desc->headroom; 86 priv->tailroom = desc->tailroom; 87 priv->privacy_caps = desc->privacy_caps; 88 priv->rx_keycache_size = desc->rx_keycache_size; 89 if (le32_to_cpu(bootrec->len) == 11) 90 priv->rx_mtu = le16_to_cpu(desc->rx_mtu); 91 else 92 priv->rx_mtu = (size_t) 93 0x620 - priv->tx_hdr_len; 94 maxlen = priv->tx_hdr_len + /* USB devices */ 95 sizeof(struct p54_rx_data) + 96 4 + /* rx alignment */ 97 IEEE80211_MAX_FRAG_THRESHOLD; 98 if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) { 99 printk(KERN_INFO "p54: rx_mtu reduced from %d " 100 "to %d\n", priv->rx_mtu, maxlen); 101 priv->rx_mtu = maxlen; 102 } 103 break; 104 } 105 case BR_CODE_EXPOSED_IF: 106 exp_if = (struct exp_if *) bootrec->data; 107 for (i = 0; i < (len * sizeof(*exp_if) / 4); i++) 108 if (exp_if[i].if_id == cpu_to_le16(IF_ID_LMAC)) 109 priv->fw_var = le16_to_cpu(exp_if[i].variant); 110 break; 111 case BR_CODE_DEPENDENT_IF: 112 break; 113 case BR_CODE_END_OF_BRA: 114 case LEGACY_BR_CODE_END_OF_BRA: 115 end_data = NULL; 116 break; 117 default: 118 break; 119 } 120 bootrec = (struct bootrec *)&bootrec->data[len]; 121 } 122 123 if (fw_version) { 124 wiphy_info(priv->hw->wiphy, 125 "FW rev %s - Softmac protocol %x.%x\n", 126 fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); 127 snprintf(dev->wiphy->fw_version, sizeof(dev->wiphy->fw_version), 128 "%s - %x.%x", fw_version, 129 priv->fw_var >> 8, priv->fw_var & 0xff); 130 } 131 132 if (priv->fw_var < 0x500) 133 wiphy_info(priv->hw->wiphy, 134 "you are using an obsolete firmware. " 135 "visit http://wireless.wiki.kernel.org/en/users/Drivers/p54 " 136 "and grab one for \"kernel >= 2.6.28\"!\n"); 137 138 if (priv->fw_var >= 0x300) { 139 /* Firmware supports QoS, use it! */ 140 141 if (priv->fw_var >= 0x500) { 142 priv->tx_stats[P54_QUEUE_AC_VO].limit = 16; 143 priv->tx_stats[P54_QUEUE_AC_VI].limit = 16; 144 priv->tx_stats[P54_QUEUE_AC_BE].limit = 16; 145 priv->tx_stats[P54_QUEUE_AC_BK].limit = 16; 146 } else { 147 priv->tx_stats[P54_QUEUE_AC_VO].limit = 3; 148 priv->tx_stats[P54_QUEUE_AC_VI].limit = 4; 149 priv->tx_stats[P54_QUEUE_AC_BE].limit = 3; 150 priv->tx_stats[P54_QUEUE_AC_BK].limit = 2; 151 } 152 priv->hw->queues = P54_QUEUE_AC_NUM; 153 } 154 155 wiphy_info(priv->hw->wiphy, 156 "cryptographic accelerator WEP:%s, TKIP:%s, CCMP:%s\n", 157 (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" : "no", 158 (priv->privacy_caps & 159 (BR_DESC_PRIV_CAP_TKIP | BR_DESC_PRIV_CAP_MICHAEL)) 160 ? "YES" : "no", 161 (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) 162 ? "YES" : "no"); 163 164 if (priv->rx_keycache_size) { 165 /* 166 * NOTE: 167 * 168 * The firmware provides at most 255 (0 - 254) slots 169 * for keys which are then used to offload decryption. 170 * As a result the 255 entry (aka 0xff) can be used 171 * safely by the driver to mark keys that didn't fit 172 * into the full cache. This trick saves us from 173 * keeping a extra list for uploaded keys. 174 */ 175 176 priv->used_rxkeys = bitmap_zalloc(priv->rx_keycache_size, 177 GFP_KERNEL); 178 if (!priv->used_rxkeys) 179 return -ENOMEM; 180 } 181 182 return 0; 183 } 184 EXPORT_SYMBOL_GPL(p54_parse_firmware); 185 186 static struct sk_buff *p54_alloc_skb(struct p54_common *priv, u16 hdr_flags, 187 u16 payload_len, u16 type, gfp_t memflags) 188 { 189 struct p54_hdr *hdr; 190 struct sk_buff *skb; 191 size_t frame_len = sizeof(*hdr) + payload_len; 192 193 if (frame_len > P54_MAX_CTRL_FRAME_LEN) 194 return NULL; 195 196 if (unlikely(skb_queue_len(&priv->tx_pending) > 64)) 197 return NULL; 198 199 skb = __dev_alloc_skb(priv->tx_hdr_len + frame_len, memflags); 200 if (!skb) 201 return NULL; 202 skb_reserve(skb, priv->tx_hdr_len); 203 204 hdr = skb_put(skb, sizeof(*hdr)); 205 hdr->flags = cpu_to_le16(hdr_flags); 206 hdr->len = cpu_to_le16(payload_len); 207 hdr->type = cpu_to_le16(type); 208 hdr->tries = hdr->rts_tries = 0; 209 return skb; 210 } 211 212 int p54_download_eeprom(struct p54_common *priv, void *buf, 213 u16 offset, u16 len) 214 { 215 struct p54_eeprom_lm86 *eeprom_hdr; 216 struct sk_buff *skb; 217 size_t eeprom_hdr_size; 218 int ret = 0; 219 long timeout; 220 221 if (priv->fw_var >= 0x509) 222 eeprom_hdr_size = sizeof(*eeprom_hdr); 223 else 224 eeprom_hdr_size = 0x4; 225 226 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL, eeprom_hdr_size + 227 len, P54_CONTROL_TYPE_EEPROM_READBACK, 228 GFP_KERNEL); 229 if (unlikely(!skb)) 230 return -ENOMEM; 231 232 mutex_lock(&priv->eeprom_mutex); 233 priv->eeprom = buf; 234 eeprom_hdr = skb_put(skb, eeprom_hdr_size + len); 235 236 if (priv->fw_var < 0x509) { 237 eeprom_hdr->v1.offset = cpu_to_le16(offset); 238 eeprom_hdr->v1.len = cpu_to_le16(len); 239 } else { 240 eeprom_hdr->v2.offset = cpu_to_le32(offset); 241 eeprom_hdr->v2.len = cpu_to_le16(len); 242 eeprom_hdr->v2.magic2 = 0xf; 243 memcpy(eeprom_hdr->v2.magic, (const char *)"LOCK", 4); 244 } 245 246 p54_tx(priv, skb); 247 248 timeout = wait_for_completion_interruptible_timeout( 249 &priv->eeprom_comp, HZ); 250 if (timeout <= 0) { 251 wiphy_err(priv->hw->wiphy, 252 "device does not respond or signal received!\n"); 253 ret = -EBUSY; 254 } 255 priv->eeprom = NULL; 256 mutex_unlock(&priv->eeprom_mutex); 257 return ret; 258 } 259 260 int p54_update_beacon_tim(struct p54_common *priv, u16 aid, bool set) 261 { 262 struct sk_buff *skb; 263 struct p54_tim *tim; 264 265 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*tim), 266 P54_CONTROL_TYPE_TIM, GFP_ATOMIC); 267 if (unlikely(!skb)) 268 return -ENOMEM; 269 270 tim = skb_put(skb, sizeof(*tim)); 271 tim->count = 1; 272 tim->entry[0] = cpu_to_le16(set ? (aid | 0x8000) : aid); 273 p54_tx(priv, skb); 274 return 0; 275 } 276 277 int p54_sta_unlock(struct p54_common *priv, u8 *addr) 278 { 279 struct sk_buff *skb; 280 struct p54_sta_unlock *sta; 281 282 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*sta), 283 P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC); 284 if (unlikely(!skb)) 285 return -ENOMEM; 286 287 sta = skb_put(skb, sizeof(*sta)); 288 memcpy(sta->addr, addr, ETH_ALEN); 289 p54_tx(priv, skb); 290 return 0; 291 } 292 293 int p54_tx_cancel(struct p54_common *priv, __le32 req_id) 294 { 295 struct sk_buff *skb; 296 struct p54_txcancel *cancel; 297 u32 _req_id = le32_to_cpu(req_id); 298 299 if (unlikely(_req_id < priv->rx_start || _req_id > priv->rx_end)) 300 return -EINVAL; 301 302 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*cancel), 303 P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC); 304 if (unlikely(!skb)) 305 return -ENOMEM; 306 307 cancel = skb_put(skb, sizeof(*cancel)); 308 cancel->req_id = req_id; 309 p54_tx(priv, skb); 310 return 0; 311 } 312 313 int p54_setup_mac(struct p54_common *priv) 314 { 315 struct sk_buff *skb; 316 struct p54_setup_mac *setup; 317 u16 mode; 318 319 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup), 320 P54_CONTROL_TYPE_SETUP, GFP_ATOMIC); 321 if (!skb) 322 return -ENOMEM; 323 324 setup = skb_put(skb, sizeof(*setup)); 325 if (!(priv->hw->conf.flags & IEEE80211_CONF_IDLE)) { 326 switch (priv->mode) { 327 case NL80211_IFTYPE_STATION: 328 mode = P54_FILTER_TYPE_STATION; 329 break; 330 case NL80211_IFTYPE_AP: 331 mode = P54_FILTER_TYPE_AP; 332 break; 333 case NL80211_IFTYPE_ADHOC: 334 case NL80211_IFTYPE_MESH_POINT: 335 mode = P54_FILTER_TYPE_IBSS; 336 break; 337 case NL80211_IFTYPE_MONITOR: 338 mode = P54_FILTER_TYPE_PROMISCUOUS; 339 break; 340 default: 341 mode = P54_FILTER_TYPE_HIBERNATE; 342 break; 343 } 344 345 /* 346 * "TRANSPARENT and PROMISCUOUS are mutually exclusive" 347 * STSW45X0C LMAC API - page 12 348 */ 349 if (priv->filter_flags & FIF_OTHER_BSS && 350 (mode != P54_FILTER_TYPE_PROMISCUOUS)) 351 mode |= P54_FILTER_TYPE_TRANSPARENT; 352 } else { 353 mode = P54_FILTER_TYPE_HIBERNATE; 354 } 355 356 setup->mac_mode = cpu_to_le16(mode); 357 memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN); 358 memcpy(setup->bssid, priv->bssid, ETH_ALEN); 359 setup->rx_antenna = 2 & priv->rx_diversity_mask; /* automatic */ 360 setup->rx_align = 0; 361 if (priv->fw_var < 0x500) { 362 setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); 363 memset(setup->v1.rts_rates, 0, 8); 364 setup->v1.rx_addr = cpu_to_le32(priv->rx_end); 365 setup->v1.max_rx = cpu_to_le16(priv->rx_mtu); 366 setup->v1.rxhw = cpu_to_le16(priv->rxhw); 367 setup->v1.wakeup_timer = cpu_to_le16(priv->wakeup_timer); 368 setup->v1.unalloc0 = cpu_to_le16(0); 369 } else { 370 setup->v2.rx_addr = cpu_to_le32(priv->rx_end); 371 setup->v2.max_rx = cpu_to_le16(priv->rx_mtu); 372 setup->v2.rxhw = cpu_to_le16(priv->rxhw); 373 setup->v2.timer = cpu_to_le16(priv->wakeup_timer); 374 setup->v2.truncate = cpu_to_le16(48896); 375 setup->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); 376 setup->v2.sbss_offset = 0; 377 setup->v2.mcast_window = 0; 378 setup->v2.rx_rssi_threshold = 0; 379 setup->v2.rx_ed_threshold = 0; 380 setup->v2.ref_clock = cpu_to_le32(644245094); 381 setup->v2.lpf_bandwidth = cpu_to_le16(65535); 382 setup->v2.osc_start_delay = cpu_to_le16(65535); 383 } 384 p54_tx(priv, skb); 385 priv->phy_idle = mode == P54_FILTER_TYPE_HIBERNATE; 386 return 0; 387 } 388 389 int p54_scan(struct p54_common *priv, u16 mode, u16 dwell) 390 { 391 struct sk_buff *skb; 392 struct p54_hdr *hdr; 393 struct p54_scan_head *head; 394 struct p54_iq_autocal_entry *iq_autocal; 395 union p54_scan_body_union *body; 396 struct p54_scan_tail_rate *rate; 397 struct pda_rssi_cal_entry *rssi; 398 struct p54_rssi_db_entry *rssi_data; 399 unsigned int i; 400 void *entry; 401 __le16 freq = cpu_to_le16(priv->hw->conf.chandef.chan->center_freq); 402 403 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) + 404 2 + sizeof(*iq_autocal) + sizeof(*body) + 405 sizeof(*rate) + 2 * sizeof(*rssi), 406 P54_CONTROL_TYPE_SCAN, GFP_ATOMIC); 407 if (!skb) 408 return -ENOMEM; 409 410 head = skb_put(skb, sizeof(*head)); 411 memset(head->scan_params, 0, sizeof(head->scan_params)); 412 head->mode = cpu_to_le16(mode); 413 head->dwell = cpu_to_le16(dwell); 414 head->freq = freq; 415 416 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { 417 __le16 *pa_power_points = skb_put(skb, 2); 418 *pa_power_points = cpu_to_le16(0x0c); 419 } 420 421 iq_autocal = skb_put(skb, sizeof(*iq_autocal)); 422 for (i = 0; i < priv->iq_autocal_len; i++) { 423 if (priv->iq_autocal[i].freq != freq) 424 continue; 425 426 memcpy(iq_autocal, &priv->iq_autocal[i].params, 427 sizeof(struct p54_iq_autocal_entry)); 428 break; 429 } 430 if (i == priv->iq_autocal_len) 431 goto err; 432 433 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) 434 body = skb_put(skb, sizeof(body->longbow)); 435 else 436 body = skb_put(skb, sizeof(body->normal)); 437 438 for (i = 0; i < priv->output_limit->entries; i++) { 439 __le16 *entry_freq = (void *) (priv->output_limit->data + 440 priv->output_limit->entry_size * i); 441 442 if (*entry_freq != freq) 443 continue; 444 445 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { 446 memcpy(&body->longbow.power_limits, 447 (void *) entry_freq + sizeof(__le16), 448 priv->output_limit->entry_size); 449 } else { 450 struct pda_channel_output_limit *limits = 451 (void *) entry_freq; 452 453 body->normal.val_barker = 0x38; 454 body->normal.val_bpsk = body->normal.dup_bpsk = 455 limits->val_bpsk; 456 body->normal.val_qpsk = body->normal.dup_qpsk = 457 limits->val_qpsk; 458 body->normal.val_16qam = body->normal.dup_16qam = 459 limits->val_16qam; 460 body->normal.val_64qam = body->normal.dup_64qam = 461 limits->val_64qam; 462 } 463 break; 464 } 465 if (i == priv->output_limit->entries) 466 goto err; 467 468 entry = (void *)(priv->curve_data->data + priv->curve_data->offset); 469 for (i = 0; i < priv->curve_data->entries; i++) { 470 if (*((__le16 *)entry) != freq) { 471 entry += priv->curve_data->entry_size; 472 continue; 473 } 474 475 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { 476 memcpy(&body->longbow.curve_data, 477 entry + sizeof(__le16), 478 priv->curve_data->entry_size); 479 } else { 480 struct p54_scan_body *chan = &body->normal; 481 struct pda_pa_curve_data *curve_data = 482 (void *) priv->curve_data->data; 483 484 entry += sizeof(__le16); 485 chan->pa_points_per_curve = 8; 486 memset(chan->curve_data, 0, sizeof(chan->curve_data)); 487 memcpy(chan->curve_data, entry, 488 sizeof(struct p54_pa_curve_data_sample) * 489 min((u8)8, curve_data->points_per_channel)); 490 } 491 break; 492 } 493 if (i == priv->curve_data->entries) 494 goto err; 495 496 if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) { 497 rate = skb_put(skb, sizeof(*rate)); 498 rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); 499 for (i = 0; i < sizeof(rate->rts_rates); i++) 500 rate->rts_rates[i] = i; 501 } 502 503 rssi = skb_put(skb, sizeof(*rssi)); 504 rssi_data = p54_rssi_find(priv, le16_to_cpu(freq)); 505 rssi->mul = cpu_to_le16(rssi_data->mul); 506 rssi->add = cpu_to_le16(rssi_data->add); 507 if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { 508 /* Longbow frontend needs ever more */ 509 rssi = skb_put(skb, sizeof(*rssi)); 510 rssi->mul = cpu_to_le16(rssi_data->longbow_unkn); 511 rssi->add = cpu_to_le16(rssi_data->longbow_unk2); 512 } 513 514 if (priv->fw_var >= 0x509) { 515 rate = skb_put(skb, sizeof(*rate)); 516 rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); 517 for (i = 0; i < sizeof(rate->rts_rates); i++) 518 rate->rts_rates[i] = i; 519 } 520 521 hdr = (struct p54_hdr *) skb->data; 522 hdr->len = cpu_to_le16(skb->len - sizeof(*hdr)); 523 524 p54_tx(priv, skb); 525 priv->cur_rssi = rssi_data; 526 return 0; 527 528 err: 529 wiphy_err(priv->hw->wiphy, "frequency change to channel %d failed.\n", 530 ieee80211_frequency_to_channel( 531 priv->hw->conf.chandef.chan->center_freq)); 532 533 dev_kfree_skb_any(skb); 534 return -EINVAL; 535 } 536 537 int p54_set_leds(struct p54_common *priv) 538 { 539 struct sk_buff *skb; 540 struct p54_led *led; 541 542 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led), 543 P54_CONTROL_TYPE_LED, GFP_ATOMIC); 544 if (unlikely(!skb)) 545 return -ENOMEM; 546 547 led = skb_put(skb, sizeof(*led)); 548 led->flags = cpu_to_le16(0x0003); 549 led->mask[0] = led->mask[1] = cpu_to_le16(priv->softled_state); 550 led->delay[0] = cpu_to_le16(1); 551 led->delay[1] = cpu_to_le16(0); 552 p54_tx(priv, skb); 553 return 0; 554 } 555 556 int p54_set_edcf(struct p54_common *priv) 557 { 558 struct sk_buff *skb; 559 struct p54_edcf *edcf; 560 u8 rtd; 561 562 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf), 563 P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC); 564 if (unlikely(!skb)) 565 return -ENOMEM; 566 567 edcf = skb_put(skb, sizeof(*edcf)); 568 if (priv->use_short_slot) { 569 edcf->slottime = 9; 570 edcf->sifs = 0x10; 571 edcf->eofpad = 0x00; 572 } else { 573 edcf->slottime = 20; 574 edcf->sifs = 0x0a; 575 edcf->eofpad = 0x06; 576 } 577 /* 578 * calculate the extra round trip delay according to the 579 * formula from 802.11-2007 17.3.8.6. 580 */ 581 rtd = 3 * priv->coverage_class; 582 edcf->slottime += rtd; 583 edcf->round_trip_delay = cpu_to_le16(rtd); 584 /* (see prism54/isl_oid.h for further details) */ 585 edcf->frameburst = cpu_to_le16(0); 586 edcf->flags = 0; 587 memset(edcf->mapping, 0, sizeof(edcf->mapping)); 588 memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue)); 589 p54_tx(priv, skb); 590 return 0; 591 } 592 593 int p54_set_ps(struct p54_common *priv) 594 { 595 struct sk_buff *skb; 596 struct p54_psm *psm; 597 unsigned int i; 598 u16 mode; 599 600 if (priv->hw->conf.flags & IEEE80211_CONF_PS && 601 !priv->powersave_override) 602 mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM | 603 P54_PSM_CHECKSUM | P54_PSM_MCBC; 604 else 605 mode = P54_PSM_CAM; 606 607 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*psm), 608 P54_CONTROL_TYPE_PSM, GFP_ATOMIC); 609 if (!skb) 610 return -ENOMEM; 611 612 psm = skb_put(skb, sizeof(*psm)); 613 psm->mode = cpu_to_le16(mode); 614 psm->aid = cpu_to_le16(priv->aid); 615 for (i = 0; i < ARRAY_SIZE(psm->intervals); i++) { 616 psm->intervals[i].interval = 617 cpu_to_le16(priv->hw->conf.listen_interval); 618 psm->intervals[i].periods = cpu_to_le16(1); 619 } 620 621 psm->beacon_rssi_skip_max = 200; 622 psm->rssi_delta_threshold = 0; 623 psm->nr = 1; 624 psm->exclude[0] = WLAN_EID_TIM; 625 626 p54_tx(priv, skb); 627 priv->phy_ps = mode != P54_PSM_CAM; 628 return 0; 629 } 630 631 int p54_init_xbow_synth(struct p54_common *priv) 632 { 633 struct sk_buff *skb; 634 struct p54_xbow_synth *xbow; 635 636 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow), 637 P54_CONTROL_TYPE_XBOW_SYNTH_CFG, GFP_KERNEL); 638 if (unlikely(!skb)) 639 return -ENOMEM; 640 641 xbow = skb_put(skb, sizeof(*xbow)); 642 xbow->magic1 = cpu_to_le16(0x1); 643 xbow->magic2 = cpu_to_le16(0x2); 644 xbow->freq = cpu_to_le16(5390); 645 memset(xbow->padding, 0, sizeof(xbow->padding)); 646 p54_tx(priv, skb); 647 return 0; 648 } 649 650 int p54_upload_key(struct p54_common *priv, u8 algo, int slot, u8 idx, u8 len, 651 u8 *addr, u8* key) 652 { 653 struct sk_buff *skb; 654 struct p54_keycache *rxkey; 655 656 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey), 657 P54_CONTROL_TYPE_RX_KEYCACHE, GFP_KERNEL); 658 if (unlikely(!skb)) 659 return -ENOMEM; 660 661 rxkey = skb_put(skb, sizeof(*rxkey)); 662 rxkey->entry = slot; 663 rxkey->key_id = idx; 664 rxkey->key_type = algo; 665 if (addr) 666 memcpy(rxkey->mac, addr, ETH_ALEN); 667 else 668 eth_broadcast_addr(rxkey->mac); 669 670 switch (algo) { 671 case P54_CRYPTO_WEP: 672 case P54_CRYPTO_AESCCMP: 673 rxkey->key_len = min_t(u8, 16, len); 674 memcpy(rxkey->key, key, rxkey->key_len); 675 break; 676 677 case P54_CRYPTO_TKIPMICHAEL: 678 rxkey->key_len = 24; 679 memcpy(rxkey->key, key, 16); 680 memcpy(&(rxkey->key[16]), &(key 681 [NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]), 8); 682 break; 683 684 case P54_CRYPTO_NONE: 685 rxkey->key_len = 0; 686 memset(rxkey->key, 0, sizeof(rxkey->key)); 687 break; 688 689 default: 690 wiphy_err(priv->hw->wiphy, 691 "invalid cryptographic algorithm: %d\n", algo); 692 dev_kfree_skb(skb); 693 return -EINVAL; 694 } 695 696 p54_tx(priv, skb); 697 return 0; 698 } 699 700 int p54_fetch_statistics(struct p54_common *priv) 701 { 702 struct ieee80211_tx_info *txinfo; 703 struct p54_tx_info *p54info; 704 struct sk_buff *skb; 705 706 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL, 707 sizeof(struct p54_statistics), 708 P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL); 709 if (!skb) 710 return -ENOMEM; 711 712 /* 713 * The statistic feedback causes some extra headaches here, if it 714 * is not to crash/corrupt the firmware data structures. 715 * 716 * Unlike all other Control Get OIDs we can not use helpers like 717 * skb_put to reserve the space for the data we're requesting. 718 * Instead the extra frame length -which will hold the results later- 719 * will only be told to the p54_assign_address, so that following 720 * frames won't be placed into the allegedly empty area. 721 */ 722 txinfo = IEEE80211_SKB_CB(skb); 723 p54info = (void *) txinfo->rate_driver_data; 724 p54info->extra_len = sizeof(struct p54_statistics); 725 726 p54_tx(priv, skb); 727 return 0; 728 } 729 730 int p54_set_groupfilter(struct p54_common *priv) 731 { 732 struct p54_group_address_table *grp; 733 struct sk_buff *skb; 734 bool on = false; 735 736 skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*grp), 737 P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE, GFP_KERNEL); 738 if (!skb) 739 return -ENOMEM; 740 741 grp = skb_put(skb, sizeof(*grp)); 742 743 on = !(priv->filter_flags & FIF_ALLMULTI) && 744 (priv->mc_maclist_num > 0 && 745 priv->mc_maclist_num <= MC_FILTER_ADDRESS_NUM); 746 747 if (on) { 748 grp->filter_enable = cpu_to_le16(1); 749 grp->num_address = cpu_to_le16(priv->mc_maclist_num); 750 memcpy(grp->mac_list, priv->mc_maclist, sizeof(grp->mac_list)); 751 } else { 752 grp->filter_enable = cpu_to_le16(0); 753 grp->num_address = cpu_to_le16(0); 754 memset(grp->mac_list, 0, sizeof(grp->mac_list)); 755 } 756 757 p54_tx(priv, skb); 758 return 0; 759 } 760