summaryrefslogtreecommitdiff
path: root/drivers/target/target_core_user.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-10 13:01:12 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-10 13:01:12 -0700
commit5f85942c2ea2ed59d8f19c954bbb0f5c1a2ebdd1 (patch)
treeffd0c606829178dd0be28c557685203f760438d8 /drivers/target/target_core_user.c
parent0c14e43a42e4e44f70963f8ccf89461290c4e4da (diff)
parent1b5c2cb196684f1418fe82257a1b0a8cb0aabc9d (diff)
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley: "This is mostly updates to the usual drivers: ufs, qedf, mpt3sas, lpfc, xfcp, hisi_sas, cxlflash, qla2xxx. In the absence of Nic, we're also taking target updates which are mostly minor except for the tcmu refactor. The only real core change to worry about is the removal of high page bouncing (in sas, storvsc and iscsi). This has been well tested and no problems have shown up so far" * tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (268 commits) scsi: lpfc: update driver version to 12.0.0.4 scsi: lpfc: Fix port initialization failure. scsi: lpfc: Fix 16gb hbas failing cq create. scsi: lpfc: Fix crash in blk_mq layer when executing modprobe -r lpfc scsi: lpfc: correct oversubscription of nvme io requests for an adapter scsi: lpfc: Fix MDS diagnostics failure (Rx < Tx) scsi: hisi_sas: Mark PHY as in reset for nexus reset scsi: hisi_sas: Fix return value when get_free_slot() failed scsi: hisi_sas: Terminate STP reject quickly for v2 hw scsi: hisi_sas: Add v2 hw force PHY function for internal ATA command scsi: hisi_sas: Include TMF elements in struct hisi_sas_slot scsi: hisi_sas: Try wait commands before before controller reset scsi: hisi_sas: Init disks after controller reset scsi: hisi_sas: Create a scsi_host_template per HW module scsi: hisi_sas: Reset disks when discovered scsi: hisi_sas: Add LED feature for v3 hw scsi: hisi_sas: Change common allocation mode of device id scsi: hisi_sas: change slot index allocation mode scsi: hisi_sas: Introduce hisi_sas_phy_set_linkrate() scsi: hisi_sas: fix a typo in hisi_sas_task_prep() ...
Diffstat (limited to 'drivers/target/target_core_user.c')
-rw-r--r--drivers/target/target_core_user.c160
1 files changed, 121 insertions, 39 deletions
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 4f26bdc3d1dc..94b183efd236 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -42,7 +42,11 @@
#include <linux/target_core_user.h>
-/*
+/**
+ * DOC: Userspace I/O
+ * Userspace I/O
+ * -------------
+ *
* Define a shared-memory interface for LIO to pass SCSI commands and
* data to userspace for processing. This is to allow backends that
* are too complex for in-kernel support to be possible.
@@ -53,7 +57,7 @@
* See the .h file for how the ring is laid out. Note that while the
* command ring is defined, the particulars of the data area are
* not. Offset values in the command entry point to other locations
- * internal to the mmap()ed area. There is separate space outside the
+ * internal to the mmap-ed area. There is separate space outside the
* command ring for data buffers. This leaves maximum flexibility for
* moving buffer allocations, or even page flipping or other
* allocation techniques, without altering the command ring layout.
@@ -1382,7 +1386,7 @@ static struct page *tcmu_try_get_block_page(struct tcmu_dev *udev, uint32_t dbi)
return page;
}
-static int tcmu_vma_fault(struct vm_fault *vmf)
+static vm_fault_t tcmu_vma_fault(struct vm_fault *vmf)
{
struct tcmu_dev *udev = vmf->vma->vm_private_data;
struct uio_info *info = &udev->uio_info;
@@ -1586,8 +1590,9 @@ static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev)
return ret;
}
-static int tcmu_netlink_event(struct tcmu_dev *udev, enum tcmu_genl_cmd cmd,
- int reconfig_attr, const void *reconfig_data)
+static int tcmu_netlink_event_init(struct tcmu_dev *udev,
+ enum tcmu_genl_cmd cmd,
+ struct sk_buff **buf, void **hdr)
{
struct sk_buff *skb;
void *msg_header;
@@ -1613,46 +1618,66 @@ static int tcmu_netlink_event(struct tcmu_dev *udev, enum tcmu_genl_cmd cmd,
if (ret < 0)
goto free_skb;
- if (cmd == TCMU_CMD_RECONFIG_DEVICE) {
- switch (reconfig_attr) {
- case TCMU_ATTR_DEV_CFG:
- ret = nla_put_string(skb, reconfig_attr, reconfig_data);
- break;
- case TCMU_ATTR_DEV_SIZE:
- ret = nla_put_u64_64bit(skb, reconfig_attr,
- *((u64 *)reconfig_data),
- TCMU_ATTR_PAD);
- break;
- case TCMU_ATTR_WRITECACHE:
- ret = nla_put_u8(skb, reconfig_attr,
- *((u8 *)reconfig_data));
- break;
- default:
- BUG();
- }
+ *buf = skb;
+ *hdr = msg_header;
+ return ret;
- if (ret < 0)
- goto free_skb;
- }
+free_skb:
+ nlmsg_free(skb);
+ return ret;
+}
+
+static int tcmu_netlink_event_send(struct tcmu_dev *udev,
+ enum tcmu_genl_cmd cmd,
+ struct sk_buff **buf, void **hdr)
+{
+ int ret = 0;
+ struct sk_buff *skb = *buf;
+ void *msg_header = *hdr;
genlmsg_end(skb, msg_header);
tcmu_init_genl_cmd_reply(udev, cmd);
ret = genlmsg_multicast_allns(&tcmu_genl_family, skb, 0,
- TCMU_MCGRP_CONFIG, GFP_KERNEL);
- /* We don't care if no one is listening */
+ TCMU_MCGRP_CONFIG, GFP_KERNEL);
+ /* We don't care if no one is listening */
if (ret == -ESRCH)
ret = 0;
if (!ret)
ret = tcmu_wait_genl_cmd_reply(udev);
-
- return ret;
-free_skb:
- nlmsg_free(skb);
return ret;
}
+static int tcmu_send_dev_add_event(struct tcmu_dev *udev)
+{
+ struct sk_buff *skb = NULL;
+ void *msg_header = NULL;
+ int ret = 0;
+
+ ret = tcmu_netlink_event_init(udev, TCMU_CMD_ADDED_DEVICE, &skb,
+ &msg_header);
+ if (ret < 0)
+ return ret;
+ return tcmu_netlink_event_send(udev, TCMU_CMD_ADDED_DEVICE, &skb,
+ &msg_header);
+
+}
+
+static int tcmu_send_dev_remove_event(struct tcmu_dev *udev)
+{
+ struct sk_buff *skb = NULL;
+ void *msg_header = NULL;
+ int ret = 0;
+
+ ret = tcmu_netlink_event_init(udev, TCMU_CMD_REMOVED_DEVICE,
+ &skb, &msg_header);
+ if (ret < 0)
+ return ret;
+ return tcmu_netlink_event_send(udev, TCMU_CMD_REMOVED_DEVICE,
+ &skb, &msg_header);
+}
+
static int tcmu_update_uio_info(struct tcmu_dev *udev)
{
struct tcmu_hba *hba = udev->hba->hba_ptr;
@@ -1762,7 +1787,7 @@ static int tcmu_configure_device(struct se_device *dev)
*/
kref_get(&udev->kref);
- ret = tcmu_netlink_event(udev, TCMU_CMD_ADDED_DEVICE, 0, NULL);
+ ret = tcmu_send_dev_add_event(udev);
if (ret)
goto err_netlink;
@@ -1812,7 +1837,7 @@ static void tcmu_destroy_device(struct se_device *dev)
list_del(&udev->node);
mutex_unlock(&root_udev_mutex);
- tcmu_netlink_event(udev, TCMU_CMD_REMOVED_DEVICE, 0, NULL);
+ tcmu_send_dev_remove_event(udev);
uio_unregister_device(&udev->uio_info);
@@ -2151,6 +2176,27 @@ static ssize_t tcmu_dev_config_show(struct config_item *item, char *page)
return snprintf(page, PAGE_SIZE, "%s\n", udev->dev_config);
}
+static int tcmu_send_dev_config_event(struct tcmu_dev *udev,
+ const char *reconfig_data)
+{
+ struct sk_buff *skb = NULL;
+ void *msg_header = NULL;
+ int ret = 0;
+
+ ret = tcmu_netlink_event_init(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+ if (ret < 0)
+ return ret;
+ ret = nla_put_string(skb, TCMU_ATTR_DEV_CFG, reconfig_data);
+ if (ret < 0) {
+ nlmsg_free(skb);
+ return ret;
+ }
+ return tcmu_netlink_event_send(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+}
+
+
static ssize_t tcmu_dev_config_store(struct config_item *item, const char *page,
size_t count)
{
@@ -2165,8 +2211,7 @@ static ssize_t tcmu_dev_config_store(struct config_item *item, const char *page,
/* Check if device has been configured before */
if (tcmu_dev_configured(udev)) {
- ret = tcmu_netlink_event(udev, TCMU_CMD_RECONFIG_DEVICE,
- TCMU_ATTR_DEV_CFG, page);
+ ret = tcmu_send_dev_config_event(udev, page);
if (ret) {
pr_err("Unable to reconfigure device\n");
return ret;
@@ -2193,6 +2238,26 @@ static ssize_t tcmu_dev_size_show(struct config_item *item, char *page)
return snprintf(page, PAGE_SIZE, "%zu\n", udev->dev_size);
}
+static int tcmu_send_dev_size_event(struct tcmu_dev *udev, u64 size)
+{
+ struct sk_buff *skb = NULL;
+ void *msg_header = NULL;
+ int ret = 0;
+
+ ret = tcmu_netlink_event_init(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+ if (ret < 0)
+ return ret;
+ ret = nla_put_u64_64bit(skb, TCMU_ATTR_DEV_SIZE,
+ size, TCMU_ATTR_PAD);
+ if (ret < 0) {
+ nlmsg_free(skb);
+ return ret;
+ }
+ return tcmu_netlink_event_send(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+}
+
static ssize_t tcmu_dev_size_store(struct config_item *item, const char *page,
size_t count)
{
@@ -2208,8 +2273,7 @@ static ssize_t tcmu_dev_size_store(struct config_item *item, const char *page,
/* Check if device has been configured before */
if (tcmu_dev_configured(udev)) {
- ret = tcmu_netlink_event(udev, TCMU_CMD_RECONFIG_DEVICE,
- TCMU_ATTR_DEV_SIZE, &val);
+ ret = tcmu_send_dev_size_event(udev, val);
if (ret) {
pr_err("Unable to reconfigure device\n");
return ret;
@@ -2257,6 +2321,25 @@ static ssize_t tcmu_emulate_write_cache_show(struct config_item *item,
return snprintf(page, PAGE_SIZE, "%i\n", da->emulate_write_cache);
}
+static int tcmu_send_emulate_write_cache(struct tcmu_dev *udev, u8 val)
+{
+ struct sk_buff *skb = NULL;
+ void *msg_header = NULL;
+ int ret = 0;
+
+ ret = tcmu_netlink_event_init(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+ if (ret < 0)
+ return ret;
+ ret = nla_put_u8(skb, TCMU_ATTR_WRITECACHE, val);
+ if (ret < 0) {
+ nlmsg_free(skb);
+ return ret;
+ }
+ return tcmu_netlink_event_send(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+}
+
static ssize_t tcmu_emulate_write_cache_store(struct config_item *item,
const char *page, size_t count)
{
@@ -2272,8 +2355,7 @@ static ssize_t tcmu_emulate_write_cache_store(struct config_item *item,
/* Check if device has been configured before */
if (tcmu_dev_configured(udev)) {
- ret = tcmu_netlink_event(udev, TCMU_CMD_RECONFIG_DEVICE,
- TCMU_ATTR_WRITECACHE, &val);
+ ret = tcmu_send_emulate_write_cache(udev, val);
if (ret) {
pr_err("Unable to reconfigure device\n");
return ret;