Skip to content

Commit

Permalink
qlcnic: Fix for flash update failure on 83xx adapter
Browse files Browse the repository at this point in the history
Flash update routine was improperly checking register read API return value.
Modify register read API and perform proper error check.

Signed-off-by: Himanshu Madhani <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Himanshu Madhani authored and davem330 committed Aug 3, 2013
1 parent b1f5037 commit 4bd8e73
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 132 deletions.
12 changes: 3 additions & 9 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -1400,8 +1400,8 @@ 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) \
(adapter->ahw->hw_ops->read_reg)(adapter, off)
#define QLCRD32(adapter, off, err) \
(adapter->ahw->hw_ops->read_reg)(adapter, off, err)

#define QLCWR32(adapter, off, val) \
adapter->ahw->hw_ops->write_reg(adapter, off, val)
Expand Down Expand Up @@ -1604,7 +1604,7 @@ struct qlcnic_nic_template {
struct qlcnic_hardware_ops {
void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
void (*write_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
int (*read_reg) (struct qlcnic_adapter *, ulong);
int (*read_reg) (struct qlcnic_adapter *, ulong, int *);
int (*write_reg) (struct qlcnic_adapter *, ulong, u32);
void (*get_ocm_win) (struct qlcnic_hardware_context *);
int (*get_mac_address) (struct qlcnic_adapter *, u8 *);
Expand Down Expand Up @@ -1662,12 +1662,6 @@ static inline void qlcnic_write_crb(struct qlcnic_adapter *adapter, char *buf,
adapter->ahw->hw_ops->write_crb(adapter, buf, offset, size);
}

static inline int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter,
ulong off)
{
return adapter->ahw->hw_ops->read_reg(adapter, off);
}

static inline int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter,
ulong off, u32 data)
{
Expand Down
101 changes: 60 additions & 41 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,17 +228,17 @@ static int __qlcnic_set_win_base(struct qlcnic_adapter *adapter, u32 addr)
return 0;
}

int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *adapter, ulong addr)
int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *adapter, ulong addr,
int *err)
{
int ret;
struct qlcnic_hardware_context *ahw = adapter->ahw;

ret = __qlcnic_set_win_base(adapter, (u32) addr);
if (!ret) {
*err = __qlcnic_set_win_base(adapter, (u32) addr);
if (!*err) {
return QLCRDX(ahw, QLCNIC_WILDCARD);
} else {
dev_err(&adapter->pdev->dev,
"%s failed, addr = 0x%x\n", __func__, (int)addr);
"%s failed, addr = 0x%lx\n", __func__, addr);
return -EIO;
}
}
Expand Down Expand Up @@ -561,7 +561,7 @@ void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *adapter)
void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
loff_t offset, size_t size)
{
int ret;
int ret = 0;
u32 data;

if (qlcnic_api_lock(adapter)) {
Expand All @@ -571,7 +571,7 @@ void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
return;
}

ret = qlcnic_83xx_rd_reg_indirect(adapter, (u32) offset);
data = QLCRD32(adapter, (u32) offset, &ret);
qlcnic_api_unlock(adapter);

if (ret == -EIO) {
Expand All @@ -580,7 +580,6 @@ void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
__func__, (u32)offset);
return;
}
data = ret;
memcpy(buf, &data, size);
}

Expand Down Expand Up @@ -2391,9 +2390,9 @@ int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter,
u32 flash_addr, u8 *p_data,
int count)
{
int i, ret;
u32 word, range, flash_offset, addr = flash_addr;
u32 word, range, flash_offset, addr = flash_addr, ret;
ulong indirect_add, direct_window;
int i, err = 0;

flash_offset = addr & (QLCNIC_FLASH_SECTOR_SIZE - 1);
if (addr & 0x3) {
Expand All @@ -2411,10 +2410,9 @@ int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter,
/* Multi sector read */
for (i = 0; i < count; i++) {
indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr);
ret = qlcnic_83xx_rd_reg_indirect(adapter,
indirect_add);
if (ret == -EIO)
return -EIO;
ret = QLCRD32(adapter, indirect_add, &err);
if (err == -EIO)
return err;

word = ret;
*(u32 *)p_data = word;
Expand All @@ -2435,10 +2433,9 @@ int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter,
/* Single sector read */
for (i = 0; i < count; i++) {
indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr);
ret = qlcnic_83xx_rd_reg_indirect(adapter,
indirect_add);
if (ret == -EIO)
return -EIO;
ret = QLCRD32(adapter, indirect_add, &err);
if (err == -EIO)
return err;

word = ret;
*(u32 *)p_data = word;
Expand All @@ -2454,10 +2451,13 @@ static int qlcnic_83xx_poll_flash_status_reg(struct qlcnic_adapter *adapter)
{
u32 status;
int retries = QLC_83XX_FLASH_READ_RETRY_COUNT;
int err = 0;

do {
status = qlcnic_83xx_rd_reg_indirect(adapter,
QLC_83XX_FLASH_STATUS);
status = QLCRD32(adapter, QLC_83XX_FLASH_STATUS, &err);
if (err == -EIO)
return err;

if ((status & QLC_83XX_FLASH_STATUS_READY) ==
QLC_83XX_FLASH_STATUS_READY)
break;
Expand Down Expand Up @@ -2509,7 +2509,8 @@ int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *adapter)

int qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *adapter)
{
int ret, mfg_id;
int ret, err = 0;
u32 mfg_id;

if (qlcnic_83xx_lock_flash(adapter))
return -EIO;
Expand All @@ -2524,9 +2525,11 @@ int qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *adapter)
return -EIO;
}

mfg_id = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_RDDATA);
if (mfg_id == -EIO)
return -EIO;
mfg_id = QLCRD32(adapter, QLC_83XX_FLASH_RDDATA, &err);
if (err == -EIO) {
qlcnic_83xx_unlock_flash(adapter);
return err;
}

adapter->flash_mfg_id = (mfg_id & 0xFF);
qlcnic_83xx_unlock_flash(adapter);
Expand Down Expand Up @@ -2643,7 +2646,7 @@ int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
u32 *p_data, int count)
{
u32 temp;
int ret = -EIO;
int ret = -EIO, err = 0;

if ((count < QLC_83XX_FLASH_WRITE_MIN) ||
(count > QLC_83XX_FLASH_WRITE_MAX)) {
Expand All @@ -2652,8 +2655,10 @@ int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
return -EIO;
}

temp = qlcnic_83xx_rd_reg_indirect(adapter,
QLC_83XX_FLASH_SPI_CONTROL);
temp = QLCRD32(adapter, QLC_83XX_FLASH_SPI_CONTROL, &err);
if (err == -EIO)
return err;

qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_SPI_CONTROL,
(temp | QLC_83XX_FLASH_SPI_CTRL));
qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
Expand Down Expand Up @@ -2702,13 +2707,18 @@ int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,
return -EIO;
}

ret = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_SPI_STATUS);
ret = QLCRD32(adapter, QLC_83XX_FLASH_SPI_STATUS, &err);
if (err == -EIO)
return err;

if ((ret & QLC_83XX_FLASH_SPI_CTRL) == QLC_83XX_FLASH_SPI_CTRL) {
dev_err(&adapter->pdev->dev, "%s: failed at %d\n",
__func__, __LINE__);
/* Operation failed, clear error bit */
temp = qlcnic_83xx_rd_reg_indirect(adapter,
QLC_83XX_FLASH_SPI_CONTROL);
temp = QLCRD32(adapter, QLC_83XX_FLASH_SPI_CONTROL, &err);
if (err == -EIO)
return err;

qlcnic_83xx_wrt_reg_indirect(adapter,
QLC_83XX_FLASH_SPI_CONTROL,
(temp | QLC_83XX_FLASH_SPI_CTRL));
Expand Down Expand Up @@ -2830,6 +2840,7 @@ int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr,
{
int i, j, ret = 0;
u32 temp;
int err = 0;

/* Check alignment */
if (addr & 0xF)
Expand Down Expand Up @@ -2862,8 +2873,12 @@ int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr,
QLCNIC_TA_WRITE_START);

for (j = 0; j < MAX_CTL_CHECK; j++) {
temp = qlcnic_83xx_rd_reg_indirect(adapter,
QLCNIC_MS_CTRL);
temp = QLCRD32(adapter, QLCNIC_MS_CTRL, &err);
if (err == -EIO) {
mutex_unlock(&adapter->ahw->mem_lock);
return err;
}

if ((temp & TA_CTL_BUSY) == 0)
break;
}
Expand All @@ -2885,9 +2900,9 @@ int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr,
int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
u8 *p_data, int count)
{
int i, ret;
u32 word, addr = flash_addr;
u32 word, addr = flash_addr, ret;
ulong indirect_addr;
int i, err = 0;

if (qlcnic_83xx_lock_flash(adapter) != 0)
return -EIO;
Expand All @@ -2907,10 +2922,10 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
}

indirect_addr = QLC_83XX_FLASH_DIRECT_DATA(addr);
ret = qlcnic_83xx_rd_reg_indirect(adapter,
indirect_addr);
if (ret == -EIO)
return -EIO;
ret = QLCRD32(adapter, indirect_addr, &err);
if (err == -EIO)
return err;

word = ret;
*(u32 *)p_data = word;
p_data = p_data + 4;
Expand Down Expand Up @@ -3376,7 +3391,8 @@ int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *adapter,

static int qlcnic_83xx_read_flash_status_reg(struct qlcnic_adapter *adapter)
{
int ret;
int ret, err = 0;
u32 temp;

qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR,
QLC_83XX_FLASH_OEM_READ_SIG);
Expand All @@ -3386,8 +3402,11 @@ static int qlcnic_83xx_read_flash_status_reg(struct qlcnic_adapter *adapter)
if (ret)
return -EIO;

ret = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_RDDATA);
return ret & 0xFF;
temp = QLCRD32(adapter, QLC_83XX_FLASH_RDDATA, &err);
if (err == -EIO)
return err;

return temp & 0xFF;
}

int qlcnic_83xx_flash_test(struct qlcnic_adapter *adapter)
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *);
void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *);
void qlcnic_83xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
void qlcnic_83xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *, ulong);
int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *, ulong, int *);
int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32);
void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *, int, u64 []);
int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32);
Expand Down
Loading

0 comments on commit 4bd8e73

Please sign in to comment.