/* * This function get's called after lbs_setup_firmware() determined the * firmware capabities. So we can setup the wiphy according to our * hardware/firmware. */ int lbs_cfg_register(struct lbs_private *priv) { struct wireless_dev *wdev = priv->wdev; int ret; lbs_deb_enter(LBS_DEB_CFG80211); wdev->wiphy->max_scan_ssids = 1; wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; /* TODO: BIT(NL80211_IFTYPE_ADHOC); */ wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); /* TODO: honor priv->regioncode */ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz; /* * We could check priv->fwcapinfo && FW_CAPINFO_WPA, but I have * never seen a firmware without WPA */ wdev->wiphy->cipher_suites = cipher_suites; wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); ret = wiphy_register(wdev->wiphy); if (ret < 0) lbs_pr_err("cannot register wiphy device\n"); ret = register_netdev(priv->dev); if (ret) lbs_pr_err("cannot register network device\n"); lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); return ret; }
/** * @brief Get function for sysfs attribute mesh_id */ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, char *buf) { struct mrvl_mesh_defaults defs; int maxlen; int ret; ret = mesh_get_default_parameters(dev, &defs); if (ret) return ret; if (defs.meshie.val.mesh_id_len > IW_ESSID_MAX_SIZE) { lbs_pr_err("inconsistent mesh ID length"); defs.meshie.val.mesh_id_len = IW_ESSID_MAX_SIZE; } /* SSID not null terminated: reserve room for \0 + \n */ maxlen = defs.meshie.val.mesh_id_len + 2; maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE; defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0'; return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id); }
static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) { struct sk_buff *skb = NULL; u16 len; u8 *data; lbs_deb_enter(LBS_DEB_CS); len = if_cs_read16(priv->card, IF_CS_READ_LEN); if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); priv->dev->stats.rx_dropped++; goto dat_err; } skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2); if (!skb) goto out; skb_put(skb, len); skb_reserve(skb, 2);/* 16 byte align */ data = skb->data; /* read even number of bytes, then odd byte if necessary */ if_cs_read16_rep(priv->card, IF_CS_READ, data, len/sizeof(u16)); if (len & 1) data[len-1] = if_cs_read8(priv->card, IF_CS_READ); dat_err: if_cs_write16(priv->card, IF_CS_HOST_STATUS, IF_CS_BIT_RX); if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_RX); out: lbs_deb_leave_args(LBS_DEB_CS, "ret %p", skb); return skb; }
/*********************************************************************************************** ****函数名:lbs_rev_pkt ****描述:函数完成WIFI链路层的数据接收,接收得到的数据存放于struct lbs_private *priv->rx_pkt中。 ****参数:无 ****返回:返回接收数据长度, ***********************************************************************************************/ u16 lbs_rev_pkt(void) { struct lbs_private *priv = pgmarvel_priv; struct if_sdio_card *card = priv->card; struct eth_packet *rx_pkt = &priv->rx_pkt; int ret; sdio_sys_wait = 0; memset(rx_pkt,0,sizeof(struct eth_packet )); ret = poll_sdio_interrupt(card->func); if(ret < 0){ lbs_pr_err("read interrupt error!\n"); try_bug(0); } else if(ret&(IF_SDIO_H_INT_UPLD|IF_SDIO_H_INT_DNLD)){ if_sdio_interrupt(card->func); if(rx_pkt->len){ //Data available. sdio_sys_wait = 1; return rx_pkt->len; } } else{ sdio_sys_wait = 1; return 0; } sdio_sys_wait = 1; return 0; }
struct lbs_private *lbs_add_card(void *card) { struct lbs_private *priv =&gmarvell_priv; lbs_deb_enter("enter lbs_add_card!\n"); memset(priv,0,sizeof(struct lbs_private)); if (lbs_init_adapter(priv)) {//Initialize priv structure. lbs_pr_err("failed to initialize adapter structure.\n"); goto err_init_adapter; } priv->card = card;//if_sdio_card priv->mesh_open = 0; priv->infra_open = 0; _hx_sprintf((char *)priv->mesh_ssid,"mesh"); priv->mesh_ssid_len = 4; priv->wol_criteria = 0xffffffff; priv->wol_gpio = 0xff; goto done; err_init_adapter: done: lbs_deb_leave_args("leave lbs_add_card",0); return priv; }
/** * @brief This function adds mshX interface * * @param priv A pointer to the struct lbs_private structure * @return 0 if successful, -X otherwise */ int lbs_add_mesh(struct lbs_private *priv) { struct net_device *mesh_dev = NULL; int ret = 0; lbs_deb_enter(LBS_DEB_MESH); /* Allocate a virtual mesh device */ mesh_dev = alloc_netdev(0, "msh%d", ether_setup); if (!mesh_dev) { lbs_deb_mesh("init mshX device failed\n"); ret = -ENOMEM; goto done; } mesh_dev->ml_priv = priv; priv->mesh_dev = mesh_dev; mesh_dev->netdev_ops = &mesh_netdev_ops; mesh_dev->ethtool_ops = &lbs_ethtool_ops; memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, ETH_ALEN); SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); #ifdef WIRELESS_EXT mesh_dev->wireless_handlers = &mesh_handler_def; #endif mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; /* Register virtual mesh interface */ ret = register_netdev(mesh_dev); if (ret) { lbs_pr_err("cannot register mshX virtual interface\n"); goto err_free; } ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); if (ret) goto err_unregister; lbs_persist_config_init(mesh_dev); /* Everything successful */ ret = 0; goto done; err_unregister: unregister_netdev(mesh_dev); err_free: free_netdev(mesh_dev); done: lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); return ret; }
/* * Get the command result out of the card. */ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) { unsigned long flags; int ret = -1; u16 status; lbs_deb_enter(LBS_DEB_CS); /* is hardware ready? */ status = if_cs_read16(priv->card, IF_CS_CARD_STATUS); if ((status & IF_CS_BIT_RESP) == 0) { lbs_pr_err("no cmd response in card\n"); *len = 0; goto out; } *len = if_cs_read16(priv->card, IF_CS_RESP_LEN); if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) { lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len); goto out; } /* read even number of bytes, then odd byte if necessary */ if_cs_read16_rep(priv->card, IF_CS_RESP, data, *len/sizeof(u16)); if (*len & 1) data[*len-1] = if_cs_read8(priv->card, IF_CS_RESP); /* This is a workaround for a firmware that reports too much * bytes */ *len -= 8; ret = 0; /* Clear this flag again */ spin_lock_irqsave(&priv->driver_lock, flags); priv->dnld_sent = DNLD_RES_RECEIVED; spin_unlock_irqrestore(&priv->driver_lock, flags); out: lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len); return ret; }
static void if_usb_fw_timeo(unsigned long priv) { struct if_usb_card *cardp = (void *)priv; if (cardp->fwdnldover) { lbs_deb_usb("Download complete, no event. Assuming success\n"); } else { lbs_pr_err("Download timed out\n"); cardp->surprise_removed = 1; } wake_up(&cardp->fw_wq); }
static ssize_t lbs_host_sleep_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { struct lbs_private *priv = file->private_data; ssize_t buf_size, ret; int host_sleep; unsigned long addr = get_zeroed_page(GFP_KERNEL); char *buf = (char *)addr; if (!buf) return -ENOMEM; buf_size = min(count, len - 1); if (copy_from_user(buf, user_buf, buf_size)) { ret = -EFAULT; goto out_unlock; } ret = sscanf(buf, "%d", &host_sleep); if (ret != 1) { ret = -EINVAL; goto out_unlock; } if (host_sleep == 0) ret = lbs_set_host_sleep(priv, 0); else if (host_sleep == 1) { if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { lbs_pr_info("wake parameters not configured"); ret = -EINVAL; goto out_unlock; } ret = lbs_set_host_sleep(priv, 1); } else { lbs_pr_err("invalid option\n"); ret = -EINVAL; } if (!ret) ret = count; out_unlock: free_page(addr); return ret; }
/* * Called from if_cs_host_to_card to send a command to the hardware */ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb) { struct if_cs_card *card = (struct if_cs_card *)priv->card; int ret = -1; int loops = 0; lbs_deb_enter(LBS_DEB_CS); if_cs_disable_ints(card); /* Is hardware ready? */ while (1) { u16 status = if_cs_read16(card, IF_CS_CARD_STATUS); if (status & IF_CS_BIT_COMMAND) break; if (++loops > 100) { lbs_pr_err("card not ready for commands\n"); goto done; } mdelay(1); } if_cs_write16(card, IF_CS_CMD_LEN, nb); if_cs_write16_rep(card, IF_CS_CMD, buf, nb / 2); /* Are we supposed to transfer an odd amount of bytes? */ if (nb & 1) if_cs_write8(card, IF_CS_CMD, buf[nb-1]); /* "Assert the download over interrupt command in the Host * status register" */ if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); /* "Assert the download over interrupt command in the Card * interrupt case register" */ if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND); ret = 0; done: if_cs_enable_ints(card); lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); return ret; }
static int __if_usb_submit_rx_urb(wlan_private * priv, void (*callbackfn) (struct urb *urb)) { struct usb_card_rec *cardp = priv->card; struct sk_buff *skb; struct read_cb_info *rinfo = &cardp->rinfo; int ret = -1; if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) { lbs_pr_err("No free skb\n"); goto rx_ret; } rinfo->skb = skb; /* Fill the receive configuration URB and initialise the Rx call back */ usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, usb_rcvbulkpipe(cardp->udev, cardp->bulk_in_endpointAddr), (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET), MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, rinfo); cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; /* lbs_deb_usbd(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); */ if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) { /* handle failure conditions */ lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed\n"); ret = -1; } else { /* lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB success\n"); */ ret = 0; } rx_ret: return ret; }
static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, void (*callbackfn)(struct urb *urb)) { struct sk_buff *skb; int ret = -1; if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) { lbs_pr_err("No free skb\n"); goto rx_ret; } cardp->rx_skb = skb; /* Fill the receive configuration URB and initialise the Rx call back */ usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, usb_rcvbulkpipe(cardp->udev, cardp->ep_in), (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET), MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp); cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; lbs_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) { lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret); kfree_skb(skb); cardp->rx_skb = NULL; ret = -1; } else { lbs_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n"); ret = 0; } rx_ret: return ret; }
/** * @brief sets the configuration values * @param ifnum interface number * @param id pointer to usb_device_id * @return 0 on success, error code on failure */ static int if_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; wlan_private *priv; struct usb_card_rec *cardp; int i; udev = interface_to_usbdev(intf); cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL); if (!cardp) { lbs_pr_err("Out of memory allocating private data.\n"); goto error; } cardp->udev = udev; iface_desc = intf->cur_altsetting; lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n", le16_to_cpu(udev->descriptor.bcdUSB), udev->descriptor.bDeviceClass, udev->descriptor.bDeviceSubClass, udev->descriptor.bDeviceProtocol); for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk in endpoint */ lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n", le16_to_cpu(endpoint->wMaxPacketSize)); if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) { lbs_deb_usbd(&udev->dev, "Rx URB allocation failed\n"); goto dealloc; } cardp->rx_urb_recall = 0; cardp->bulk_in_size = le16_to_cpu(endpoint->wMaxPacketSize); cardp->bulk_in_endpointAddr = (endpoint-> bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n", endpoint->bEndpointAddress); } if (((endpoint-> bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* We found bulk out endpoint */ if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) { lbs_deb_usbd(&udev->dev, "Tx URB allocation failed\n"); goto dealloc; } cardp->bulk_out_size = le16_to_cpu(endpoint->wMaxPacketSize); lbs_deb_usbd(&udev->dev, "Bulk out size is %d\n", le16_to_cpu(endpoint->wMaxPacketSize)); cardp->bulk_out_endpointAddr = endpoint->bEndpointAddress; lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n", endpoint->bEndpointAddress); cardp->bulk_out_buffer = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL); if (!cardp->bulk_out_buffer) { lbs_deb_usbd(&udev->dev, "Could not allocate buffer\n"); goto dealloc; } } } if (!(priv = libertas_add_card(cardp, &udev->dev))) goto dealloc; if (libertas_add_mesh(priv, &udev->dev)) goto err_add_mesh; priv->hw_register_dev = if_usb_register_dev; priv->hw_unregister_dev = if_usb_unregister_dev; priv->hw_prog_firmware = if_usb_prog_firmware; priv->hw_host_to_card = if_usb_host_to_card; priv->hw_get_int_status = if_usb_get_int_status; priv->hw_read_event_cause = if_usb_read_event_cause; if (libertas_activate_card(priv, libertas_fw_name)) goto err_activate_card; list_add_tail(&cardp->list, &usb_devices); usb_get_dev(udev); usb_set_intfdata(intf, cardp); return 0; err_activate_card: libertas_remove_mesh(priv); err_add_mesh: free_netdev(priv->dev); kfree(priv->adapter); dealloc: if_usb_free(cardp); error: return -ENOMEM; }
/** * @brief sets the configuration values * @param ifnum interface number * @param id pointer to usb_device_id * @return 0 on success, error code on failure */ static int if_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; struct lbs_private *priv; struct if_usb_card *cardp; int i; udev = interface_to_usbdev(intf); cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL); if (!cardp) { lbs_pr_err("Out of memory allocating private data.\n"); goto error; } setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp); init_waitqueue_head(&cardp->fw_wq); cardp->udev = udev; iface_desc = intf->cur_altsetting; lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n", le16_to_cpu(udev->descriptor.bcdUSB), udev->descriptor.bDeviceClass, udev->descriptor.bDeviceSubClass, udev->descriptor.bDeviceProtocol); for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { cardp->ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize); cardp->ep_in = usb_endpoint_num(endpoint); lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in); lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size); } else if (usb_endpoint_is_bulk_out(endpoint)) { cardp->ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize); cardp->ep_out = usb_endpoint_num(endpoint); lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out); lbs_deb_usbd(&udev->dev, "Bulk out size is %d\n", cardp->ep_out_size); } } if (!cardp->ep_out_size || !cardp->ep_in_size) { lbs_deb_usbd(&udev->dev, "Endpoints not found\n"); goto dealloc; } if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) { lbs_deb_usbd(&udev->dev, "Rx URB allocation failed\n"); goto dealloc; } if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) { lbs_deb_usbd(&udev->dev, "Tx URB allocation failed\n"); goto dealloc; } cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL); if (!cardp->ep_out_buf) { lbs_deb_usbd(&udev->dev, "Could not allocate buffer\n"); goto dealloc; } /* Upload firmware */ if (if_usb_prog_firmware(cardp)) { lbs_deb_usbd(&udev->dev, "FW upload failed\n"); goto err_prog_firmware; } if (!(priv = lbs_add_card(cardp, &udev->dev))) goto err_prog_firmware; cardp->priv = priv; cardp->priv->fw_ready = 1; priv->hw_host_to_card = if_usb_host_to_card; #ifdef CONFIG_OLPC if (machine_is_olpc()) priv->reset_card = if_usb_reset_olpc_card; #endif cardp->boot2_version = udev->descriptor.bcdDevice; if_usb_submit_rx_urb(cardp); if (lbs_start_card(priv)) goto err_start_card; if_usb_setup_firmware(priv); usb_get_dev(udev); usb_set_intfdata(intf, cardp); return 0; err_start_card: lbs_remove_card(priv); err_prog_firmware: if_usb_reset_device(cardp); dealloc: if_usb_free(cardp); error: return -ENOMEM; }
static inline int handle_cmd_response(struct lbs_private *priv, struct cmd_header *cmd_response) { struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response; int ret = 0; unsigned long flags; uint16_t respcmd = le16_to_cpu(resp->command); lbs_deb_enter(LBS_DEB_HOST); switch (respcmd) { case CMD_RET(CMD_MAC_REG_ACCESS): case CMD_RET(CMD_BBP_REG_ACCESS): case CMD_RET(CMD_RF_REG_ACCESS): ret = lbs_ret_reg_access(priv, respcmd, resp); break; case CMD_RET_802_11_ASSOCIATE: case CMD_RET(CMD_802_11_ASSOCIATE): case CMD_RET(CMD_802_11_REASSOCIATE): ret = lbs_ret_80211_associate(priv, resp); break; case CMD_RET(CMD_802_11_SET_AFC): case CMD_RET(CMD_802_11_GET_AFC): spin_lock_irqsave(&priv->driver_lock, flags); memmove((void *)priv->cur_cmd->callback_arg, &resp->params.afc, sizeof(struct cmd_ds_802_11_afc)); spin_unlock_irqrestore(&priv->driver_lock, flags); break; case CMD_RET(CMD_802_11_AUTHENTICATE): case CMD_RET(CMD_802_11_BEACON_STOP): break; case CMD_RET(CMD_802_11_RSSI): ret = lbs_ret_802_11_rssi(priv, resp); break; case CMD_RET(CMD_802_11D_DOMAIN_INFO): ret = lbs_ret_802_11d_domain_info(resp); break; case CMD_RET(CMD_802_11_TPC_CFG): spin_lock_irqsave(&priv->driver_lock, flags); memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg, sizeof(struct cmd_ds_802_11_tpc_cfg)); spin_unlock_irqrestore(&priv->driver_lock, flags); break; case CMD_RET(CMD_802_11_LED_GPIO_CTRL): spin_lock_irqsave(&priv->driver_lock, flags); memmove((void *)priv->cur_cmd->callback_arg, &resp->params.ledgpio, sizeof(struct cmd_ds_802_11_led_ctrl)); spin_unlock_irqrestore(&priv->driver_lock, flags); break; case CMD_RET(CMD_GET_TSF): spin_lock_irqsave(&priv->driver_lock, flags); memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.gettsf.tsfvalue, sizeof(u64)); spin_unlock_irqrestore(&priv->driver_lock, flags); break; case CMD_RET(CMD_BT_ACCESS): spin_lock_irqsave(&priv->driver_lock, flags); if (priv->cur_cmd->callback_arg) memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.bt.addr1, 2 * ETH_ALEN); spin_unlock_irqrestore(&priv->driver_lock, flags); break; case CMD_RET(CMD_FWT_ACCESS): spin_lock_irqsave(&priv->driver_lock, flags); if (priv->cur_cmd->callback_arg) memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.fwt, sizeof(resp->params.fwt)); spin_unlock_irqrestore(&priv->driver_lock, flags); break; case CMD_RET(CMD_802_11_BEACON_CTRL): ret = lbs_ret_802_11_bcn_ctrl(priv, resp); break; default: lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n", le16_to_cpu(resp->command)); break; } lbs_deb_leave(LBS_DEB_HOST); return ret; }
/* * Check mesh FW version and appropriately send the mesh start * command */ int lbs_init_mesh(struct lbs_private *priv) { struct net_device *dev = priv->dev; int ret = 0; lbs_deb_enter(LBS_DEB_MESH); priv->mesh_connect_status = LBS_DISCONNECTED; /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ /* 5.110.22 have mesh command with 0xa3 command id */ /* 10.0.0.p0 FW brings in mesh config command with different id */ /* Check FW version MSB and initialize mesh_fw_ver */ if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) { /* Enable mesh, if supported, and work out which TLV it uses. 0x100 + 291 is an unofficial value used in 5.110.20.pXX 0x100 + 37 is the official value used in 5.110.21.pXX but we check them in that order because 20.pXX doesn't give an error -- it just silently fails. */ /* 5.110.20.pXX firmware will fail the command if the channel doesn't match the existing channel. But only if the TLV is correct. If the channel is wrong, _BOTH_ versions will give an error to 0x100+291, and allow 0x100+37 to succeed. It's just that 5.110.20.pXX will not have done anything useful */ priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->channel)) { priv->mesh_tlv = TLV_TYPE_MESH_ID; if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->channel)) priv->mesh_tlv = 0; } } else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) { /* 10.0.0.pXX new firmwares should succeed with TLV * 0x100+37; Do not invoke command with old TLV. */ priv->mesh_tlv = TLV_TYPE_MESH_ID; if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->channel)) priv->mesh_tlv = 0; } if (priv->mesh_tlv) { sprintf(priv->mesh_ssid, "mesh"); priv->mesh_ssid_len = 4; lbs_add_mesh(priv); if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) lbs_pr_err("cannot register lbs_mesh attribute\n"); ret = 1; } lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); return ret; }
static int lbs_init_adapter(struct lbs_private *priv) { size_t bufsize; int i, ret = 0; static u8 gnet_bss_desc[MAX_NETWORK_COUNT * sizeof(struct bss_descriptor)]; lbs_deb_enter("enter lbs_init_adapter\n"); /* Allocate buffer to store the BSSID list */ bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor); /*priv->networks = kzalloc(bufsize, GFP_KERNEL); if (!priv->networks) { lbs_pr_err("Out of memory allocating beacons\n"); ret = -1; goto out; }*/ priv->networks=(struct bss_descriptor *)gnet_bss_desc; memset(priv->networks,0,bufsize); /* Initialize scan result lists */ INIT_LIST_HEAD(&priv->network_free_list);//Initialize scan related list and objects. INIT_LIST_HEAD(&priv->network_list); //Link all bss descriptors into free list. for (i = 0; i < MAX_NETWORK_COUNT; i++) { list_add_tail(&priv->networks[i].list, &priv->network_free_list); } memset(priv->current_addr, 0xff, ETH_ALEN); priv->connect_status = LBS_DISCONNECTED; priv->mesh_connect_status = LBS_DISCONNECTED; priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; priv->mode = IW_MODE_INFRA; priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; priv->radio_on = 1; priv->enablehwauto = 1; priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; priv->psmode = LBS802_11POWERMODECAM; priv->psstate = PS_STATE_FULL_POWER; //mutex_init(&priv->lock); /*setup_timer(&priv->command_timer, command_timer_fn, (unsigned long)priv);*/ INIT_LIST_HEAD(&priv->cmdfreeq); INIT_LIST_HEAD(&priv->cmdpendingq); /*spin_lock_init(&priv->driver_lock); init_waitqueue_head(&priv->cmd_pending);*/ /* Allocate the command buffers */ if (lbs_allocate_cmd_buffer(priv)) { lbs_pr_err("Out of memory allocating command buffers\n"); ret = -ENOMEM; goto out; } priv->resp_idx = 0; priv->resp_len[0] = 0; //Contains the response from hardware. /* Create the event FIFO */ /*priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL); if (IS_ERR(priv->event_fifo)) { lbs_pr_err("Out of memory allocating event FIFO buffer\n"); ret = -ENOMEM; goto out; }*/ out: lbs_deb_leave_args("leave lbs_init_adapter(ret=%d)\n", ret); return ret; }