コード例 #1
0
/*
 * Broadcast Logging service ready indication to any Logging application
 * Each netlink message will have a message of type tAniMsgHdr inside.
 */
void wlan_logging_srv_nl_ready_indication(void)
{
	struct sk_buff *skb = NULL;
	struct nlmsghdr *nlh;
	tAniNlHdr *wnl = NULL;
	int payload_len;
	int    err;
	static int rate_limit;

	payload_len = sizeof(tAniHdr) + sizeof(wlan_logging_ready) +
		sizeof(wnl->radio);
	skb = dev_alloc_skb(NLMSG_SPACE(payload_len));
	if (NULL == skb) {
		if (!rate_limit) {
			LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR,
					"NLINK: skb alloc fail %s", __func__);
		}
		rate_limit = 1;
		return;
	}
	rate_limit = 0;

	nlh = nlmsg_put(skb, 0, 0, ANI_NL_MSG_LOG, payload_len,
			NLM_F_REQUEST);
	if (NULL == nlh) {
		LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR,
				"%s: nlmsg_put() failed for msg size[%d]",
				__func__, payload_len);
		kfree_skb(skb);
		return;
	}

	wnl = (tAniNlHdr *) nlh;
	wnl->radio = 0;
	wnl->wmsg.type = ANI_NL_MSG_READY_IND_TYPE;
	wnl->wmsg.length = sizeof(wlan_logging_ready);
	memcpy((char*)&wnl->wmsg + sizeof(tAniHdr),
			wlan_logging_ready,
			sizeof(wlan_logging_ready));

	/* sender is in group 1<<0 */
	NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID;

	/*multicast the message to all listening processes*/
	err = nl_srv_bcast(skb);
	if (err) {
		LOGGING_TRACE(VOS_TRACE_LEVEL_INFO_LOW,
			"NLINK: Ready Indication Send Fail %s, err %d",
			__func__, err);
	}
	return;
}
コード例 #2
0
static int send_filled_buffers_to_user(void)
{
	int ret = -1;
	struct log_msg *plog_msg;
	int payload_len;
	int tot_msg_len;
	tAniNlHdr *wnl;
	struct sk_buff *skb = NULL;
	struct nlmsghdr *nlh;
	static int nlmsg_seq;
	unsigned long flags;
	static int rate_limit;

	while (!list_empty(&gwlan_logging.filled_list)
		&& !gwlan_logging.exit) {

		skb = dev_alloc_skb(MAX_LOGMSG_LENGTH);
		if (skb == NULL) {
			if (!rate_limit) {
				pr_err("%s: dev_alloc_skb() failed for msg size[%d] drop count = %u\n",
					__func__, MAX_LOGMSG_LENGTH,
					gwlan_logging.drop_count);
			}
			rate_limit = 1;
			ret = -ENOMEM;
			break;
		}
		rate_limit = 0;

		spin_lock_irqsave(&gwlan_logging.spin_lock, flags);

		plog_msg = (struct log_msg *)
			(gwlan_logging.filled_list.next);
		list_del_init(gwlan_logging.filled_list.next);
		spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);
		/* 4 extra bytes for the radio idx */
		payload_len = plog_msg->filled_length +
			sizeof(wnl->radio) + sizeof(tAniHdr);

		tot_msg_len = NLMSG_SPACE(payload_len);
		nlh = nlmsg_put(skb, 0, nlmsg_seq++,
				ANI_NL_MSG_LOG, payload_len,
				NLM_F_REQUEST);
		if (NULL == nlh) {
			spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
			list_add_tail(&plog_msg->node,
				&gwlan_logging.free_list);
			spin_unlock_irqrestore(&gwlan_logging.spin_lock,
							flags);
			pr_err("%s: drop_count = %u\n", __func__,
				++gwlan_logging.drop_count);
			pr_err("%s: nlmsg_put() failed for msg size[%d]\n",
				__func__, tot_msg_len);
			dev_kfree_skb(skb);
			skb = NULL;
			ret = -EINVAL;
			continue;
		}

		wnl = (tAniNlHdr *) nlh;
		wnl->radio = plog_msg->radio;
		vos_mem_copy(&wnl->wmsg, plog_msg->logbuf,
				plog_msg->filled_length +
				sizeof(tAniHdr));

		spin_lock_irqsave(&gwlan_logging.spin_lock, flags);
		list_add_tail(&plog_msg->node,
				&gwlan_logging.free_list);
		spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);

		ret = nl_srv_bcast(skb);
		if (ret < 0) {
			if (__ratelimit(&errCnt))
			{
			    pr_info("%s: Send Failed %d drop_count = %u\n",
				  __func__, ret, gwlan_logging.drop_count);
			}
			gwlan_logging.drop_count++;
			skb = NULL;
			break;
		} else {
			skb = NULL;
			ret = 0;
		}
	}

	return ret;
}
コード例 #3
0
ファイル: wlan_btc_svc.c プロジェクト: Zoldyck07/prima
/*
 * Send a netlink message to the user space. 
 * Destination pid as zero implies broadcast
 */
