Commit aeb54272 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull SCSI fixes from James Bottomley:
 "Three fixes, all in drivers (qedi and iscsi target) so no wider impact
  even if the code changes are a bit extensive"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: qedi: Add the CRC size within iSCSI NVM image
  scsi: iscsi: target: Fix conn_ops double free
  scsi: iscsi: target: Set conn->sess to NULL when iscsi_login_set_conn_values fails
parents 5e335542 c77a2fa3
...@@ -77,6 +77,11 @@ enum qedi_nvm_tgts { ...@@ -77,6 +77,11 @@ enum qedi_nvm_tgts {
QEDI_NVM_TGT_SEC, QEDI_NVM_TGT_SEC,
}; };
struct qedi_nvm_iscsi_image {
struct nvm_iscsi_cfg iscsi_cfg;
u32 crc;
};
struct qedi_uio_ctrl { struct qedi_uio_ctrl {
/* meta data */ /* meta data */
u32 uio_hsi_version; u32 uio_hsi_version;
...@@ -294,7 +299,7 @@ struct qedi_ctx { ...@@ -294,7 +299,7 @@ struct qedi_ctx {
void *bdq_pbl_list; void *bdq_pbl_list;
dma_addr_t bdq_pbl_list_dma; dma_addr_t bdq_pbl_list_dma;
u8 bdq_pbl_list_num_entries; u8 bdq_pbl_list_num_entries;
struct nvm_iscsi_cfg *iscsi_cfg; struct qedi_nvm_iscsi_image *iscsi_image;
dma_addr_t nvm_buf_dma; dma_addr_t nvm_buf_dma;
void __iomem *bdq_primary_prod; void __iomem *bdq_primary_prod;
void __iomem *bdq_secondary_prod; void __iomem *bdq_secondary_prod;
......
...@@ -1346,23 +1346,26 @@ static int qedi_setup_int(struct qedi_ctx *qedi) ...@@ -1346,23 +1346,26 @@ static int qedi_setup_int(struct qedi_ctx *qedi)
static void qedi_free_nvm_iscsi_cfg(struct qedi_ctx *qedi) static void qedi_free_nvm_iscsi_cfg(struct qedi_ctx *qedi)
{ {
if (qedi->iscsi_cfg) if (qedi->iscsi_image)
dma_free_coherent(&qedi->pdev->dev, dma_free_coherent(&qedi->pdev->dev,
sizeof(struct nvm_iscsi_cfg), sizeof(struct qedi_nvm_iscsi_image),
qedi->iscsi_cfg, qedi->nvm_buf_dma); qedi->iscsi_image, qedi->nvm_buf_dma);
} }
static int qedi_alloc_nvm_iscsi_cfg(struct qedi_ctx *qedi) static int qedi_alloc_nvm_iscsi_cfg(struct qedi_ctx *qedi)
{ {
qedi->iscsi_cfg = dma_zalloc_coherent(&qedi->pdev->dev, struct qedi_nvm_iscsi_image nvm_image;
sizeof(struct nvm_iscsi_cfg),
&qedi->nvm_buf_dma, GFP_KERNEL); qedi->iscsi_image = dma_zalloc_coherent(&qedi->pdev->dev,
if (!qedi->iscsi_cfg) { sizeof(nvm_image),
&qedi->nvm_buf_dma,
GFP_KERNEL);
if (!qedi->iscsi_image) {
QEDI_ERR(&qedi->dbg_ctx, "Could not allocate NVM BUF.\n"); QEDI_ERR(&qedi->dbg_ctx, "Could not allocate NVM BUF.\n");
return -ENOMEM; return -ENOMEM;
} }
QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO, QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
"NVM BUF addr=0x%p dma=0x%llx.\n", qedi->iscsi_cfg, "NVM BUF addr=0x%p dma=0x%llx.\n", qedi->iscsi_image,
qedi->nvm_buf_dma); qedi->nvm_buf_dma);
return 0; return 0;
...@@ -1905,7 +1908,7 @@ qedi_get_nvram_block(struct qedi_ctx *qedi) ...@@ -1905,7 +1908,7 @@ qedi_get_nvram_block(struct qedi_ctx *qedi)
struct nvm_iscsi_block *block; struct nvm_iscsi_block *block;
pf = qedi->dev_info.common.abs_pf_id; pf = qedi->dev_info.common.abs_pf_id;
block = &qedi->iscsi_cfg->block[0]; block = &qedi->iscsi_image->iscsi_cfg.block[0];
for (i = 0; i < NUM_OF_ISCSI_PF_SUPPORTED; i++, block++) { for (i = 0; i < NUM_OF_ISCSI_PF_SUPPORTED; i++, block++) {
flags = ((block->id) & NVM_ISCSI_CFG_BLK_CTRL_FLAG_MASK) >> flags = ((block->id) & NVM_ISCSI_CFG_BLK_CTRL_FLAG_MASK) >>
NVM_ISCSI_CFG_BLK_CTRL_FLAG_OFFSET; NVM_ISCSI_CFG_BLK_CTRL_FLAG_OFFSET;
...@@ -2194,15 +2197,14 @@ static void qedi_boot_release(void *data) ...@@ -2194,15 +2197,14 @@ static void qedi_boot_release(void *data)
static int qedi_get_boot_info(struct qedi_ctx *qedi) static int qedi_get_boot_info(struct qedi_ctx *qedi)
{ {
int ret = 1; int ret = 1;
u16 len; struct qedi_nvm_iscsi_image nvm_image;
len = sizeof(struct nvm_iscsi_cfg);
QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO, QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_INFO,
"Get NVM iSCSI CFG image\n"); "Get NVM iSCSI CFG image\n");
ret = qedi_ops->common->nvm_get_image(qedi->cdev, ret = qedi_ops->common->nvm_get_image(qedi->cdev,
QED_NVM_IMAGE_ISCSI_CFG, QED_NVM_IMAGE_ISCSI_CFG,
(char *)qedi->iscsi_cfg, len); (char *)qedi->iscsi_image,
sizeof(nvm_image));
if (ret) if (ret)
QEDI_ERR(&qedi->dbg_ctx, QEDI_ERR(&qedi->dbg_ctx,
"Could not get NVM image. ret = %d\n", ret); "Could not get NVM image. ret = %d\n", ret);
......
...@@ -4208,22 +4208,15 @@ int iscsit_close_connection( ...@@ -4208,22 +4208,15 @@ int iscsit_close_connection(
crypto_free_ahash(tfm); crypto_free_ahash(tfm);
} }
free_cpumask_var(conn->conn_cpumask);
kfree(conn->conn_ops);
conn->conn_ops = NULL;
if (conn->sock) if (conn->sock)
sock_release(conn->sock); sock_release(conn->sock);
if (conn->conn_transport->iscsit_free_conn) if (conn->conn_transport->iscsit_free_conn)
conn->conn_transport->iscsit_free_conn(conn); conn->conn_transport->iscsit_free_conn(conn);
iscsit_put_transport(conn->conn_transport);
pr_debug("Moving to TARG_CONN_STATE_FREE.\n"); pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
conn->conn_state = TARG_CONN_STATE_FREE; conn->conn_state = TARG_CONN_STATE_FREE;
kfree(conn); iscsit_free_conn(conn);
spin_lock_bh(&sess->conn_lock); spin_lock_bh(&sess->conn_lock);
atomic_dec(&sess->nconn); atomic_dec(&sess->nconn);
......
...@@ -67,45 +67,10 @@ static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn) ...@@ -67,45 +67,10 @@ static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn)
goto out_req_buf; goto out_req_buf;
} }
conn->conn_ops = kzalloc(sizeof(struct iscsi_conn_ops), GFP_KERNEL);
if (!conn->conn_ops) {
pr_err("Unable to allocate memory for"
" struct iscsi_conn_ops.\n");
goto out_rsp_buf;
}
init_waitqueue_head(&conn->queues_wq);
INIT_LIST_HEAD(&conn->conn_list);
INIT_LIST_HEAD(&conn->conn_cmd_list);
INIT_LIST_HEAD(&conn->immed_queue_list);
INIT_LIST_HEAD(&conn->response_queue_list);
init_completion(&conn->conn_post_wait_comp);
init_completion(&conn->conn_wait_comp);
init_completion(&conn->conn_wait_rcfr_comp);
init_completion(&conn->conn_waiting_on_uc_comp);
init_completion(&conn->conn_logout_comp);
init_completion(&conn->rx_half_close_comp);
init_completion(&conn->tx_half_close_comp);
init_completion(&conn->rx_login_comp);
spin_lock_init(&conn->cmd_lock);
spin_lock_init(&conn->conn_usage_lock);
spin_lock_init(&conn->immed_queue_lock);
spin_lock_init(&conn->nopin_timer_lock);
spin_lock_init(&conn->response_queue_lock);
spin_lock_init(&conn->state_lock);
if (!zalloc_cpumask_var(&conn->conn_cpumask, GFP_KERNEL)) {
pr_err("Unable to allocate conn->conn_cpumask\n");
goto out_conn_ops;
}
conn->conn_login = login; conn->conn_login = login;
return login; return login;
out_conn_ops:
kfree(conn->conn_ops);
out_rsp_buf:
kfree(login->rsp_buf);
out_req_buf: out_req_buf:
kfree(login->req_buf); kfree(login->req_buf);
out_login: out_login:
...@@ -310,11 +275,9 @@ static int iscsi_login_zero_tsih_s1( ...@@ -310,11 +275,9 @@ static int iscsi_login_zero_tsih_s1(
return -ENOMEM; return -ENOMEM;
} }
ret = iscsi_login_set_conn_values(sess, conn, pdu->cid); if (iscsi_login_set_conn_values(sess, conn, pdu->cid))
if (unlikely(ret)) { goto free_sess;
kfree(sess);
return ret;
}
sess->init_task_tag = pdu->itt; sess->init_task_tag = pdu->itt;
memcpy(&sess->isid, pdu->isid, 6); memcpy(&sess->isid, pdu->isid, 6);
sess->exp_cmd_sn = be32_to_cpu(pdu->cmdsn); sess->exp_cmd_sn = be32_to_cpu(pdu->cmdsn);
...@@ -1149,6 +1112,75 @@ iscsit_conn_set_transport(struct iscsi_conn *conn, struct iscsit_transport *t) ...@@ -1149,6 +1112,75 @@ iscsit_conn_set_transport(struct iscsi_conn *conn, struct iscsit_transport *t)
return 0; return 0;
} }
static struct iscsi_conn *iscsit_alloc_conn(struct iscsi_np *np)
{
struct iscsi_conn *conn;
conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL);
if (!conn) {
pr_err("Could not allocate memory for new connection\n");
return NULL;
}
pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
conn->conn_state = TARG_CONN_STATE_FREE;
init_waitqueue_head(&conn->queues_wq);
INIT_LIST_HEAD(&conn->conn_list);
INIT_LIST_HEAD(&conn->conn_cmd_list);
INIT_LIST_HEAD(&conn->immed_queue_list);
INIT_LIST_HEAD(&conn->response_queue_list);
init_completion(&conn->conn_post_wait_comp);
init_completion(&conn->conn_wait_comp);
init_completion(&conn->conn_wait_rcfr_comp);
init_completion(&conn->conn_waiting_on_uc_comp);
init_completion(&conn->conn_logout_comp);
init_completion(&conn->rx_half_close_comp);
init_completion(&conn->tx_half_close_comp);
init_completion(&conn->rx_login_comp);
spin_lock_init(&conn->cmd_lock);
spin_lock_init(&conn->conn_usage_lock);
spin_lock_init(&conn->immed_queue_lock);
spin_lock_init(&conn->nopin_timer_lock);
spin_lock_init(&conn->response_queue_lock);
spin_lock_init(&conn->state_lock);
timer_setup(&conn->nopin_response_timer,
iscsit_handle_nopin_response_timeout, 0);
timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0);
if (iscsit_conn_set_transport(conn, np->np_transport) < 0)
goto free_conn;
conn->conn_ops = kzalloc(sizeof(struct iscsi_conn_ops), GFP_KERNEL);
if (!conn->conn_ops) {
pr_err("Unable to allocate memory for struct iscsi_conn_ops.\n");
goto put_transport;
}
if (!zalloc_cpumask_var(&conn->conn_cpumask, GFP_KERNEL)) {
pr_err("Unable to allocate conn->conn_cpumask\n");
goto free_mask;
}
return conn;
free_mask:
free_cpumask_var(conn->conn_cpumask);
put_transport:
iscsit_put_transport(conn->conn_transport);
free_conn:
kfree(conn);
return NULL;
}
void iscsit_free_conn(struct iscsi_conn *conn)
{
free_cpumask_var(conn->conn_cpumask);
kfree(conn->conn_ops);
iscsit_put_transport(conn->conn_transport);
kfree(conn);
}
void iscsi_target_login_sess_out(struct iscsi_conn *conn, void iscsi_target_login_sess_out(struct iscsi_conn *conn,
struct iscsi_np *np, bool zero_tsih, bool new_sess) struct iscsi_np *np, bool zero_tsih, bool new_sess)
{ {
...@@ -1198,10 +1230,6 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn, ...@@ -1198,10 +1230,6 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn,
crypto_free_ahash(tfm); crypto_free_ahash(tfm);
} }
free_cpumask_var(conn->conn_cpumask);
kfree(conn->conn_ops);
if (conn->param_list) { if (conn->param_list) {
iscsi_release_param_list(conn->param_list); iscsi_release_param_list(conn->param_list);
conn->param_list = NULL; conn->param_list = NULL;
...@@ -1219,8 +1247,7 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn, ...@@ -1219,8 +1247,7 @@ void iscsi_target_login_sess_out(struct iscsi_conn *conn,
if (conn->conn_transport->iscsit_free_conn) if (conn->conn_transport->iscsit_free_conn)
conn->conn_transport->iscsit_free_conn(conn); conn->conn_transport->iscsit_free_conn(conn);
iscsit_put_transport(conn->conn_transport); iscsit_free_conn(conn);
kfree(conn);
} }
static int __iscsi_target_login_thread(struct iscsi_np *np) static int __iscsi_target_login_thread(struct iscsi_np *np)
...@@ -1250,31 +1277,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) ...@@ -1250,31 +1277,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
} }
spin_unlock_bh(&np->np_thread_lock); spin_unlock_bh(&np->np_thread_lock);
conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL); conn = iscsit_alloc_conn(np);
if (!conn) { if (!conn) {
pr_err("Could not allocate memory for"
" new connection\n");
/* Get another socket */ /* Get another socket */
return 1; return 1;
} }
pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
conn->conn_state = TARG_CONN_STATE_FREE;
timer_setup(&conn->nopin_response_timer,
iscsit_handle_nopin_response_timeout, 0);
timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0);
if (iscsit_conn_set_transport(conn, np->np_transport) < 0) {
kfree(conn);
return 1;
}
rc = np->np_transport->iscsit_accept_np(np, conn); rc = np->np_transport->iscsit_accept_np(np, conn);
if (rc == -ENOSYS) { if (rc == -ENOSYS) {
complete(&np->np_restart_comp); complete(&np->np_restart_comp);
iscsit_put_transport(conn->conn_transport); iscsit_free_conn(conn);
kfree(conn);
conn = NULL;
goto exit; goto exit;
} else if (rc < 0) { } else if (rc < 0) {
spin_lock_bh(&np->np_thread_lock); spin_lock_bh(&np->np_thread_lock);
...@@ -1282,17 +1294,13 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) ...@@ -1282,17 +1294,13 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
np->np_thread_state = ISCSI_NP_THREAD_ACTIVE; np->np_thread_state = ISCSI_NP_THREAD_ACTIVE;
spin_unlock_bh(&np->np_thread_lock); spin_unlock_bh(&np->np_thread_lock);
complete(&np->np_restart_comp); complete(&np->np_restart_comp);
iscsit_put_transport(conn->conn_transport); iscsit_free_conn(conn);
kfree(conn);
conn = NULL;
/* Get another socket */ /* Get another socket */
return 1; return 1;
} }
spin_unlock_bh(&np->np_thread_lock); spin_unlock_bh(&np->np_thread_lock);
iscsit_put_transport(conn->conn_transport); iscsit_free_conn(conn);
kfree(conn); return 1;
conn = NULL;
goto out;
} }
/* /*
* Perform the remaining iSCSI connection initialization items.. * Perform the remaining iSCSI connection initialization items..
...@@ -1442,7 +1450,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) ...@@ -1442,7 +1450,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
tpg_np = NULL; tpg_np = NULL;
} }
out:
return 1; return 1;
exit: exit:
......
...@@ -19,7 +19,7 @@ extern int iscsi_target_setup_login_socket(struct iscsi_np *, ...@@ -19,7 +19,7 @@ extern int iscsi_target_setup_login_socket(struct iscsi_np *,
extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *); extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *);
extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *); extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *);
extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32); extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32);
extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *); extern void iscsit_free_conn(struct iscsi_conn *);
extern int iscsit_start_kthreads(struct iscsi_conn *); extern int iscsit_start_kthreads(struct iscsi_conn *);
extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *, extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment