Browse Source

qcacmn: Hawkeye emulation WAR

SKBs allocated from higher memory instead of
lower memory range. This is needed for Hawkeye
emulation

Change-Id: Ibeb27c43ee882d772b9166731804faefab2e406e
CRs-Fixed: 2046721
Kris Muthusamy 8 years ago
parent
commit
ea7dc9339d
1 changed files with 65 additions and 0 deletions
  1. 65 0
      qdf/linux/src/qdf_nbuf.c

+ 65 - 0
qdf/linux/src/qdf_nbuf.c

@@ -183,21 +183,41 @@ qdf_nbuf_free_t nbuf_free_cb;
  *
  * Return: nbuf or %NULL if no memory
  */
+#if defined(QCA_WIFI_QCA8074) && defined (BUILD_X86)
 struct sk_buff *__qdf_nbuf_alloc(qdf_device_t osdev, size_t size, int reserve,
 			 int align, int prio)
 {
 	struct sk_buff *skb;
 	unsigned long offset;
+	uint32_t lowmem_alloc_tries = 0;
 
 	if (align)
 		size += (align - 1);
 
+realloc:
 	skb = dev_alloc_skb(size);
 
 	if (!skb) {
 		pr_info("ERROR:NBUF alloc failed\n");
 		return NULL;
 	}
+
+	/* Hawkeye M2M emulation cannot handle memory addresses below 0x50000040
+	 * Though we are trying to reserve low memory upfront to prevent this,
+	 * we sometimes see SKBs allocated from low memory.
+	 */
+	if (virt_to_phys(qdf_nbuf_data(skb) < 0x50000040)) {
+		lowmem_alloc_tries++;
+		if (lowmem_alloc_tries > 100) {
+			qdf_print("%s Failed \n",__func__);
+			return NULL;
+		} else {
+			/* Not freeing to make sure it
+			 * will not get allocated again
+			 */
+			goto realloc;
+		}
+	}
 	memset(skb->cb, 0x0, sizeof(skb->cb));
 
 	/*
@@ -226,6 +246,51 @@ struct sk_buff *__qdf_nbuf_alloc(qdf_device_t osdev, size_t size, int reserve,
 
 	return skb;
 }
+#else
+struct sk_buff *__qdf_nbuf_alloc(qdf_device_t osdev, size_t size, int reserve,
+			 int align, int prio)
+{
+	struct sk_buff *skb;
+	unsigned long offset;
+
+	if (align)
+		size += (align - 1);
+
+	skb = dev_alloc_skb(size);
+
+	if (!skb) {
+		pr_info("ERROR:NBUF alloc failed\n");
+		return NULL;
+	}
+	memset(skb->cb, 0x0, sizeof(skb->cb));
+
+	/*
+	 * The default is for netbuf fragments to be interpreted
+	 * as wordstreams rather than bytestreams.
+	 */
+	QDF_NBUF_CB_TX_EXTRA_FRAG_WORDSTR_EFRAG(skb) = 1;
+	QDF_NBUF_CB_TX_EXTRA_FRAG_WORDSTR_NBUF(skb) = 1;
+
+	/*
+	 * XXX:how about we reserve first then align
+	 * Align & make sure that the tail & data are adjusted properly
+	 */
+
+	if (align) {
+		offset = ((unsigned long)skb->data) % align;
+		if (offset)
+			skb_reserve(skb, align - offset);
+	}
+
+	/*
+	 * NOTE:alloc doesn't take responsibility if reserve unaligns the data
+	 * pointer
+	 */
+	skb_reserve(skb, reserve);
+
+	return skb;
+}
+#endif
 EXPORT_SYMBOL(__qdf_nbuf_alloc);
 
 /**