svn commit: r250340 - head/sys/dev/qlxgb

David C Somayajulu davidcs at FreeBSD.org
Tue May 7 22:58:46 UTC 2013


Author: davidcs
Date: Tue May  7 22:58:42 2013
New Revision: 250340
URL: http://svnweb.freebsd.org/changeset/base/250340

Log:
  1. Updated Copyright Information
  2. Added Flash Read/Update Support
  3. Fixed TSO Handling
  
  Submitted by: David C Somayajulu (davidcs at freebsd.org)
  Reviewed by: George Neville-Neil (gnn at freebsd.org)
  Approved by: George Neville-Neil (gnn at freebsd.org)

Modified:
  head/sys/dev/qlxgb/README.txt
  head/sys/dev/qlxgb/qla_dbg.c
  head/sys/dev/qlxgb/qla_dbg.h
  head/sys/dev/qlxgb/qla_def.h
  head/sys/dev/qlxgb/qla_glbl.h
  head/sys/dev/qlxgb/qla_hw.c
  head/sys/dev/qlxgb/qla_hw.h
  head/sys/dev/qlxgb/qla_inline.h
  head/sys/dev/qlxgb/qla_ioctl.c
  head/sys/dev/qlxgb/qla_ioctl.h
  head/sys/dev/qlxgb/qla_isr.c
  head/sys/dev/qlxgb/qla_misc.c
  head/sys/dev/qlxgb/qla_os.c
  head/sys/dev/qlxgb/qla_os.h
  head/sys/dev/qlxgb/qla_reg.h
  head/sys/dev/qlxgb/qla_ver.h

Modified: head/sys/dev/qlxgb/README.txt
==============================================================================
--- head/sys/dev/qlxgb/README.txt	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/README.txt	Tue May  7 22:58:42 2013	(r250340)
@@ -93,7 +93,7 @@ Technical Support at any phase of integr
 Technical Support can be reached by the following methods: 
 Web:    http://support.qlogic.com
 E-mail: support at qlogic.com
-(c) Copyright 2011. All rights reserved worldwide. QLogic, the QLogic 
+(c) Copyright 2013. All rights reserved worldwide. QLogic, the QLogic 
 logo, and the Powered by QLogic logo are registered trademarks of
 QLogic Corporation. All other brand and product names are trademarks 
 or registered trademarks of their respective owners. 

Modified: head/sys/dev/qlxgb/qla_dbg.c
==============================================================================
--- head/sys/dev/qlxgb/qla_dbg.c	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_dbg.c	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without

Modified: head/sys/dev/qlxgb/qla_dbg.h
==============================================================================
--- head/sys/dev/qlxgb/qla_dbg.h	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_dbg.h	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without

Modified: head/sys/dev/qlxgb/qla_def.h
==============================================================================
--- head/sys/dev/qlxgb/qla_def.h	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_def.h	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -194,6 +194,8 @@ struct qla_host {
 	/* debug stuff */
 	volatile const char 	*qla_lock;
 	volatile const char	*qla_unlock;
+
+	uint8_t			fw_ver_str[32];
 };
 typedef struct qla_host qla_host_t;
 

Modified: head/sys/dev/qlxgb/qla_glbl.h
==============================================================================
--- head/sys/dev/qlxgb/qla_glbl.h	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_glbl.h	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -56,14 +56,6 @@ extern void qla_start(struct ifnet *ifp)
 extern int qla_get_mbuf(qla_host_t *ha, qla_rx_buf_t *rxb, struct mbuf *nmp,
 	        uint32_t jumbo);
 
-
-/*
- * from qla_flash.c
- */
-extern int qla_flash_rd32_words(qla_host_t *ha, uint32_t addr,
-		uint32_t *val, uint32_t num);
-extern int qla_flash_rd32(qla_host_t *ha, uint32_t addr, uint32_t *val);
-
 /*
  * from qla_hw.c
  */
@@ -97,6 +89,14 @@ extern int qla_init_hw(qla_host_t *ha);
 extern int qla_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val,
 		uint32_t rd);
 extern int qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data);
+extern int qla_flash_rd32_words(qla_host_t *ha, uint32_t addr,
+		uint32_t *val, uint32_t num);
+extern int qla_flash_rd32(qla_host_t *ha, uint32_t addr, uint32_t *val);
+extern int qla_fw_update(qla_host_t *ha, void *fdata, uint32_t off,
+		uint32_t size);
+extern int qla_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size);
+extern int qla_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size,
+		void *buf, uint32_t pattern);
 
 /*
  * from qla_ioctl.c

Modified: head/sys/dev/qlxgb/qla_hw.c
==============================================================================
--- head/sys/dev/qlxgb/qla_hw.c	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_hw.c	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2012 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -711,20 +711,18 @@ qla_config_ipv4_addr(qla_host_t *ha, uin
  *	Ring Structure are plugged in.
  */
 static int
-qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd)
+qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
 {
 	struct ether_vlan_header *eh;
 	struct ip *ip = NULL;
 	struct tcphdr *th = NULL;
-	uint32_t ehdrlen,  hdrlen, ip_hlen, tcp_hlen;
+	uint32_t ehdrlen,  hdrlen = 0, ip_hlen, tcp_hlen, tcp_opt_off;
 	uint16_t etype, opcode, offload = 1;
+	uint8_t *tcp_opt;
 	device_t dev;
 
 	dev = ha->pci_dev;
 
-	if (mp->m_pkthdr.len <= ha->max_frame_size)
-		return (-1);
-
 	eh = mtod(mp, struct ether_vlan_header *);
 
 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
@@ -737,14 +735,26 @@ qla_tx_tso(qla_host_t *ha, struct mbuf *
 
 	switch (etype) {
 		case ETHERTYPE_IP:
-			ip = (struct ip *)(mp->m_data + ehdrlen);
+
+			tcp_opt_off = ehdrlen + sizeof(struct ip) +
+					sizeof(struct tcphdr);
+
+			if (mp->m_len < tcp_opt_off) {
+				m_copydata(mp, 0, tcp_opt_off, hdr);
+				ip = (struct ip *)hdr;
+			} else {
+				ip = (struct ip *)(mp->m_data + ehdrlen);
+			}
+
 			ip_hlen = ip->ip_hl << 2;
 			opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
 
-			if (ip->ip_p != IPPROTO_TCP) {
+			if ((ip->ip_p != IPPROTO_TCP) ||
+				(ip_hlen != sizeof (struct ip))) {
 				offload = 0;
-			} else
+			} else {
 				th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
+			}
 		break;
 
 		default:
@@ -758,11 +768,43 @@ qla_tx_tso(qla_host_t *ha, struct mbuf *
 
 	tcp_hlen = th->th_off << 2;
 
+
 	hdrlen = ehdrlen + ip_hlen + tcp_hlen;
 
 	if (mp->m_len < hdrlen) {
-		device_printf(dev, "%s: (mp->m_len < hdrlen)\n", __func__);
-		return (-1);
+		if (mp->m_len < tcp_opt_off) {
+			if (tcp_hlen > sizeof(struct tcphdr)) {
+				m_copydata(mp, tcp_opt_off,
+					(tcp_hlen - sizeof(struct tcphdr)),
+					&hdr[tcp_opt_off]);
+			}
+		} else {
+			m_copydata(mp, 0, hdrlen, hdr);
+		}
+	}
+
+	if ((mp->m_pkthdr.csum_flags & CSUM_TSO) == 0) {
+
+		/* If TCP options are preset only time stamp option is supported */
+		if ((tcp_hlen - sizeof(struct tcphdr)) != 10) 
+			return -1;
+		else {
+
+			if (mp->m_len < hdrlen) {
+				tcp_opt = &hdr[tcp_opt_off];
+			} else {
+				tcp_opt = (uint8_t *)(mp->m_data + tcp_opt_off);
+			}
+
+			if ((*tcp_opt != 0x01) || (*(tcp_opt + 1) != 0x01) ||
+				(*(tcp_opt + 2) != 0x08) || (*(tcp_opt + 2) != 10)) {
+				return -1;
+			}
+		}
+
+		tx_cmd->mss = ha->max_frame_size - ETHER_CRC_LEN - hdrlen;
+	} else {
+		tx_cmd->mss = mp->m_pkthdr.tso_segsz;
 	}
 
 	tx_cmd->flags_opcode = opcode ;
@@ -776,6 +818,10 @@ qla_tx_tso(qla_host_t *ha, struct mbuf *
 		tx_cmd->flags_opcode = Q8_TX_CMD_FLAGS_MULTICAST;
 	}
 
+	if (mp->m_len < hdrlen) {
+		return (1);
+	}
+
 	return (0);
 }
 
@@ -815,7 +861,7 @@ qla_tx_chksum(qla_host_t *ha, struct mbu
 		case ETHERTYPE_IP:
 			ip = (struct ip *)(mp->m_data + ehdrlen);
 
-			ip_hlen = ip->ip_hl << 2;
+			ip_hlen = sizeof (struct ip);
 
 			if (mp->m_len < (ehdrlen + ip_hlen)) {
 				device_printf(dev, "%s: ipv4 mlen\n", __func__);
@@ -886,7 +932,8 @@ qla_hw_send(qla_host_t *ha, bus_dma_segm
 	uint32_t num_tx_cmds, hdr_len = 0;
 	uint32_t total_length = 0, bytes, tx_cmd_count = 0;
 	device_t dev;
-	int i;
+	int i, ret;
+	uint8_t *src = NULL, *dst = NULL;
 
 	dev = ha->pci_dev;
 
@@ -902,26 +949,36 @@ qla_hw_send(qla_host_t *ha, bus_dma_segm
 			__func__, total_length);
 		return (-1);
 	}
+	eh = mtod(mp, struct ether_vlan_header *);
 
-	bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
+	if ((mp->m_pkthdr.len > ha->max_frame_size)||(nsegs > Q8_TX_MAX_SEGMENTS)) {
 
-	if (qla_tx_tso(ha, mp, &tso_cmd) == 0) {
-		/* find the additional tx_cmd descriptors required */
+		bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
 
-		hdr_len = tso_cmd.total_hdr_len;
+		src = ha->hw.frame_hdr;
+		ret = qla_tx_tso(ha, mp, &tso_cmd, src);
 
-		bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
-		bytes = QL_MIN(bytes, hdr_len);
+		if (!(ret & ~1)) {
+			/* find the additional tx_cmd descriptors required */
 
-		num_tx_cmds++;
-		hdr_len -= bytes;
+			hdr_len = tso_cmd.total_hdr_len;
 
-		while (hdr_len) {
-			bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
-			hdr_len -= bytes;
+			bytes = sizeof(q80_tx_cmd_t) - Q8_TX_CMD_TSO_ALIGN;
+			bytes = QL_MIN(bytes, hdr_len);
+	
 			num_tx_cmds++;
+			hdr_len -= bytes;
+
+			while (hdr_len) {
+				bytes = QL_MIN((sizeof(q80_tx_cmd_t)), hdr_len);
+				hdr_len -= bytes;
+				num_tx_cmds++;
+			}
+			hdr_len = tso_cmd.total_hdr_len;
+
+			if (ret == 0)
+				src = (uint8_t *)eh;
 		}
-		hdr_len = tso_cmd.total_hdr_len;
 	}
 
 	if (hw->txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
@@ -957,7 +1014,6 @@ qla_hw_send(qla_host_t *ha, bus_dma_segm
 		bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
 	}
 
-	eh = mtod(mp, struct ether_vlan_header *);
 	if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN))
         	tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
 	else if (mp->m_flags & M_VLANTAG) {
@@ -1015,9 +1071,6 @@ qla_hw_send(qla_host_t *ha, bus_dma_segm
 
 	if (hdr_len) {
 		/* TSO : Copy the header in the following tx cmd descriptors */
-		uint8_t *src, *dst;
-
-		src = (uint8_t *)eh;
 
 		tx_cmd = &hw->tx_ring_base[hw->txr_next];
 		bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
@@ -1704,6 +1757,7 @@ void
 qla_update_link_state(qla_host_t *ha)
 {
 	uint32_t link_state;
+	uint32_t prev_link_state;
 
 	if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
 		ha->hw.flags.link_up = 0;
@@ -1711,10 +1765,20 @@ qla_update_link_state(qla_host_t *ha)
 	}
 	link_state = READ_REG32(ha, Q8_LINK_STATE);
 
-	if (ha->pci_func == 0) 
+	prev_link_state =  ha->hw.flags.link_up;
+
+	if (ha->pci_func == 0)
 		ha->hw.flags.link_up = (((link_state & 0xF) == 1)? 1 : 0);
 	else
 		ha->hw.flags.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
+
+	if (prev_link_state !=  ha->hw.flags.link_up) {
+		if (ha->hw.flags.link_up) {
+			if_link_state_change(ha->ifp, LINK_STATE_UP);
+		} else {
+			if_link_state_change(ha->ifp, LINK_STATE_DOWN);
+		}
+	}
 }
 
 int

Modified: head/sys/dev/qlxgb/qla_hw.h
==============================================================================
--- head/sys/dev/qlxgb/qla_hw.h	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_hw.h	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -724,6 +724,8 @@ typedef struct _qla_sds {
 	volatile uint32_t rcv_active;
 } qla_sds_t;
 
+#define QL_FRAME_HDR_SIZE (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN +\
+		sizeof (struct ip) + sizeof (struct tcphdr) + 16)
 /*
  * struct for storing hardware specific information for a given interface
  */
@@ -791,6 +793,8 @@ typedef struct _qla_hw {
 	bus_addr_t	rx_cntxt_rsp_paddr;
 	
 	qla_sds_t	sds[MAX_SDS_RINGS]; 
+
+	uint8_t		frame_hdr[QL_FRAME_HDR_SIZE];
 } qla_hw_t;
 
 #define QL_UPDATE_RDS_PRODUCER_INDEX(ha, i, val) \

Modified: head/sys/dev/qlxgb/qla_inline.h
==============================================================================
--- head/sys/dev/qlxgb/qla_inline.h	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_inline.h	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without

Modified: head/sys/dev/qlxgb/qla_ioctl.c
==============================================================================
--- head/sys/dev/qlxgb/qla_ioctl.c	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_ioctl.c	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -82,10 +82,15 @@ qla_eioctl(struct cdev *dev, u_long cmd,
         int rval = 0;
         qla_reg_val_t *rv;
         qla_rd_flash_t *rdf;
+	qla_wr_flash_t *wrf;
+	qla_rd_pci_ids_t *pci_ids;
+	device_t pci_dev;
 
         if ((ha = (qla_host_t *)dev->si_drv1) == NULL)
                 return ENXIO;
 
+	pci_dev= ha->pci_dev;
+
         switch(cmd) {
 
         case QLA_RDWR_REG:
@@ -110,6 +115,30 @@ qla_eioctl(struct cdev *dev, u_long cmd,
                 if ((rval = qla_rd_flash32(ha, rdf->off, &rdf->data)))
                         rval = ENXIO;
                 break;
+
+        case QLA_WR_FLASH:
+                wrf = (qla_wr_flash_t *)data;
+                if ((rval = qla_wr_flash_buffer(ha, wrf->off, wrf->size,
+					wrf->buffer, wrf->pattern)))
+                        rval = ENXIO;
+                break;
+
+
+	case QLA_ERASE_FLASH:
+		if (qla_erase_flash(ha, ((qla_erase_flash_t *)data)->off,
+			((qla_erase_flash_t *)data)->size))
+			rval = ENXIO;
+		break;
+
+	case QLA_RD_PCI_IDS:
+		pci_ids = (qla_rd_pci_ids_t *)data;
+		pci_ids->ven_id = pci_get_vendor(pci_dev);
+		pci_ids->dev_id = pci_get_device(pci_dev);
+		pci_ids->subsys_ven_id = pci_get_subvendor(pci_dev);
+		pci_ids->subsys_dev_id = pci_get_subdevice(pci_dev);
+		pci_ids->rev_id = pci_read_config(pci_dev, PCIR_REVID, 1);
+		break;
+		
         default:
                 break;
         }

Modified: head/sys/dev/qlxgb/qla_ioctl.h
==============================================================================
--- head/sys/dev/qlxgb/qla_ioctl.h	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_ioctl.h	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -50,6 +50,28 @@ struct qla_rd_flash {
 };
 typedef struct qla_rd_flash qla_rd_flash_t;
 
+struct qla_wr_flash {
+	uint32_t off;
+	uint32_t size;
+	void *buffer;
+	uint32_t pattern;
+};
+typedef struct qla_wr_flash qla_wr_flash_t;
+
+struct qla_erase_flash {
+	uint32_t off;
+	uint32_t size;
+};
+typedef struct qla_erase_flash qla_erase_flash_t;
+
+struct qla_rd_pci_ids {
+	uint16_t ven_id;
+	uint16_t dev_id;
+	uint16_t subsys_ven_id;
+	uint16_t subsys_dev_id;
+	uint8_t rev_id;
+};
+typedef struct qla_rd_pci_ids qla_rd_pci_ids_t;
 
 /*
  * Read/Write Register
@@ -61,4 +83,19 @@ typedef struct qla_rd_flash qla_rd_flash
  */
 #define QLA_RD_FLASH                    _IOWR('q', 2, qla_rd_flash_t)
 
+/*
+ * Write Flash
+ */
+#define QLA_WR_FLASH			_IOWR('q', 3, qla_wr_flash_t)
+
+/*
+ * Erase Flash
+ */
+#define QLA_ERASE_FLASH			_IOWR('q', 5, qla_erase_flash_t)
+
+/*
+ * Read PCI IDs 
+ */
+#define QLA_RD_PCI_IDS			_IOWR('q', 6, qla_rd_pci_ids_t)			
+
 #endif /* #ifndef _QLA_IOCTL_H_ */

Modified: head/sys/dev/qlxgb/qla_isr.c
==============================================================================
--- head/sys/dev/qlxgb/qla_isr.c	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_isr.c	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without

Modified: head/sys/dev/qlxgb/qla_misc.c
==============================================================================
--- head/sys/dev/qlxgb/qla_misc.c	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_misc.c	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -344,6 +344,17 @@ qla_rd_flash32(qla_host_t *ha, uint32_t 
 	return 0;
 }
 
+static int
+qla_p3p_sem_lock2(qla_host_t *ha)
+{
+        if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
+                device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
+                return (-1);
+        }
+        WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
+        return (0);
+}
+
 /*
  * Name: qla_int_to_pci_addr_map
  * Function: Convert's Internal(CRB) Address to Indirect Address
@@ -402,7 +413,7 @@ qla_filter_pci_addr(qla_host_t *ha, uint
 static int
 qla_crb_init(qla_host_t *ha)
 {
-	uint32_t val, sig;
+	uint32_t val = 0, sig = 0;
 	uint32_t offset, count, i;
 	addr_val_t *addr_val_map, *avmap;
 
@@ -611,6 +622,21 @@ qla_init_hw(qla_host_t *ha)
 	if (val != CMDPEG_PHAN_INIT_COMPLETE) {
         	ret = qla_init_from_flash(ha);
 		qla_mdelay(__func__, 100);
+	} else {
+        	ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
+        	ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
+		ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
+
+		if (qla_rd_flash32(ha, 0x100004, &val) == 0) {
+
+			if (((val & 0xFF) != ha->fw_ver_major) ||
+				(((val >> 8) & 0xFF) != ha->fw_ver_minor) ||
+				(((val >> 16) & 0xFF) != ha->fw_ver_sub)) {
+
+        			ret = qla_init_from_flash(ha);
+				qla_mdelay(__func__, 100);
+			}
+		}
 	}
 
 qla_init_exit:
@@ -622,3 +648,403 @@ qla_init_exit:
         return (ret);
 }
 
+static int
+qla_wait_for_flash_busy(qla_host_t *ha)
+{
+	uint32_t count = 100;
+	uint32_t val;
+
+	QLA_USEC_DELAY(100);
+
+	while (count--) {
+		val = READ_OFFSET32(ha, Q8_ROM_STATUS);
+
+		if (val & BIT_1)
+			return 0;
+		qla_mdelay(__func__, 1);
+	}
+	return -1;
+}
+
+static int
+qla_flash_write_enable(qla_host_t *ha)
+{
+	uint32_t val, rval;
+
+	val = 0;
+	qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
+
+	val = ROM_OPCODE_WR_ENABLE;
+	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
+
+	rval = qla_wait_for_flash_busy(ha);
+
+	if (rval)
+		device_printf(ha->pci_dev, "%s: failed \n", __func__);
+
+	return (rval);
+}
+
+static int
+qla_flash_unprotect(qla_host_t *ha)
+{
+	uint32_t val, rval;
+
+	if (qla_flash_write_enable(ha) != 0) 
+		return(-1);
+
+	val = 0;
+	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
+
+	val = ROM_OPCODE_WR_STATUS_REG;
+	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
+	
+	rval = qla_wait_for_flash_busy(ha);
+
+	if (rval) {
+		device_printf(ha->pci_dev, "%s: failed \n", __func__);
+		return rval;
+	}
+
+	if (qla_flash_write_enable(ha) != 0) 
+		return(-1);
+
+	val = 0;
+	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
+
+	val = ROM_OPCODE_WR_STATUS_REG;
+	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
+	
+	rval = qla_wait_for_flash_busy(ha);
+
+	if (rval)
+		device_printf(ha->pci_dev, "%s: failed \n", __func__);
+
+	return rval;
+}
+
+static int
+qla_flash_protect(qla_host_t *ha)
+{
+	uint32_t val, rval;
+
+	if (qla_flash_write_enable(ha) != 0) 
+		return(-1);
+
+	val = 0x9C;
+	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
+
+	val = ROM_OPCODE_WR_STATUS_REG;
+	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
+	
+	rval = qla_wait_for_flash_busy(ha);
+
+	if (rval)
+		device_printf(ha->pci_dev, "%s: failed \n", __func__);
+
+	return rval;
+}
+
+static uint32_t
+qla_flash_get_status(qla_host_t *ha)
+{
+	uint32_t count = 1000;
+	uint32_t val, rval;
+
+	while (count--) {
+		val = 0;
+		qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
+			
+		val = ROM_OPCODE_RD_STATUS_REG;
+		qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
+	
+		rval = qla_wait_for_flash_busy(ha);
+
+		if (rval == 0) {
+			qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
+
+			if ((val & BIT_0) == 0)
+				return (val);
+		}
+		qla_mdelay(__func__, 1);
+	}
+	return -1;
+}
+
+static int
+qla_wait_for_flash_unprotect(qla_host_t *ha)
+{
+	uint32_t delay = 1000;
+
+	while (delay--) {
+
+		if (qla_flash_get_status(ha) == 0)
+			return 0;
+
+		qla_mdelay(__func__, 1);
+	}
+
+	return -1;
+}
+
+static int
+qla_wait_for_flash_protect(qla_host_t *ha)
+{
+	uint32_t delay = 1000;
+
+	while (delay--) {
+
+		if (qla_flash_get_status(ha) == 0x9C)
+			return 0;
+
+		qla_mdelay(__func__, 1);
+	}
+
+	return -1;
+}
+
+static int
+qla_erase_flash_sector(qla_host_t *ha, uint32_t start)
+{
+	uint32_t val;
+	int rval;
+
+	if (qla_flash_write_enable(ha) != 0) 
+		return(-1);
+
+        val = start;
+        qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
+
+        val = 3;
+        qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
+
+        val = ROM_OPCODE_SECTOR_ERASE;
+        qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
+
+	rval = qla_wait_for_flash_busy(ha);
+
+	if (rval)
+		device_printf(ha->pci_dev, "%s: failed \n", __func__);
+	return rval;
+}
+
+#define Q8_FLASH_SECTOR_SIZE 0x10000
+int
+qla_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
+{
+	int rval = 0;
+	uint32_t start;
+
+	if (off & (Q8_FLASH_SECTOR_SIZE -1))
+		return -1;
+
+	if ((rval = qla_p3p_sem_lock2(ha)))
+		goto qla_erase_flash_exit;
+
+	if ((rval = qla_flash_unprotect(ha)))
+		goto qla_erase_flash_unlock_exit;
+
+	if ((rval = qla_wait_for_flash_unprotect(ha)))
+		goto qla_erase_flash_unlock_exit;
+
+	for (start = off; start < (off + size); start = start + 0x10000) {
+		if (qla_erase_flash_sector(ha, start)) {
+			rval = -1;
+			break;
+		}
+	}
+
+	rval = qla_flash_protect(ha);
+
+qla_erase_flash_unlock_exit:
+	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
+
+qla_erase_flash_exit:
+	return (rval);
+}
+
+static int
+qla_flash_write32(qla_host_t *ha, uint32_t off, uint32_t data)
+{
+	uint32_t val;
+	int rval = 0;
+
+        val = data;
+        qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
+
+        val = off;
+        qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
+
+        val = 3;
+        qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
+
+        val = ROM_OPCODE_PROG_PAGE;
+        qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
+
+	rval = qla_wait_for_flash_busy(ha);
+
+	if (rval)
+		device_printf(ha->pci_dev, "%s: failed \n", __func__);
+
+	return rval;
+}
+
+static int
+qla_flash_wait_for_write_complete(qla_host_t *ha)
+{
+	uint32_t val, count = 1000;
+	int rval = 0;
+
+	while (count--) {
+
+		val = 0;
+		qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
+
+		val = ROM_OPCODE_RD_STATUS_REG;
+		qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
+
+		
+		rval = qla_wait_for_flash_busy(ha);
+
+		if (rval == 0) {
+			qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
+
+			if ((val & BIT_0) == 0)
+				return (0);
+		}
+		qla_mdelay(__func__, 1);
+	}
+	return -1;
+}
+
+static int
+qla_flash_write(qla_host_t *ha, uint32_t off, uint32_t data)
+{
+	if (qla_flash_write_enable(ha) != 0) 
+		return(-1);
+
+	if (qla_flash_write32(ha, off, data) != 0)
+		return -1;
+
+	if (qla_flash_wait_for_write_complete(ha))
+		return -1;
+
+	return 0;
+}
+
+
+static int
+qla_flash_write_pattern(qla_host_t *ha, uint32_t off, uint32_t size,
+	uint32_t pattern)
+{
+	int rval = 0;
+	uint32_t start;
+
+
+	if ((rval = qla_p3p_sem_lock2(ha)))
+		goto qla_wr_pattern_exit;
+
+	if ((rval = qla_flash_unprotect(ha)))
+		goto qla_wr_pattern_unlock_exit;
+
+	if ((rval = qla_wait_for_flash_unprotect(ha)))
+		goto qla_wr_pattern_unlock_exit;
+
+	for (start = off; start < (off + size); start = start + 4) {
+		if (qla_flash_write(ha, start, pattern)) {
+			rval = -1;
+			break;
+		}
+	}
+
+	rval = qla_flash_protect(ha);
+
+	if (rval == 0)
+		rval = qla_wait_for_flash_protect(ha);
+
+qla_wr_pattern_unlock_exit:
+	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
+
+qla_wr_pattern_exit:
+	return (rval);
+}
+
+static int
+qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
+	void *data)
+{
+	int rval = 0;
+	uint32_t start;
+	uint32_t *data32 = data;
+
+
+	if ((rval = qla_p3p_sem_lock2(ha)))
+		goto qla_wr_pattern_exit;
+
+	if ((rval = qla_flash_unprotect(ha)))
+		goto qla_wr_pattern_unlock_exit;
+
+	if ((rval = qla_wait_for_flash_unprotect(ha)))
+		goto qla_wr_pattern_unlock_exit;
+
+	for (start = off; start < (off + size); start = start + 4) {
+		
+		if (*data32 != 0xFFFFFFFF) {
+			if (qla_flash_write(ha, start, *data32)) {
+				rval = -1;
+				break;
+			}
+		}
+		data32++;
+	}
+
+	rval = qla_flash_protect(ha);
+
+	if (rval == 0)
+		rval = qla_wait_for_flash_protect(ha);
+
+qla_wr_pattern_unlock_exit:
+	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
+
+qla_wr_pattern_exit:
+	return (rval);
+}
+ 
+int
+qla_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf,
+	uint32_t pattern)
+{
+	int rval = 0;
+	void *data;
+
+
+	if (size == 0)
+		return 0;
+
+	size = size << 2;
+
+	if (buf == NULL) {
+		rval = qla_flash_write_pattern(ha, off, size, pattern);
+		return (rval);
+	}
+
+	if ((data = malloc(size, M_QLA8XXXBUF, M_NOWAIT)) == NULL) {
+		device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
+		rval = -1;
+		goto qla_wr_flash_buffer_exit;
+	}
+
+	if ((rval = copyin(buf, data, size))) {
+		device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
+		goto qla_wr_flash_buffer_free_exit;
+	}
+
+	rval = qla_flash_write_data(ha, off, size, data);
+
+qla_wr_flash_buffer_free_exit:
+	free(data, M_QLA8XXXBUF);
+
+qla_wr_flash_buffer_exit:
+	return (rval);
+}
+

Modified: head/sys/dev/qlxgb/qla_os.c
==============================================================================
--- head/sys/dev/qlxgb/qla_os.c	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_os.c	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
@@ -154,6 +154,11 @@ qla_add_sysctls(qla_host_t *ha)
                 (void *)ha, 0,
                 qla_sysctl_get_stats, "I", "Statistics");
 
+	SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev),
+		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+		OID_AUTO, "fw_version", CTLFLAG_RD,
+		&ha->fw_ver_str, 0, "firmware version");
+
 	dbg_level = 0;
         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
                 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
@@ -347,6 +352,10 @@ qla_pci_attach(device_t dev)
 		ha->fw_ver_major, ha->fw_ver_minor, ha->fw_ver_sub,
 		ha->fw_ver_build);
 
+	snprintf(ha->fw_ver_str, sizeof(ha->fw_ver_str), "%d.%d.%d.%d",
+			ha->fw_ver_major, ha->fw_ver_minor, ha->fw_ver_sub,
+			ha->fw_ver_build);
+
 	//qla_get_hw_caps(ha);
 	qla_read_mac_addr(ha);
 
@@ -660,6 +669,7 @@ qla_init_ifnet(device_t dev, qla_host_t 
 
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 
+	ifp->if_mtu = ETHERMTU;
 	ifp->if_baudrate = (1 * 1000 * 1000 *1000);
 	ifp->if_init = qla_init;
 	ifp->if_softc = ha;

Modified: head/sys/dev/qlxgb/qla_os.h
==============================================================================
--- head/sys/dev/qlxgb/qla_os.h	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_os.h	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without

Modified: head/sys/dev/qlxgb/qla_reg.h
==============================================================================
--- head/sys/dev/qlxgb/qla_reg.h	Tue May  7 22:49:56 2013	(r250339)
+++ head/sys/dev/qlxgb/qla_reg.h	Tue May  7 22:58:42 2013	(r250340)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Qlogic Corporation
+ * Copyright (c) 2011-2013 Qlogic Corporation
  * All rights reserved.
  *

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list