mirror of
https://github.com/hardkernel/linux.git
synced 2026-03-24 19:40:21 +09:00
Merge tag 'v4.9.252' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into odroidg12-4.9.y
This is the 4.9.252 stable release
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 251
|
||||
SUBLEVEL = 252
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
||||
@@ -224,10 +224,12 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
|
||||
break;
|
||||
case BUS_NOTIFY_BIND_DRIVER:
|
||||
od = to_omap_device(pdev);
|
||||
if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) &&
|
||||
pm_runtime_status_suspended(dev)) {
|
||||
if (od) {
|
||||
od->_driver_status = BUS_NOTIFY_BIND_DRIVER;
|
||||
pm_runtime_set_active(dev);
|
||||
if (od->_state == OMAP_DEVICE_STATE_ENABLED &&
|
||||
pm_runtime_status_suspended(dev)) {
|
||||
pm_runtime_set_active(dev);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BUS_NOTIFY_ADD_DEVICE:
|
||||
|
||||
@@ -450,6 +450,10 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
|
||||
{
|
||||
u64 pmcr, val;
|
||||
|
||||
/* No PMU available, PMCR_EL0 may UNDEF... */
|
||||
if (!kvm_arm_support_pmu_v3())
|
||||
return;
|
||||
|
||||
pmcr = read_sysreg(pmcr_el0);
|
||||
/*
|
||||
* Writable bits of PMCR_EL0 (ARMV8_PMU_PMCR_MASK) are reset to UNKNOWN
|
||||
|
||||
@@ -411,9 +411,9 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
if (pte_val(*ptep) & _PAGE_HASHPTE)
|
||||
flush_hash_entry(mm, ptep, addr);
|
||||
__asm__ __volatile__("\
|
||||
stw%U0%X0 %2,%0\n\
|
||||
stw%X0 %2,%0\n\
|
||||
eieio\n\
|
||||
stw%U0%X0 %L2,%1"
|
||||
stw%X1 %L2,%1"
|
||||
: "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
|
||||
: "r" (pte) : "memory");
|
||||
|
||||
|
||||
@@ -155,9 +155,9 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||
flush_hash_entry(mm, ptep, addr);
|
||||
#endif
|
||||
__asm__ __volatile__("\
|
||||
stw%U0%X0 %2,%0\n\
|
||||
stw%X0 %2,%0\n\
|
||||
eieio\n\
|
||||
stw%U0%X0 %L2,%1"
|
||||
stw%X1 %L2,%1"
|
||||
: "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
|
||||
: "r" (pte) : "memory");
|
||||
|
||||
|
||||
@@ -159,14 +159,17 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter)
|
||||
part = rcu_dereference(ptbl->part[piter->idx]);
|
||||
if (!part)
|
||||
continue;
|
||||
get_device(part_to_dev(part));
|
||||
piter->part = part;
|
||||
if (!part_nr_sects_read(part) &&
|
||||
!(piter->flags & DISK_PITER_INCL_EMPTY) &&
|
||||
!(piter->flags & DISK_PITER_INCL_EMPTY_PART0 &&
|
||||
piter->idx == 0))
|
||||
piter->idx == 0)) {
|
||||
put_device(part_to_dev(part));
|
||||
piter->part = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
get_device(part_to_dev(part));
|
||||
piter->part = part;
|
||||
piter->idx += inc;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -530,6 +530,7 @@ config BLK_DEV_RBD
|
||||
config BLK_DEV_RSXX
|
||||
tristate "IBM Flash Adapter 900GB Full Height PCIe Device Driver"
|
||||
depends on PCI
|
||||
select CRC32
|
||||
help
|
||||
Device driver for IBM's high speed PCIe SSD
|
||||
storage device: Flash Adapter 900GB Full Height.
|
||||
|
||||
@@ -887,9 +887,9 @@ static int get_transition_latency(struct powernow_k8_data *data)
|
||||
|
||||
/* Take a frequency, and issue the fid/vid transition command */
|
||||
static int transition_frequency_fidvid(struct powernow_k8_data *data,
|
||||
unsigned int index)
|
||||
unsigned int index,
|
||||
struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpufreq_policy *policy;
|
||||
u32 fid = 0;
|
||||
u32 vid = 0;
|
||||
int res;
|
||||
@@ -921,9 +921,6 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
|
||||
freqs.old = find_khz_freq_from_fid(data->currfid);
|
||||
freqs.new = find_khz_freq_from_fid(fid);
|
||||
|
||||
policy = cpufreq_cpu_get(smp_processor_id());
|
||||
cpufreq_cpu_put(policy);
|
||||
|
||||
cpufreq_freq_transition_begin(policy, &freqs);
|
||||
res = transition_fid_vid(data, fid, vid);
|
||||
cpufreq_freq_transition_end(policy, &freqs, res);
|
||||
@@ -978,7 +975,7 @@ static long powernowk8_target_fn(void *arg)
|
||||
|
||||
powernow_k8_acpi_pst_values(data, newstate);
|
||||
|
||||
ret = transition_frequency_fidvid(data, newstate);
|
||||
ret = transition_frequency_fidvid(data, newstate, pol);
|
||||
|
||||
if (ret) {
|
||||
pr_err("transition frequency failed\n");
|
||||
|
||||
@@ -2357,7 +2357,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
|
||||
has_dre = false;
|
||||
|
||||
if (!has_dre)
|
||||
xdev->common.copy_align = fls(width - 1);
|
||||
xdev->common.copy_align = (enum dmaengine_alignment)fls(width - 1);
|
||||
|
||||
if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel") ||
|
||||
of_device_is_compatible(node, "xlnx,axi-dma-mm2s-channel") ||
|
||||
@@ -2630,7 +2630,11 @@ static int xilinx_dma_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* Register the DMA engine with the core */
|
||||
dma_async_device_register(&xdev->common);
|
||||
err = dma_async_device_register(&xdev->common);
|
||||
if (err) {
|
||||
dev_err(xdev->dev, "failed to register the dma device\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = of_dma_controller_register(node, of_dma_xilinx_xlate,
|
||||
xdev);
|
||||
|
||||
@@ -882,7 +882,7 @@ eb_vma_misplaced(struct i915_vma *vma)
|
||||
return !only_mappable_for_reloc(entry->flags);
|
||||
|
||||
if ((entry->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) == 0 &&
|
||||
(vma->node.start + vma->node.size - 1) >> 32)
|
||||
(vma->node.start + vma->node.size + 4095) >> 32)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1350,6 +1350,8 @@ static int intel_irq_remapping_alloc(struct irq_domain *domain,
|
||||
irq_data = irq_domain_get_irq_data(domain, virq + i);
|
||||
irq_cfg = irqd_cfg(irq_data);
|
||||
if (!irq_data || !irq_cfg) {
|
||||
if (!i)
|
||||
kfree(data);
|
||||
ret = -EINVAL;
|
||||
goto out_free_data;
|
||||
}
|
||||
|
||||
@@ -930,6 +930,7 @@ err_destroy_groups:
|
||||
ft->g[ft->num_groups] = NULL;
|
||||
mlx5e_destroy_groups(ft);
|
||||
kvfree(in);
|
||||
kfree(ft->g);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -295,6 +295,7 @@ config SLIC_DS26522
|
||||
tristate "Slic Maxim ds26522 card support"
|
||||
depends on SPI
|
||||
depends on FSL_SOC || ARCH_MXC || ARCH_LAYERSCAPE || COMPILE_TEST
|
||||
select BITREVERSE
|
||||
help
|
||||
This module initializes and configures the slic maxim card
|
||||
in T1 or E1 mode.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
config WIL6210
|
||||
tristate "Wilocity 60g WiFi card wil6210 support"
|
||||
select WANT_DEV_COREDUMP
|
||||
select CRC32
|
||||
depends on CFG80211
|
||||
depends on PCI
|
||||
default n
|
||||
|
||||
@@ -1606,7 +1606,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
master = spi_alloc_master(dev, sizeof(struct driver_data));
|
||||
master = devm_spi_alloc_master(dev, sizeof(*drv_data));
|
||||
if (!master) {
|
||||
dev_err(&pdev->dev, "cannot alloc spi_master\n");
|
||||
pxa_ssp_free(ssp);
|
||||
@@ -1788,7 +1788,6 @@ out_error_clock_enabled:
|
||||
free_irq(ssp->irq, drv_data);
|
||||
|
||||
out_error_master_alloc:
|
||||
spi_master_put(master);
|
||||
pxa_ssp_free(ssp);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -1736,6 +1736,10 @@ void transport_generic_request_failure(struct se_cmd *cmd,
|
||||
case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
|
||||
case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
|
||||
case TCM_COPY_TARGET_DEVICE_NOT_REACHABLE:
|
||||
case TCM_TOO_MANY_TARGET_DESCS:
|
||||
case TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE:
|
||||
case TCM_TOO_MANY_SEGMENT_DESCS:
|
||||
case TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE:
|
||||
break;
|
||||
case TCM_OUT_OF_RESOURCES:
|
||||
sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
@@ -2886,6 +2890,26 @@ static const struct sense_info sense_info_table[] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */
|
||||
},
|
||||
[TCM_TOO_MANY_TARGET_DESCS] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x26,
|
||||
.ascq = 0x06, /* TOO MANY TARGET DESCRIPTORS */
|
||||
},
|
||||
[TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x26,
|
||||
.ascq = 0x07, /* UNSUPPORTED TARGET DESCRIPTOR TYPE CODE */
|
||||
},
|
||||
[TCM_TOO_MANY_SEGMENT_DESCS] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x26,
|
||||
.ascq = 0x08, /* TOO MANY SEGMENT DESCRIPTORS */
|
||||
},
|
||||
[TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x26,
|
||||
.ascq = 0x09, /* UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE */
|
||||
},
|
||||
[TCM_PARAMETER_LIST_LENGTH_ERROR] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */
|
||||
|
||||
@@ -52,64 +52,87 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int target_xcopy_locate_se_dev_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
|
||||
bool src)
|
||||
/**
|
||||
* target_xcopy_locate_se_dev_e4_iter - compare XCOPY NAA device identifiers
|
||||
*
|
||||
* @se_dev: device being considered for match
|
||||
* @dev_wwn: XCOPY requested NAA dev_wwn
|
||||
* @return: 1 on match, 0 on no-match
|
||||
*/
|
||||
static int target_xcopy_locate_se_dev_e4_iter(struct se_device *se_dev,
|
||||
const unsigned char *dev_wwn)
|
||||
{
|
||||
struct se_device *se_dev;
|
||||
unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN], *dev_wwn;
|
||||
unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
|
||||
int rc;
|
||||
|
||||
if (src)
|
||||
dev_wwn = &xop->dst_tid_wwn[0];
|
||||
else
|
||||
dev_wwn = &xop->src_tid_wwn[0];
|
||||
|
||||
mutex_lock(&g_device_mutex);
|
||||
list_for_each_entry(se_dev, &g_device_list, g_dev_node) {
|
||||
|
||||
if (!se_dev->dev_attrib.emulate_3pc)
|
||||
continue;
|
||||
|
||||
memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
|
||||
target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]);
|
||||
|
||||
rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
|
||||
if (rc != 0)
|
||||
continue;
|
||||
|
||||
if (src) {
|
||||
xop->dst_dev = se_dev;
|
||||
pr_debug("XCOPY 0xe4: Setting xop->dst_dev: %p from located"
|
||||
" se_dev\n", xop->dst_dev);
|
||||
} else {
|
||||
xop->src_dev = se_dev;
|
||||
pr_debug("XCOPY 0xe4: Setting xop->src_dev: %p from located"
|
||||
" se_dev\n", xop->src_dev);
|
||||
}
|
||||
|
||||
rc = target_depend_item(&se_dev->dev_group.cg_item);
|
||||
if (rc != 0) {
|
||||
pr_err("configfs_depend_item attempt failed:"
|
||||
" %d for se_dev: %p\n", rc, se_dev);
|
||||
mutex_unlock(&g_device_mutex);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pr_debug("Called configfs_depend_item for se_dev: %p"
|
||||
" se_dev->se_dev_group: %p\n", se_dev,
|
||||
&se_dev->dev_group);
|
||||
|
||||
mutex_unlock(&g_device_mutex);
|
||||
if (!se_dev->dev_attrib.emulate_3pc) {
|
||||
pr_debug("XCOPY: emulate_3pc disabled on se_dev %p\n", se_dev);
|
||||
return 0;
|
||||
}
|
||||
mutex_unlock(&g_device_mutex);
|
||||
|
||||
memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN);
|
||||
target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]);
|
||||
|
||||
rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN);
|
||||
if (rc != 0) {
|
||||
pr_debug("XCOPY: skip non-matching: %*ph\n",
|
||||
XCOPY_NAA_IEEE_REGEX_LEN, tmp_dev_wwn);
|
||||
return 0;
|
||||
}
|
||||
pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int target_xcopy_locate_se_dev_e4(struct se_session *sess,
|
||||
const unsigned char *dev_wwn,
|
||||
struct se_device **_found_dev,
|
||||
struct percpu_ref **_found_lun_ref)
|
||||
{
|
||||
struct se_dev_entry *deve;
|
||||
struct se_node_acl *nacl;
|
||||
struct se_lun *this_lun = NULL;
|
||||
struct se_device *found_dev = NULL;
|
||||
|
||||
/* cmd with NULL sess indicates no associated $FABRIC_MOD */
|
||||
if (!sess)
|
||||
goto err_out;
|
||||
|
||||
pr_debug("XCOPY 0xe4: searching for: %*ph\n",
|
||||
XCOPY_NAA_IEEE_REGEX_LEN, dev_wwn);
|
||||
|
||||
nacl = sess->se_node_acl;
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) {
|
||||
struct se_device *this_dev;
|
||||
int rc;
|
||||
|
||||
this_lun = rcu_dereference(deve->se_lun);
|
||||
this_dev = rcu_dereference_raw(this_lun->lun_se_dev);
|
||||
|
||||
rc = target_xcopy_locate_se_dev_e4_iter(this_dev, dev_wwn);
|
||||
if (rc) {
|
||||
if (percpu_ref_tryget_live(&this_lun->lun_ref))
|
||||
found_dev = this_dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
if (found_dev == NULL)
|
||||
goto err_out;
|
||||
|
||||
pr_debug("lun_ref held for se_dev: %p se_dev->se_dev_group: %p\n",
|
||||
found_dev, &found_dev->dev_group);
|
||||
*_found_dev = found_dev;
|
||||
*_found_lun_ref = &this_lun->lun_ref;
|
||||
return 0;
|
||||
err_out:
|
||||
pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop,
|
||||
unsigned char *p, bool src)
|
||||
unsigned char *p, unsigned short cscd_index)
|
||||
{
|
||||
unsigned char *desc = p;
|
||||
unsigned short ript;
|
||||
@@ -154,7 +177,13 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (src) {
|
||||
if (cscd_index != xop->stdi && cscd_index != xop->dtdi) {
|
||||
pr_debug("XCOPY 0xe4: ignoring CSCD entry %d - neither src nor "
|
||||
"dest\n", cscd_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cscd_index == xop->stdi) {
|
||||
memcpy(&xop->src_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
|
||||
/*
|
||||
* Determine if the source designator matches the local device
|
||||
@@ -166,10 +195,15 @@ static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op
|
||||
pr_debug("XCOPY 0xe4: Set xop->src_dev %p from source"
|
||||
" received xop\n", xop->src_dev);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (cscd_index == xop->dtdi) {
|
||||
memcpy(&xop->dst_tid_wwn[0], &desc[8], XCOPY_NAA_IEEE_REGEX_LEN);
|
||||
/*
|
||||
* Determine if the destination designator matches the local device
|
||||
* Determine if the destination designator matches the local
|
||||
* device. If @cscd_index corresponds to both source (stdi) and
|
||||
* destination (dtdi), or dtdi comes after stdi, then
|
||||
* XCOL_DEST_RECV_OP wins.
|
||||
*/
|
||||
if (!memcmp(&xop->local_dev_wwn[0], &xop->dst_tid_wwn[0],
|
||||
XCOPY_NAA_IEEE_REGEX_LEN)) {
|
||||
@@ -189,9 +223,9 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
|
||||
{
|
||||
struct se_device *local_dev = se_cmd->se_dev;
|
||||
unsigned char *desc = p;
|
||||
int offset = tdll % XCOPY_TARGET_DESC_LEN, rc, ret = 0;
|
||||
int offset = tdll % XCOPY_TARGET_DESC_LEN, rc;
|
||||
unsigned short cscd_index = 0;
|
||||
unsigned short start = 0;
|
||||
bool src = true;
|
||||
|
||||
*sense_ret = TCM_INVALID_PARAMETER_LIST;
|
||||
|
||||
@@ -214,25 +248,19 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
|
||||
|
||||
while (start < tdll) {
|
||||
/*
|
||||
* Check target descriptor identification with 0xE4 type with
|
||||
* use VPD 0x83 WWPN matching ..
|
||||
* Check target descriptor identification with 0xE4 type, and
|
||||
* compare the current index with the CSCD descriptor IDs in
|
||||
* the segment descriptor. Use VPD 0x83 WWPN matching ..
|
||||
*/
|
||||
switch (desc[0]) {
|
||||
case 0xe4:
|
||||
rc = target_xcopy_parse_tiddesc_e4(se_cmd, xop,
|
||||
&desc[0], src);
|
||||
&desc[0], cscd_index);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
/*
|
||||
* Assume target descriptors are in source -> destination order..
|
||||
*/
|
||||
if (src)
|
||||
src = false;
|
||||
else
|
||||
src = true;
|
||||
start += XCOPY_TARGET_DESC_LEN;
|
||||
desc += XCOPY_TARGET_DESC_LEN;
|
||||
ret++;
|
||||
cscd_index++;
|
||||
break;
|
||||
default:
|
||||
pr_err("XCOPY unsupported descriptor type code:"
|
||||
@@ -241,10 +269,25 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
|
||||
}
|
||||
}
|
||||
|
||||
if (xop->op_origin == XCOL_SOURCE_RECV_OP)
|
||||
rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, true);
|
||||
else
|
||||
rc = target_xcopy_locate_se_dev_e4(se_cmd, xop, false);
|
||||
switch (xop->op_origin) {
|
||||
case XCOL_SOURCE_RECV_OP:
|
||||
rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
|
||||
xop->dst_tid_wwn,
|
||||
&xop->dst_dev,
|
||||
&xop->remote_lun_ref);
|
||||
break;
|
||||
case XCOL_DEST_RECV_OP:
|
||||
rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess,
|
||||
xop->src_tid_wwn,
|
||||
&xop->src_dev,
|
||||
&xop->remote_lun_ref);
|
||||
break;
|
||||
default:
|
||||
pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - "
|
||||
"stdi: %hu dtdi: %hu\n", xop->stdi, xop->dtdi);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If a matching IEEE NAA 0x83 descriptor for the requested device
|
||||
* is not located on this node, return COPY_ABORTED with ASQ/ASQC
|
||||
@@ -261,7 +304,7 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd,
|
||||
pr_debug("XCOPY TGT desc: Dest dev: %p NAA IEEE WWN: 0x%16phN\n",
|
||||
xop->dst_dev, &xop->dst_tid_wwn[0]);
|
||||
|
||||
return ret;
|
||||
return cscd_index;
|
||||
|
||||
out:
|
||||
return -EINVAL;
|
||||
@@ -305,17 +348,26 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
|
||||
|
||||
static int target_xcopy_parse_segment_descriptors(struct se_cmd *se_cmd,
|
||||
struct xcopy_op *xop, unsigned char *p,
|
||||
unsigned int sdll)
|
||||
unsigned int sdll, sense_reason_t *sense_ret)
|
||||
{
|
||||
unsigned char *desc = p;
|
||||
unsigned int start = 0;
|
||||
int offset = sdll % XCOPY_SEGMENT_DESC_LEN, rc, ret = 0;
|
||||
|
||||
*sense_ret = TCM_INVALID_PARAMETER_LIST;
|
||||
|
||||
if (offset != 0) {
|
||||
pr_err("XCOPY segment descriptor list length is not"
|
||||
" multiple of %d\n", XCOPY_SEGMENT_DESC_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (sdll > RCR_OP_MAX_SG_DESC_COUNT * XCOPY_SEGMENT_DESC_LEN) {
|
||||
pr_err("XCOPY supports %u segment descriptor(s), sdll: %u too"
|
||||
" large..\n", RCR_OP_MAX_SG_DESC_COUNT, sdll);
|
||||
/* spc4r37 6.4.3.5 SEGMENT DESCRIPTOR LIST LENGTH field */
|
||||
*sense_ret = TCM_TOO_MANY_SEGMENT_DESCS;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (start < sdll) {
|
||||
/*
|
||||
@@ -372,18 +424,12 @@ static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd)
|
||||
|
||||
static void xcopy_pt_undepend_remotedev(struct xcopy_op *xop)
|
||||
{
|
||||
struct se_device *remote_dev;
|
||||
|
||||
if (xop->op_origin == XCOL_SOURCE_RECV_OP)
|
||||
remote_dev = xop->dst_dev;
|
||||
pr_debug("putting dst lun_ref for %p\n", xop->dst_dev);
|
||||
else
|
||||
remote_dev = xop->src_dev;
|
||||
pr_debug("putting src lun_ref for %p\n", xop->src_dev);
|
||||
|
||||
pr_debug("Calling configfs_undepend_item for"
|
||||
" remote_dev: %p remote_dev->dev_group: %p\n",
|
||||
remote_dev, &remote_dev->dev_group.cg_item);
|
||||
|
||||
target_undepend_item(&remote_dev->dev_group.cg_item);
|
||||
percpu_ref_put(xop->remote_lun_ref);
|
||||
}
|
||||
|
||||
static void xcopy_pt_release_cmd(struct se_cmd *se_cmd)
|
||||
@@ -893,6 +939,20 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
|
||||
" tdll: %hu sdll: %u inline_dl: %u\n", list_id, list_id_usage,
|
||||
tdll, sdll, inline_dl);
|
||||
|
||||
/*
|
||||
* skip over the target descriptors until segment descriptors
|
||||
* have been passed - CSCD ids are needed to determine src and dest.
|
||||
*/
|
||||
seg_desc = &p[16] + tdll;
|
||||
|
||||
rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc,
|
||||
sdll, &ret);
|
||||
if (rc <= 0)
|
||||
goto out;
|
||||
|
||||
pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
|
||||
rc * XCOPY_SEGMENT_DESC_LEN);
|
||||
|
||||
rc = target_xcopy_parse_target_descriptors(se_cmd, xop, &p[16], tdll, &ret);
|
||||
if (rc <= 0)
|
||||
goto out;
|
||||
@@ -910,18 +970,8 @@ sense_reason_t target_do_xcopy(struct se_cmd *se_cmd)
|
||||
|
||||
pr_debug("XCOPY: Processed %d target descriptors, length: %u\n", rc,
|
||||
rc * XCOPY_TARGET_DESC_LEN);
|
||||
seg_desc = &p[16];
|
||||
seg_desc += (rc * XCOPY_TARGET_DESC_LEN);
|
||||
|
||||
rc = target_xcopy_parse_segment_descriptors(se_cmd, xop, seg_desc, sdll);
|
||||
if (rc <= 0) {
|
||||
xcopy_pt_undepend_remotedev(xop);
|
||||
goto out;
|
||||
}
|
||||
transport_kunmap_data_sg(se_cmd);
|
||||
|
||||
pr_debug("XCOPY: Processed %d segment descriptors, length: %u\n", rc,
|
||||
rc * XCOPY_SEGMENT_DESC_LEN);
|
||||
INIT_WORK(&xop->xop_work, target_xcopy_do_work);
|
||||
queue_work(xcopy_wq, &xop->xop_work);
|
||||
return TCM_NO_SENSE;
|
||||
|
||||
@@ -19,6 +19,7 @@ struct xcopy_op {
|
||||
struct se_device *dst_dev;
|
||||
unsigned char dst_tid_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
|
||||
unsigned char local_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN];
|
||||
struct percpu_ref *remote_lun_ref;
|
||||
|
||||
sector_t src_lba;
|
||||
sector_t dst_lba;
|
||||
|
||||
@@ -331,7 +331,7 @@ void ubifs_pad(const struct ubifs_info *c, void *buf, int pad)
|
||||
{
|
||||
uint32_t crc;
|
||||
|
||||
ubifs_assert(pad >= 0 && !(pad & 7));
|
||||
ubifs_assert(pad >= 0);
|
||||
|
||||
if (pad >= UBIFS_PAD_NODE_SZ) {
|
||||
struct ubifs_ch *ch = buf;
|
||||
@@ -721,6 +721,10 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
|
||||
* write-buffer.
|
||||
*/
|
||||
memcpy(wbuf->buf + wbuf->used, buf, len);
|
||||
if (aligned_len > len) {
|
||||
ubifs_assert(aligned_len - len < 8);
|
||||
ubifs_pad(c, wbuf->buf + wbuf->used + len, aligned_len - len);
|
||||
}
|
||||
|
||||
if (aligned_len == wbuf->avail) {
|
||||
dbg_io("flush jhead %s wbuf to LEB %d:%d",
|
||||
@@ -813,13 +817,18 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
|
||||
}
|
||||
|
||||
spin_lock(&wbuf->lock);
|
||||
if (aligned_len)
|
||||
if (aligned_len) {
|
||||
/*
|
||||
* And now we have what's left and what does not take whole
|
||||
* max. write unit, so write it to the write-buffer and we are
|
||||
* done.
|
||||
*/
|
||||
memcpy(wbuf->buf, buf + written, len);
|
||||
if (aligned_len > len) {
|
||||
ubifs_assert(aligned_len - len < 8);
|
||||
ubifs_pad(c, wbuf->buf + len, aligned_len - len);
|
||||
}
|
||||
}
|
||||
|
||||
if (c->leb_size - wbuf->offs >= c->max_write_size)
|
||||
wbuf->size = c->max_write_size;
|
||||
|
||||
@@ -178,6 +178,10 @@ enum tcm_sense_reason_table {
|
||||
TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = R(0x16),
|
||||
TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = R(0x17),
|
||||
TCM_COPY_TARGET_DEVICE_NOT_REACHABLE = R(0x18),
|
||||
TCM_TOO_MANY_TARGET_DESCS = R(0x19),
|
||||
TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE = R(0x1a),
|
||||
TCM_TOO_MANY_SEGMENT_DESCS = R(0x1b),
|
||||
TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE = R(0x1c),
|
||||
#undef R
|
||||
};
|
||||
|
||||
|
||||
@@ -1592,6 +1592,12 @@ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len)
|
||||
skb->csum = csum_block_sub(skb->csum,
|
||||
skb_checksum(skb, len, delta, 0),
|
||||
len);
|
||||
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
int hdlen = (len > skb_headlen(skb)) ? skb_headlen(skb) : len;
|
||||
int offset = skb_checksum_start_offset(skb) + skb->csum_offset;
|
||||
|
||||
if (offset + sizeof(__sum16) > hdlen)
|
||||
return -EINVAL;
|
||||
}
|
||||
return __pskb_trim(skb, len);
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *sk
|
||||
if (skb_is_gso(skb))
|
||||
return ip_finish_output_gso(net, sk, skb, mtu);
|
||||
|
||||
if (skb->len > mtu || (IPCB(skb)->flags & IPSKB_FRAG_PMTU))
|
||||
if (skb->len > mtu || IPCB(skb)->frag_max_size)
|
||||
return ip_fragment(net, sk, skb, mtu, ip_finish_output2);
|
||||
|
||||
return ip_finish_output2(net, sk, skb);
|
||||
|
||||
@@ -743,7 +743,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||
goto tx_error;
|
||||
}
|
||||
|
||||
if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph)) {
|
||||
df = tnl_params->frag_off;
|
||||
if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
|
||||
df |= (inner_iph->frag_off & htons(IP_DF));
|
||||
|
||||
if (tnl_update_pmtu(dev, skb, rt, df, inner_iph)) {
|
||||
ip_rt_put(rt);
|
||||
goto tx_error;
|
||||
}
|
||||
@@ -771,10 +775,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
|
||||
ttl = ip4_dst_hoplimit(&rt->dst);
|
||||
}
|
||||
|
||||
df = tnl_params->frag_off;
|
||||
if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
|
||||
df |= (inner_iph->frag_off&htons(IP_DF));
|
||||
|
||||
max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
|
||||
+ rt->dst.header_len + ip_encap_hlen(&tunnel->encap);
|
||||
if (max_headroom > dev->needed_headroom)
|
||||
|
||||
Reference in New Issue
Block a user