RE: system hung up when offlining CPUs
On Mon, 30 Oct 2017, Shivasharan Srikanteshwara wrote: > In managed-interrupts case, interrupts which were affine to the offlined > CPU is not getting migrated to another available CPU. But the > documentation at below link says that "all interrupts" are migrated to a > new CPU. So not all interrupts are getting migrated to a new CPU then. Correct. > https://www.kernel.org/doc/html/v4.11/core-api/cpu_hotplug.html#the-offlin > e-case > "- All interrupts targeted to this CPU are migrated to a new CPU" Well, documentation is not always up to date :) > Once the last CPU in the affinity mask is offlined and a particular IRQ > is shutdown, is there a way currently for the device driver to get > callback to complete all outstanding requests on that queue? No and I have no idea how the other drivers deal with that. The way you can do that is to have your own hotplug callback which is invoked when the cpu goes down, but way before the interrupt is shut down, which is one of the last steps. Ideally this would be a callback in the generic block code which then calls out to all instances like its done for the cpu dead state. Jens, Christoph? Thanks, tglx
[PATCH 2/9] iscsi: associate endpoints with a host
Right now the iscsi_endpoint is only linked to a connection once that connection has been established. For net namespace filtering of the sysfs objects, associate an endpoint with the host that it was allocated for when it is created. Signed-off-by: Chris Leech --- drivers/infiniband/ulp/iser/iscsi_iser.c | 2 +- drivers/scsi/be2iscsi/be_iscsi.c | 2 +- drivers/scsi/bnx2i/bnx2i_iscsi.c | 2 +- drivers/scsi/cxgbi/libcxgbi.c| 2 +- drivers/scsi/qedi/qedi_iscsi.c | 2 +- drivers/scsi/qla4xxx/ql4_os.c| 2 +- drivers/scsi/scsi_transport_iscsi.c | 3 ++- include/scsi/scsi_transport_iscsi.h | 6 +- 8 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 19624e023ebd..0a4214be4877 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -817,7 +817,7 @@ iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, struct iser_conn *iser_conn; struct iscsi_endpoint *ep; - ep = iscsi_create_endpoint(0); + ep = iscsi_create_endpoint(shost, 0); if (!ep) return ERR_PTR(-ENOMEM); diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index a398c54139aa..33f79f385660 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -1157,7 +1157,7 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, return ERR_PTR(ret); } - ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint)); + ep = iscsi_create_endpoint(shost, sizeof(struct beiscsi_endpoint)); if (!ep) { ret = -ENOMEM; return ERR_PTR(ret); diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 03c104b47f31..19fadb5d3b3c 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -384,7 +384,7 @@ static struct iscsi_endpoint *bnx2i_alloc_ep(struct bnx2i_hba *hba) struct bnx2i_endpoint *bnx2i_ep; u32 ec_div; - ep = iscsi_create_endpoint(sizeof(*bnx2i_ep)); + ep = iscsi_create_endpoint(hba->shost, sizeof(*bnx2i_ep)); if (!ep) { printk(KERN_ERR "bnx2i: Could not allocate ep\n"); return NULL; diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 858e32e8ad2d..558484f72738 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -2616,7 +2616,7 @@ struct iscsi_endpoint *cxgbi_ep_connect(struct Scsi_Host *shost, goto release_conn; } - ep = iscsi_create_endpoint(sizeof(*cep)); + ep = iscsi_create_endpoint(shost, sizeof(*cep)); if (!ep) { err = -ENOMEM; pr_info("iscsi alloc ep, OOM.\n"); diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index a02b34ea5cab..5ae589ea1dd2 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -847,7 +847,7 @@ qedi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, return ERR_PTR(ret); } - ep = iscsi_create_endpoint(sizeof(struct qedi_endpoint)); + ep = iscsi_create_endpoint(shost, sizeof(struct qedi_endpoint)); if (!ep) { QEDI_ERR(&qedi->dbg_ctx, "endpoint create fail\n"); ret = -ENOMEM; diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 64c6fa563fdb..5785bf6c3ec0 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1673,7 +1673,7 @@ qla4xxx_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, } ha = iscsi_host_priv(shost); - ep = iscsi_create_endpoint(sizeof(struct qla_endpoint)); + ep = iscsi_create_endpoint(shost, sizeof(struct qla_endpoint)); if (!ep) { ret = -ENOMEM; return ERR_PTR(ret); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 0b23ba346cbe..6ab7ca82b121 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -194,7 +194,7 @@ static int iscsi_match_epid(struct device *dev, const void *data) } struct iscsi_endpoint * -iscsi_create_endpoint(int dd_size) +iscsi_create_endpoint(struct Scsi_Host *shost, int dd_size) { struct device *dev; struct iscsi_endpoint *ep; @@ -221,6 +221,7 @@ iscsi_create_endpoint(int dd_size) ep->id = id; ep->dev.class = &iscsi_endpoint_class; + ep->dev.parent = &shost->shost_gendev; dev_set_name(&ep->dev, "ep-%llu", (unsigned long long) id); err = device_register(&ep->dev); if (err) diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index b266d2a3bcb1..3b40
[PATCH 0/9] use network namespace for iSCSI control interfaces
This series of changes makes the iSCSI netlink and sysfs control interfaces filtered by network namespace. This is required to run iscsid in any network namespace other than the initial default one. Currently the netlink communication will fail if iscsid is started in a non-default network namespace, as there is no kernel side socket. After fixing that, the rest of these changes are to filter visibility of the iSCSI transport objects by netns. This allows for multiple iscsid instances to be run, one per netns, each controlling it's own set of iSCSI sessions. The iSCSI transport objects are filtered, but not the SCSI or block layer devices. So while iSCSI hosts and sessions become limited to a network namespace, any attached devices remain visible system wide. This currently only supports iscsi_tcp running in a new namespace, as it creates a virtual host per session. Support could be added later to allow assignment of iSCSI HBAs to network namespace, much as is done for network interfaces. Chris Leech (9): iscsi: create per-net iscsi netlink kernel sockets iscsi: associate endpoints with a host iscsi: sysfs filtering by network namespace iscsi: make all iSCSI netlink multicast namespace aware iscsi: set netns for iscsi_tcp hosts iscsi: check net namespace for all iscsi lookups iscsi: convert flashnode devices from bus to class iscsi: rename iscsi_bus_flash_* to iscsi_flash_* iscsi: filter flashnode sysfs by net namespace drivers/infiniband/ulp/iser/iscsi_iser.c | 7 +- drivers/scsi/be2iscsi/be_iscsi.c | 6 +- drivers/scsi/bnx2i/bnx2i_iscsi.c | 6 +- drivers/scsi/cxgbi/libcxgbi.c| 6 +- drivers/scsi/iscsi_tcp.c | 7 + drivers/scsi/qedi/qedi_iscsi.c | 6 +- drivers/scsi/qla4xxx/ql4_os.c| 62 +-- drivers/scsi/scsi_transport_iscsi.c | 625 ++- include/scsi/scsi_transport_iscsi.h | 63 ++-- 9 files changed, 538 insertions(+), 250 deletions(-) -- 2.9.5
[PATCH 3/9] iscsi: sysfs filtering by network namespace
This makes the iscsi_host, iscsi_session, iscsi_connection, iscsi_iface, and iscsi_endpoint transport class devices only visible in sysfs under a matching network namespace. The network namespace for all of these objects is tracked in the iscsi_cls_host structure. Signed-off-by: Chris Leech --- drivers/scsi/scsi_transport_iscsi.c | 128 +++- include/scsi/scsi_transport_iscsi.h | 1 + 2 files changed, 112 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 6ab7ca82b121..d29c095ccc7d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -161,9 +161,31 @@ static void iscsi_endpoint_release(struct device *dev) kfree(ep); } +static struct net *iscsi_host_net(struct iscsi_cls_host *ihost) +{ + return ihost->netns; +} + +static struct net *iscsi_endpoint_net(struct iscsi_endpoint *ep) +{ + struct Scsi_Host *shost = iscsi_endpoint_to_shost(ep); + struct iscsi_cls_host *ihost = shost->shost_data; + + return iscsi_host_net(ihost); +} + +static const void *iscsi_endpoint_namespace(struct device *dev) +{ + struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev); + + return iscsi_endpoint_net(ep); +} + static struct class iscsi_endpoint_class = { .name = "iscsi_endpoint", .dev_release = iscsi_endpoint_release, + .ns_type = &net_ns_type_operations, + .namespace = iscsi_endpoint_namespace, }; static ssize_t @@ -285,10 +307,26 @@ static void iscsi_iface_release(struct device *dev) put_device(parent); } +static struct net *iscsi_iface_net(struct iscsi_iface *iface) +{ + struct Scsi_Host *shost = iscsi_iface_to_shost(iface); + struct iscsi_cls_host *ihost = shost->shost_data; + + return iscsi_host_net(ihost); +} + +static const void *iscsi_iface_namespace(struct device *dev) +{ + struct iscsi_iface *iface = iscsi_dev_to_iface(dev); + + return iscsi_iface_net(iface); +} static struct class iscsi_iface_class = { .name = "iscsi_iface", .dev_release = iscsi_iface_release, + .ns_type = &net_ns_type_operations, + .namespace = iscsi_iface_namespace, }; #define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store) \ @@ -1566,6 +1604,7 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev, memset(ihost, 0, sizeof(*ihost)); atomic_set(&ihost->nr_scans, 0); mutex_init(&ihost->mutex); + ihost->netns = &init_net; iscsi_bsg_host_add(shost, ihost); /* ignore any bsg add error - we just can't do sgio */ @@ -1586,23 +1625,78 @@ static int iscsi_remove_host(struct transport_container *tc, return 0; } -static DECLARE_TRANSPORT_CLASS(iscsi_host_class, - "iscsi_host", - iscsi_setup_host, - iscsi_remove_host, - NULL); - -static DECLARE_TRANSPORT_CLASS(iscsi_session_class, - "iscsi_session", - NULL, - NULL, - NULL); - -static DECLARE_TRANSPORT_CLASS(iscsi_connection_class, - "iscsi_connection", - NULL, - NULL, - NULL); +#define DECLARE_TRANSPORT_CLASS_NS(cls, nm, su, rm, cfg, ns, nslookup) \ +struct transport_class cls = { \ + .class = { \ + .name = nm, \ + .ns_type = ns, \ + .namespace = nslookup, \ + }, \ + .setup = su,\ + .remove = rm, \ + .configure = cfg, \ +} + +static const void *iscsi_host_namespace(struct device *dev) +{ + struct Scsi_Host *shost = transport_class_to_shost(dev); + struct iscsi_cls_host *ihost = shost->shost_data; + + return iscsi_host_net(ihost); +} + +static DECLARE_TRANSPORT_CLASS_NS(iscsi_host_class, + "iscsi_host", + iscsi_setup_host, + iscsi_remove_host, + NULL, + &net_ns_type_operations, + iscsi_host_namespace); + +static struct net *iscsi_sess_net(struct iscsi_cls_session *cls_session) +{ + struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); + struct iscsi_cls_host *ihost
[PATCH 5/9] iscsi: set netns for iscsi_tcp hosts
This lets iscsi_tcp operate in multiple namespaces. It uses current during session creation to find the net namespace, but it might be better to manage to pass it along from the iscsi netlink socket. Signed-off-by: Chris Leech --- drivers/scsi/iscsi_tcp.c| 7 +++ drivers/scsi/scsi_transport_iscsi.c | 7 ++- include/scsi/scsi_transport_iscsi.h | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 4d934d6c3e13..b368c94c884b 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -957,6 +957,11 @@ static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev) return 0; } +static struct net *iscsi_sw_tcp_netns(struct Scsi_Host *shost) +{ + return current->nsproxy->net_ns; +} + static struct scsi_host_template iscsi_sw_tcp_sht = { .module = THIS_MODULE, .name = "iSCSI Initiator over TCP/IP", @@ -1013,6 +1018,8 @@ static struct iscsi_transport iscsi_sw_tcp_transport = { .alloc_pdu = iscsi_sw_tcp_pdu_alloc, /* recovery */ .session_recovery_timedout = iscsi_session_recovery_timedout, + /* net namespace */ + .get_netns = iscsi_sw_tcp_netns, }; static int __init iscsi_sw_tcp_init(void) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 1fc5878b1a8c..2ec10f6ac3a2 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1600,11 +1600,16 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev, { struct Scsi_Host *shost = dev_to_shost(dev); struct iscsi_cls_host *ihost = shost->shost_data; + struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); + struct iscsi_transport *transport = priv->iscsi_transport; memset(ihost, 0, sizeof(*ihost)); atomic_set(&ihost->nr_scans, 0); mutex_init(&ihost->mutex); - ihost->netns = &init_net; + if (transport->get_netns) + ihost->netns = transport->get_netns(shost); + else + ihost->netns = &init_net; iscsi_bsg_host_add(shost, ihost); /* ignore any bsg add error - we just can't do sgio */ diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 8c8191dfdc21..3c4cd4779f72 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -168,6 +168,7 @@ struct iscsi_transport { int (*logout_flashnode_sid) (struct iscsi_cls_session *cls_sess); int (*get_host_stats) (struct Scsi_Host *shost, char *buf, int len); u8 (*check_protection)(struct iscsi_task *task, sector_t *sector); + struct net *(*get_netns)(struct Scsi_Host *shost); }; /* -- 2.9.5
[PATCH 4/9] iscsi: make all iSCSI netlink multicast namespace aware
Make use of the per-net netlink sockets. Responses are sent back on the same socket/namespace the request was received on. Async events are reported on the socket/namespace stored in the iscsi_cls_host associated with the event. Signed-off-by: Chris Leech --- drivers/scsi/scsi_transport_iscsi.c | 92 - 1 file changed, 61 insertions(+), 31 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index d29c095ccc7d..1fc5878b1a8c 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2418,8 +2418,8 @@ iscsi_if_transport_lookup(struct iscsi_transport *tt) } static int -iscsi_multicast_netns(struct net *net, struct sk_buff *skb, - uint32_t group, gfp_t gfp) +iscsi_multicast_skb(struct net *net, struct sk_buff *skb, + uint32_t group, gfp_t gfp) { struct sock *nls; struct iscsi_net *isn; @@ -2429,12 +2429,6 @@ iscsi_multicast_netns(struct net *net, struct sk_buff *skb, return nlmsg_multicast(nls, skb, 0, group, gfp); } -static int -iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp) -{ - return iscsi_multicast_netns(&init_net, skb, group, gfp); -} - int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size) { @@ -2443,6 +2437,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, struct iscsi_uevent *ev; char *pdu; struct iscsi_internal *priv; + struct net *net; int len = nlmsg_total_size(sizeof(*ev) + sizeof(struct iscsi_hdr) + data_size); @@ -2469,7 +2464,8 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); - return iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC); + net = iscsi_conn_net(conn); + return iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC); } EXPORT_SYMBOL_GPL(iscsi_recv_pdu); @@ -2480,6 +2476,7 @@ int iscsi_offload_mesg(struct Scsi_Host *shost, struct nlmsghdr *nlh; struct sk_buff *skb; struct iscsi_uevent *ev; + struct net *net; int len = nlmsg_total_size(sizeof(*ev) + data_size); skb = alloc_skb(len, GFP_ATOMIC); @@ -2504,7 +2501,8 @@ int iscsi_offload_mesg(struct Scsi_Host *shost, memcpy((char *)ev + sizeof(*ev), data, data_size); - return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC); + net = iscsi_host_net(shost->shost_data); + return iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC); } EXPORT_SYMBOL_GPL(iscsi_offload_mesg); @@ -2514,6 +2512,7 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error) struct sk_buff *skb; struct iscsi_uevent *ev; struct iscsi_internal *priv; + struct net *net; int len = nlmsg_total_size(sizeof(*ev)); priv = iscsi_if_transport_lookup(conn->transport); @@ -2535,7 +2534,8 @@ void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error) ev->r.connerror.cid = conn->cid; ev->r.connerror.sid = iscsi_conn_get_sid(conn); - iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC); + net = iscsi_conn_net(conn); + iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC); iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n", error); @@ -2549,6 +2549,7 @@ void iscsi_conn_login_event(struct iscsi_cls_conn *conn, struct sk_buff *skb; struct iscsi_uevent *ev; struct iscsi_internal *priv; + struct net *net; int len = nlmsg_total_size(sizeof(*ev)); priv = iscsi_if_transport_lookup(conn->transport); @@ -2569,7 +2570,9 @@ void iscsi_conn_login_event(struct iscsi_cls_conn *conn, ev->r.conn_login.state = state; ev->r.conn_login.cid = conn->cid; ev->r.conn_login.sid = iscsi_conn_get_sid(conn); - iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC); + + net = iscsi_conn_net(conn); + iscsi_multicast_skb(net, skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC); iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn login (%d)\n", state); @@ -2580,11 +2583,17 @@ void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport, enum iscsi_host_event_code code, uint32_t data_size, uint8_t *data) { + struct Scsi_Host *shost; + struct net *net; struct nlmsghdr *nlh; struct sk_buff *skb; struct iscsi_uevent *ev; int len = nlmsg_total_size(sizeof(*ev) + data_size); + shost = scsi_host_lookup(host_no); + if (
[PATCH 6/9] iscsi: check net namespace for all iscsi lookups
All internal lookups of iSCSI transport objects need to be filtered by net namespace. Signed-off-by: Chris Leech --- drivers/infiniband/ulp/iser/iscsi_iser.c | 5 +- drivers/scsi/be2iscsi/be_iscsi.c | 4 +- drivers/scsi/bnx2i/bnx2i_iscsi.c | 4 +- drivers/scsi/cxgbi/libcxgbi.c| 4 +- drivers/scsi/qedi/qedi_iscsi.c | 4 +- drivers/scsi/qla4xxx/ql4_os.c| 6 +- drivers/scsi/scsi_transport_iscsi.c | 201 +++ include/scsi/scsi_transport_iscsi.h | 5 +- 8 files changed, 150 insertions(+), 83 deletions(-) diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 0a4214be4877..6d088634a806 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -464,15 +464,18 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, struct iscsi_conn *conn = cls_conn->dd_data; struct iser_conn *iser_conn; struct iscsi_endpoint *ep; + struct net *net; int error; error = iscsi_conn_bind(cls_session, cls_conn, is_leading); if (error) return error; + /* the transport ep handle comes from user space so it must be * verified against the global ib connections list */ - ep = iscsi_lookup_endpoint(transport_eph); + net = iscsi_sess_net(cls_session); + ep = iscsi_lookup_endpoint(net, transport_eph); if (!ep) { iser_err("can't bind eph %llx\n", (unsigned long long)transport_eph); diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 33f79f385660..1f4b1b98b4e6 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -181,8 +181,10 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, struct beiscsi_endpoint *beiscsi_ep; struct iscsi_endpoint *ep; uint16_t cri_index; + struct net *net; - ep = iscsi_lookup_endpoint(transport_fd); + net = iscsi_sess_net(cls_session); + ep = iscsi_lookup_endpoint(net, transport_fd); if (!ep) return -EINVAL; diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 19fadb5d3b3c..58dca20f0ba0 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1414,9 +1414,11 @@ static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session, struct bnx2i_hba *hba = iscsi_host_priv(shost); struct bnx2i_endpoint *bnx2i_ep; struct iscsi_endpoint *ep; + struct net *net; int ret_code; - ep = iscsi_lookup_endpoint(transport_fd); + net = iscsi_sess_net(cls_session); + ep = iscsi_lookup_endpoint(net, transport_fd); if (!ep) return -EINVAL; /* diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 558484f72738..e768fe285e85 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -2373,9 +2373,11 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session, struct iscsi_endpoint *ep; struct cxgbi_endpoint *cep; struct cxgbi_sock *csk; + struct net *net; int err; - ep = iscsi_lookup_endpoint(transport_eph); + net = iscsi_sess_net(cls_session); + ep = iscsi_lookup_endpoint(net, transport_eph); if (!ep) return -EINVAL; diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 5ae589ea1dd2..5cd267a457f4 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -381,8 +381,10 @@ static int qedi_conn_bind(struct iscsi_cls_session *cls_session, struct qedi_ctx *qedi = iscsi_host_priv(shost); struct qedi_endpoint *qedi_ep; struct iscsi_endpoint *ep; + struct net *net; - ep = iscsi_lookup_endpoint(transport_fd); + net = iscsi_sess_net(cls_session); + ep = iscsi_lookup_endpoint(net, transport_fd); if (!ep) return -EINVAL; diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 5785bf6c3ec0..770313d0b986 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -3178,6 +3178,7 @@ static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session, struct ddb_entry *ddb_entry; struct scsi_qla_host *ha; struct iscsi_session *sess; + struct net *net; sess = cls_session->dd_data; ddb_entry = sess->dd_data; @@ -3186,9 +3187,12 @@ static int qla4xxx_conn_bind(struct iscsi_cls_session *cls_session, DEBUG2(ql4_printk(KERN_INFO, ha, "%s: sid = %d, cid = %d\n", __func__, cls_session->sid, cls_conn->cid)); + net = iscsi_sess_net(cls_session); + ep = iscsi_lookup_endpoint(net, transport_fd); +
[PATCH 7/9] iscsi: convert flashnode devices from bus to class
The flashnode session and connection devices should be filtered by net namespace along with the iscsi_host, but we can't do that with a bus device. As these don't use any of the bus matching functionality, they make more sense as a class device anyway. Signed-off-by: Chris Leech --- drivers/scsi/qla4xxx/ql4_os.c | 2 +- drivers/scsi/scsi_transport_iscsi.c | 36 +++- include/scsi/scsi_transport_iscsi.h | 2 ++ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 770313d0b986..55a729568873 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -7164,7 +7164,7 @@ static int qla4xxx_sysfs_ddb_is_non_persistent(struct device *dev, void *data) { struct iscsi_bus_flash_session *fnode_sess; - if (!iscsi_flashnode_bus_match(dev, NULL)) + if (!iscsi_is_flashnode_session_dev(dev)) return 0; fnode_sess = iscsi_dev_to_flash_session(dev); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index fbec3a019f00..b053d57a482d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1060,6 +1060,12 @@ static const struct device_type iscsi_flashnode_sess_dev_type = { .release = iscsi_flashnode_sess_release, }; +bool iscsi_is_flashnode_session_dev(struct device *dev) +{ + return dev->type == &iscsi_flashnode_sess_dev_type; +} +EXPORT_SYMBOL_GPL(iscsi_is_flashnode_session_dev); + /* flash node connection attrs show */ #define iscsi_flashnode_conn_attr_show(type, name, param) \ static ssize_t \ @@ -1246,20 +1252,8 @@ static const struct device_type iscsi_flashnode_conn_dev_type = { .release = iscsi_flashnode_conn_release, }; -static struct bus_type iscsi_flashnode_bus; - -int iscsi_flashnode_bus_match(struct device *dev, -struct device_driver *drv) -{ - if (dev->bus == &iscsi_flashnode_bus) - return 1; - return 0; -} -EXPORT_SYMBOL_GPL(iscsi_flashnode_bus_match); - -static struct bus_type iscsi_flashnode_bus = { +static struct class iscsi_flashnode_bus = { .name = "iscsi_flashnode", - .match = &iscsi_flashnode_bus_match, }; /** @@ -1290,7 +1284,7 @@ iscsi_create_flashnode_sess(struct Scsi_Host *shost, int index, fnode_sess->transport = transport; fnode_sess->target_id = index; fnode_sess->dev.type = &iscsi_flashnode_sess_dev_type; - fnode_sess->dev.bus = &iscsi_flashnode_bus; + fnode_sess->dev.class = &iscsi_flashnode_bus; fnode_sess->dev.parent = &shost->shost_gendev; dev_set_name(&fnode_sess->dev, "flashnode_sess-%u:%u", shost->host_no, index); @@ -1338,7 +1332,7 @@ iscsi_create_flashnode_conn(struct Scsi_Host *shost, fnode_conn->transport = transport; fnode_conn->dev.type = &iscsi_flashnode_conn_dev_type; - fnode_conn->dev.bus = &iscsi_flashnode_bus; + fnode_conn->dev.class = &iscsi_flashnode_bus; fnode_conn->dev.parent = &fnode_sess->dev; dev_set_name(&fnode_conn->dev, "flashnode_conn-%u:%u:0", shost->host_no, fnode_sess->target_id); @@ -1371,7 +1365,7 @@ EXPORT_SYMBOL_GPL(iscsi_create_flashnode_conn); */ static int iscsi_is_flashnode_conn_dev(struct device *dev, void *data) { - return dev->bus == &iscsi_flashnode_bus; + return dev->type == &iscsi_flashnode_conn_dev_type; } static int iscsi_destroy_flashnode_conn(struct iscsi_bus_flash_conn *fnode_conn) @@ -1385,7 +1379,7 @@ static int flashnode_match_index(struct device *dev, void *data) struct iscsi_bus_flash_session *fnode_sess = NULL; int ret = 0; - if (!iscsi_flashnode_bus_match(dev, NULL)) + if (dev->type != &iscsi_flashnode_sess_dev_type) goto exit_match_index; fnode_sess = iscsi_dev_to_flash_session(dev); @@ -1491,7 +1485,7 @@ EXPORT_SYMBOL_GPL(iscsi_destroy_flashnode_sess); static int iscsi_iter_destroy_flashnode_fn(struct device *dev, void *data) { - if (!iscsi_flashnode_bus_match(dev, NULL)) + if (dev->type != &iscsi_flashnode_sess_dev_type) return 0; iscsi_destroy_flashnode_sess(iscsi_dev_to_flash_session(dev)); @@ -4752,7 +4746,7 @@ static __init int iscsi_transport_init(void) if (err) goto unregister_conn_class; - err = bus_register(&iscsi_flashnode_bus); + err = class_register(&iscsi_flashnode_bus); if (err) goto unregister_session_class; @@ -4773,7 +4767,7 @@ static __init int iscsi_transport_init(void) unregister_pernet_subsys: unregister_pernet_subsys(&iscsi_net_ops); unregister_flashnode_bus: - bus_unregister(&iscsi_flashnode_bus); + class_unregister(&iscsi_flashnode_
[PATCH 9/9] iscsi: filter flashnode sysfs by net namespace
Finished the net namespace support for flashnode sysfs devices Signed-off-by: Chris Leech --- drivers/scsi/scsi_transport_iscsi.c | 33 + 1 file changed, 33 insertions(+) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 5ffda170ac9d..783971d72c4c 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1268,8 +1268,41 @@ static int iscsi_is_flashnode_conn_dev(struct device *dev, void *data) return dev->type == &iscsi_flashnode_conn_dev_type; } +static struct net *iscsi_flashnode_sess_net(struct iscsi_flash_session *f_sess) +{ + struct Scsi_Host *shost = iscsi_flash_session_to_shost(f_sess); + struct iscsi_cls_host *ihost = shost->shost_data; + + return iscsi_host_net(ihost); +} + +static struct net *iscsi_flashnode_conn_net(struct iscsi_flash_conn *f_conn) +{ + struct iscsi_flash_session *f_sess = + iscsi_flash_conn_to_flash_session(f_conn); + + return iscsi_flashnode_sess_net(f_sess); +} + +static const void *iscsi_flashnode_namespace(struct device *dev) +{ + struct iscsi_flash_conn *f_conn; + struct iscsi_flash_session *f_sess; + + if (iscsi_is_flashnode_conn_dev(dev, NULL)) { + f_conn = iscsi_dev_to_flash_conn(dev); + return iscsi_flashnode_conn_net(f_conn); + } else if (iscsi_is_flashnode_session_dev(dev)) { + f_sess = iscsi_dev_to_flash_session(dev); + return iscsi_flashnode_sess_net(f_sess); + } + return NULL; +} + static struct class iscsi_flashnode = { .name = "iscsi_flashnode", + .ns_type = &net_ns_type_operations, + .namespace = iscsi_flashnode_namespace, }; /** -- 2.9.5
[PATCH 8/9] iscsi: rename iscsi_bus_flash_* to iscsi_flash_*
cleanups after the bus to class conversion Signed-off-by: Chris Leech --- drivers/scsi/qla4xxx/ql4_os.c | 52 +- drivers/scsi/scsi_transport_iscsi.c | 102 ++-- include/scsi/scsi_transport_iscsi.h | 48 + 3 files changed, 102 insertions(+), 100 deletions(-) diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 55a729568873..9c80688d0681 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -169,20 +169,20 @@ static int qla4xxx_host_reset(struct Scsi_Host *shost, int reset_type); * iSCSI Flash DDB sysfs entry points */ static int -qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, - struct iscsi_bus_flash_conn *fnode_conn, +qla4xxx_sysfs_ddb_set_param(struct iscsi_flash_session *fnode_sess, + struct iscsi_flash_conn *fnode_conn, void *data, int len); static int -qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, +qla4xxx_sysfs_ddb_get_param(struct iscsi_flash_session *fnode_sess, int param, char *buf); static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf, int len); static int -qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess); -static int qla4xxx_sysfs_ddb_login(struct iscsi_bus_flash_session *fnode_sess, - struct iscsi_bus_flash_conn *fnode_conn); -static int qla4xxx_sysfs_ddb_logout(struct iscsi_bus_flash_session *fnode_sess, - struct iscsi_bus_flash_conn *fnode_conn); +qla4xxx_sysfs_ddb_delete(struct iscsi_flash_session *fnode_sess); +static int qla4xxx_sysfs_ddb_login(struct iscsi_flash_session *fnode_sess, + struct iscsi_flash_conn *fnode_conn); +static int qla4xxx_sysfs_ddb_logout(struct iscsi_flash_session *fnode_sess, + struct iscsi_flash_conn *fnode_conn); static int qla4xxx_sysfs_ddb_logout_sid(struct iscsi_cls_session *cls_sess); static struct qla4_8xxx_legacy_intr_set legacy_intr[] = @@ -3454,8 +3454,8 @@ static int qla4xxx_task_xmit(struct iscsi_task *task) return -ENOSYS; } -static int qla4xxx_copy_from_fwddb_param(struct iscsi_bus_flash_session *sess, -struct iscsi_bus_flash_conn *conn, +static int qla4xxx_copy_from_fwddb_param(struct iscsi_flash_session *sess, +struct iscsi_flash_conn *conn, struct dev_db_entry *fw_ddb_entry) { unsigned long options = 0; @@ -3596,8 +3596,8 @@ static int qla4xxx_copy_from_fwddb_param(struct iscsi_bus_flash_session *sess, return rc; } -static int qla4xxx_copy_to_fwddb_param(struct iscsi_bus_flash_session *sess, - struct iscsi_bus_flash_conn *conn, +static int qla4xxx_copy_to_fwddb_param(struct iscsi_flash_session *sess, + struct iscsi_flash_conn *conn, struct dev_db_entry *fw_ddb_entry) { uint16_t options; @@ -7162,7 +7162,7 @@ static void qla4xxx_build_new_nt_list(struct scsi_qla_host *ha, **/ static int qla4xxx_sysfs_ddb_is_non_persistent(struct device *dev, void *data) { - struct iscsi_bus_flash_session *fnode_sess; + struct iscsi_flash_session *fnode_sess; if (!iscsi_is_flashnode_session_dev(dev)) return 0; @@ -7192,8 +7192,8 @@ static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha, struct dev_db_entry *fw_ddb_entry, uint16_t *idx, int user) { - struct iscsi_bus_flash_session *fnode_sess = NULL; - struct iscsi_bus_flash_conn *fnode_conn = NULL; + struct iscsi_flash_session *fnode_sess = NULL; + struct iscsi_flash_conn *fnode_conn = NULL; int rc = QLA_ERROR; fnode_sess = iscsi_create_flashnode_sess(ha->host, *idx, @@ -7330,8 +7330,8 @@ static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf, * This writes the contents of target ddb buffer to Flash with a valid cookie * value in order to make the ddb entry persistent. **/ -static int qla4xxx_sysfs_ddb_apply(struct iscsi_bus_flash_session *fnode_sess, - struct iscsi_bus_flash_conn *fnode_conn) +static int qla4xxx_sysfs_ddb_apply(struct iscsi_flash_session *fnode_sess, + struct iscsi_flash_conn *fnode_conn) { struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); struct scsi_qla_host *ha = to_qla_host(shost); @@ -7520,8 +7520,8 @@ static int qla4xxx_ddb_login_nt(struct scsi_qla_host *ha, * * This logs in to the specified target **/ -static int ql
[PATCH 1/9] iscsi: create per-net iscsi netlink kernel sockets
Prepare iSCSI netlink to operate in multiple namespaces. Signed-off-by: Chris Leech --- drivers/scsi/scsi_transport_iscsi.c | 67 +++-- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 7404d26895f5..0b23ba346cbe 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include #include @@ -1601,7 +1603,11 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class, NULL, NULL); -static struct sock *nls; +struct iscsi_net { + struct sock *nls; +}; + +static int iscsi_net_id __read_mostly; static DEFINE_MUTEX(rx_queue_mutex); static LIST_HEAD(sesslist); @@ -2317,11 +2323,23 @@ iscsi_if_transport_lookup(struct iscsi_transport *tt) } static int -iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp) +iscsi_multicast_netns(struct net *net, struct sk_buff *skb, + uint32_t group, gfp_t gfp) { + struct sock *nls; + struct iscsi_net *isn; + + isn = net_generic(net, iscsi_net_id); + nls = isn->nls; return nlmsg_multicast(nls, skb, 0, group, gfp); } +static int +iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp) +{ + return iscsi_multicast_netns(&init_net, skb, group, gfp); +} + int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, char *data, uint32_t data_size) { @@ -4490,13 +4508,42 @@ int iscsi_unregister_transport(struct iscsi_transport *tt) } EXPORT_SYMBOL_GPL(iscsi_unregister_transport); -static __init int iscsi_transport_init(void) +static int __net_init iscsi_net_init(struct net *net) { - int err; + struct sock *nls; + struct iscsi_net *isn; struct netlink_kernel_cfg cfg = { .groups = 1, .input = iscsi_if_rx, }; + + nls = netlink_kernel_create(net, NETLINK_ISCSI, &cfg); + if (!nls) + return -ENOMEM; + isn = net_generic(net, iscsi_net_id); + isn->nls = nls; + return 0; +} + +static void __net_exit iscsi_net_exit(struct net *net) +{ + struct iscsi_net *isn; + + isn = net_generic(net, iscsi_net_id); + netlink_kernel_release(isn->nls); + isn->nls = NULL; +} + +static struct pernet_operations iscsi_net_ops = { + .init = iscsi_net_init, + .exit = iscsi_net_exit, + .id = &iscsi_net_id, + .size = sizeof(struct iscsi_net), +}; + +static __init int iscsi_transport_init(void) +{ + int err; printk(KERN_INFO "Loading iSCSI transport class v%s.\n", ISCSI_TRANSPORT_VERSION); @@ -4530,8 +4577,8 @@ static __init int iscsi_transport_init(void) if (err) goto unregister_session_class; - nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, &cfg); - if (!nls) { + err = register_pernet_subsys(&iscsi_net_ops); + if (err) { err = -ENOBUFS; goto unregister_flashnode_bus; } @@ -4539,13 +4586,13 @@ static __init int iscsi_transport_init(void) iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh"); if (!iscsi_eh_timer_workq) { err = -ENOMEM; - goto release_nls; + goto unregister_pernet_subsys; } return 0; -release_nls: - netlink_kernel_release(nls); +unregister_pernet_subsys: + unregister_pernet_subsys(&iscsi_net_ops); unregister_flashnode_bus: bus_unregister(&iscsi_flashnode_bus); unregister_session_class: @@ -4566,7 +4613,7 @@ static __init int iscsi_transport_init(void) static void __exit iscsi_transport_exit(void) { destroy_workqueue(iscsi_eh_timer_workq); - netlink_kernel_release(nls); + unregister_pernet_subsys(&iscsi_net_ops); bus_unregister(&iscsi_flashnode_bus); transport_class_unregister(&iscsi_connection_class); transport_class_unregister(&iscsi_session_class); -- 2.9.5
[PATCH] storvsc: Avoid excessive host scan on controller change
From: Long Li When there are multiple disks attached to the same SCSI controller, the host may send several VSTOR_OPERATION_REMOVE_DEVICE or VSTOR_OPERATION_ENUMERATE_BUS messages in a row, to indicate there is a change on the SCSI controller. In response, storvsc rescans the SCSI host. There is no need to do multiple scans on the same host. Fix the code to do only one scan. Signed-off-by: Long Li --- drivers/scsi/storvsc_drv.c | 26 +++--- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 6febcdb..b602f52 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -488,6 +488,8 @@ struct hv_host_device { unsigned char target; struct workqueue_struct *handle_error_wq; char work_q_name[20]; + struct work_struct host_scan_work; + struct Scsi_Host *host; }; struct storvsc_scan_work { @@ -516,13 +518,12 @@ static void storvsc_device_scan(struct work_struct *work) static void storvsc_host_scan(struct work_struct *work) { - struct storvsc_scan_work *wrk; struct Scsi_Host *host; struct scsi_device *sdev; + struct hv_host_device *host_device = + container_of(work, struct hv_host_device, host_scan_work); - wrk = container_of(work, struct storvsc_scan_work, work); - host = wrk->host; - + host = host_device->host; /* * Before scanning the host, first check to see if any of the * currrently known devices have been hot removed. We issue a @@ -542,8 +543,6 @@ static void storvsc_host_scan(struct work_struct *work) * Now scan the host to discover LUNs that may have been added. */ scsi_scan_host(host); - - kfree(wrk); } static void storvsc_remove_lun(struct work_struct *work) @@ -1119,8 +1118,7 @@ static void storvsc_on_receive(struct storvsc_device *stor_device, struct vstor_packet *vstor_packet, struct storvsc_cmd_request *request) { - struct storvsc_scan_work *work; - + struct hv_host_device *host_dev; switch (vstor_packet->operation) { case VSTOR_OPERATION_COMPLETE_IO: storvsc_on_io_completion(stor_device, vstor_packet, request); @@ -1128,13 +1126,9 @@ static void storvsc_on_receive(struct storvsc_device *stor_device, case VSTOR_OPERATION_REMOVE_DEVICE: case VSTOR_OPERATION_ENUMERATE_BUS: - work = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC); - if (!work) - return; - - INIT_WORK(&work->work, storvsc_host_scan); - work->host = stor_device->host; - schedule_work(&work->work); + host_dev = shost_priv(stor_device->host); + queue_work( + host_dev->handle_error_wq, &host_dev->host_scan_work); break; case VSTOR_OPERATION_FCHBA_DATA: @@ -1747,6 +1741,7 @@ static int storvsc_probe(struct hv_device *device, host_dev->port = host->host_no; host_dev->dev = device; + host_dev->host = host; stor_device = kzalloc(sizeof(struct storvsc_device), GFP_KERNEL); @@ -1815,6 +1810,7 @@ static int storvsc_probe(struct hv_device *device, create_singlethread_workqueue(host_dev->work_q_name); if (!host_dev->handle_error_wq) goto err_out2; + INIT_WORK(&host_dev->host_scan_work, storvsc_host_scan); /* Register the HBA and start the scsi bus scan */ ret = scsi_add_host(host, &device->device); if (ret != 0) -- 2.7.4
Re: [PATCH] scsi: ibmvscsi: Convert timers to use timer_setup()
On 10/25/2017 03:06 AM, Kees Cook wrote: > In preparation for unconditionally passing the struct timer_list pointer to > all timer callbacks, switch to using the new timer_setup() and from_timer() > to pass the timer pointer explicitly. > > Cc: "Martin K. Petersen" > Cc: Tyrel Datwyler > Cc: Benjamin Herrenschmidt > Cc: Paul Mackerras > Cc: Michael Ellerman > Cc: "James E.J. Bottomley" > Cc: linux-scsi@vger.kernel.org > Cc: linuxppc-...@lists.ozlabs.org > Signed-off-by: Kees Cook > --- > drivers/scsi/ibmvscsi/ibmvfc.c | 14 ++ > drivers/scsi/ibmvscsi/ibmvscsi.c | 7 +++ > 2 files changed, 9 insertions(+), 12 deletions(-) Acked-by: Tyrel Datwyler
[PATCH RESEND] scsi: fnic: Clean up redundant variables
Remove variables that are set but not used. Signed-off-by: Christos Gkekas --- drivers/scsi/fnic/fnic_fcs.c | 9 - drivers/scsi/fnic/vnic_rq.c | 3 --- drivers/scsi/fnic/vnic_wq.c | 3 --- 3 files changed, 15 deletions(-) diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index 999fc75..bc1fcce 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c @@ -293,12 +293,10 @@ static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip, struct fc_frame_header *fh = NULL; struct fip_desc *desc; struct fip_encaps *els; - enum fip_desc_type els_dtype = 0; u16 op; u8 els_op; u8 sub; - size_t els_len = 0; size_t rlen; size_t dlen = 0; @@ -330,10 +328,8 @@ static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip, if (dlen < sizeof(*els) + sizeof(*fh) + 1) return 0; - els_len = dlen - sizeof(*els); els = (struct fip_encaps *)desc; fh = (struct fc_frame_header *)(els + 1); - els_dtype = desc->fip_dtype; if (!fh) return 0; @@ -360,7 +356,6 @@ static void fnic_fcoe_send_vlan_req(struct fnic *fnic) struct fnic_stats *fnic_stats = &fnic->fnic_stats; struct sk_buff *skb; char *eth_fr; - int fr_len; struct fip_vlan *vlan; u64 vlan_tov; @@ -375,7 +370,6 @@ static void fnic_fcoe_send_vlan_req(struct fnic *fnic) if (!skb) return; - fr_len = sizeof(*vlan); eth_fr = (char *)skb->data; vlan = (struct fip_vlan *)eth_fr; @@ -823,7 +817,6 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc struct sk_buff *skb; struct fc_frame *fp; struct fnic_stats *fnic_stats = &fnic->fnic_stats; - unsigned int eth_hdrs_stripped; u8 type, color, eop, sop, ingress_port, vlan_stripped; u8 fcoe = 0, fcoe_sof, fcoe_eof; u8 fcoe_fc_crc_ok = 1, fcoe_enc_error = 0; @@ -853,7 +846,6 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc &ingress_port, &packet_error, &fcoe_enc_error, &fcs_ok, &vlan_stripped, &vlan); - eth_hdrs_stripped = 1; skb_trim(skb, fcp_bytes_written); fr_sof(fp) = sof; fr_eof(fp) = eof; @@ -870,7 +862,6 @@ static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc &tcp_udp_csum_ok, &udp, &tcp, &ipv4_csum_ok, &ipv6, &ipv4, &ipv4_fragment, &fcs_ok); - eth_hdrs_stripped = 0; skb_trim(skb, bytes_written); if (!fcs_ok) { atomic64_inc(&fnic_stats->misc_stats.frame_errors); diff --git a/drivers/scsi/fnic/vnic_rq.c b/drivers/scsi/fnic/vnic_rq.c index fd2068f..ae8b78c 100644 --- a/drivers/scsi/fnic/vnic_rq.c +++ b/drivers/scsi/fnic/vnic_rq.c @@ -27,12 +27,9 @@ static int vnic_rq_alloc_bufs(struct vnic_rq *rq) { struct vnic_rq_buf *buf; - struct vnic_dev *vdev; unsigned int i, j, count = rq->ring.desc_count; unsigned int blks = VNIC_RQ_BUF_BLKS_NEEDED(count); - vdev = rq->vdev; - for (i = 0; i < blks; i++) { rq->bufs[i] = kzalloc(VNIC_RQ_BUF_BLK_SZ, GFP_ATOMIC); if (!rq->bufs[i]) { diff --git a/drivers/scsi/fnic/vnic_wq.c b/drivers/scsi/fnic/vnic_wq.c index a414135..5f57809 100644 --- a/drivers/scsi/fnic/vnic_wq.c +++ b/drivers/scsi/fnic/vnic_wq.c @@ -27,12 +27,9 @@ static int vnic_wq_alloc_bufs(struct vnic_wq *wq) { struct vnic_wq_buf *buf; - struct vnic_dev *vdev; unsigned int i, j, count = wq->ring.desc_count; unsigned int blks = VNIC_WQ_BUF_BLKS_NEEDED(count); - vdev = wq->vdev; - for (i = 0; i < blks; i++) { wq->bufs[i] = kzalloc(VNIC_WQ_BUF_BLK_SZ, GFP_ATOMIC); if (!wq->bufs[i]) { -- 2.7.4
[PATCH 4/4] scsi: qla2xxx: Convert qla2x00_sp_timeout() to use timer_setup()
In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, switch to using the new timer_setup() and from_timer() to pass the timer pointer explicitly for the qla2x00_sp_timeout() callback and associated timer. Cc: Himanshu Madhani Cc: Bart Van Assche Cc: "Martin K. Petersen" Cc: qla2xxx-upstr...@qlogic.com Cc: linux-scsi@vger.kernel.org Signed-off-by: Kees Cook --- drivers/scsi/qla2xxx/qla_gbl.h| 2 +- drivers/scsi/qla2xxx/qla_init.c | 4 ++-- drivers/scsi/qla2xxx/qla_inline.h | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index ab5b88203886..3ad375f85b59 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -753,7 +753,7 @@ extern int qla82xx_restart_isp(scsi_qla_host_t *); /* IOCB related functions */ extern int qla82xx_start_scsi(srb_t *); extern void qla2x00_sp_free(void *); -extern void qla2x00_sp_timeout(unsigned long); +extern void qla2x00_sp_timeout(struct timer_list *); extern void qla2x00_bsg_job_done(void *, int); extern void qla2x00_bsg_sp_free(void *); extern void qla2x00_start_iocbs(struct scsi_qla_host *, struct req_que *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index b5b48ddca962..44cf875a484a 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -45,9 +45,9 @@ static void qla24xx_handle_prli_done_event(struct scsi_qla_host *, /* SRB Extensions -- */ void -qla2x00_sp_timeout(unsigned long __data) +qla2x00_sp_timeout(struct timer_list *t) { - srb_t *sp = (srb_t *)__data; + srb_t *sp = from_timer(sp, t, u.iocb_cmd.timer); struct srb_iocb *iocb; scsi_qla_host_t *vha = sp->vha; struct req_que *req; diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 34cdb5d9c87c..17d2c20f1f75 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -269,8 +269,7 @@ qla2x00_rel_sp(srb_t *sp) static inline void qla2x00_init_timer(srb_t *sp, unsigned long tmo) { - setup_timer(&sp->u.iocb_cmd.timer, qla2x00_sp_timeout, - (unsigned long)sp); + timer_setup(&sp->u.iocb_cmd.timer, qla2x00_sp_timeout, 0); sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ; add_timer(&sp->u.iocb_cmd.timer); sp->free = qla2x00_sp_free; -- 2.7.4
[PATCH 3/4] scsi: qla2xxx: Convert qla2x00_timer() to use timer_setup()
In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, switch to using the new timer_setup() and from_timer() to pass the timer pointer explicitly for the qla2x00_timer() callback and associated timer. Cc: Himanshu Madhani Cc: Bart Van Assche Cc: "Martin K. Petersen" Cc: qla2xxx-upstr...@qlogic.com Cc: linux-scsi@vger.kernel.org Signed-off-by: Kees Cook --- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_os.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 541a087cdb45..ab5b88203886 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -206,7 +206,7 @@ int qla24xx_async_abort_cmd(srb_t *); */ extern struct scsi_host_template qla2xxx_driver_template; extern struct scsi_transport_template *qla2xxx_transport_vport_template; -extern void qla2x00_timer(scsi_qla_host_t *); +extern void qla2x00_timer(struct timer_list *); extern void qla2x00_start_timer(scsi_qla_host_t *, unsigned long); extern void qla24xx_deallocate_vp_id(scsi_qla_host_t *); extern int qla24xx_disable_vp (scsi_qla_host_t *); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7e7e5d095c26..f97e585dee77 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -332,8 +332,7 @@ struct scsi_transport_template *qla2xxx_transport_vport_template = NULL; __inline__ void qla2x00_start_timer(scsi_qla_host_t *vha, unsigned long interval) { - setup_timer(&vha->timer, (void (*)(unsigned long))qla2x00_timer, - (unsigned long)vha); + timer_setup(&vha->timer, qla2x00_timer, 0); vha->timer.expires = jiffies + interval * HZ; add_timer(&vha->timer); vha->timer_active = 1; @@ -5994,8 +5993,9 @@ qla2x00_rst_aen(scsi_qla_host_t *vha) * Context: Interrupt ***/ void -qla2x00_timer(scsi_qla_host_t *vha) +qla2x00_timer(struct timer_list *t) { + scsi_qla_host_t *vha = from_timer(vha, t, timer); unsigned long cpu_flags = 0; int start_dpc = 0; int index; -- 2.7.4
[PATCH 1/4] scsi: qla2xxx: Convert timers to use setup_timer()
In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, take the first step by switching from init_timer() and open-coded .function and .data assignments to using the old setup_timer() API. Cc: Himanshu Madhani Cc: Bart Van Assche Cc: qla2xxx-upstr...@qlogic.com Cc: "Martin K. Petersen" Cc: linux-scsi@vger.kernel.org Signed-off-by: Kees Cook --- drivers/scsi/qla2xxx/qla_inline.h | 5 ++--- drivers/scsi/qla2xxx/qla_os.c | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 9a2c86eacf44..34cdb5d9c87c 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -269,10 +269,9 @@ qla2x00_rel_sp(srb_t *sp) static inline void qla2x00_init_timer(srb_t *sp, unsigned long tmo) { - init_timer(&sp->u.iocb_cmd.timer); + setup_timer(&sp->u.iocb_cmd.timer, qla2x00_sp_timeout, + (unsigned long)sp); sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ; - sp->u.iocb_cmd.timer.data = (unsigned long)sp; - sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout; add_timer(&sp->u.iocb_cmd.timer); sp->free = qla2x00_sp_free; if (IS_QLAFX00(sp->vha->hw) && (sp->type == SRB_FXIOCB_DCMD)) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3bd956d3bc5d..6c10a7b970c0 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -332,10 +332,9 @@ struct scsi_transport_template *qla2xxx_transport_vport_template = NULL; __inline__ void qla2x00_start_timer(scsi_qla_host_t *vha, void *func, unsigned long interval) { - init_timer(&vha->timer); + setup_timer(&vha->timer, (void (*)(unsigned long))func, + (unsigned long)vha); vha->timer.expires = jiffies + interval * HZ; - vha->timer.data = (unsigned long)vha; - vha->timer.function = (void (*)(unsigned long))func; add_timer(&vha->timer); vha->timer_active = 1; } -- 2.7.4
[PATCH 2/4] scsi: qla2xxx: Refactor qla2x00_start_timer()
In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, this refactors qla2x00_start_timer() to not pass a callback argument, since all callers use the same callback. Cc: Himanshu Madhani Cc: Bart Van Assche Cc: "Martin K. Petersen" Cc: qla2xxx-upstr...@qlogic.com Cc: linux-scsi@vger.kernel.org Signed-off-by: Kees Cook --- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_mid.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index f852ca60c49f..541a087cdb45 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -207,7 +207,7 @@ int qla24xx_async_abort_cmd(srb_t *); extern struct scsi_host_template qla2xxx_driver_template; extern struct scsi_transport_template *qla2xxx_transport_vport_template; extern void qla2x00_timer(scsi_qla_host_t *); -extern void qla2x00_start_timer(scsi_qla_host_t *, void *, unsigned long); +extern void qla2x00_start_timer(scsi_qla_host_t *, unsigned long); extern void qla24xx_deallocate_vp_id(scsi_qla_host_t *); extern int qla24xx_disable_vp (scsi_qla_host_t *); extern int qla24xx_enable_vp (scsi_qla_host_t *); diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index c0f8f6c17b79..cbf544dbf883 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -487,7 +487,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) atomic_set(&vha->loop_state, LOOP_DOWN); atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); - qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL); + qla2x00_start_timer(vha, WATCH_INTERVAL); vha->req = base_vha->req; host->can_queue = base_vha->req->length + 128; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6c10a7b970c0..7e7e5d095c26 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -330,9 +330,9 @@ struct scsi_transport_template *qla2xxx_transport_vport_template = NULL; */ __inline__ void -qla2x00_start_timer(scsi_qla_host_t *vha, void *func, unsigned long interval) +qla2x00_start_timer(scsi_qla_host_t *vha, unsigned long interval) { - setup_timer(&vha->timer, (void (*)(unsigned long))func, + setup_timer(&vha->timer, (void (*)(unsigned long))qla2x00_timer, (unsigned long)vha); vha->timer.expires = jiffies + interval * HZ; add_timer(&vha->timer); @@ -3245,7 +3245,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) base_vha->host->irq = ha->pdev->irq; /* Initialized the timer */ - qla2x00_start_timer(base_vha, qla2x00_timer, WATCH_INTERVAL); + qla2x00_start_timer(base_vha, WATCH_INTERVAL); ql_dbg(ql_dbg_init, base_vha, 0x00ef, "Started qla2x00_timer with " "interval=%d.\n", WATCH_INTERVAL); -- 2.7.4
[PATCH 0/4] scsi: qla2xxx: Convert timers to use timer_setup()
This breaks out the logical steps to convert the qla2xxx timers: 1) init_timer() -> setup_timer() 2) refactor qla2x00_start_timer() to not pass callback as argument 3) qla2x00_timer() to use timer_setup() 4) qla2x00_sp_timeout() to use timer_setup() The resulting diff is identical to the patch that appears to lock up the driver. This should help identify which step causes this behavior. -Kees
RE: [PATCH] scsi: megaraid: Convert timers to use timer_setup()
-Original Message- From: Kees Cook [mailto:keesc...@chromium.org] Sent: Wednesday, October 25, 2017 3:37 PM To: Martin K. Petersen Cc: Kashyap Desai; Sumit Saxena; Shivasharan S; James E.J. Bottomley; megaraidlinux@broadcom.com; linux-scsi@vger.kernel.org; linux-ker...@vger.kernel.org Subject: [PATCH] scsi: megaraid: Convert timers to use timer_setup() In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, switch to using the new timer_setup() and from_timer() to pass the timer pointer explicitly. Also consolidates the timer setup functions arguments, which are all identical, and corrects on-stack timer usage. Cc: Kashyap Desai Cc: Sumit Saxena Cc: Shivasharan S Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Cc: megaraidlinux@broadcom.com Cc: linux-scsi@vger.kernel.org Signed-off-by: Kees Cook --- drivers/scsi/megaraid/megaraid_ioctl.h | 6 + drivers/scsi/megaraid/megaraid_mbox.c | 26 ++--- drivers/scsi/megaraid/megaraid_mm.c | 27 +++--- drivers/scsi/megaraid/megaraid_sas_base.c | 35 +++-- drivers/scsi/megaraid/megaraid_sas_fusion.c | 15 +++-- 5 files changed, 47 insertions(+), 62 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h index 05f6e4ec3453..eedcbde46459 100644 --- a/drivers/scsi/megaraid/megaraid_ioctl.h +++ b/drivers/scsi/megaraid/megaraid_ioctl.h @@ -19,6 +19,7 @@ #include #include +#include #include "mbox_defs.h" @@ -153,6 +154,11 @@ typedef struct uioc { } __attribute__ ((aligned(1024),packed)) uioc_t; +/* For on-stack uioc timers. */ +struct uioc_timeout { + struct timer_list timer; + uioc_t*uioc; +}; /** * struct mraid_hba_info - information about the controller diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index ec3c43854978..530358cdcb39 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -3904,19 +3904,19 @@ megaraid_sysfs_get_ldmap_done(uioc_t *uioc) wake_up(&raid_dev->sysfs_wait_q); } - /** * megaraid_sysfs_get_ldmap_timeout - timeout handling for get ldmap - * @data : timed out packet + * @t : timed out timer * * Timeout routine to recover and return to application, in case the adapter * has stopped responding. A timeout of 60 seconds for this command seems like * a good value. */ static void -megaraid_sysfs_get_ldmap_timeout(unsigned long data) +megaraid_sysfs_get_ldmap_timeout(struct timer_list *t) { - uioc_t *uioc = (uioc_t *)data; + struct uioc_timeout *timeout = from_timer(timeout, t, timer); + uioc_t *uioc = timeout->uioc; adapter_t *adapter = (adapter_t *)uioc->buf_vaddr; mraid_device_t *raid_dev = ADAP2RAIDDEV(adapter); @@ -3951,8 +3951,7 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter) mbox64_t*mbox64; mbox_t *mbox; char*raw_mbox; - struct timer_list sysfs_timer; - struct timer_list *timerp; + struct uioc_timeout timeout; caddr_t ldmap; int rval = 0; @@ -3988,14 +3987,12 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter) /* * Setup a timer to recover from a non-responding controller */ - timerp = &sysfs_timer; - init_timer(timerp); - - timerp->function= megaraid_sysfs_get_ldmap_timeout; - timerp->data= (unsigned long)uioc; - timerp->expires = jiffies + 60 * HZ; + timeout.uioc = uioc; + timer_setup_on_stack(&timeout.timer, +megaraid_sysfs_get_ldmap_timeout, 0); Kees, Does calling "timer_setup_on_stack" instead of "timer_setup" intentional ? If yes, please help me understand the reason. Otherwise changes look good to me. - add_timer(timerp); + timeout.timer.expires = jiffies + 60 * HZ; + add_timer(&timeout.timer); /* * Send the command to the firmware @@ -4033,7 +4030,8 @@ megaraid_sysfs_get_ldmap(adapter_t *adapter) } - del_timer_sync(timerp); + del_timer_sync(&timeout.timer); + destroy_timer_on_stack(&timeout.timer); mutex_unlock(&raid_dev->sysfs_mtx); diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index 65b6f6ace3a5..bb802b0c12b8 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -35,7 +35,7 @@ static int kioc_to_mimd(uioc_t *, mimd_t __user *); static int handle_drvrcmd(void __user *, uint8_t, int *); static int lld_ioctl(mraid_mmadp_t *, uioc_t *); static void ioctl_done(uioc_t *); -static void lld_timedout(unsigned long); +static void lld_timedout(struct timer_list *); static void hinfo_
Re: [PATCH] scsi: qla2xxx: Convert timers to use timer_setup()
On Tue, Oct 31, 2017 at 11:36 AM, Madhani, Himanshu wrote: > Hi Kees, > >> On Oct 31, 2017, at 11:28 AM, Kees Cook wrote: >> >> How very strange. I don't see any code change with this patch. Even >> the passed arguments are the same; it's only enforcing the types now. >> And the system is fine with only this patch reverted? > > Yes. Agree patch looks okay, but with the patch built into driver I see > system going into infinite loop of trying to bring link up and lock up > after few minutes, Only way to recover is hard reboot. > > I reverted this patch after system boot up and rebuild qla2xxx and able > to load driver. The patch is a result of three logical steps, so maybe something unexpected is happening. I'll send the 3 steps broken out... -Kees -- Kees Cook Pixel Security
Re: [PATCH] scsi: qla2xxx: Convert timers to use timer_setup()
Hi Kees, > On Oct 31, 2017, at 11:28 AM, Kees Cook wrote: > > How very strange. I don't see any code change with this patch. Even > the passed arguments are the same; it's only enforcing the types now. > And the system is fine with only this patch reverted? Yes. Agree patch looks okay, but with the patch built into driver I see system going into infinite loop of trying to bring link up and lock up after few minutes, Only way to recover is hard reboot. I reverted this patch after system boot up and rebuild qla2xxx and able to load driver. Thanks, - Himanshu
Re: [PATCH] scsi: qla2xxx: Convert timers to use timer_setup()
On Tue, Oct 31, 2017 at 11:16 AM, Madhani, Himanshu wrote: > Hi Bart, > >> On Oct 31, 2017, at 11:12 AM, Bart Van Assche wrote: >> >> On Tue, 2017-10-31 at 18:03 +, Madhani, Himanshu wrote: >>> On Oct 31, 2017, at 8:49 AM, Martin K. Petersen >>> wrote: > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. Cavium folks: Please verify! >>> >>> I’ve checked on my setup and i am seeing regression with this patch applied. >>> >>> Driver load locks up the system with this patch applied. How very strange. I don't see any code change with this patch. Even the passed arguments are the same; it's only enforcing the types now. And the system is fine with only this patch reverted? -Kees >>> >>> NACK >> >> That feedback is not very helpful … >> > > Here’s my setup details > > 4.14.0-rc7 + scsi_misc-4.15 qla2xxx patches from Martin’s tree + current > patch. > > System has 3 adapters 8G/16G/32G. > >> Anyway, what kernel source tree did you use in your testing? I may be able to >> free up some time to look into this myself. >> >> Bart. > > Thanks, > - Himanshu -- Kees Cook Pixel Security
Re: [PATCH] scsi: qla2xxx: Convert timers to use timer_setup()
Hi Bart, > On Oct 31, 2017, at 11:12 AM, Bart Van Assche wrote: > > On Tue, 2017-10-31 at 18:03 +, Madhani, Himanshu wrote: >> On Oct 31, 2017, at 8:49 AM, Martin K. Petersen >> wrote: In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, switch to using the new timer_setup() and from_timer() to pass the timer pointer explicitly. >>> >>> Cavium folks: Please verify! >> >> I’ve checked on my setup and i am seeing regression with this patch applied. >> >> Driver load locks up the system with this patch applied. >> >> NACK > > That feedback is not very helpful … > Here’s my setup details 4.14.0-rc7 + scsi_misc-4.15 qla2xxx patches from Martin’s tree + current patch. System has 3 adapters 8G/16G/32G. > Anyway, what kernel source tree did you use in your testing? I may be able to > free up some time to look into this myself. > > Bart. Thanks, - Himanshu
Re: [PATCH] scsi: sas: Convert timers to use timer_setup()
On 25/10/2017 11:08, Kees Cook wrote: In preparation for unconditionally passing the struct timer_list pointer to all timer callbacks, switch to using the new timer_setup() and from_timer() to pass the timer pointer explicitly. This requires adding a pointer to hold the timer's target task, as there isn't a link back from slow_task. Cc: John Garry Cc: "James E.J. Bottomley" Cc: "Martin K. Petersen" Cc: Jack Wang Cc: lindar_...@usish.com Cc: Jens Axboe Cc: Hannes Reinecke Cc: Johannes Thumshirn Cc: Benjamin Block Cc: Baoyou Xie Cc: Wei Yongjun Cc: linux-scsi@vger.kernel.org Signed-off-by: Kees Cook Acked-by: John Garry #for hisi_sas part Tested-by: John Garry # basic sanity test for hisi_sas (+ libsas) --- drivers/scsi/hisi_sas/hisi_sas.h | 1 - drivers/scsi/hisi_sas/hisi_sas_main.c | 14 ++ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 6 +++--- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 24 +++- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2 +- drivers/scsi/libsas/sas_expander.c | 8 drivers/scsi/libsas/sas_init.c | 3 ++- drivers/scsi/libsas/sas_scsi_host.c| 2 +- drivers/scsi/mvsas/mv_init.c | 3 +-- drivers/scsi/mvsas/mv_sas.c| 15 +++ drivers/scsi/mvsas/mv_sas.h| 1 - drivers/scsi/pm8001/pm8001_sas.c | 11 +-- include/scsi/libsas.h | 1 + 13 files changed, 42 insertions(+), 49 deletions(-)
Re: [PATCH v2] target/iscsi: Convert timers to use timer_setup()
Kees, > That was my plan. Does that sound okay? Yep, that's fine. -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH v2] target/iscsi: Convert timers to use timer_setup()
On Tue, Oct 31, 2017 at 10:42 AM, Martin K. Petersen wrote: > > Bart, > >> The tree I tested indeed includes that rebased patch. BTW, since the code >> touched by that patch has not been modified in the past months, the rebased >> patch is identical to the patch I posted in May 2017. > > OK. Just checking. > > So what's the plan here? Should both patches be routed through the timer > tree? That was my plan. Does that sound okay? -Kees -- Kees Cook Pixel Security
Re: [PATCH] scsi: qla2xxx: Convert timers to use timer_setup()
On Tue, 2017-10-31 at 18:03 +, Madhani, Himanshu wrote: > On Oct 31, 2017, at 8:49 AM, Martin K. Petersen > wrote: > > > In preparation for unconditionally passing the struct timer_list > > > pointer to all timer callbacks, switch to using the new timer_setup() > > > and from_timer() to pass the timer pointer explicitly. > > > > Cavium folks: Please verify! > > I’ve checked on my setup and i am seeing regression with this patch applied. > > Driver load locks up the system with this patch applied. > > NACK That feedback is not very helpful ... Anyway, what kernel source tree did you use in your testing? I may be able to free up some time to look into this myself. Bart.
Re: [PATCH] scsi: qla2xxx: Convert timers to use timer_setup()
Hi Martin/Kees, > On Oct 31, 2017, at 8:49 AM, Martin K. Petersen > wrote: > > > Kees, > >> In preparation for unconditionally passing the struct timer_list >> pointer to all timer callbacks, switch to using the new timer_setup() >> and from_timer() to pass the timer pointer explicitly. > > Cavium folks: Please verify! > I’ve checked on my setup and i am seeing regression with this patch applied. Driver load locks up the system with this patch applied. NACK > Reviewed-by: Martin K. Petersen > > -- > Martin K. PetersenOracle Linux Engineering Thanks, - Himanshu
Re: [PATCH v2] target/iscsi: Convert timers to use timer_setup()
Bart, > The tree I tested indeed includes that rebased patch. BTW, since the code > touched by that patch has not been modified in the past months, the rebased > patch is identical to the patch I posted in May 2017. OK. Just checking. So what's the plan here? Should both patches be routed through the timer tree? -- Martin K. Petersen Oracle Linux Engineering
RE: [PATCH 1/2] scsi: megaraid: Remove redundant code in megasas_alloc_cmds
-Original Message- From: Yisheng Xie [mailto:xieyishe...@huawei.com] Sent: Wednesday, October 25, 2017 3:27 PM To: kashyap.de...@broadcom.com; sumit.sax...@broadcom.com; shivasharan.srikanteshw...@broadcom.com; j...@linux.vnet.ibm.com; martin.peter...@oracle.com Cc: megaraidlinux@broadcom.com; linux-scsi@vger.kernel.org; linux-ker...@vger.kernel.org; Yisheng Xie Subject: [PATCH 1/2] scsi: megaraid: Remove redundant code in megasas_alloc_cmds megasas_alloc_cmds is to alloc cmd_list of instance instead of fusion, and fusion is useless in this function. Just remove it. Signed-off-by: Yisheng Xie --- drivers/scsi/megaraid/megaraid_sas_base.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index e518dad..0640168 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4033,9 +4033,7 @@ int megasas_alloc_cmds(struct megasas_instance *instance) int j; u16 max_cmd; struct megasas_cmd *cmd; - struct fusion_context *fusion; - fusion = instance->ctrl_context; max_cmd = instance->max_mfi_cmds; /* Acked-by: Sumit Saxena -- 1.7.12.4
Re: [PATCH v2] target/iscsi: Convert timers to use timer_setup()
On Tue, 2017-10-31 at 13:20 -0400, Martin K. Petersen wrote: > > That tree passed the iSCSI target tests I ran so feel free to add my > > Reviewed-by and Tested-by to [PATCH v2] target/iscsi: Convert timers > > to use timer_setup(). > > Is that with your rebased patch from a few days ago? Hello Martin, The tree I tested indeed includes that rebased patch. BTW, since the code touched by that patch has not been modified in the past months, the rebased patch is identical to the patch I posted in May 2017. Bart.
Re: [PATCH v2] target/iscsi: Convert timers to use timer_setup()
Bart, > That tree passed the iSCSI target tests I ran so feel free to add my > Reviewed-by and Tested-by to [PATCH v2] target/iscsi: Convert timers > to use timer_setup(). Is that with your rebased patch from a few days ago? -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH v2] target/iscsi: Convert timers to use timer_setup()
On Mon, 2017-10-30 at 17:04 -0700, Kees Cook wrote: > On Fri, Oct 27, 2017 at 5:57 AM, Bart Van Assche > wrote: > > On Fri, 2017-10-27 at 02:19 -0700, Kees Cook wrote: > > > In preparation for unconditionally passing the struct timer_list pointer > > > to > > > all timer callbacks, switch to using the new timer_setup() and > > > from_timer() > > > to pass the timer pointer explicitly. Includes a fix for correcting an > > > on-stack timer usage. > > > > These changes look good to me but I would like to test this patch. Is there > > a tree available somewhere that includes this patch? > > I didn't, but in case it's easier to test, I have put it up here, > which is just tip/timers/core with the two target timer patches on > top: > > https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/log/?h=kspp/timer/tip/target Hello Kees, That tree passed the iSCSI target tests I ran so feel free to add my Reviewed-by and Tested-by to [PATCH v2] target/iscsi: Convert timers to use timer_setup(). Bart.
Re: [PATCH] scsi_error.c: DID_SOFT_ERROR comment clean up
Petros, > Updated comment. We are keeping track of maximum number of retries per > command via retries/allowed in struct scsi_cmnd. Corrected comment > positioning. This didn't apply to 4.15/scsi-queue. I applied it by hand. -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: aic7xxx: Convert timers to use timer_setup()
Kees, > stat_timer only ever assigns the same function and data, so > consolidate to using timer_setup(), adjust callback, drop everything > else used to pass things around, and remove needless typedefs. Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH 1/1] scsi: hisi_sas: fix for the build error log_non_standard_event undefined
Shiju, > This patch fix the build error log_non_standard_event undefined > for the i386 build for COMPILE_TEST. This is messy. You have one patch addressing build problems in two different patches. This breaks our ability to bisect. I combined the ECC and AXI patches into one and then added the build fix on top. Really hope that works. -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: sas: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. This requires > adding a pointer to hold the timer's target task, as there isn't a > link back from slow_task. Would be good to get John and Jack to take a closer look... Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: qla4xxx: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. Cavium folks (for good measure): Please review! Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: qla2xxx: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. Cavium folks: Please verify! Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: pmcraid: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list pointer to > all timer callbacks, switch to using the new timer_setup() and from_timer() > to pass the timer pointer explicitly. Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: megaraid: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. Also > consolidates the timer setup functions arguments, which are all > identical, and corrects on-stack timer usage. Same with this one. Broadcom folks, please review! Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: lpfc: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. Looks good to me but since it's a bit gnarly it would be good for James or Dick to take a closer look. Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: ipr: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: ibmvscsi: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: fcoe: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: cxgbi: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH] scsi: csiostor: Convert timers to use timer_setup()
Kees, > In preparation for unconditionally passing the struct timer_list > pointer to all timer callbacks, switch to using the new timer_setup() > and from_timer() to pass the timer pointer explicitly. Reviewed-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
[PATCH V3] scsi: storvsc: Allow only one remove lun work item to be issued per lun
When running multipath on a VM if all available paths go down the driver can schedule large amounts of storvsc_remove_lun work items to the same lun. In response to the failing paths typically storvsc responds by taking host->scan_mutex and issuing a TUR per lun. If there has been heavy IO to the failed device all the failed IOs are returned from the host. A remove lun work item is issued per failed IO. If the outstanding TURs have not been completed in a timely manner the scan_mutex is never released or released too late. Consequently the many remove lun work items are not completed as scsi_remove_device also tries to take host->scan_mutex. This results in dragging the VM down and sometimes completely. This patch only allows one remove lun to be issued to a particular lun while it is an instantiated member of the scsi stack. Changes since v1: Use single threaded workqueue to serialize work in storvsc_handle_error [Christoph Hellwig] Changes since v2: Replaced create_singlethread_workqueue with alloc_ordered_workqueue [Christoph Hellwig] Added reviewed by's. Signed-off-by: Cathy Avery Reviewed-by: Christoph Hellwig Reviewed-by: Long Li --- drivers/scsi/storvsc_drv.c | 26 +- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 5e7200f..7e3cd12 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -486,6 +486,7 @@ struct hv_host_device { unsigned int port; unsigned char path; unsigned char target; + struct workqueue_struct *handle_error_wq; }; struct storvsc_scan_work { @@ -922,6 +923,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, { struct storvsc_scan_work *wrk; void (*process_err_fn)(struct work_struct *work); + struct hv_host_device *host_dev = shost_priv(host); bool do_work = false; switch (SRB_STATUS(vm_srb->srb_status)) { @@ -988,7 +990,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, wrk->lun = vm_srb->lun; wrk->tgt_id = vm_srb->target_id; INIT_WORK(&wrk->work, process_err_fn); - schedule_work(&wrk->work); + queue_work(host_dev->handle_error_wq, &wrk->work); } @@ -1803,10 +1805,19 @@ static int storvsc_probe(struct hv_device *device, if (stor_device->num_sc != 0) host->nr_hw_queues = stor_device->num_sc + 1; + /* +* Set the error handler work queue. +*/ + host_dev->handle_error_wq = + alloc_ordered_workqueue("storvsc_error_wq_%d", + WQ_MEM_RECLAIM, + host->host_no); + if (!host_dev->handle_error_wq) + goto err_out2; /* Register the HBA and start the scsi bus scan */ ret = scsi_add_host(host, &device->device); if (ret != 0) - goto err_out2; + goto err_out3; if (!dev_is_ide) { scsi_scan_host(host); @@ -1815,7 +1826,7 @@ static int storvsc_probe(struct hv_device *device, device->dev_instance.b[4]); ret = scsi_add_device(host, 0, target, 0); if (ret) - goto err_out3; + goto err_out4; } #if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) if (host->transportt == fc_transport_template) { @@ -1827,14 +1838,17 @@ static int storvsc_probe(struct hv_device *device, fc_host_port_name(host) = stor_device->port_name; stor_device->rport = fc_remote_port_add(host, 0, &ids); if (!stor_device->rport) - goto err_out3; + goto err_out4; } #endif return 0; -err_out3: +err_out4: scsi_remove_host(host); +err_out3: + destroy_workqueue(host_dev->handle_error_wq); + err_out2: /* * Once we have connected with the host, we would need to @@ -1858,6 +1872,7 @@ static int storvsc_remove(struct hv_device *dev) { struct storvsc_device *stor_device = hv_get_drvdata(dev); struct Scsi_Host *host = stor_device->host; + struct hv_host_device *host_dev = shost_priv(host); #if IS_ENABLED(CONFIG_SCSI_FC_ATTRS) if (host->transportt == fc_transport_template) { @@ -1865,6 +1880,7 @@ static int storvsc_remove(struct hv_device *dev) fc_remove_host(host); } #endif + destroy_workqueue(host_dev->handle_error_wq); scsi_remove_host(host); storvsc_dev_remove(dev); scsi_host_put(host); -- 2.5.0
[PATCH 04/13] mpt3sas: API 's to support NVMe drive addition to SML
Below Functions are added in various paths to support NVMe drive addition. _scsih_pcie_add_device _scsih_pcie_device_add _scsih_pcie_device_init_add _scsih_check_pcie_access_status _scsih_pcie_check_device mpt3sas_get_pdev_by_handle mpt3sas_config_get_pcie_device_pg0 mpt3sas_config_get_pcie_device_pg2 Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.h | 10 + drivers/scsi/mpt3sas/mpt3sas_config.c | 100 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 457 +- 3 files changed, 565 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 034b34d..a4ec459 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -1464,6 +1464,10 @@ struct _sas_device *mpt3sas_get_sdev_by_addr( struct MPT3SAS_ADAPTER *ioc, u64 sas_address); struct _sas_device *__mpt3sas_get_sdev_by_addr( struct MPT3SAS_ADAPTER *ioc, u64 sas_address); +struct _sas_device *mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, + u16 handle); +struct _pcie_device *mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc, + u16 handle); void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc); struct _raid_device * @@ -1502,6 +1506,12 @@ int mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc, int mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle); +int mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, + u32 form, u32 handle); +int mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page, + u32 form, u32 handle); int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz); diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c b/drivers/scsi/mpt3sas/mpt3sas_config.c index dd62701..1c747cf 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_config.c +++ b/drivers/scsi/mpt3sas/mpt3sas_config.c @@ -150,6 +150,24 @@ _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING: desc = "driver_mapping"; break; + case MPI2_CONFIG_EXTPAGETYPE_SAS_PORT: + desc = "sas_port"; + break; + case MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING: + desc = "ext_manufacturing"; + break; + case MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT: + desc = "pcie_io_unit"; + break; + case MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH: + desc = "pcie_switch"; + break; + case MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE: + desc = "pcie_device"; + break; + case MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK: + desc = "pcie_link"; + break; } break; } @@ -1053,6 +1071,88 @@ mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc, } /** + * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0 + * @ioc: per adapter object + * @mpi_reply: reply mf payload returned from firmware + * @config_page: contents of the config page + * @form: GET_NEXT_HANDLE or HANDLE + * @handle: device handle + * Context: sleep. + * + * Returns 0 for success, non-zero for failure. + */ +int +mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc, + Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page, + u32 form, u32 handle) +{ + Mpi2ConfigRequest_t mpi_request; + int r; + + memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); + mpi_request.Function = MPI2_FUNCTION_CONFIG; + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; + mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; + mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE; + mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION; + mpi_request.Header.PageNumber = 0; + ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); + if (r) + goto out; + + mpi_request.PageAddress = cpu_to_le32(form | handle); + mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; + r = _config_request(ioc, &mpi_request, mpi_reply, + MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page
[PATCH 00/13] mpt3sas driver NVMe support:
Ventura Series controller are Tri-mode. The controller and firmware are capable of supporting NVMe devices and PCIe switches to be connected with the controller. This patch set adds driver level support for NVMe devices and PCIe switches. Suganath Prabu S (13): mpt3sas: Add nvme device support in slave alloc, target alloc and probe mpt3sas: SGL to PRP Translation for I/Os to NVMe devices mpt3sas: Added support for nvme encapsulated request message. mpt3sas: API 's to support NVMe drive addition to SML mpt3sas: API's to remove nvme drive from sml mpt3sas: Handle NVMe PCIe device related events generated from firmware. mpt3sas: Set NVMe device queue depth as 128 mpt3sas: scan and add nvme device after controller reset mpt3as: Add-Task-management-debug-info-for-NVMe-drives. mpt3sas: NVMe drive support for BTDHMAPPING ioctl command and log info mpt3sas: Fix nvme drives checking for tlr. mpt3sas: Fix sparse warnings mpt3sas: Update mpt3sas driver version. drivers/scsi/mpt3sas/mpt3sas_base.c | 643 - drivers/scsi/mpt3sas/mpt3sas_base.h | 171 ++- drivers/scsi/mpt3sas/mpt3sas_config.c| 100 ++ drivers/scsi/mpt3sas/mpt3sas_ctl.c | 158 ++- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 2080 +++--- drivers/scsi/mpt3sas/mpt3sas_warpdrive.c |2 +- 7 files changed, 3054 insertions(+), 330 deletions(-) Thanks, Suganath Prabu S -- 2.5.5
[PATCH 02/13] mpt3sas: SGL to PRP Translation for I/Os to NVMe devices
* Added support for translating the SGLs associated with incoming commands either to IEE SGL or NVMe PRPs for NVMe devices. * The hardware translation of IEEE SGL to NVMe PRPs has limitation and if a command cannot be translated by hardware then it will go to firmware and the firmware needs to translate it. And this will have a performance reduction. To avoid that driver proactively checks whether the translation will be done in hardware or not, if not then driver try to translate inside the driver. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 339 ++- drivers/scsi/mpt3sas/mpt3sas_base.h | 41 +++- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 1 + drivers/scsi/mpt3sas/mpt3sas_scsih.c | 14 +- drivers/scsi/mpt3sas/mpt3sas_warpdrive.c | 2 +- 5 files changed, 380 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 11c6afe..1ad3cbb 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -59,6 +59,7 @@ #include #include #include +#include /* To get host page size per arch */ #include @@ -1344,7 +1345,218 @@ _base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge, } } -/* IEEE format sgls */ +/** + * base_make_prp_nvme - + * Prepare PRPs(Physical Region Page)- SGLs specific to NVMe drives only + * + * @ioc: per adapter object + * @scmd: SCSI command from the mid-layer + * @mpi_request: mpi request + * @smid: msg Index + * @sge_count: scatter gather element count. + * + * Returns:true: PRPs are built + * false: IEEE SGLs needs to be built + */ +void +base_make_prp_nvme(struct MPT3SAS_ADAPTER *ioc, + struct scsi_cmnd *scmd, + Mpi25SCSIIORequest_t *mpi_request, + u16 smid, int sge_count) +{ + int sge_len, offset, num_prp_in_chain = 0; + Mpi25IeeeSgeChain64_t *main_chain_element, *ptr_first_sgl; + u64 *curr_buff; + dma_addr_t msg_phys; + u64 sge_addr; + u32 page_mask, page_mask_result; + struct scatterlist *sg_scmd; + u32 first_prp_len; + int data_len = scsi_bufflen(scmd); + u32 nvme_pg_size; + + nvme_pg_size = max_t(u32, ioc->page_size, NVME_PRP_PAGE_SIZE); + /* +* Nvme has a very convoluted prp format. One prp is required +* for each page or partial page. Driver need to split up OS sg_list +* entries if it is longer than one page or cross a page +* boundary. Driver also have to insert a PRP list pointer entry as +* the last entry in each physical page of the PRP list. +* +* NOTE: The first PRP "entry" is actually placed in the first +* SGL entry in the main message as IEEE 64 format. The 2nd +* entry in the main message is the chain element, and the rest +* of the PRP entries are built in the contiguous pcie buffer. +*/ + page_mask = nvme_pg_size - 1; + + /* +* Native SGL is needed. +* Put a chain element in main message frame that points to the first +* chain buffer. +* +* NOTE: The ChainOffset field must be 0 when using a chain pointer to +*a native SGL. +*/ + + /* Set main message chain element pointer */ + main_chain_element = (pMpi25IeeeSgeChain64_t)&mpi_request->SGL; + /* +* For NVMe the chain element needs to be the 2nd SG entry in the main +* message. +*/ + main_chain_element = (Mpi25IeeeSgeChain64_t *) + ((u8 *)main_chain_element + sizeof(MPI25_IEEE_SGE_CHAIN64)); + + /* +* For the PRP entries, use the specially allocated buffer of +* contiguous memory. Normal chain buffers can't be used +* because each chain buffer would need to be the size of an OS +* page (4k). +*/ + curr_buff = mpt3sas_base_get_pcie_sgl(ioc, smid); + msg_phys = (dma_addr_t)mpt3sas_base_get_pcie_sgl_dma(ioc, smid); + + main_chain_element->Address = cpu_to_le64(msg_phys); + main_chain_element->NextChainOffset = 0; + main_chain_element->Flags = MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT | + MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR | + MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP; + + /* Build first prp, sge need not to be page aligned*/ + ptr_first_sgl = (pMpi25IeeeSgeChain64_t)&mpi_request->SGL; + sg_scmd = scsi_sglist(scmd); + sge_addr = sg_dma_address(sg_scmd); + sge_len = sg_dma_len(sg_scmd); + + offset = (u32)(sge_addr & page_mask); + first_prp_len = nvme_pg_size - offset; + + ptr_first_sgl->Address = cpu_to_le64(sge_addr); + ptr_first_sgl->Length = cpu_to_le32(first_prp_len); + + data_len -= first_prp_len; + +
[PATCH 01/13] mpt3sas: Add nvme device support in slave alloc, target alloc and probe
1) Added support for probing pcie device and adding NVMe drives to SML and driver's internal list pcie_device_list. 2) Added support for determing NVMe as boot device. 3) Added nvme device support for call back functions scan_finished target_alloc,slave_alloc,target destroy and slave destroy. a) During scan, pcie devices are probed and added to SML to drivers internal list. b) target_alloc & slave alloc API's allocates resources for (MPT3SAS_TARGET & MPT3SAS_DEVICE) private datas and holds information like handle, target_id etc. c) slave_destroy & target_destroy are called when driver unregisters or removes device. Also frees allocated resources and info. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.h | 110 +++- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 431 +-- 3 files changed, 647 insertions(+), 124 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 0fe3969..dd04a28 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -161,6 +161,7 @@ #define MPT_TARGET_FLAGS_VOLUME0x02 #define MPT_TARGET_FLAGS_DELETED 0x04 #define MPT_TARGET_FASTPATH_IO 0x08 +#define MPT_TARGET_FLAGS_PCIE_DEVICE 0x10 #define SAS2_PCI_DEVICE_B0_REVISION(0x01) #define SAS3_PCI_DEVICE_C0_REVISION(0x02) @@ -359,7 +360,8 @@ struct Mpi2ManufacturingPage11_t { * @flags: MPT_TARGET_FLAGS_XXX flags * @deleted: target flaged for deletion * @tm_busy: target is busy with TM request. - * @sdev: The sas_device associated with this target + * @sas_dev: The sas_device associated with this target + * @pcie_dev: The pcie device associated with this target */ struct MPT3SAS_TARGET { struct scsi_target *starget; @@ -370,7 +372,8 @@ struct MPT3SAS_TARGET { u32 flags; u8 deleted; u8 tm_busy; - struct _sas_device *sdev; + struct _sas_device *sas_dev; + struct _pcie_device *pcie_dev; }; @@ -514,6 +517,89 @@ static inline void sas_device_put(struct _sas_device *s) kref_put(&s->refcount, sas_device_free); } +/* + * struct _pcie_device - attached PCIe device information + * @list: pcie device list + * @starget: starget object + * @wwid: device WWID + * @handle: device handle + * @device_info: bitfield provides detailed info about the device + * @id: target id + * @channel: target channel + * @slot: slot number + * @port_num: port number + * @responding: used in _scsih_pcie_device_mark_responding + * @fast_path: fast path feature enable bit + * @nvme_mdts: MaximumDataTransferSize from PCIe Device Page 2 for + * NVMe device only + * @enclosure_handle: enclosure handle + * @enclosure_logical_id: enclosure logical identifier + * @enclosure_level: The level of device's enclosure from the controller + * @connector_name: ASCII value of the Connector's name + * @serial_number: pointer of serial number string allocated runtime + * @refcount: reference count for deletion + */ +struct _pcie_device { + struct list_head list; + struct scsi_target *starget; + u64 wwid; + u16 handle; + u32 device_info; + int id; + int channel; + u16 slot; + u8 port_num; + u8 responding; + u8 fast_path; + u32 nvme_mdts; + u16 enclosure_handle; + u64 enclosure_logical_id; + u8 enclosure_level; + u8 connector_name[4]; + u8 *serial_number; + struct kref refcount; +}; +/** + * pcie_device_get - Increment the pcie device reference count + * + * @p: pcie_device object + * + * When ever this function called it will increment the + * reference count of the pcie device for which this function called. + * + */ +static inline void pcie_device_get(struct _pcie_device *p) +{ + kref_get(&p->refcount); +} + +/** + * pcie_device_free - Release the pcie device object + * @r - kref object + * + * Free's the pcie device object. It will be called when reference count + * reaches to zero. + */ +static inline void pcie_device_free(struct kref *r) +{ + kfree(container_of(r, struct _pcie_device, refcount)); +} + +/** + * pcie_device_put - Decrement the pcie device reference count + * + * @p: pcie_device object + * + * When ever this function called it will decrement the + * reference count of the pcie device for which this function called. + * + * When refernce count reaches to Zero, this will call pcie_device_free to the + * pcie_device object. + */ +static inline void pcie_device_put(struct _pcie_device *p) +{ + kref_put(&p->refcount, pcie_device_free); +} /** * struct _raid_device - raid volume link list * @list: sas device list @@ -562,12 +648,13 @@ struct _raid_device { /** * struct _boot_device - boot device info - * @is_raid: flag to indicate whether this is volume - * @d
答复: 答复: [PATCH v5 2/5] dt-bindings: scsi: ufs: add document for hisi-ufs
Hi, Arnd Thank you for your reply. -邮件原件- 发件人: arndbergm...@gmail.com [mailto:arndbergm...@gmail.com] 代表 Arnd Bergmann 发送时间: 2017年10月30日 23:22 收件人: liwei (CM) 抄送: Rob Herring; Mark Rutland; xuwei (O); Catalin Marinas; Will Deacon; Vinayak Holikatti; James E.J. Bottomley; Martin K. Petersen; Kevin Hilman; Gregory CLEMENT; Thomas Petazzoni; Masahiro Yamada; Riku Voipio; Thierry Reding; Krzysztof Kozlowski; Eric Anholt; DTML; Linux Kernel Mailing List; Linux ARM; linux-scsi; Guodong Xu; Fengbaopeng (kevin, Kirin Solution Dept); lihuan (Z); wangyupeng (A) 主题: Re: 答复: [PATCH v5 2/5] dt-bindings: scsi: ufs: add document for hisi-ufs On Tue, Oct 24, 2017 at 11:06 AM, liwei (CM) wrote: > what's your opinion about my explanation and revision method? > I am looking forward to your reply, thanks! Sorry for the delay, I was travelling last week. > 发件人: arndbergm...@gmail.com [mailto:arndbergm...@gmail.com] 代表 Arnd > Bergmann On Fri, Oct 20, 2017 at 10:52 AM, Li Wei wrote: >> --- /dev/null >> +++ b/Documentation/devicetree/bindings/ufs/ufs-hisi.txt >> @@ -0,0 +1,46 @@ >> +* Hisilicon Universal Flash Storage (UFS) Host Controller >> + >> +UFS nodes are defined to describe on-chip UFS hardware macro. >> +Each UFS Host Controller should have its own node. >> + >> +Required properties: >> +- compatible: compatible list, contains one of the following - >> + "hisilicon,hi3660-ufs" for hisi ufs host controller >> +present on Hi3660 chipset. One more thing I just noticed: you don't describe the device as compatible with the ufshcd spec as defined in the generic binding. Shouldn't we have both compatible strings listed here? Ok, I will fix it in patch v6; > In particular, I wonder if what you describe as the "UFS SYS CTRL" > area corresponds to what Qualcomm have described as their PHY implementation. > It certainly seems to driver some of the properties that would normally be > associated with a PHY. > > Liwei:Yes, a part of "UFS SYS CTRL" is associated with a PHY, but from our > chip colleague that we assure "UFS SYS CTRL" is associated with > clk/reset/power on/power off and so on. > In fact, in addition to the controller itself, the controller related > periphery are all in this area. So it's not appropriate to put this into a > separate phy node. I'm not sure I understand here. Do you mean the reset handle is for resetting the PHY rather than the UFS HCD? Maybe my description is not clear enough, our UFS host soc implementation can be divided into two parts: UFS controller and related peripheral circuit, that "HCI standard"<-> UFS controller, "UFS SYS CTRL"<-> related peripheral circuit, and PHY is part of the peripheral circuit. So the "UFS SYS CTRL" area does not correspond completely to what Qualcomm have described as their PHY implementation. The root reason is that our UFS host had not divided into UFS controller and PHY; > > For the "clock-names" property, you specify "clk_ref", which I assume is > > the same as what Qualcomm call "ref_clk". I'd suggest you use the existing > > name and add that as the default name in the ufshcd-pltfrm.txt binding > > document. > > Liwei:" ref_clk " is already in the ufshcd-pltfrm.txt binding > document, and parse in ufshcd.c, so we will replace "clk_ref" with > "ref_clk". I will fix it in patch v6; ok > > The "clk_phy" property appears to be related to the PHY, so it might be > > better to have a separate phy node with either just the clk, or with the > > clk plus the "UFS SYS CTRL" register area, whichever matches your hardware > > better, and then use teh "phys/phy-names" property to refer to that. > > Liwei: OK, I will add a separate phy node and fix it in patch v6; Thanks. >> The reset handling you describe here (both resets and reset-gpios) appears >> to be completely generic, so I'd suggest adding those to ufshcd-pltfrm.txt >> instead of your own binding, to ensure that future drivers use the same >> identifiers. > > Liwei: From our soc chip colleague, reset include "rst", "assert" is > not generic and related with our soc implementation, you can see > ufs_hisi_soc_init() in drivers/scsi/ufs/ufs-hisi.c, the position of > rst and assert is very special, it's hard to put it in a generic > process; It seems odd that the ability to reset a device is specific to your implementation. What I meant is that other implementations may also require a reset, so describing the way you refer to this into the generic binding would be helpful, to prevent others from adding another incompatible way to do the same thing. A lot of generic bindings have a reference to a reset controller that if present needs to be used before first accessing the device itself. I mean our reset process is really special, but there is no parse of this "reset" in generic driver code like ufshcd.c or ufshcd-pltfrm.c; Even if I add those to ufshcd-pltfrm.txt and implement the common parsing code, b
[PATCH 06/13] mpt3sas: Handle NVMe PCIe device related events generated from firmware.
* The controller firmware sends separate events for NVMe devices and PCIe switches similar to existing SAS events. * NVMe device detection, addition and removal are reported by the firmware through PCIe Topology Change list events. * The PCIe device state change events are sent when the firmware detects any abnormal conditions with a NVMe device or switch. * The enumeration event are sent when the firmware starts PCIe device enumeration and stops. * This patch has the code change to handle the events and add/remove NVMe devices in driver's inventory. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 30 ++- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 471 ++- 2 files changed, 495 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index b0a75c6..0da639d 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -663,6 +663,26 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc, case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION: desc = "Cable Event"; break; + case MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE: + desc = "PCIE Device Status Change"; + break; + case MPI2_EVENT_PCIE_ENUMERATION: + { + Mpi26EventDataPCIeEnumeration_t *event_data = + (Mpi26EventDataPCIeEnumeration_t *)mpi_reply->EventData; + pr_info(MPT3SAS_FMT "PCIE Enumeration: (%s)", ioc->name, + (event_data->ReasonCode == + MPI26_EVENT_PCIE_ENUM_RC_STARTED) ? + "start" : "stop"); + if (event_data->EnumerationStatus) + pr_info("enumeration_status(0x%08x)", + le32_to_cpu(event_data->EnumerationStatus)); + pr_info("\n"); + return; + } + case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST: + desc = "PCIE Topology Change List"; + break; } if (!desc) @@ -6125,7 +6145,15 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); _base_unmask_events(ioc, MPI2_EVENT_TEMP_THRESHOLD); _base_unmask_events(ioc, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION); - + if (ioc->hba_mpi_version_belonged == MPI26_VERSION) { + if (ioc->is_gen35_ioc) { + _base_unmask_events(ioc, + MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE); + _base_unmask_events(ioc, MPI2_EVENT_PCIE_ENUMERATION); + _base_unmask_events(ioc, + MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST); + } + } r = _base_make_ioc_operational(ioc); if (r) goto out_free_resources; diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index d83560c..21260bd 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -75,6 +75,8 @@ static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, static int _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle); static void _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc, struct _pcie_device *pcie_device); +static void +_scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle); static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid); /* global parameters */ @@ -3476,8 +3478,6 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) struct _sas_device *sas_device; sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); - if (!sas_device) - return; shost_for_each_device(sdev, ioc->shost) { sas_device_priv_data = sdev->hostdata; @@ -3487,7 +3487,7 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) continue; if (sas_device_priv_data->block) continue; - if (sas_device->pend_sas_rphy_add) + if (sas_device && sas_device->pend_sas_rphy_add) continue; if (sas_device_priv_data->ignore_delay_remove) { sdev_printk(KERN_INFO, sdev, @@ -3498,7 +3498,8 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) _scsih_internal_device_block(sdev, sas_device_priv_data); } - sas_device_put(sas_device); + if (sas_device) + sas_device_put(sas_device); } /** @@ -3582,6 +3583,33 @@ _scsih_block_io_to_children_attached_directly(struct MPT3SAS_ADAPTER *ioc, } /** + * _scsih_block_io_to_pcie_children_attached_directly + * @ioc: per adapter object + * @event_data: topology ch
[PATCH 09/13] mpt3as: Add-Task-management-debug-info-for-NVMe-drives.
Added debug information for NVMe/PCIe drives in target rest path Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 80 1 file changed, 71 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 81f4d2d..dc1fdad 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2929,6 +2929,7 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) struct scsi_target *starget = scmd->device->sdev_target; struct MPT3SAS_TARGET *priv_target = starget->hostdata; struct _sas_device *sas_device = NULL; + struct _pcie_device *pcie_device = NULL; unsigned long flags; char *device_str = NULL; @@ -2945,6 +2946,31 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) "%s handle(0x%04x), %s wwid(0x%016llx)\n", device_str, priv_target->handle, device_str, (unsigned long long)priv_target->sas_address); + + } else if (priv_target->flags & MPT_TARGET_FLAGS_PCIE_DEVICE) { + spin_lock_irqsave(&ioc->pcie_device_lock, flags); + pcie_device = __mpt3sas_get_pdev_from_target(ioc, priv_target); + if (pcie_device) { + starget_printk(KERN_INFO, starget, + "handle(0x%04x), wwid(0x%016llx), port(%d)\n", + pcie_device->handle, + (unsigned long long)pcie_device->wwid, + pcie_device->port_num); + if (pcie_device->enclosure_handle != 0) + starget_printk(KERN_INFO, starget, + "enclosure logical id(0x%016llx), slot(%d)\n", + (unsigned long long) + pcie_device->enclosure_logical_id, + pcie_device->slot); + if (pcie_device->connector_name[0] != '\0') + starget_printk(KERN_INFO, starget, + "enclosure level(0x%04x), connector name( %s)\n", + pcie_device->enclosure_level, + pcie_device->connector_name); + pcie_device_put(pcie_device); + } + spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); + } else { spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = __mpt3sas_get_sdev_from_target(ioc, priv_target); @@ -3680,18 +3706,14 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) Mpi2SCSITaskManagementRequest_t *mpi_request; u16 smid; struct _sas_device *sas_device = NULL; + struct _pcie_device *pcie_device = NULL; struct MPT3SAS_TARGET *sas_target_priv_data = NULL; u64 sas_address = 0; unsigned long flags; struct _tr_list *delayed_tr; u32 ioc_state; - if (ioc->remove_host) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host has been removed: handle(0x%04x)\n", - __func__, ioc->name, handle)); - return; - } else if (ioc->pci_error_recovery) { + if (ioc->pci_error_recovery) { dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: host in pci error recovery: handle(0x%04x)\n", __func__, ioc->name, @@ -3722,14 +3744,52 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) sas_address = sas_device->sas_address; } spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - + if (!sas_device) { + spin_lock_irqsave(&ioc->pcie_device_lock, flags); + pcie_device = __mpt3sas_get_pdev_by_handle(ioc, handle); + if (pcie_device && pcie_device->starget && + pcie_device->starget->hostdata) { + sas_target_priv_data = pcie_device->starget->hostdata; + sas_target_priv_data->deleted = 1; + sas_address = pcie_device->wwid; + } + spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); + } if (sas_target_priv_data) { dewtprintk(ioc, pr_info(MPT3SAS_FMT "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, handle, (unsigned long long)sas_address)); - dewtprintk(ioc, _scsih_display_enclosure_chassis_info(ioc, - sas_device, NULL, NULL)); + if (sas_device) { + if (sas_device
[PATCH 08/13] mpt3sas: scan and add nvme device after controller reset
After Controller reset, Scan and add nvme device back to the topology. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 194 ++- 1 file changed, 190 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 9006a60..81f4d2d 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -4887,6 +4887,7 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, char *desc_scsi_state = ioc->tmp_string; u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); struct _sas_device *sas_device = NULL; + struct _pcie_device *pcie_device = NULL; struct scsi_target *starget = scmd->device->sdev_target; struct MPT3SAS_TARGET *priv_target = starget->hostdata; char *device_str = NULL; @@ -5019,6 +5020,28 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name, device_str, (unsigned long long)priv_target->sas_address); + } else if (priv_target->flags & MPT_TARGET_FLAGS_PCIE_DEVICE) { + pcie_device = mpt3sas_get_pdev_from_target(ioc, priv_target); + if (pcie_device) { + pr_info(MPT3SAS_FMT "\twwid(0x%016llx), port(%d)\n", + ioc->name, + (unsigned long long)pcie_device->wwid, + pcie_device->port_num); + if (pcie_device->enclosure_handle != 0) + pr_info(MPT3SAS_FMT + "\tenclosure logical id(0x%016llx), " + "slot(%d)\n", ioc->name, + (unsigned long long) + pcie_device->enclosure_logical_id, + pcie_device->slot); + if (pcie_device->connector_name[0]) + pr_info(MPT3SAS_FMT + "\tenclosure level(0x%04x)," + "connector name( %s)\n", + ioc->name, pcie_device->enclosure_level, + pcie_device->connector_name); + pcie_device_put(pcie_device); + } } else { sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target); if (sas_device) { @@ -5055,11 +5078,10 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, struct sense_info data; _scsih_normalize_sense(scmd->sense_buffer, &data); pr_warn(MPT3SAS_FMT - "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n", - ioc->name, data.skey, - data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount)); + "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n", + ioc->name, data.skey, + data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount)); } - if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { response_info = le32_to_cpu(mpi_reply->ResponseInfo); response_bytes = (u8 *)&response_info; @@ -8559,6 +8581,130 @@ _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc) } /** + * _scsih_mark_responding_pcie_device - mark a pcie_device as responding + * @ioc: per adapter object + * @pcie_device_pg0: PCIe Device page 0 + * + * After host reset, find out whether devices are still responding. + * Used in _scsih_remove_unresponding_devices. + * + * Return nothing. + */ +static void +_scsih_mark_responding_pcie_device(struct MPT3SAS_ADAPTER *ioc, + Mpi26PCIeDevicePage0_t *pcie_device_pg0) +{ + struct MPT3SAS_TARGET *sas_target_priv_data = NULL; + struct scsi_target *starget; + struct _pcie_device *pcie_device; + unsigned long flags; + + spin_lock_irqsave(&ioc->pcie_device_lock, flags); + list_for_each_entry(pcie_device, &ioc->pcie_device_list, list) { + if ((pcie_device->wwid == pcie_device_pg0->WWID) && + (pcie_device->slot == pcie_device_pg0->Slot)) { + pcie_device->responding = 1; + starget = pcie_device->starget; + if (starget && starget->hostdata) { + sas_target_priv_data = starget->hostdata; + sas_target_priv_data->tm_busy = 0; + sas_target_priv_data->deleted = 0; + } else + sas_target_priv_data = NULL; + if (star
[PATCH 03/13] mpt3sas: Added support for nvme encapsulated request message.
* Mpt3sas driver uses the NVMe Encapsulated Request message to send an NVMe command to an NVMe device attached to the IOC. * Normal I/O commands like reads and writes are passed to the controller as SCSI commands and the controller has the ability to translate the commands to NVMe equivalent. * This encapsulated NVMe command is used by applications to send direct NVMe commands to NVMe drives. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 276 +++- drivers/scsi/mpt3sas/mpt3sas_base.h | 4 + drivers/scsi/mpt3sas/mpt3sas_ctl.c | 69 - 3 files changed, 342 insertions(+), 7 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 1ad3cbb..b0a75c6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -557,6 +557,11 @@ _base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply, frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size; func_str = "smp_passthru"; break; + case MPI2_FUNCTION_NVME_ENCAPSULATED: + frame_sz = sizeof(Mpi26NVMeEncapsulatedRequest_t) + + ioc->sge_size; + func_str = "nvme_encapsulated"; + break; default: frame_sz = 32; func_str = "unknown"; @@ -985,7 +990,9 @@ _base_interrupt(int irq, void *bus_id) if (request_desript_type == MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS || request_desript_type == - MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) { + MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS || + request_desript_type == + MPI26_RPY_DESCRIPT_FLAGS_PCIE_ENCAPSULATED_SUCCESS) { cb_idx = _base_get_cb_idx(ioc, smid); if ((likely(cb_idx < MPT_MAX_CALLBACKS)) && (likely(mpt_callbacks[cb_idx] != NULL))) { @@ -1345,6 +1352,225 @@ _base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge, } } +/* IEEE format sgls */ + +/** + * _base_build_nvme_prp - This function is called for NVMe end devices to build + * a native SGL (NVMe PRP). The native SGL is built starting in the first PRP + * entry of the NVMe message (PRP1). If the data buffer is small enough to be + * described entirely using PRP1, then PRP2 is not used. If needed, PRP2 is + * used to describe a larger data buffer. If the data buffer is too large to + * describe using the two PRP entriess inside the NVMe message, then PRP1 + * describes the first data memory segment, and PRP2 contains a pointer to a PRP + * list located elsewhere in memory to describe the remaining data memory + * segments. The PRP list will be contiguous. + + * The native SGL for NVMe devices is a Physical Region Page (PRP). A PRP + * consists of a list of PRP entries to describe a number of noncontigous + * physical memory segments as a single memory buffer, just as a SGL does. Note + * however, that this function is only used by the IOCTL call, so the memory + * given will be guaranteed to be contiguous. There is no need to translate + * non-contiguous SGL into a PRP in this case. All PRPs will describe + * contiguous space that is one page size each. + * + * Each NVMe message contains two PRP entries. The first (PRP1) either contains + * a PRP list pointer or a PRP element, depending upon the command. PRP2 + * contains the second PRP element if the memory being described fits within 2 + * PRP entries, or a PRP list pointer if the PRP spans more than two entries. + * + * A PRP list pointer contains the address of a PRP list, structured as a linear + * array of PRP entries. Each PRP entry in this list describes a segment of + * physical memory. + * + * Each 64-bit PRP entry comprises an address and an offset field. The address + * always points at the beginning of a 4KB physical memory page, and the offset + * describes where within that 4KB page the memory segment begins. Only the + * first element in a PRP list may contain a non-zero offest, implying that all + * memory segments following the first begin at the start of a 4KB page. + * + * Each PRP element normally describes 4KB of physical memory, with exceptions + * for the first and last elements in the list. If the memory being described + * by the list begins at a non-zero offset within the first 4KB page, then the + * first PRP element will contain a non-zero offset indicating where the region + * begins within the 4KB page. The last memory segment may end before the end + * of the 4KB segment, depending upon the overall size of the memory being + * described by the PRP list. + * + * Since PRP entries lack any indication of size, the overall data buffer length + * is used to determine where the end of the data memory buf
[PATCH 05/13] mpt3sas: API's to remove nvme drive from sml
Below API's are included in nvme drive remove path. _scsih_pcie_device_remove_by_handle _scsih_pcie_device_remove_from_sml Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 148 ++- 1 file changed, 145 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index d3f8a10..d83560c 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -73,6 +73,8 @@ static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 retry_count, u8 is_pd); static int _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle); +static void _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc, + struct _pcie_device *pcie_device); static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid); /* global parameters */ @@ -1126,6 +1128,41 @@ _scsih_pcie_device_remove(struct MPT3SAS_ADAPTER *ioc, pcie_device_put(pcie_device); } } + + +/** + * _scsih_pcie_device_remove_by_handle - removing pcie device object by handle + * @ioc: per adapter object + * @handle: device handle + * + * Return nothing. + */ +static void +_scsih_pcie_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) +{ + struct _pcie_device *pcie_device; + unsigned long flags; + int was_on_pcie_device_list = 0; + + if (ioc->shost_recovery) + return; + + spin_lock_irqsave(&ioc->pcie_device_lock, flags); + pcie_device = __mpt3sas_get_pdev_by_handle(ioc, handle); + if (pcie_device) { + if (!list_empty(&pcie_device->list)) { + list_del_init(&pcie_device->list); + was_on_pcie_device_list = 1; + pcie_device_put(pcie_device); + } + } + spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); + if (was_on_pcie_device_list) { + _scsih_pcie_device_remove_from_sml(ioc, pcie_device); + pcie_device_put(pcie_device); + } +} + /** * _scsih_pcie_device_add - add pcie_device object * @ioc: per adapter object @@ -6567,6 +6604,83 @@ _scsih_check_pcie_access_status(struct MPT3SAS_ADAPTER *ioc, u64 wwid, (unsigned long long)wwid, handle); return rc; } + +/** + * _scsih_pcie_device_remove_from_sml - removing pcie device + * from SML and free up associated memory + * @ioc: per adapter object + * @pcie_device: the pcie_device object + * + * Return nothing. + */ +static void +_scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc, + struct _pcie_device *pcie_device) +{ + struct MPT3SAS_TARGET *sas_target_priv_data; + + dewtprintk(ioc, pr_info(MPT3SAS_FMT + "%s: enter: handle(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__, + pcie_device->handle, (unsigned long long) + pcie_device->wwid)); + if (pcie_device->enclosure_handle != 0) + dewtprintk(ioc, pr_info(MPT3SAS_FMT + "%s: enter: enclosure logical id(0x%016llx), slot(%d)\n", + ioc->name, __func__, + (unsigned long long)pcie_device->enclosure_logical_id, + pcie_device->slot)); + if (pcie_device->connector_name[0] != '\0') + dewtprintk(ioc, pr_info(MPT3SAS_FMT + "%s: enter: enclosure level(0x%04x), connector name( %s)\n", + ioc->name, __func__, + pcie_device->enclosure_level, + pcie_device->connector_name)); + + if (pcie_device->starget && pcie_device->starget->hostdata) { + sas_target_priv_data = pcie_device->starget->hostdata; + sas_target_priv_data->deleted = 1; + _scsih_ublock_io_device(ioc, pcie_device->wwid); + sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE; + } + + pr_info(MPT3SAS_FMT + "removing handle(0x%04x), wwid (0x%016llx)\n", + ioc->name, pcie_device->handle, + (unsigned long long) pcie_device->wwid); + if (pcie_device->enclosure_handle != 0) + pr_info(MPT3SAS_FMT + "removing : enclosure logical id(0x%016llx), slot(%d)\n", + ioc->name, + (unsigned long long)pcie_device->enclosure_logical_id, + pcie_device->slot); + if (pcie_device->connector_name[0] != '\0') + pr_info(MPT3SAS_FMT + "removing: enclosure level(0x%04x), connector name( %s)\n", + ioc->name, pcie_device->enclosure_level, + pcie_device->connector_name); + + if (pcie_device->starget) + scsi_remove_target(&pcie_device->starget->dev); + dewtpri
[PATCH 10/13] mpt3sas: NVMe drive support for BTDHMAPPING ioctl command and log info
* Added debug prints for pcie devices in ioctl debug path. Which will be helpful for debugging. * Added PCIe device support for ioctl BTDHMAPPING ioctl. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 88 +- 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 205c443..b4c374b 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -79,32 +79,6 @@ enum block_state { }; /** - * _ctl_sas_device_find_by_handle - sas device search - * @ioc: per adapter object - * @handle: sas device handle (assigned by firmware) - * Context: Calling function should acquire ioc->sas_device_lock - * - * This searches for sas_device based on sas_address, then return sas_device - * object. - */ -static struct _sas_device * -_ctl_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_device *sas_device, *r; - - r = NULL; - list_for_each_entry(sas_device, &ioc->sas_device_list, list) { - if (sas_device->handle != handle) - continue; - r = sas_device; - goto out; - } - - out: - return r; -} - -/** * _ctl_display_some_debug - debug routine * @ioc: per adapter object * @smid: system request message index @@ -229,10 +203,9 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, Mpi2SCSIIOReply_t *scsi_reply = (Mpi2SCSIIOReply_t *)mpi_reply; struct _sas_device *sas_device = NULL; - unsigned long flags; + struct _pcie_device *pcie_device = NULL; - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _ctl_sas_device_find_by_handle(ioc, + sas_device = mpt3sas_get_sdev_by_handle(ioc, le16_to_cpu(scsi_reply->DevHandle)); if (sas_device) { pr_warn(MPT3SAS_FMT "\tsas_address(0x%016llx), phy(%d)\n", @@ -242,8 +215,25 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, "\tenclosure_logical_id(0x%016llx), slot(%d)\n", ioc->name, (unsigned long long) sas_device->enclosure_logical_id, sas_device->slot); + sas_device_put(sas_device); + } + if (!sas_device) { + pcie_device = mpt3sas_get_pdev_by_handle(ioc, + le16_to_cpu(scsi_reply->DevHandle)); + if (pcie_device) { + pr_warn(MPT3SAS_FMT + "\tWWID(0x%016llx), port(%d)\n", ioc->name, + (unsigned long long)pcie_device->wwid, + pcie_device->port_num); + if (pcie_device->enclosure_handle != 0) + pr_warn(MPT3SAS_FMT + "\tenclosure_logical_id(0x%016llx), slot(%d)\n", + ioc->name, (unsigned long long) + pcie_device->enclosure_logical_id, + pcie_device->slot); + pcie_device_put(pcie_device); + } } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); if (scsi_reply->SCSIState || scsi_reply->SCSIStatus) pr_info(MPT3SAS_FMT "\tscsi_state(0x%02x), scsi_status" @@ -1347,6 +1337,42 @@ _ctl_btdh_search_sas_device(struct MPT3SAS_ADAPTER *ioc, } /** + * _ctl_btdh_search_pcie_device - searching for pcie device + * @ioc: per adapter object + * @btdh: btdh ioctl payload + */ +static int +_ctl_btdh_search_pcie_device(struct MPT3SAS_ADAPTER *ioc, + struct mpt3_ioctl_btdh_mapping *btdh) +{ + struct _pcie_device *pcie_device; + unsigned long flags; + int rc = 0; + + if (list_empty(&ioc->pcie_device_list)) + return rc; + + spin_lock_irqsave(&ioc->pcie_device_lock, flags); + list_for_each_entry(pcie_device, &ioc->pcie_device_list, list) { + if (btdh->bus == 0x && btdh->id == 0x && + btdh->handle == pcie_device->handle) { + btdh->bus = pcie_device->channel; + btdh->id = pcie_device->id; + rc = 1; + goto out; + } else if (btdh->bus == pcie_device->channel && btdh->id == + pcie_device->id && btdh->handle == 0x) { + btdh->handle = pcie_device->handle; + rc = 1; +
[PATCH 11/13] mpt3sas: Fix nvme drives checking for tlr.
Check for NVMe drives before enabling or checking tlr. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 22 -- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index dc1fdad..72dd57f 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2048,6 +2048,14 @@ scsih_is_raid(struct device *dev) return (sdev->channel == RAID_CHANNEL) ? 1 : 0; } +static int +scsih_is_nvme(struct device *dev) +{ + struct scsi_device *sdev = to_scsi_device(dev); + + return (sdev->channel == PCIE_CHANNEL) ? 1 : 0; +} + /** * scsih_get_resync - get raid volume resync percent complete * @dev the device struct object @@ -4834,8 +4842,9 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) /* Make sure Device is not raid volume. * We do not expose raid functionality to upper layer for warpdrive. */ - if (!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev) - && sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32) + if (((!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev)) + && !scsih_is_nvme(&scmd->device->sdev_gendev)) + && sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32) mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd); @@ -4880,8 +4889,8 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) raid_device = sas_target_priv_data->raid_device; if (raid_device && raid_device->direct_io_enabled) - mpt3sas_setup_direct_io(ioc, scmd, raid_device, mpi_request, - smid); + mpt3sas_setup_direct_io(ioc, scmd, + raid_device, mpi_request, smid); if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) { if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) { @@ -5411,9 +5420,10 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF; if (!sas_device_priv_data->tlr_snoop_check) { sas_device_priv_data->tlr_snoop_check++; - if (!ioc->is_warpdrive && + if ((!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev) && - sas_is_tlr_enabled(scmd->device) && + !scsih_is_nvme(&scmd->device->sdev_gendev)) + && sas_is_tlr_enabled(scmd->device) && response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) { sas_disable_tlr(scmd->device); sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n"); -- 2.5.5
[PATCH 12/13] mpt3sas: Fix sparse warnings
1) Used variable __le64/__le32 whichever required in building NVME PRP, and passed to LE Controller. 2) Remove unused functions, And Declared functions as static which are used only in mpt3sas_scsih.c. Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.c | 22 ++--- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 37 +--- 2 files changed, 16 insertions(+), 43 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 0da639d..3061c17 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -1437,8 +1437,8 @@ _base_build_nvme_prp(struct MPT3SAS_ADAPTER *ioc, u16 smid, size_t data_in_sz) { int prp_size = NVME_PRP_SIZE; - u64 *prp_entry, *prp1_entry, *prp2_entry, *prp_entry_phys; - u64 *prp_page, *prp_page_phys; + __le64 *prp_entry, *prp1_entry, *prp2_entry, *prp_entry_phys; + __le64 *prp_page, *prp_page_phys; u32 offset, entry_len; u32 page_mask_result, page_mask; dma_addr_t paddr; @@ -1455,17 +1455,17 @@ _base_build_nvme_prp(struct MPT3SAS_ADAPTER *ioc, u16 smid, * PRP1 is located at a 24 byte offset from the start of the NVMe * command. Then set the current PRP entry pointer to PRP1. */ - prp1_entry = (u64 *)(nvme_encap_request->NVMe_Command + + prp1_entry = (__le64 *)(nvme_encap_request->NVMe_Command + NVME_CMD_PRP1_OFFSET); - prp2_entry = (u64 *)(nvme_encap_request->NVMe_Command + + prp2_entry = (__le64 *)(nvme_encap_request->NVMe_Command + NVME_CMD_PRP2_OFFSET); prp_entry = prp1_entry; /* * For the PRP entries, use the specially allocated buffer of * contiguous memory. */ - prp_page = (u64 *)mpt3sas_base_get_pcie_sgl(ioc, smid); - prp_page_phys = (u64 *)mpt3sas_base_get_pcie_sgl_dma(ioc, smid); + prp_page = (__le64 *)mpt3sas_base_get_pcie_sgl(ioc, smid); + prp_page_phys = (__le64 *)mpt3sas_base_get_pcie_sgl_dma(ioc, smid); /* * Check if we are within 1 entry of a page boundary we don't @@ -1475,8 +1475,8 @@ _base_build_nvme_prp(struct MPT3SAS_ADAPTER *ioc, u16 smid, page_mask_result = (uintptr_t)((u8 *)prp_page + prp_size) & page_mask; if (!page_mask_result) { /* Bump up to next page boundary. */ - prp_page = (u64 *)((u8 *)prp_page + prp_size); - prp_page_phys = (u64 *)((u8 *)prp_page_phys + prp_size); + prp_page = (__le64 *)((u8 *)prp_page + prp_size); + prp_page_phys = (__le64 *)((u8 *)prp_page_phys + prp_size); } /* @@ -1604,7 +1604,7 @@ _base_build_nvme_prp(struct MPT3SAS_ADAPTER *ioc, u16 smid, * Returns:true: PRPs are built * false: IEEE SGLs needs to be built */ -void +static void base_make_prp_nvme(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, Mpi25SCSIIORequest_t *mpi_request, @@ -1612,7 +1612,7 @@ base_make_prp_nvme(struct MPT3SAS_ADAPTER *ioc, { int sge_len, offset, num_prp_in_chain = 0; Mpi25IeeeSgeChain64_t *main_chain_element, *ptr_first_sgl; - u64 *curr_buff; + __le64 *curr_buff; dma_addr_t msg_phys; u64 sge_addr; u32 page_mask, page_mask_result; @@ -1740,7 +1740,7 @@ base_is_prp_possible(struct MPT3SAS_ADAPTER *ioc, struct scatterlist *sg_scmd; bool build_prp = true; - data_length = cpu_to_le32(scsi_bufflen(scmd)); + data_length = scsi_bufflen(scmd); sg_scmd = scsi_sglist(scmd); /* If Datalenth is <= 16K and number of SGE???s entries are <= 2 diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 72dd57f..31e9343 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -599,7 +599,7 @@ __mpt3sas_get_pdev_from_target(struct MPT3SAS_ADAPTER *ioc, * * This searches for pcie_device from target, then return pcie_device object. */ -struct _pcie_device * +static struct _pcie_device * mpt3sas_get_pdev_from_target(struct MPT3SAS_ADAPTER *ioc, struct MPT3SAS_TARGET *tgt_priv) { @@ -942,7 +942,7 @@ _scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc, } -struct _pcie_device * +static struct _pcie_device * __mpt3sas_get_pdev_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid) { struct _pcie_device *pcie_device; @@ -975,7 +975,7 @@ found_device: * * This searches for pcie_device based on wwid, then return pcie_device object. */ -struct _pcie_device * +static struct _pcie_device * mpt3sas_get_pdev_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid) { struct _pcie_device *pcie_device; @@ -989,7 +989,7 @@ mpt3sas_get_pdev_by_w
[PATCH 07/13] mpt3sas: Set NVMe device queue depth as 128
Sets nvme device queue depth, name and displays device capabilities Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 50 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index a4ec459..2d005af 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -117,7 +117,7 @@ #define MPT3SAS_RAID_MAX_SECTORS 8192 #define MPT3SAS_HOST_PAGE_SIZE_4K 12 - +#define MPT3SAS_NVME_QUEUE_DEPTH 128 #define MPT_NAME_LENGTH32 /* generic length of strings */ #define MPT_STRING_LENGTH 64 diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 21260bd..9006a60 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -2324,6 +2324,7 @@ scsih_slave_configure(struct scsi_device *sdev) struct MPT3SAS_DEVICE *sas_device_priv_data; struct MPT3SAS_TARGET *sas_target_priv_data; struct _sas_device *sas_device; + struct _pcie_device *pcie_device; struct _raid_device *raid_device; unsigned long flags; int qdepth; @@ -2454,6 +2455,55 @@ scsih_slave_configure(struct scsi_device *sdev) } } + /* PCIe handling */ + if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_PCIE_DEVICE) { + spin_lock_irqsave(&ioc->pcie_device_lock, flags); + pcie_device = __mpt3sas_get_pdev_by_wwid(ioc, + sas_device_priv_data->sas_target->sas_address); + if (!pcie_device) { + spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); + dfailprintk(ioc, pr_warn(MPT3SAS_FMT + "failure at %s:%d/%s()!\n", ioc->name, __FILE__, + __LINE__, __func__)); + return 1; + } + + qdepth = MPT3SAS_NVME_QUEUE_DEPTH; + ds = "NVMe"; + sdev_printk(KERN_INFO, sdev, + "%s: handle(0x%04x), wwid(0x%016llx), port(%d)\n", + ds, handle, (unsigned long long)pcie_device->wwid, + pcie_device->port_num); + if (pcie_device->enclosure_handle != 0) + sdev_printk(KERN_INFO, sdev, + "%s: enclosure logical id(0x%016llx), slot(%d)\n", + ds, + (unsigned long long)pcie_device->enclosure_logical_id, + pcie_device->slot); + if (pcie_device->connector_name[0] != '\0') + sdev_printk(KERN_INFO, sdev, + "%s: enclosure level(0x%04x)," + "connector name( %s)\n", ds, + pcie_device->enclosure_level, + pcie_device->connector_name); + pcie_device_put(pcie_device); + spin_unlock_irqrestore(&ioc->pcie_device_lock, flags); + scsih_change_queue_depth(sdev, qdepth); + + if (pcie_device->nvme_mdts) + blk_queue_max_hw_sectors(sdev->request_queue, + pcie_device->nvme_mdts/512); + /* Enable QUEUE_FLAG_NOMERGES flag, so that IOs won't be +** merged and can eliminate holes created during merging +** operation. +**/ + queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, + sdev->request_queue); + blk_queue_virt_boundary(sdev->request_queue, + ioc->page_size - 1); + return 0; + } + spin_lock_irqsave(&ioc->sas_device_lock, flags); sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_device_priv_data->sas_target->sas_address); -- 2.5.5
[PATCH 13/13] mpt3sas: Update mpt3sas driver version.
Updated mpt3sas driver version to 17.100.00.00 Signed-off-by: Chaitra P B Signed-off-by: Suganath Prabu S --- drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index 2d005af..ef7d001 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h @@ -74,8 +74,8 @@ #define MPT3SAS_DRIVER_NAME"mpt3sas" #define MPT3SAS_AUTHOR "Avago Technologies " #define MPT3SAS_DESCRIPTION"LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "16.100.00.00" -#define MPT3SAS_MAJOR_VERSION 16 +#define MPT3SAS_DRIVER_VERSION "17.100.00.00" +#define MPT3SAS_MAJOR_VERSION 17 #define MPT3SAS_MINOR_VERSION 100 #define MPT3SAS_BUILD_VERSION 0 #define MPT3SAS_RELEASE_VERSION00 -- 2.5.5
Re: [PATCH] scsi_debug: write_same: fix error report
Doug, > The scsi_debug driver incorrectly suggests there is an error with > the SCSI WRITE SAME command when the number_of_logical_blocks is > greater than 1. It will also suggest there is an error when NDOB > (no data-out buffer) is set and the number_of_logical_blocks is > greater than 0. Both are valid, fix. Applied to 4.15/scsi-queue. Thanks! -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH V2] scsi: storvsc: Allow only one remove lun work item to be issued per lun
On 10/31/2017 08:24 AM, Martin K. Petersen wrote: If you use alloc_ordered_workqueue directly instead of create_singlethread_workqueue you can pass a format string and don't need the separate allocation. But I'm not sure if Tejun is fine with using __WQ_LEGACY directly.. The only thing that flag does is exempting the workqueue from possible flush deadlock check as we don't know whether WQ_MEM_RECLAIM on a legacy workqueue is intentional. There's no reason to add it when converting to alloc_ordered_workqueue(). Just decide whether it needs forward progress guarantee and use WQ_MEM_RECLAIM if so. Cathy? Sorry for the delay. Long was working on a similar problem and we needed to add a couple of extra patches. I was thinking of sending all three in series but I can send the V3 of this now and follow up with the additional patches. Does that make sense?
[PATCH 1/1] scsi: hisi_sas: fix for the build error log_non_standard_event undefined
This patch fix the build error log_non_standard_event undefined for the i386 build for COMPILE_TEST. https://lists.01.org/pipermail/kbuild-all/2017-October/039518.html The function call log_non_standard_event is replaced with the function call trace_non_standard_event. Signed-off-by: Shiju Jose Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 41 ++ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 433412a..72f606a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -2959,12 +2959,13 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p) if (trace_ns_event_enabled) { err_data.physical_addr = val; err_data.type = ecc_error->type; - log_non_standard_event(&CPER_SEC_TYPE_HISI_SAS, - &NULL_UUID_LE, - dev_name(dev), - GHES_SEV_RECOVERABLE, - (const u8 *)&err_data, - sizeof(err_data)); + trace_non_standard_event( + &CPER_SEC_TYPE_HISI_SAS, + &NULL_UUID_LE, + dev_name(dev), + GHES_SEV_RECOVERABLE, + (const u8 *)&err_data, + sizeof(err_data)); } else { dev_warn(dev, ecc_error->msg, val); } @@ -3000,12 +3001,13 @@ static void multi_bit_ecc_error_process_v2_hw(struct hisi_hba *hisi_hba, if (trace_ns_event_enabled) { err_data.physical_addr = val; err_data.type = ecc_error->type; - log_non_standard_event(&CPER_SEC_TYPE_HISI_SAS, - &NULL_UUID_LE, - dev_name(dev), - GHES_SEV_PANIC, - (const u8 *)&err_data, - sizeof(err_data)); + trace_non_standard_event( + &CPER_SEC_TYPE_HISI_SAS, + &NULL_UUID_LE, + dev_name(dev), + GHES_SEV_PANIC, + (const u8 *)&err_data, + sizeof(err_data)); } else { dev_warn(dev, ecc_error->msg, irq_value, val); } @@ -3135,7 +3137,7 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p) HISI_SAS_VALID_AXI_ERR_INFO; err_data.type = axi_error->type; err_data.axi_err_info = sub->msk; - log_non_standard_event( + trace_non_standard_event( &CPER_SEC_TYPE_HISI_SAS, &NULL_UUID_LE, dev_name(dev), @@ -3152,12 +3154,13 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void *p) err_data.validation_bits = HISI_SAS_VALID_ERR_TYPE; err_data.type = axi_error->type; - log_non_standard_event(&CPER_SEC_TYPE_HISI_SAS, - &NULL_UUID_LE, - dev_name(dev), - GHES_SEV_PANIC, - (const u8 *)&err_data, - sizeof(err_data)); + trace_non_standard_event( + &CPER_SEC_TYPE_HISI_SAS, + &NULL_UUID_LE, + dev_name(dev), + GHES_SE
Re: [PATCH] scsi: scsi_transport_iscsi: fix spelling mistake: 'Cound' -> 'Could'
Arvind, > Trivial fix to spelling mistakes in 'iscsi_get_host_stats'. Applied to 4.15/scsi-queue. -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH V2] scsi: storvsc: Allow only one remove lun work item to be issued per lun
>> If you use alloc_ordered_workqueue directly instead of >> create_singlethread_workqueue you can pass a format string and don't >> need the separate allocation. >> >> But I'm not sure if Tejun is fine with using __WQ_LEGACY directly.. > > The only thing that flag does is exempting the workqueue from possible > flush deadlock check as we don't know whether WQ_MEM_RECLAIM on a > legacy workqueue is intentional. There's no reason to add it when > converting to alloc_ordered_workqueue(). Just decide whether it needs > forward progress guarantee and use WQ_MEM_RECLAIM if so. Cathy? -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH 0/5] nvmet/nvmet_fc: add events for discovery controller rescan
James, > Note: These patches were posted to the nvme list this morning. I should > have cc'd the scsi list as well - so I'm not posting to the scsi list. > I fully expect all patches to be pulled via the nvme-4.15 tree then the > block tree. The SCSI pieces look OK to me. Acked-by: Martin K. Petersen -- Martin K. Petersen Oracle Linux Engineering
Re: scsi/NCR5380: Suppress SDTR and WDTR message logging
Finn, > The 5380 drivers only support asynchronous transfers and the 5380 > controllers only have narrow busses. Hence, the core driver will reject > any SDTR and WDTR messages from target devices. Don't log this, it's > expected behaviour. Also, fix the off-by-one array indices in the > arguments to scmd_printk(). Applied to 4.15/scsi-queue. Thanks. -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH 2/2] scsi: megaraid: Track the page allocations for struct fusion_context
Yisheng, >> Do you still see leaks reported with the megaraid driver update recently >> merged into 4.15/scsi-queue? >> > No, the related code have been optimized and __get_free_pages is not used > to allocate fusion_context anymore. So, please ignore this one, and sorry > for disturbing. > > BTW, what about the Patch 1/2, which is just a minor clean up? Kashyap? Shivasharan? Sumit? -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH 0/3] cxlflash: Miscellaneous fixes
Uma, > This patch series contains miscellaneous fixes. All three patches resolve > minor issues. > > This series is intended for 4.15 and is bisectable. Applied to 4.15/scsi-queue. Thank you! -- Martin K. Petersen Oracle Linux Engineering
Re: [PATCH 1/1] qla2xxx: Fix oops in qla2x00_probe_one error path
Douglas, > On error, kthread_create() returns an errno-encoded pointer, not NULL. > The routine qla2x00_probe_one() detects the error case and jumps > to probe_failed, but has already assigned the return value from > kthread_create() to ha->dpc_thread. Then probe_failed checks to see > if ha->dpc_thread is not NULL before doing cleanup on it. Since in the > error case this is also not NULL, it ends up trying to access an invalid > task pointer. > > Solution is to assign NULL to ha->dpc_thread in the error path to avoid > kthread cleanup in that case. Applied to 4.14/scsi-fixes. Thank you! -- Martin K. Petersen Oracle Linux Engineering