diff options
-rw-r--r-- | drivers/infiniband/ulp/srp/ib_srp.c | 4 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aicasm/Makefile | 18 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c | 1 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_iscsi.c | 4 | ||||
-rw-r--r-- | drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_dbg.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qedf/qedf_debugfs.c | 35 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 15 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 80 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_configfs.c | 72 | ||||
-rw-r--r-- | drivers/ufs/core/ufshcd.c | 4 | ||||
-rw-r--r-- | drivers/ufs/host/ufs-qcom.c | 131 | ||||
-rw-r--r-- | drivers/ufs/host/ufs-qcom.h | 3 | ||||
-rw-r--r-- | drivers/ufs/host/ufshcd-pltfrm.c | 4 | ||||
-rw-r--r-- | include/scsi/scsi_transport_iscsi.h | 1 | ||||
-rw-r--r-- | include/ufs/unipro.h | 6 |
16 files changed, 277 insertions, 105 deletions
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 0e513a7e5ac8..1574218764e0 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1979,12 +1979,8 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp) if (unlikely(rsp->flags & SRP_RSP_FLAG_DIUNDER)) scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); - else if (unlikely(rsp->flags & SRP_RSP_FLAG_DIOVER)) - scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_in_res_cnt)); else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOUNDER)) scsi_set_resid(scmnd, be32_to_cpu(rsp->data_out_res_cnt)); - else if (unlikely(rsp->flags & SRP_RSP_FLAG_DOOVER)) - scsi_set_resid(scmnd, -be32_to_cpu(rsp->data_out_res_cnt)); srp_free_req(ch, req, scmnd, be32_to_cpu(rsp->req_lim_delta)); diff --git a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile index 243adb0a38d1..a3f2357a3f08 100644 --- a/drivers/scsi/aic7xxx/aicasm/Makefile +++ b/drivers/scsi/aic7xxx/aicasm/Makefile @@ -61,23 +61,11 @@ $(OUTDIR)/aicdb.h: clean: rm -f $(clean-files) -# Create a dependency chain in generated files -# to avoid concurrent invocations of the single -# rule that builds them all. -$(OUTDIR)/aicasm_gram.c: $(OUTDIR)/aicasm_gram.h $(OUTDIR)/aicasm_gram.c $(OUTDIR)/aicasm_gram.h: aicasm_gram.y - $(YACC) $(YFLAGS) -b $(<:.y=) $< - mv $(<:.y=).tab.c $(OUTDIR)/$(<:.y=.c) - mv $(<:.y=).tab.h $(OUTDIR)/$(<:.y=.h) - -# Create a dependency chain in generated files -# to avoid concurrent invocations of the single -# rule that builds them all. -$(OUTDIR)/aicasm_macro_gram.c: $(OUTDIR)/aicasm_macro_gram.h + $(YACC) $(YFLAGS) -b $(<:.y=) $< -o $(OUTDIR)/$(<:.y=.c) + $(OUTDIR)/aicasm_macro_gram.c $(OUTDIR)/aicasm_macro_gram.h: aicasm_macro_gram.y - $(YACC) $(YFLAGS) -b $(<:.y=) -p mm $< - mv $(<:.y=).tab.c $(OUTDIR)/$(<:.y=.c) - mv $(<:.y=).tab.h $(OUTDIR)/$(<:.y=.h) + $(YACC) $(YFLAGS) -b $(<:.y=) -p mm $< -o $(OUTDIR)/$(<:.y=.c) $(OUTDIR)/aicasm_scan.c: aicasm_scan.l $(LEX) $(LFLAGS) -o $@ $< diff --git a/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c b/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c index 975fcfcc0d8f..2b44eb5702eb 100644 --- a/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c +++ b/drivers/scsi/aic7xxx/aicasm/aicasm_symbol.c @@ -52,6 +52,7 @@ #include <stdlib.h> #include <string.h> #include <sysexits.h> +#include <ctype.h> #include "aicasm_symbol.h" #include "aicasm.h" diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 8aeaddc93b16..8d374ae863ba 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -450,6 +450,10 @@ int beiscsi_iface_set_param(struct Scsi_Host *shost, } nla_for_each_attr(attrib, data, dt_len, rm_len) { + /* ignore nla_type as it is never used */ + if (nla_len(attrib) < sizeof(*iface_param)) + return -EINVAL; + iface_param = nla_data(attrib); if (iface_param->param_type != ISCSI_NET_PARAM) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 7aad495d78e5..a676558b096b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -4582,7 +4582,7 @@ static int debugfs_fifo_data_v3_hw_show(struct seq_file *s, void *p) debugfs_read_fifo_data_v3_hw(phy); debugfs_show_row_32_v3_hw(s, 0, HISI_SAS_FIFO_DATA_DW_SIZE * 4, - phy->fifo.rd_data); + (__le32 *)phy->fifo.rd_data); return 0; } diff --git a/drivers/scsi/qedf/qedf_dbg.h b/drivers/scsi/qedf/qedf_dbg.h index f4d81127239e..5ec2b817c694 100644 --- a/drivers/scsi/qedf/qedf_dbg.h +++ b/drivers/scsi/qedf/qedf_dbg.h @@ -59,6 +59,8 @@ extern uint qedf_debug; #define QEDF_LOG_NOTICE 0x40000000 /* Notice logs */ #define QEDF_LOG_WARN 0x80000000 /* Warning logs */ +#define QEDF_DEBUGFS_LOG_LEN (2 * PAGE_SIZE) + /* Debug context structure */ struct qedf_dbg_ctx { unsigned int host_no; diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c index a3ed681c8ce3..451fd236bfd0 100644 --- a/drivers/scsi/qedf/qedf_debugfs.c +++ b/drivers/scsi/qedf/qedf_debugfs.c @@ -8,6 +8,7 @@ #include <linux/uaccess.h> #include <linux/debugfs.h> #include <linux/module.h> +#include <linux/vmalloc.h> #include "qedf.h" #include "qedf_dbg.h" @@ -98,7 +99,9 @@ static ssize_t qedf_dbg_fp_int_cmd_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { + ssize_t ret; size_t cnt = 0; + char *cbuf; int id; struct qedf_fastpath *fp = NULL; struct qedf_dbg_ctx *qedf_dbg = @@ -108,19 +111,25 @@ qedf_dbg_fp_int_cmd_read(struct file *filp, char __user *buffer, size_t count, QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n"); - cnt = sprintf(buffer, "\nFastpath I/O completions\n\n"); + cbuf = vmalloc(QEDF_DEBUGFS_LOG_LEN); + if (!cbuf) + return 0; + + cnt += scnprintf(cbuf + cnt, QEDF_DEBUGFS_LOG_LEN - cnt, "\nFastpath I/O completions\n\n"); for (id = 0; id < qedf->num_queues; id++) { fp = &(qedf->fp_array[id]); if (fp->sb_id == QEDF_SB_ID_NULL) continue; - cnt += sprintf((buffer + cnt), "#%d: %lu\n", id, - fp->completions); + cnt += scnprintf(cbuf + cnt, QEDF_DEBUGFS_LOG_LEN - cnt, + "#%d: %lu\n", id, fp->completions); } - cnt = min_t(int, count, cnt - *ppos); - *ppos += cnt; - return cnt; + ret = simple_read_from_buffer(buffer, count, ppos, cbuf, cnt); + + vfree(cbuf); + + return ret; } static ssize_t @@ -138,15 +147,14 @@ qedf_dbg_debug_cmd_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { int cnt; + char cbuf[32]; struct qedf_dbg_ctx *qedf_dbg = (struct qedf_dbg_ctx *)filp->private_data; QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "debug mask=0x%x\n", qedf_debug); - cnt = sprintf(buffer, "debug mask = 0x%x\n", qedf_debug); + cnt = scnprintf(cbuf, sizeof(cbuf), "debug mask = 0x%x\n", qedf_debug); - cnt = min_t(int, count, cnt - *ppos); - *ppos += cnt; - return cnt; + return simple_read_from_buffer(buffer, count, ppos, cbuf, cnt); } static ssize_t @@ -185,18 +193,17 @@ qedf_dbg_stop_io_on_error_cmd_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos) { int cnt; + char cbuf[7]; struct qedf_dbg_ctx *qedf_dbg = (struct qedf_dbg_ctx *)filp->private_data; struct qedf_ctx *qedf = container_of(qedf_dbg, struct qedf_ctx, dbg_ctx); QEDF_INFO(qedf_dbg, QEDF_LOG_DEBUGFS, "entered\n"); - cnt = sprintf(buffer, "%s\n", + cnt = scnprintf(cbuf, sizeof(cbuf), "%s\n", qedf->stop_io_on_error ? "true" : "false"); - cnt = min_t(int, count, cnt - *ppos); - *ppos += cnt; - return cnt; + return simple_read_from_buffer(buffer, count, ppos, cbuf, cnt); } static ssize_t diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index b2a3988e1e15..675332e49a7b 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -968,6 +968,11 @@ static int qla4xxx_set_chap_entry(struct Scsi_Host *shost, void *data, int len) memset(&chap_rec, 0, sizeof(chap_rec)); nla_for_each_attr(attr, data, len, rem) { + if (nla_len(attr) < sizeof(*param_info)) { + rc = -EINVAL; + goto exit_set_chap; + } + param_info = nla_data(attr); switch (param_info->param) { @@ -2750,6 +2755,11 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len) } nla_for_each_attr(attr, data, len, rem) { + if (nla_len(attr) < sizeof(*iface_param)) { + rval = -EINVAL; + goto exit_init_fw_cb; + } + iface_param = nla_data(attr); if (iface_param->param_type == ISCSI_NET_PARAM) { @@ -8104,6 +8114,11 @@ qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, memset((void *)&chap_tbl, 0, sizeof(chap_tbl)); nla_for_each_attr(attr, data, len, rem) { + if (nla_len(attr) < sizeof(*fnode_param)) { + rc = -EINVAL; + goto exit_set_param; + } + fnode_param = nla_data(attr); switch (fnode_param->param) { diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index e527ece12453..3075b2ddf7a6 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -3014,14 +3014,15 @@ iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev } static int -iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) +iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen) { char *data = (char*)ev + sizeof(*ev); struct iscsi_cls_conn *conn; struct iscsi_cls_session *session; int err = 0, value = 0, state; - if (ev->u.set_param.len > PAGE_SIZE) + if (ev->u.set_param.len > rlen || + ev->u.set_param.len > PAGE_SIZE) return -EINVAL; session = iscsi_session_lookup(ev->u.set_param.sid); @@ -3029,6 +3030,10 @@ iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) if (!conn || !session) return -EINVAL; + /* data will be regarded as NULL-ended string, do length check */ + if (strlen(data) > ev->u.set_param.len) + return -EINVAL; + switch (ev->u.set_param.param) { case ISCSI_PARAM_SESS_RECOVERY_TMO: sscanf(data, "%d", &value); @@ -3118,7 +3123,7 @@ put_ep: static int iscsi_if_transport_ep(struct iscsi_transport *transport, - struct iscsi_uevent *ev, int msg_type) + struct iscsi_uevent *ev, int msg_type, u32 rlen) { struct iscsi_endpoint *ep; int rc = 0; @@ -3126,7 +3131,10 @@ iscsi_if_transport_ep(struct iscsi_transport *transport, switch (msg_type) { case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST: case ISCSI_UEVENT_TRANSPORT_EP_CONNECT: - rc = iscsi_if_ep_connect(transport, ev, msg_type); + if (rlen < sizeof(struct sockaddr)) + rc = -EINVAL; + else + rc = iscsi_if_ep_connect(transport, ev, msg_type); break; case ISCSI_UEVENT_TRANSPORT_EP_POLL: if (!transport->ep_poll) @@ -3150,12 +3158,15 @@ iscsi_if_transport_ep(struct iscsi_transport *transport, static int iscsi_tgt_dscvr(struct iscsi_transport *transport, - struct iscsi_uevent *ev) + struct iscsi_uevent *ev, u32 rlen) { struct Scsi_Host *shost; struct sockaddr *dst_addr; int err; + if (rlen < sizeof(*dst_addr)) + return -EINVAL; + if (!transport->tgt_dscvr) return -EINVAL; @@ -3176,7 +3187,7 @@ iscsi_tgt_dscvr(struct iscsi_transport *transport, static int iscsi_set_host_param(struct iscsi_transport *transport, - struct iscsi_uevent *ev) + struct iscsi_uevent *ev, u32 rlen) { char *data = (char*)ev + sizeof(*ev); struct Scsi_Host *shost; @@ -3185,7 +3196,8 @@ iscsi_set_host_param(struct iscsi_transport *transport, if (!transport->set_host_param) return -ENOSYS; - if (ev->u.set_host_param.len > PAGE_SIZE) + if (ev->u.set_host_param.len > rlen || + ev->u.set_host_param.len > PAGE_SIZE) return -EINVAL; shost = scsi_host_lookup(ev->u.set_host_param.host_no); @@ -3195,6 +3207,10 @@ iscsi_set_host_param(struct iscsi_transport *transport, return -ENODEV; } + /* see similar check in iscsi_if_set_param() */ + if (strlen(data) > ev->u.set_host_param.len) + return -EINVAL; + err = transport->set_host_param(shost, ev->u.set_host_param.param, data, ev->u.set_host_param.len); scsi_host_put(shost); @@ -3202,12 +3218,15 @@ iscsi_set_host_param(struct iscsi_transport *transport, } static int -iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev) +iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen) { struct Scsi_Host *shost; struct iscsi_path *params; int err; + if (rlen < sizeof(*params)) + return -EINVAL; + if (!transport->set_path) return -ENOSYS; @@ -3267,12 +3286,15 @@ iscsi_set_iface_params(struct iscsi_transport *transport, } static int -iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev) +iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen) { struct Scsi_Host *shost; struct sockaddr *dst_addr; int err; + if (rlen < sizeof(*dst_addr)) + return -EINVAL; + if (!transport->send_ping) return -ENOSYS; @@ -3770,13 +3792,12 @@ exit_host_stats: } static int iscsi_if_transport_conn(struct iscsi_transport *transport, - struct nlmsghdr *nlh) + struct nlmsghdr *nlh, u32 pdu_len) { struct iscsi_uevent *ev = nlmsg_data(nlh); struct iscsi_cls_session *session; struct iscsi_cls_conn *conn = NULL; struct iscsi_endpoint *ep; - uint32_t pdu_len; int err = 0; switch (nlh->nlmsg_type) { @@ -3861,8 +3882,6 @@ static int iscsi_if_transport_conn(struct iscsi_transport *transport, break; case ISCSI_UEVENT_SEND_PDU: - pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev); - if ((ev->u.send_pdu.hdr_size > pdu_len) || (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) { err = -EINVAL; @@ -3892,6 +3911,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) struct iscsi_internal *priv; struct iscsi_cls_session *session; struct iscsi_endpoint *ep = NULL; + u32 rlen; if (!netlink_capable(skb, CAP_SYS_ADMIN)) return -EPERM; @@ -3911,6 +3931,13 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) portid = NETLINK_CB(skb).portid; + /* + * Even though the remaining payload may not be regarded as nlattr, + * (like address or something else), calculate the remaining length + * here to ease following length checks. + */ + rlen = nlmsg_attrlen(nlh, sizeof(*ev)); + switch (nlh->nlmsg_type) { case ISCSI_UEVENT_CREATE_SESSION: err = iscsi_if_create_session(priv, ep, ev, @@ -3967,7 +3994,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) err = -EINVAL; break; case ISCSI_UEVENT_SET_PARAM: - err = iscsi_if_set_param(transport, ev); + err = iscsi_if_set_param(transport, ev, rlen); break; case ISCSI_UEVENT_CREATE_CONN: case ISCSI_UEVENT_DESTROY_CONN: @@ -3975,7 +4002,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) case ISCSI_UEVENT_START_CONN: case ISCSI_UEVENT_BIND_CONN: case ISCSI_UEVENT_SEND_PDU: - err = iscsi_if_transport_conn(transport, nlh); + err = iscsi_if_transport_conn(transport, nlh, rlen); break; case ISCSI_UEVENT_GET_STATS: err = iscsi_if_get_stats(transport, nlh); @@ -3984,23 +4011,22 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) case ISCSI_UEVENT_TRANSPORT_EP_POLL: case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST: - err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type); + err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type, rlen); break; case ISCSI_UEVENT_TGT_DSCVR: - err = iscsi_tgt_dscvr(transport, ev); + err = iscsi_tgt_dscvr(transport, ev, rlen); break; case ISCSI_UEVENT_SET_HOST_PARAM: - err = iscsi_set_host_param(transport, ev); + err = iscsi_set_host_param(transport, ev, rlen); break; case ISCSI_UEVENT_PATH_UPDATE: - err = iscsi_set_path(transport, ev); + err = iscsi_set_path(transport, ev, rlen); break; case ISCSI_UEVENT_SET_IFACE_PARAMS: - err = iscsi_set_iface_params(transport, ev, - nlmsg_attrlen(nlh, sizeof(*ev))); + err = iscsi_set_iface_params(transport, ev, rlen); break; case ISCSI_UEVENT_PING: - err = iscsi_send_ping(transport, ev); + err = iscsi_send_ping(transport, ev, rlen); break; case ISCSI_UEVENT_GET_CHAP: err = iscsi_get_chap(transport, nlh); @@ -4009,13 +4035,10 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) err = iscsi_delete_chap(transport, ev); break; case ISCSI_UEVENT_SET_FLASHNODE_PARAMS: - err = iscsi_set_flashnode_param(transport, ev, - nlmsg_attrlen(nlh, - sizeof(*ev))); + err = iscsi_set_flashnode_param(transport, ev, rlen); break; case ISCSI_UEVENT_NEW_FLASHNODE: - err = iscsi_new_flashnode(transport, ev, - nlmsg_attrlen(nlh, sizeof(*ev))); + err = iscsi_new_flashnode(transport, ev, rlen); break; case ISCSI_UEVENT_DEL_FLASHNODE: err = iscsi_del_flashnode(transport, ev); @@ -4030,8 +4053,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) err = iscsi_logout_flashnode_sid(transport, ev); break; case ISCSI_UEVENT_SET_CHAP: - err = iscsi_set_chap(transport, ev, - nlmsg_attrlen(nlh, sizeof(*ev))); + err = iscsi_set_chap(transport, ev, rlen); break; case ISCSI_UEVENT_GET_HOST_STATS: err = iscsi_get_host_stats(transport, nlh); diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 6ce967f5af14..1cff6052e820 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -45,9 +45,9 @@ static ssize_t lio_target_np_driver_show(struct config_item *item, char *page, tpg_np_new = iscsit_tpg_locate_child_np(tpg_np, type); if (tpg_np_new) - rb = sprintf(page, "1\n"); + rb = sysfs_emit(page, "1\n"); else - rb = sprintf(page, "0\n"); + rb = sysfs_emit(page, "0\n"); return rb; } @@ -282,7 +282,7 @@ static ssize_t iscsi_nacl_attrib_##name##_show(struct config_item *item,\ { \ struct se_node_acl *se_nacl = attrib_to_nacl(item); \ struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); \ - return sprintf(page, "%u\n", nacl->node_attrib.name); \ + return sysfs_emit(page, "%u\n", nacl->node_attrib.name); \ } \ \ static ssize_t iscsi_nacl_attrib_##name##_store(struct config_item *item,\ @@ -320,7 +320,7 @@ static ssize_t iscsi_nacl_attrib_authentication_show(struct config_item *item, struct se_node_acl *se_nacl = attrib_to_nacl(item); struct iscsi_node_acl *nacl = to_iscsi_nacl(se_nacl); - return sprintf(page, "%d\n", nacl->node_attrib.authentication); + return sysfs_emit(page, "%d\n", nacl->node_attrib.authentication); } static ssize_t iscsi_nacl_attrib_authentication_store(struct config_item *item, @@ -533,102 +533,102 @@ static ssize_t lio_target_nacl_info_show(struct config_item *item, char *page) spin_lock_bh(&se_nacl->nacl_sess_lock); se_sess = se_nacl->nacl_sess; if (!se_sess) { - rb += sprintf(page+rb, "No active iSCSI Session for Initiator" + rb += sysfs_emit_at(page, rb, "No active iSCSI Session for Initiator" " Endpoint: %s\n", se_nacl->initiatorname); } else { sess = se_sess->fabric_sess_ptr; - rb += sprintf(page+rb, "InitiatorName: %s\n", + rb += sysfs_emit_at(page, rb, "InitiatorName: %s\n", sess->sess_ops->InitiatorName); - rb += sprintf(page+rb, "InitiatorAlias: %s\n", + rb += sysfs_emit_at(page, rb, "InitiatorAlias: %s\n", sess->sess_ops->InitiatorAlias); - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "LIO Session ID: %u ISID: 0x%6ph TSIH: %hu ", sess->sid, sess->isid, sess->tsih); - rb += sprintf(page+rb, "SessionType: %s\n", + rb += sysfs_emit_at(page, rb, "SessionType: %s\n", (sess->sess_ops->SessionType) ? "Discovery" : "Normal"); - rb += sprintf(page+rb, "Session State: "); + rb += sysfs_emit_at(page, rb, "Session State: "); switch (sess->session_state) { case TARG_SESS_STATE_FREE: - rb += sprintf(page+rb, "TARG_SESS_FREE\n"); + rb += sysfs_emit_at(page, rb, "TARG_SESS_FREE\n"); break; case TARG_SESS_STATE_ACTIVE: - rb += sprintf(page+rb, "TARG_SESS_STATE_ACTIVE\n"); + rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_ACTIVE\n"); break; case TARG_SESS_STATE_LOGGED_IN: - rb += sprintf(page+rb, "TARG_SESS_STATE_LOGGED_IN\n"); + rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_LOGGED_IN\n"); break; case TARG_SESS_STATE_FAILED: - rb += sprintf(page+rb, "TARG_SESS_STATE_FAILED\n"); + rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_FAILED\n"); break; case TARG_SESS_STATE_IN_CONTINUE: - rb += sprintf(page+rb, "TARG_SESS_STATE_IN_CONTINUE\n"); + rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_IN_CONTINUE\n"); break; default: - rb += sprintf(page+rb, "ERROR: Unknown Session" + rb += sysfs_emit_at(page, rb, "ERROR: Unknown Session" " State!\n"); break; } - rb += sprintf(page+rb, "---------------------[iSCSI Session" + rb += sysfs_emit_at(page, rb, "---------------------[iSCSI Session" " Values]-----------------------\n"); - rb += sprintf(page+rb, " CmdSN/WR : CmdSN/WC : ExpCmdSN" + rb += sysfs_emit_at(page, rb, " CmdSN/WR : CmdSN/WC : ExpCmdSN" " : MaxCmdSN : ITT : TTT\n"); max_cmd_sn = (u32) atomic_read(&sess->max_cmd_sn); - rb += sprintf(page+rb, " 0x%08x 0x%08x 0x%08x 0x%08x" + rb += sysfs_emit_at(page, rb, " 0x%08x 0x%08x 0x%08x 0x%08x" " 0x%08x 0x%08x\n", sess->cmdsn_window, (max_cmd_sn - sess->exp_cmd_sn) + 1, sess->exp_cmd_sn, max_cmd_sn, sess->init_task_tag, sess->targ_xfer_tag); - rb += sprintf(page+rb, "----------------------[iSCSI" + rb += sysfs_emit_at(page, rb, "----------------------[iSCSI" " Connections]-------------------------\n"); spin_lock(&sess->conn_lock); list_for_each_entry(conn, &sess->sess_conn_list, conn_list) { - rb += sprintf(page+rb, "CID: %hu Connection" + rb += sysfs_emit_at(page, rb, "CID: %hu Connection" " State: ", conn->cid); switch (conn->conn_state) { case TARG_CONN_STATE_FREE: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_FREE\n"); break; case TARG_CONN_STATE_XPT_UP: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_XPT_UP\n"); break; case TARG_CONN_STATE_IN_LOGIN: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_IN_LOGIN\n"); break; case TARG_CONN_STATE_LOGGED_IN: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_LOGGED_IN\n"); break; case TARG_CONN_STATE_IN_LOGOUT: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_IN_LOGOUT\n"); break; case TARG_CONN_STATE_LOGOUT_REQUESTED: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_LOGOUT_REQUESTED\n"); break; case TARG_CONN_STATE_CLEANUP_WAIT: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "TARG_CONN_STATE_CLEANUP_WAIT\n"); break; default: - rb += sprintf(page+rb, + rb += sysfs_emit_at(page, rb, "ERROR: Unknown Connection State!\n"); break; } - rb += sprintf(page+rb, " Address %pISc %s", &conn->login_sockaddr, + rb += sysfs_emit_at(page, rb, " Address %pISc %s", &conn->login_sockaddr, (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP"); - rb += sprintf(page+rb, " StatSN: 0x%08x\n", + rb += sysfs_emit_at(page, rb, " StatSN: 0x%08x\n", conn->stat_sn); } spin_unlock(&sess->conn_lock); @@ -641,7 +641,7 @@ static ssize_t lio_target_nacl_info_show(struct config_item *item, char *page) static ssize_t lio_target_nacl_cmdsn_depth_show(struct config_item *item, char *page) { - return sprintf(page, "%u\n", acl_to_nacl(item)->queue_depth); + return sysfs_emit(page, "%u\n", acl_to_nacl(item)->queue_depth); } static ssize_t lio_target_nacl_cmdsn_depth_store(struct config_item *item, @@ -750,7 +750,7 @@ static ssize_t iscsi_tpg_attrib_##name##_show(struct config_item *item, \ if (iscsit_get_tpg(tpg) < 0) \ return -EINVAL; \ \ - rb = sprintf(page, "%u\n", tpg->tpg_attrib.name); \ + rb = sysfs_emit(page, "%u\n", tpg->tpg_attrib.name); \ iscsit_put_tpg(tpg); \ return rb; \ } \ @@ -1136,7 +1136,7 @@ static void lio_target_tiqn_deltpg(struct se_portal_group *se_tpg) static ssize_t lio_target_wwn_lio_version_show(struct config_item *item, char *page) { - return sprintf(page, "Datera Inc. iSCSI Target "ISCSIT_VERSION"\n"); + return sysfs_emit(page, "Datera Inc. iSCSI Target %s\n", ISCSIT_VERSION); } CONFIGFS_ATTR_RO(lio_target_wwn_, lio_version); @@ -1144,7 +1144,7 @@ CONFIGFS_ATTR_RO(lio_target_wwn_, lio_version); static ssize_t lio_target_wwn_cpus_allowed_list_show( struct config_item *item, char *page) { - return sprintf(page, "%*pbl\n", + return sysfs_emit(page, "%*pbl\n", cpumask_pr_args(iscsit_global->allowed_cpumask)); } @@ -1281,7 +1281,7 @@ static ssize_t iscsi_disc_enforce_discovery_auth_show(struct config_item *item, { struct iscsi_node_auth *discovery_auth = &iscsit_global->discovery_acl.node_auth; - return sprintf(page, "%d\n", discovery_auth->enforce_discovery_auth); + return sysfs_emit(page, "%d\n", discovery_auth->enforce_discovery_auth); } static ssize_t iscsi_disc_enforce_discovery_auth_store(struct config_item *item, diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 2e669e64872c..f45614a840ae 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -4346,8 +4346,8 @@ static void ufshcd_init_pwr_info(struct ufs_hba *hba) { hba->pwr_info.gear_rx = UFS_PWM_G1; hba->pwr_info.gear_tx = UFS_PWM_G1; - hba->pwr_info.lane_rx = 1; - hba->pwr_info.lane_tx = 1; + hba->pwr_info.lane_rx = UFS_LANE_1; + hba->pwr_info.lane_tx = UFS_LANE_1; hba->pwr_info.pwr_rx = SLOWAUTO_MODE; hba->pwr_info.pwr_tx = SLOWAUTO_MODE; hba->pwr_info.hs_rate = 0; diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 24b53ae8ca27..e7164ce7336b 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -7,6 +7,7 @@ #include <linux/time.h> #include <linux/clk.h> #include <linux/delay.h> +#include <linux/interconnect.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> @@ -46,6 +47,49 @@ enum { TSTBUS_MAX, }; +#define QCOM_UFS_MAX_GEAR 4 +#define QCOM_UFS_MAX_LANE 2 + +enum { + MODE_MIN, + MODE_PWM, + MODE_HS_RA, + MODE_HS_RB, + MODE_MAX, +}; + +struct __ufs_qcom_bw_table { + u32 mem_bw; + u32 cfg_bw; +} ufs_qcom_bw_table[MODE_MAX + 1][QCOM_UFS_MAX_GEAR + 1][QCOM_UFS_MAX_LANE + 1] = { + [MODE_MIN][0][0] = { 0, 0 }, /* Bandwidth values in KB/s */ + [MODE_PWM][UFS_PWM_G1][UFS_LANE_1] = { 922, 1000 }, + [MODE_PWM][UFS_PWM_G2][UFS_LANE_1] = { 1844, 1000 }, + [MODE_PWM][UFS_PWM_G3][UFS_LANE_1] = { 3688, 1000 }, + [MODE_PWM][UFS_PWM_G4][UFS_LANE_1] = { 7376, 1000 }, + [MODE_PWM][UFS_PWM_G1][UFS_LANE_2] = { 1844, 1000 }, + [MODE_PWM][UFS_PWM_G2][UFS_LANE_2] = { 3688, 1000 }, + [MODE_PWM][UFS_PWM_G3][UFS_LANE_2] = { 7376, 1000 }, + [MODE_PWM][UFS_PWM_G4][UFS_LANE_2] = { 14752, 1000 }, + [MODE_HS_RA][UFS_HS_G1][UFS_LANE_1] = { 127796, 1000 }, + [MODE_HS_RA][UFS_HS_G2][UFS_LANE_1] = { 255591, 1000 }, + [MODE_HS_RA][UFS_HS_G3][UFS_LANE_1] = { 1492582, 102400 }, + [MODE_HS_RA][UFS_HS_G4][UFS_LANE_1] = { 2915200, 204800 }, + [MODE_HS_RA][UFS_HS_G1][UFS_LANE_2] = { 255591, 1000 }, + [MODE_HS_RA][UFS_HS_G2][UFS_LANE_2] = { 511181, 1000 }, + [MODE_HS_RA][UFS_HS_G3][UFS_LANE_2] = { 1492582, 204800 }, + [MODE_HS_RA][UFS_HS_G4][UFS_LANE_2] = { 2915200, 409600 }, + [MODE_HS_RB][UFS_HS_G1][UFS_LANE_1] = { 149422, 1000 }, + [MODE_HS_RB][UFS_HS_G2][UFS_LANE_1] = { 298189, 1000 }, + [MODE_HS_RB][UFS_HS_G3][UFS_LANE_1] = { 1492582, 102400 }, + [MODE_HS_RB][UFS_HS_G4][UFS_LANE_1] = { 2915200, 204800 }, + [MODE_HS_RB][UFS_HS_G1][UFS_LANE_2] = { 298189, 1000 }, + [MODE_HS_RB][UFS_HS_G2][UFS_LANE_2] = { 596378, 1000 }, + [MODE_HS_RB][UFS_HS_G3][UFS_LANE_2] = { 1492582, 204800 }, + [MODE_HS_RB][UFS_HS_G4][UFS_LANE_2] = { 2915200, 409600 }, + [MODE_MAX][0][0] = { 7643136, 307200 }, +}; + static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS]; static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host); @@ -789,6 +833,51 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable) } } +static int ufs_qcom_icc_set_bw(struct ufs_qcom_host *host, u32 mem_bw, u32 cfg_bw) +{ + struct device *dev = host->hba->dev; + int ret; + + ret = icc_set_bw(host->icc_ddr, 0, mem_bw); + if (ret < 0) { + dev_err(dev, "failed to set bandwidth request: %d\n", ret); + return ret; + } + + ret = icc_set_bw(host->icc_cpu, 0, cfg_bw); + if (ret < 0) { + dev_err(dev, "failed to set bandwidth request: %d\n", ret); + return ret; + } + + return 0; +} + +static struct __ufs_qcom_bw_table ufs_qcom_get_bw_table(struct ufs_qcom_host *host) +{ + struct ufs_pa_layer_attr *p = &host->dev_req_params; + int gear = max_t(u32, p->gear_rx, p->gear_tx); + int lane = max_t(u32, p->lane_rx, p->lane_tx); + + if (ufshcd_is_hs_mode(p)) { + if (p->hs_rate == PA_HS_MODE_B) + return ufs_qcom_bw_table[MODE_HS_RB][gear][lane]; + else + return ufs_qcom_bw_table[MODE_HS_RA][gear][lane]; + } else { + return ufs_qcom_bw_table[MODE_PWM][gear][lane]; + } +} + +static int ufs_qcom_icc_update_bw(struct ufs_qcom_host *host) +{ + struct __ufs_qcom_bw_table bw_table; + + bw_table = ufs_qcom_get_bw_table(host); + + return ufs_qcom_icc_set_bw(host, bw_table.mem_bw, bw_table.cfg_bw); +} + static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, enum ufs_notify_change_status status, struct ufs_pa_layer_attr *dev_max_params, @@ -852,6 +941,8 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba, memcpy(&host->dev_req_params, dev_req_params, sizeof(*dev_req_params)); + ufs_qcom_icc_update_bw(host); + /* disable the device ref clock if entered PWM mode */ if (ufshcd_is_hs_mode(&hba->pwr_info) && !ufshcd_is_hs_mode(dev_req_params)) @@ -981,7 +1072,9 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, switch (status) { case PRE_CHANGE: - if (!on) { + if (on) { + ufs_qcom_icc_update_bw(host); + } else { if (!ufs_qcom_is_link_active(hba)) { /* disable device ref_clk */ ufs_qcom_dev_ref_clk_ctrl(host, false); @@ -993,6 +1086,9 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, /* enable the device ref clock for HS mode*/ if (ufshcd_is_hs_mode(&hba->pwr_info)) ufs_qcom_dev_ref_clk_ctrl(host, true); + } else { + ufs_qcom_icc_set_bw(host, ufs_qcom_bw_table[MODE_MIN][0][0].mem_bw, + ufs_qcom_bw_table[MODE_MIN][0][0].cfg_bw); } break; } @@ -1031,6 +1127,34 @@ static const struct reset_control_ops ufs_qcom_reset_ops = { .deassert = ufs_qcom_reset_deassert, }; +static int ufs_qcom_icc_init(struct ufs_qcom_host *host) +{ + struct device *dev = host->hba->dev; + int ret; + + host->icc_ddr = devm_of_icc_get(dev, "ufs-ddr"); + if (IS_ERR(host->icc_ddr)) + return dev_err_probe(dev, PTR_ERR(host->icc_ddr), + "failed to acquire interconnect path\n"); + + host->icc_cpu = devm_of_icc_get(dev, "cpu-ufs"); + if (IS_ERR(host->icc_cpu)) + return dev_err_probe(dev, PTR_ERR(host->icc_cpu), + "failed to acquire interconnect path\n"); + + /* + * Set Maximum bandwidth vote before initializing the UFS controller and + * device. Ideally, a minimal interconnect vote would suffice for the + * initialization, but a max vote would allow faster initialization. + */ + ret = ufs_qcom_icc_set_bw(host, ufs_qcom_bw_table[MODE_MAX][0][0].mem_bw, + ufs_qcom_bw_table[MODE_MAX][0][0].cfg_bw); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to set bandwidth request\n"); + + return 0; +} + /** * ufs_qcom_init - bind phy with controller * @hba: host controller instance @@ -1085,6 +1209,10 @@ static int ufs_qcom_init(struct ufs_hba *hba) } } + err = ufs_qcom_icc_init(host); + if (err) + goto out_variant_clear; + host->device_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(host->device_reset)) { @@ -1282,6 +1410,7 @@ static int ufs_qcom_clk_scale_notify(struct ufs_hba *hba, dev_req_params->pwr_rx, dev_req_params->hs_rate, false); + ufs_qcom_icc_update_bw(host); ufshcd_uic_hibern8_exit(hba); } diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h index 729240367e70..d6f8e74bd538 100644 --- a/drivers/ufs/host/ufs-qcom.h +++ b/drivers/ufs/host/ufs-qcom.h @@ -206,6 +206,9 @@ struct ufs_qcom_host { struct clk *tx_l1_sync_clk; bool is_lane_clks_enabled; + struct icc_path *icc_ddr; + struct icc_path *icc_cpu; + #ifdef CONFIG_SCSI_UFS_CRYPTO struct qcom_ice *ice; #endif diff --git a/drivers/ufs/host/ufshcd-pltfrm.c b/drivers/ufs/host/ufshcd-pltfrm.c index 8729f45d4f83..c0f1f3726619 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.c +++ b/drivers/ufs/host/ufshcd-pltfrm.c @@ -307,8 +307,8 @@ EXPORT_SYMBOL_GPL(ufshcd_get_pwr_dev_param); void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param) { *dev_param = (struct ufs_dev_params){ - .tx_lanes = 2, - .rx_lanes = 2, + .tx_lanes = UFS_LANE_2, + .rx_lanes = UFS_LANE_2, .hs_rx_gear = UFS_HS_G3, .hs_tx_gear = UFS_HS_G3, .pwm_rx_gear = UFS_PWM_G4, diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 34c03707fb6e..fb3399e4cd29 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -472,7 +472,6 @@ extern struct iscsi_iface *iscsi_create_iface(struct Scsi_Host *shost, uint32_t iface_type, uint32_t iface_num, int dd_size); extern void iscsi_destroy_iface(struct iscsi_iface *iface); -extern struct iscsi_iface *iscsi_lookup_iface(int handle); extern char *iscsi_get_port_speed_name(struct Scsi_Host *shost); extern char *iscsi_get_port_state_name(struct Scsi_Host *shost); extern int iscsi_is_session_dev(const struct device *dev); diff --git a/include/ufs/unipro.h b/include/ufs/unipro.h index dc9dd1d23f0f..256eb3a43f54 100644 --- a/include/ufs/unipro.h +++ b/include/ufs/unipro.h @@ -230,6 +230,12 @@ enum ufs_hs_gear_tag { UFS_HS_G5 /* HS Gear 5 */ }; +enum ufs_lanes { + UFS_LANE_DONT_CHANGE, /* Don't change Lane */ + UFS_LANE_1, /* Lane 1 (default for reset) */ + UFS_LANE_2, /* Lane 2 */ +}; + enum ufs_unipro_ver { UFS_UNIPRO_VER_RESERVED = 0, UFS_UNIPRO_VER_1_40 = 1, /* UniPro version 1.40 */ |