Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ixl/ixl_pf_main.c
Show First 20 Lines • Show All 3,657 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
ixl_handle_nvmupd_cmd(struct ixl_pf *pf, struct ifdrv *ifd) | ixl_handle_nvmupd_cmd(struct ixl_pf *pf, struct ifdrv *ifd) | ||||
{ | { | ||||
struct i40e_hw *hw = &pf->hw; | struct i40e_hw *hw = &pf->hw; | ||||
struct i40e_nvm_access *nvma; | struct i40e_nvm_access *nvma; | ||||
device_t dev = pf->dev; | device_t dev = pf->dev; | ||||
enum i40e_status_code status = 0; | enum i40e_status_code status = 0; | ||||
int perrno; | size_t nvma_size, ifd_len, exp_len; | ||||
int err, perrno; | |||||
DEBUGFUNC("ixl_handle_nvmupd_cmd"); | DEBUGFUNC("ixl_handle_nvmupd_cmd"); | ||||
/* Sanity checks */ | /* Sanity checks */ | ||||
if (ifd->ifd_len < sizeof(struct i40e_nvm_access) || | nvma_size = sizeof(struct i40e_nvm_access); | ||||
ifd_len = ifd->ifd_len; | |||||
if (ifd_len < nvma_size || | |||||
ifd->ifd_data == NULL) { | ifd->ifd_data == NULL) { | ||||
device_printf(dev, "%s: incorrect ifdrv length or data pointer\n", | device_printf(dev, "%s: incorrect ifdrv length or data pointer\n", | ||||
__func__); | __func__); | ||||
device_printf(dev, "%s: ifdrv length: %zu, sizeof(struct i40e_nvm_access): %zu\n", | device_printf(dev, "%s: ifdrv length: %zu, sizeof(struct i40e_nvm_access): %zu\n", | ||||
__func__, ifd->ifd_len, sizeof(struct i40e_nvm_access)); | __func__, ifd_len, nvma_size); | ||||
device_printf(dev, "%s: data pointer: %p\n", __func__, | device_printf(dev, "%s: data pointer: %p\n", __func__, | ||||
ifd->ifd_data); | ifd->ifd_data); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
nvma = (struct i40e_nvm_access *)ifd->ifd_data; | nvma = malloc(ifd_len, M_DEVBUF, M_WAITOK); | ||||
err = copyin(ifd->ifd_data, nvma, ifd_len); | |||||
if (err) { | |||||
device_printf(dev, "%s: Cannot get request from user space\n", | |||||
__func__); | |||||
free(nvma, M_DEVBUF); | |||||
return (err); | |||||
} | |||||
if (pf->dbg_mask & IXL_DBG_NVMUPD) | if (pf->dbg_mask & IXL_DBG_NVMUPD) | ||||
ixl_print_nvm_cmd(dev, nvma); | ixl_print_nvm_cmd(dev, nvma); | ||||
if (pf->state & IXL_PF_STATE_ADAPTER_RESETTING) { | if (pf->state & IXL_PF_STATE_ADAPTER_RESETTING) { | ||||
int count = 0; | int count = 0; | ||||
while (count++ < 100) { | while (count++ < 100) { | ||||
i40e_msec_delay(100); | i40e_msec_delay(100); | ||||
if (!(pf->state & IXL_PF_STATE_ADAPTER_RESETTING)) | if (!(pf->state & IXL_PF_STATE_ADAPTER_RESETTING)) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (!(pf->state & IXL_PF_STATE_ADAPTER_RESETTING)) { | if (pf->state & IXL_PF_STATE_ADAPTER_RESETTING) { | ||||
free(nvma, M_DEVBUF); | |||||
return (-EBUSY); | |||||
} | |||||
if (nvma->data_size < 1 || nvma->data_size > 4096) { | |||||
device_printf(dev, "%s: invalid request, data size not in supported range\n", | |||||
__func__); | |||||
free(nvma, M_DEVBUF); | |||||
return (EINVAL); | |||||
} | |||||
/* | |||||
* Older versions of the NVM update tool don't set ifd_len to the size | |||||
* of the entire buffer passed to the ioctl. Check the data_size field | |||||
* in the contained i40e_nvm_access struct and ensure everything is | |||||
* copied in from userspace. | |||||
*/ | |||||
exp_len = nvma_size + nvma->data_size - 1; /* One byte is kept in struct */ | |||||
if (ifd_len < exp_len) { | |||||
ifd_len = exp_len; | |||||
nvma = realloc(nvma, ifd_len, M_DEVBUF, M_WAITOK); | |||||
err = copyin(ifd->ifd_data, nvma, ifd_len); | |||||
if (err) { | |||||
device_printf(dev, "%s: Cannot get request from user space\n", | |||||
__func__); | |||||
free(nvma, M_DEVBUF); | |||||
return (err); | |||||
} | |||||
} | |||||
// TODO: Might need a different lock here | // TODO: Might need a different lock here | ||||
// IXL_PF_LOCK(pf); | // IXL_PF_LOCK(pf); | ||||
status = i40e_nvmupd_command(hw, nvma, nvma->data, &perrno); | status = i40e_nvmupd_command(hw, nvma, nvma->data, &perrno); | ||||
// IXL_PF_UNLOCK(pf); | // IXL_PF_UNLOCK(pf); | ||||
} else { | |||||
perrno = -EBUSY; | err = copyout(nvma, ifd->ifd_data, ifd_len); | ||||
free(nvma, M_DEVBUF); | |||||
if (err) { | |||||
device_printf(dev, "%s: Cannot return data to user space\n", | |||||
__func__); | |||||
return (err); | |||||
} | } | ||||
/* Let the nvmupdate report errors, show them only when debug is enabled */ | /* Let the nvmupdate report errors, show them only when debug is enabled */ | ||||
if (status != 0 && (pf->dbg_mask & IXL_DBG_NVMUPD) != 0) | if (status != 0 && (pf->dbg_mask & IXL_DBG_NVMUPD) != 0) | ||||
device_printf(dev, "i40e_nvmupd_command status %s, perrno %d\n", | device_printf(dev, "i40e_nvmupd_command status %s, perrno %d\n", | ||||
i40e_stat_str(hw, status), perrno); | i40e_stat_str(hw, status), perrno); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 1,315 Lines • Show Last 20 Lines |