qlcnic: handle queue manager access
authorDhananjay Phadke <dhananjay.phadke@qlogic.com>
Thu, 1 Apr 2010 19:01:29 +0000 (19:01 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 3 Apr 2010 21:19:13 +0000 (14:19 -0700)
Check the access by tools for hardware queue engine and handle it
separately than other block registers, otherwise incorrect data
is returned.

Signed-off-by: Dhananjay Phadke <dhananjay.phadke@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/qlcnic/qlcnic.h
drivers/net/qlcnic/qlcnic_hdr.h
drivers/net/qlcnic/qlcnic_hw.c
drivers/net/qlcnic/qlcnic_main.c

index 0da94b2..8a3446d 100644 (file)
@@ -994,6 +994,11 @@ u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off);
 int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *, ulong off, u32 data);
 int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *, u64 off, u64 data);
 int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *, u64 off, u64 *data);
+void qlcnic_pci_camqm_read_2M(struct qlcnic_adapter *, u64, u64 *);
+void qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *, u64, u64);
+
+#define ADDR_IN_RANGE(addr, low, high) \
+       (((addr) < (high)) && ((addr) >= (low)))
 
 #define QLCRD32(adapter, off) \
        (qlcnic_hw_read_wx_2M(adapter, off))
index 0469f84..25465a9 100644 (file)
@@ -435,9 +435,10 @@ enum {
 #define QLCNIC_PCI_MS_2M       (0x80000)
 #define QLCNIC_PCI_OCM0_2M     (0x000c0000UL)
 #define QLCNIC_PCI_CRBSPACE    (0x06000000UL)
+#define QLCNIC_PCI_CAMQM       (0x04800000UL)
+#define QLCNIC_PCI_CAMQM_END   (0x04800800UL)
 #define QLCNIC_PCI_2MB_SIZE    (0x00200000UL)
 #define QLCNIC_PCI_CAMQM_2M_BASE       (0x000ff800UL)
-#define QLCNIC_PCI_CAMQM_2M_END        (0x04800800UL)
 
 #define QLCNIC_CRB_CAM QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_CAM)
 
index da00e16..b977874 100644 (file)
@@ -53,9 +53,6 @@ static inline void writeq(u64 val, void __iomem *addr)
 }
 #endif
 
-#define ADDR_IN_RANGE(addr, low, high) \
-       (((addr) < (high)) && ((addr) >= (low)))
-
 #define PCI_OFFSET_FIRST_RANGE(adapter, off)    \
        ((adapter)->ahw.pci_base0 + (off))
 
@@ -936,6 +933,28 @@ unlock:
        return ret;
 }
 
+void
+qlcnic_pci_camqm_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data)
+{
+       void __iomem *addr = adapter->ahw.pci_base0 +
+               QLCNIC_PCI_CAMQM_2M_BASE + (off - QLCNIC_PCI_CAMQM);
+
+       mutex_lock(&adapter->ahw.mem_lock);
+       *data = readq(addr);
+       mutex_unlock(&adapter->ahw.mem_lock);
+}
+
+void
+qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data)
+{
+       void __iomem *addr = adapter->ahw.pci_base0 +
+               QLCNIC_PCI_CAMQM_2M_BASE + (off - QLCNIC_PCI_CAMQM);
+
+       mutex_lock(&adapter->ahw.mem_lock);
+       writeq(data, addr);
+       mutex_unlock(&adapter->ahw.mem_lock);
+}
+
 #define MAX_CTL_CHECK   1000
 
 int
index fc72156..a234622 100644 (file)
@@ -2386,14 +2386,21 @@ static int
 qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
                loff_t offset, size_t size)
 {
+       size_t crb_size = 4;
+
        if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
                return -EIO;
 
-       if ((size != 4) || (offset & 0x3))
-               return  -EINVAL;
+       if (offset < QLCNIC_PCI_CRBSPACE) {
+               if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
+                                       QLCNIC_PCI_CAMQM_END))
+                       crb_size = 8;
+               else
+                       return -EINVAL;
+       }
 
-       if (offset < QLCNIC_PCI_CRBSPACE)
-               return -EINVAL;
+       if ((size != crb_size) || (offset & (crb_size-1)))
+               return  -EINVAL;
 
        return 0;
 }
@@ -2405,14 +2412,20 @@ qlcnic_sysfs_read_crb(struct kobject *kobj, struct bin_attribute *attr,
        struct device *dev = container_of(kobj, struct device, kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        u32 data;
+       u64 qmdata;
        int ret;
 
        ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
        if (ret != 0)
                return ret;
 
-       data = QLCRD32(adapter, offset);
-       memcpy(buf, &data, size);
+       if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+               qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
+               memcpy(buf, &qmdata, size);
+       } else {
+               data = QLCRD32(adapter, offset);
+               memcpy(buf, &data, size);
+       }
        return size;
 }
 
@@ -2423,14 +2436,20 @@ qlcnic_sysfs_write_crb(struct kobject *kobj, struct bin_attribute *attr,
        struct device *dev = container_of(kobj, struct device, kobj);
        struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
        u32 data;
+       u64 qmdata;
        int ret;
 
        ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
        if (ret != 0)
                return ret;
 
-       memcpy(&data, buf, size);
-       QLCWR32(adapter, offset, data);
+       if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+               memcpy(&qmdata, buf, size);
+               qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
+       } else {
+               memcpy(&data, buf, size);
+               QLCWR32(adapter, offset, data);
+       }
        return size;
 }