qlcnic: Fix flash access interface to application
Application expects flash data in little endian, but driver reads/writes flash data using readl()/writel() APIs which swaps data on big endian machine. So, swap the data after reading from and before writing to flash memory. Signed-off-by: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com> Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
d715569112
commit
26acc71252
|
@ -268,7 +268,7 @@ struct qlcnic_fdt {
|
||||||
u16 cksum;
|
u16 cksum;
|
||||||
u16 unused;
|
u16 unused;
|
||||||
u8 model[16];
|
u8 model[16];
|
||||||
u16 mfg_id;
|
u8 mfg_id;
|
||||||
u16 id;
|
u16 id;
|
||||||
u8 flag;
|
u8 flag;
|
||||||
u8 erase_cmd;
|
u8 erase_cmd;
|
||||||
|
@ -2362,6 +2362,19 @@ static inline u32 qlcnic_get_vnic_func_count(struct qlcnic_adapter *adapter)
|
||||||
return QLC_DEFAULT_VNIC_COUNT;
|
return QLC_DEFAULT_VNIC_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void qlcnic_swap32_buffer(u32 *buffer, int count)
|
||||||
|
{
|
||||||
|
#if defined(__BIG_ENDIAN)
|
||||||
|
u32 *tmp = buffer;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
*tmp = swab32(*tmp);
|
||||||
|
tmp++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_QLCNIC_HWMON
|
#ifdef CONFIG_QLCNIC_HWMON
|
||||||
void qlcnic_register_hwmon_dev(struct qlcnic_adapter *);
|
void qlcnic_register_hwmon_dev(struct qlcnic_adapter *);
|
||||||
void qlcnic_unregister_hwmon_dev(struct qlcnic_adapter *);
|
void qlcnic_unregister_hwmon_dev(struct qlcnic_adapter *);
|
||||||
|
|
|
@ -2603,7 +2603,7 @@ int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter,
|
||||||
}
|
}
|
||||||
|
|
||||||
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_DIRECT_WINDOW,
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_DIRECT_WINDOW,
|
||||||
(addr));
|
(addr & 0xFFFF0000));
|
||||||
|
|
||||||
range = flash_offset + (count * sizeof(u32));
|
range = flash_offset + (count * sizeof(u32));
|
||||||
/* Check if data is spread across multiple sectors */
|
/* Check if data is spread across multiple sectors */
|
||||||
|
@ -2753,7 +2753,7 @@ int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *adapter)
|
||||||
ret = qlcnic_83xx_lockless_flash_read32(adapter, QLCNIC_FDT_LOCATION,
|
ret = qlcnic_83xx_lockless_flash_read32(adapter, QLCNIC_FDT_LOCATION,
|
||||||
(u8 *)&adapter->ahw->fdt,
|
(u8 *)&adapter->ahw->fdt,
|
||||||
count);
|
count);
|
||||||
|
qlcnic_swap32_buffer((u32 *)&adapter->ahw->fdt, count);
|
||||||
qlcnic_83xx_unlock_flash(adapter);
|
qlcnic_83xx_unlock_flash(adapter);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -2788,7 +2788,7 @@ int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,
|
||||||
|
|
||||||
addr1 = (sector_start_addr & 0xFF) << 16;
|
addr1 = (sector_start_addr & 0xFF) << 16;
|
||||||
addr2 = (sector_start_addr & 0xFF0000) >> 16;
|
addr2 = (sector_start_addr & 0xFF0000) >> 16;
|
||||||
reversed_addr = addr1 | addr2;
|
reversed_addr = addr1 | addr2 | (sector_start_addr & 0xFF00);
|
||||||
|
|
||||||
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
|
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA,
|
||||||
reversed_addr);
|
reversed_addr);
|
||||||
|
|
|
@ -280,6 +280,7 @@ static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
qlcnic_read_crb(adapter, buf, offset, size);
|
qlcnic_read_crb(adapter, buf, offset, size);
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -296,6 +297,7 @@ static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
qlcnic_write_crb(adapter, buf, offset, size);
|
qlcnic_write_crb(adapter, buf, offset, size);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -329,6 +331,7 @@ static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
memcpy(buf, &data, size);
|
memcpy(buf, &data, size);
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -346,6 +349,7 @@ static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
memcpy(&data, buf, size);
|
memcpy(&data, buf, size);
|
||||||
|
|
||||||
if (qlcnic_pci_mem_write_2M(adapter, offset, data))
|
if (qlcnic_pci_mem_write_2M(adapter, offset, data))
|
||||||
|
@ -412,6 +416,7 @@ static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
|
||||||
if (rem)
|
if (rem)
|
||||||
return QL_STATUS_INVALID_PARAM;
|
return QL_STATUS_INVALID_PARAM;
|
||||||
|
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
|
pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
|
||||||
ret = validate_pm_config(adapter, pm_cfg, count);
|
ret = validate_pm_config(adapter, pm_cfg, count);
|
||||||
|
|
||||||
|
@ -474,6 +479,7 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
|
||||||
pm_cfg[pci_func].dest_npar = 0;
|
pm_cfg[pci_func].dest_npar = 0;
|
||||||
pm_cfg[pci_func].pci_func = i;
|
pm_cfg[pci_func].pci_func = i;
|
||||||
}
|
}
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,6 +561,7 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
|
||||||
if (rem)
|
if (rem)
|
||||||
return QL_STATUS_INVALID_PARAM;
|
return QL_STATUS_INVALID_PARAM;
|
||||||
|
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
|
esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
|
||||||
ret = validate_esw_config(adapter, esw_cfg, count);
|
ret = validate_esw_config(adapter, esw_cfg, count);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -649,6 +656,7 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
|
||||||
if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func]))
|
if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func]))
|
||||||
return QL_STATUS_INVALID_PARAM;
|
return QL_STATUS_INVALID_PARAM;
|
||||||
}
|
}
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,6 +696,7 @@ static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
|
||||||
if (rem)
|
if (rem)
|
||||||
return QL_STATUS_INVALID_PARAM;
|
return QL_STATUS_INVALID_PARAM;
|
||||||
|
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
np_cfg = (struct qlcnic_npar_func_cfg *)buf;
|
np_cfg = (struct qlcnic_npar_func_cfg *)buf;
|
||||||
ret = validate_npar_config(adapter, np_cfg, count);
|
ret = validate_npar_config(adapter, np_cfg, count);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -759,6 +768,7 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
|
||||||
np_cfg[pci_func].max_tx_queues = nic_info.max_tx_ques;
|
np_cfg[pci_func].max_tx_queues = nic_info.max_tx_ques;
|
||||||
np_cfg[pci_func].max_rx_queues = nic_info.max_rx_ques;
|
np_cfg[pci_func].max_rx_queues = nic_info.max_rx_ques;
|
||||||
}
|
}
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -916,6 +926,7 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
|
||||||
|
|
||||||
pci_cfg = (struct qlcnic_pci_func_cfg *)buf;
|
pci_cfg = (struct qlcnic_pci_func_cfg *)buf;
|
||||||
count = size / sizeof(struct qlcnic_pci_func_cfg);
|
count = size / sizeof(struct qlcnic_pci_func_cfg);
|
||||||
|
qlcnic_swap32_buffer((u32 *)pci_info, size / sizeof(u32));
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
pci_cfg[i].pci_func = pci_info[i].id;
|
pci_cfg[i].pci_func = pci_info[i].id;
|
||||||
pci_cfg[i].func_type = pci_info[i].type;
|
pci_cfg[i].func_type = pci_info[i].type;
|
||||||
|
@ -969,6 +980,7 @@ static ssize_t qlcnic_83xx_sysfs_flash_read_handler(struct file *filp,
|
||||||
}
|
}
|
||||||
|
|
||||||
qlcnic_83xx_unlock_flash(adapter);
|
qlcnic_83xx_unlock_flash(adapter);
|
||||||
|
qlcnic_swap32_buffer((u32 *)p_read_buf, count);
|
||||||
memcpy(buf, p_read_buf, size);
|
memcpy(buf, p_read_buf, size);
|
||||||
kfree(p_read_buf);
|
kfree(p_read_buf);
|
||||||
|
|
||||||
|
@ -986,9 +998,10 @@ static int qlcnic_83xx_sysfs_flash_bulk_write(struct qlcnic_adapter *adapter,
|
||||||
if (!p_cache)
|
if (!p_cache)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
count = size / sizeof(u32);
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, count);
|
||||||
memcpy(p_cache, buf, size);
|
memcpy(p_cache, buf, size);
|
||||||
p_src = p_cache;
|
p_src = p_cache;
|
||||||
count = size / sizeof(u32);
|
|
||||||
|
|
||||||
if (qlcnic_83xx_lock_flash(adapter) != 0) {
|
if (qlcnic_83xx_lock_flash(adapter) != 0) {
|
||||||
kfree(p_cache);
|
kfree(p_cache);
|
||||||
|
@ -1053,6 +1066,7 @@ static int qlcnic_83xx_sysfs_flash_write(struct qlcnic_adapter *adapter,
|
||||||
if (!p_cache)
|
if (!p_cache)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
qlcnic_swap32_buffer((u32 *)buf, size / sizeof(u32));
|
||||||
memcpy(p_cache, buf, size);
|
memcpy(p_cache, buf, size);
|
||||||
p_src = p_cache;
|
p_src = p_cache;
|
||||||
count = size / sizeof(u32);
|
count = size / sizeof(u32);
|
||||||
|
|
Loading…
Reference in New Issue