void send_btc_nlink_msg (int type, int dest_pid)
{
   struct sk_buff *skb;
   struct nlmsghdr *nlh;
   tAniMsgHdr *aniHdr;
   tWlanAssocData *assocData;
   skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
   if(skb == NULL) {
      VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
         "BTC: alloc_skb failed\n");
      return;
   }   
   nlh = (struct nlmsghdr *)skb->data;
   nlh->nlmsg_pid = 0;  /* from kernel */
   nlh->nlmsg_flags = 0;
   nlh->nlmsg_seq = 0;
   nlh->nlmsg_type = WLAN_NL_MSG_BTC;
   aniHdr = NLMSG_DATA(nlh);
   aniHdr->type = type;

  /* Set BTC driver mode correctly based on received events type */
  if(type == WLAN_BTC_SOFTAP_BSS_START)
  {
     /* Event is SoftAP BSS Start set BTC driver mode to SoftAP */
     gBtcDriverMode = WLAN_HDD_SOFTAP;
  }
  if(type == WLAN_STA_ASSOC_DONE_IND)
  {
     /* Event is STA Assoc done set BTC driver mode to INFRA STA*/
     gBtcDriverMode = WLAN_HDD_INFRA_STATION;
  }

   switch( type )
   {
      case WLAN_STA_DISASSOC_DONE_IND:
         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,
                    "WiFi unassociated; gAmpChannel %d gWiFiChannel %d", gAmpChannel, gWiFiChannel);

         /* If AMP is using a channel (non-zero), no message sent.
            Or, if WiFi wasn't using a channel before, no message sent.
            Logic presumes same channel has to be used for WiFi and AMP if both are active.
            In any case, track the WiFi channel in use (none) */
         if((gAmpChannel != 0) || (gWiFiChannel == 0))
         {
           VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,
                      "No msg for AFH will be sent");
            gWiFiChannel = 0;
            kfree_skb(skb);
            return;
         }
         gWiFiChannel = 0;

         /* No Break: Fall into next cases */

      case WLAN_MODULE_UP_IND:
      case WLAN_MODULE_DOWN_IND:
         aniHdr->length = 0; 
         nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
         skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
         break;
      case WLAN_BTC_SOFTAP_BSS_START:
      case WLAN_BTC_QUERY_STATE_RSP:
      case WLAN_STA_ASSOC_DONE_IND:
         aniHdr->length = sizeof(tWlanAssocData);
         nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + sizeof(tWlanAssocData)));
         assocData = ( tWlanAssocData *)((char*)aniHdr + sizeof(tAniMsgHdr));
         
         assocData->channel = hdd_get_operating_channel( pHddCtx, gBtcDriverMode );

         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,
                    "New WiFi channel %d gAmpChannel %d gWiFiChannel %d",
                    assocData->channel, gAmpChannel, gWiFiChannel);

         /* If WiFi has finished associating */
         if(type == WLAN_STA_ASSOC_DONE_IND)
         {
           /* If AMP is using a channel (non-zero), no message sent.
              Or, if the WiFi channel did not change, no message sent.
              Logic presumes same channel has to be used for WiFi and AMP if both are active.
              In any case, track the WiFi channel in use (1-13 or none, in assocData->channel) */
           if((gAmpChannel != 0) || (assocData->channel == gWiFiChannel))
           {
             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,
                        "No msg for AFH will be sent");
             gWiFiChannel = assocData->channel;
             kfree_skb(skb);
             return;
           }
         }
         if(type == WLAN_BTC_SOFTAP_BSS_START)
         {
             /*Replace WLAN_BTC_SOFTAP_BSS_START by WLAN_STA_ASSOC_DONE_IND*/
             aniHdr->type = WLAN_STA_ASSOC_DONE_IND;
         }
         gWiFiChannel = assocData->channel;
         skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr)+ sizeof(tWlanAssocData))));
         break;

      case WLAN_AMP_ASSOC_DONE_IND:

         /* This is an overloaded type. It means that AMP is connected (dest_pid is channel 1-13),
            or it means AMP is now disconnected (dest_pid is 0) */

         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,
                    "New AMP channel %d gAmpChannel %d gWiFiChannel %d", dest_pid, gAmpChannel, gWiFiChannel);
         /* If WiFi is using a channel (non-zero), no message sent.
            Or, if the AMP channel did not change, no message sent.
            Logic presumes same channel has to be used for WiFi and AMP if both are active.
            In any case, track the AMP channel in use (1-13 or none, in dest_pid) */
         if((gWiFiChannel != 0) || (dest_pid == gAmpChannel))
         {
           VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW,
                      "No msg for AFH will be sent");
            gAmpChannel = dest_pid;
            kfree_skb(skb);
            return;
         }

         gAmpChannel = dest_pid;

         /* Fix overloaded parameters and finish message formatting */
         if(dest_pid != 0)
         {
           aniHdr->type = WLAN_STA_ASSOC_DONE_IND;
           aniHdr->length = sizeof(tWlanAssocData);
           nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + sizeof(tWlanAssocData)));
           assocData = ( tWlanAssocData *)((char*)aniHdr + sizeof(tAniMsgHdr));
           assocData->channel = dest_pid;
           skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr)+ sizeof(tWlanAssocData))));
         }
         else
         {
           aniHdr->type = WLAN_STA_DISASSOC_DONE_IND;
           aniHdr->length = 0;
           nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr)));
           skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr)));
         }
         dest_pid = 0;
         break;

      default:
         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, 
            "BTC: Attempt to send unknown nlink message %d\n", type);
         kfree_skb(skb);
         return;
   }
   if(dest_pid == 0)
      (void)nl_srv_bcast(skb);
   else
      (void)nl_srv_ucast(skb, dest_pid);
}
コード例 #4
0
static int send_data_mgmt_log_pkt_to_user(void)
{
	int ret = -1;
	int extra_header_len, nl_payload_len;
	struct sk_buff *skb = NULL;
	static int nlmsg_seq;
	vos_pkt_t *current_pkt;
	vos_pkt_t *next_pkt;
	VOS_STATUS status = VOS_STATUS_E_FAILURE;
	unsigned long flags;

	tAniNlLogHdr msg_header;

	do {
		spin_lock_irqsave(&gwlan_logging.data_mgmt_pkt_lock, flags);

		if (!gwlan_logging.data_mgmt_pkt_queue) {
			spin_unlock_irqrestore(
				&gwlan_logging.data_mgmt_pkt_lock, flags);
			return -EIO;
		}

		/* pick first pkt from queued chain */
		current_pkt = gwlan_logging.data_mgmt_pkt_queue;

		/* get the pointer to the next packet in the chain */
		status = vos_pkt_walk_packet_chain(current_pkt, &next_pkt,
							TRUE);

		/* both "success" and "empty" are acceptable results */
		if (!((status == VOS_STATUS_SUCCESS) ||
					(status == VOS_STATUS_E_EMPTY))) {
			++gwlan_logging.pkt_drop_cnt;
			spin_unlock_irqrestore(
				&gwlan_logging.data_mgmt_pkt_lock, flags);
			pr_err("%s: Failure walking packet chain", __func__);
			return -EIO;
		}

		/* update queue head with next pkt ptr which could be NULL */
		gwlan_logging.data_mgmt_pkt_queue = next_pkt;
		--gwlan_logging.data_mgmt_pkt_qcnt;
		spin_unlock_irqrestore(&gwlan_logging.data_mgmt_pkt_lock, flags);

		status = vos_pkt_get_os_packet(current_pkt, (v_VOID_t **)&skb,
						TRUE);
		if (!VOS_IS_STATUS_SUCCESS(status)) {
			++gwlan_logging.pkt_drop_cnt;
			pr_err("%s: Failure extracting skb from vos pkt",
				__func__);
			return -EIO;
		}

		/*return vos pkt since skb is already detached */
		vos_pkt_return_packet(current_pkt);

		extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr) +
						sizeof(msg_header.frameSize);
		nl_payload_len = NLMSG_ALIGN(extra_header_len + skb->len);

		msg_header.nlh.nlmsg_type = ANI_NL_MSG_LOG;
		msg_header.nlh.nlmsg_len = nl_payload_len;
		msg_header.nlh.nlmsg_flags = NLM_F_REQUEST;
		msg_header.nlh.nlmsg_pid = 0;
		msg_header.nlh.nlmsg_seq = nlmsg_seq++;

		msg_header.radio = 0;

		msg_header.wmsg.type = ANI_NL_MSG_LOG_PKT_TYPE;
		msg_header.wmsg.length = skb->len + sizeof(uint32);

		msg_header.frameSize = WLAN_MGMT_LOGGING_FRAMESIZE_128BYTES;

		if (unlikely(skb_headroom(skb) < sizeof(msg_header))) {
			pr_err("VPKT [%d]: Insufficient headroom, head[%p],"
				" data[%p], req[%zu]", __LINE__, skb->head,
				skb->data, sizeof(msg_header));
			return -EIO;
		}

		vos_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header,
							sizeof(msg_header));

		ret =  nl_srv_bcast(skb);
		if (ret < 0) {
			pr_info("%s: Send Failed %d drop_count = %u\n",
				__func__, ret, ++gwlan_logging.pkt_drop_cnt);
		} else {
			ret = 0;
		}

	} while (next_pkt);

	return ret;
}