diff options
200 files changed, 12581 insertions, 2903 deletions
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 3 | 1 | VERSION = 3 |
| 2 | PATCHLEVEL = 9 | 2 | PATCHLEVEL = 10 |
| 3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
| 4 | EXTRAVERSION = | 4 | EXTRAVERSION = -rc1 |
| 5 | NAME = Unicycling Gorilla | 5 | NAME = Unicycling Gorilla |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 3fe5259e2fea..915fbb4fc2fe 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
| @@ -150,7 +150,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | |||
| 150 | CURRENT_THREAD_INFO(r11, r1) | 150 | CURRENT_THREAD_INFO(r11, r1) |
| 151 | ld r10,TI_FLAGS(r11) | 151 | ld r10,TI_FLAGS(r11) |
| 152 | andi. r11,r10,_TIF_SYSCALL_T_OR_A | 152 | andi. r11,r10,_TIF_SYSCALL_T_OR_A |
| 153 | bne- syscall_dotrace | 153 | bne syscall_dotrace |
| 154 | .Lsyscall_dotrace_cont: | 154 | .Lsyscall_dotrace_cont: |
| 155 | cmpldi 0,r0,NR_syscalls | 155 | cmpldi 0,r0,NR_syscalls |
| 156 | bge- syscall_enosys | 156 | bge- syscall_enosys |
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index b3a4866661c5..2af848dfa754 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h | |||
| @@ -120,6 +120,9 @@ | |||
| 120 | #define MSR_CORE_C6_RESIDENCY 0x000003fd | 120 | #define MSR_CORE_C6_RESIDENCY 0x000003fd |
| 121 | #define MSR_CORE_C7_RESIDENCY 0x000003fe | 121 | #define MSR_CORE_C7_RESIDENCY 0x000003fe |
| 122 | #define MSR_PKG_C2_RESIDENCY 0x0000060d | 122 | #define MSR_PKG_C2_RESIDENCY 0x0000060d |
| 123 | #define MSR_PKG_C8_RESIDENCY 0x00000630 | ||
| 124 | #define MSR_PKG_C9_RESIDENCY 0x00000631 | ||
| 125 | #define MSR_PKG_C10_RESIDENCY 0x00000632 | ||
| 123 | 126 | ||
| 124 | /* Run Time Average Power Limiting (RAPL) Interface */ | 127 | /* Run Time Average Power Limiting (RAPL) Interface */ |
| 125 | 128 | ||
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 4a9be6ddf054..48e8461057ba 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c | |||
| @@ -295,11 +295,10 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
| 295 | int pos; | 295 | int pos; |
| 296 | u32 table_offset, bir; | 296 | u32 table_offset, bir; |
| 297 | 297 | ||
| 298 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 298 | pos = dev->msix_cap; |
| 299 | |||
| 300 | pci_read_config_dword(dev, pos + PCI_MSIX_TABLE, | 299 | pci_read_config_dword(dev, pos + PCI_MSIX_TABLE, |
| 301 | &table_offset); | 300 | &table_offset); |
| 302 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | 301 | bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR); |
| 303 | 302 | ||
| 304 | map_irq.table_base = pci_resource_start(dev, bir); | 303 | map_irq.table_base = pci_resource_start(dev, bir); |
| 305 | map_irq.entry_nr = msidesc->msi_attrib.entry_nr; | 304 | map_irq.entry_nr = msidesc->msi_attrib.entry_nr; |
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 53d4f680c9b5..a492be2635ac 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
| @@ -85,7 +85,29 @@ | |||
| 85 | 85 | ||
| 86 | EXPORT_SYMBOL_GPL(hypercall_page); | 86 | EXPORT_SYMBOL_GPL(hypercall_page); |
| 87 | 87 | ||
| 88 | /* | ||
| 89 | * Pointer to the xen_vcpu_info structure or | ||
| 90 | * &HYPERVISOR_shared_info->vcpu_info[cpu]. See xen_hvm_init_shared_info | ||
| 91 | * and xen_vcpu_setup for details. By default it points to share_info->vcpu_info | ||
| 92 | * but if the hypervisor supports VCPUOP_register_vcpu_info then it can point | ||
| 93 | * to xen_vcpu_info. The pointer is used in __xen_evtchn_do_upcall to | ||
| 94 | * acknowledge pending events. | ||
| 95 | * Also more subtly it is used by the patched version of irq enable/disable | ||
| 96 | * e.g. xen_irq_enable_direct and xen_iret in PV mode. | ||
| 97 | * | ||
| 98 | * The desire to be able to do those mask/unmask operations as a single | ||
| 99 | * instruction by using the per-cpu offset held in %gs is the real reason | ||
| 100 | * vcpu info is in a per-cpu pointer and the original reason for this | ||
| 101 | * hypercall. | ||
| 102 | * | ||
| 103 | */ | ||
| 88 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); | 104 | DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu); |
| 105 | |||
| 106 | /* | ||
| 107 | * Per CPU pages used if hypervisor supports VCPUOP_register_vcpu_info | ||
| 108 | * hypercall. This can be used both in PV and PVHVM mode. The structure | ||
| 109 | * overrides the default per_cpu(xen_vcpu, cpu) value. | ||
| 110 | */ | ||
| 89 | DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); | 111 | DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info); |
| 90 | 112 | ||
| 91 | enum xen_domain_type xen_domain_type = XEN_NATIVE; | 113 | enum xen_domain_type xen_domain_type = XEN_NATIVE; |
| @@ -157,6 +179,21 @@ static void xen_vcpu_setup(int cpu) | |||
| 157 | 179 | ||
| 158 | BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); | 180 | BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); |
| 159 | 181 | ||
| 182 | /* | ||
| 183 | * This path is called twice on PVHVM - first during bootup via | ||
| 184 | * smp_init -> xen_hvm_cpu_notify, and then if the VCPU is being | ||
| 185 | * hotplugged: cpu_up -> xen_hvm_cpu_notify. | ||
| 186 | * As we can only do the VCPUOP_register_vcpu_info once lets | ||
| 187 | * not over-write its result. | ||
| 188 | * | ||
| 189 | * For PV it is called during restore (xen_vcpu_restore) and bootup | ||
| 190 | * (xen_setup_vcpu_info_placement). The hotplug mechanism does not | ||
| 191 | * use this function. | ||
| 192 | */ | ||
| 193 | if (xen_hvm_domain()) { | ||
| 194 | if (per_cpu(xen_vcpu, cpu) == &per_cpu(xen_vcpu_info, cpu)) | ||
| 195 | return; | ||
| 196 | } | ||
| 160 | if (cpu < MAX_VIRT_CPUS) | 197 | if (cpu < MAX_VIRT_CPUS) |
| 161 | per_cpu(xen_vcpu,cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; | 198 | per_cpu(xen_vcpu,cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; |
| 162 | 199 | ||
| @@ -172,7 +209,12 @@ static void xen_vcpu_setup(int cpu) | |||
| 172 | 209 | ||
| 173 | /* Check to see if the hypervisor will put the vcpu_info | 210 | /* Check to see if the hypervisor will put the vcpu_info |
| 174 | structure where we want it, which allows direct access via | 211 | structure where we want it, which allows direct access via |
| 175 | a percpu-variable. */ | 212 | a percpu-variable. |
| 213 | N.B. This hypercall can _only_ be called once per CPU. Subsequent | ||
| 214 | calls will error out with -EINVAL. This is due to the fact that | ||
| 215 | hypervisor has no unregister variant and this hypercall does not | ||
| 216 | allow to over-write info.mfn and info.offset. | ||
| 217 | */ | ||
| 176 | err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info); | 218 | err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, cpu, &info); |
| 177 | 219 | ||
| 178 | if (err) { | 220 | if (err) { |
| @@ -387,6 +429,9 @@ static void __init xen_init_cpuid_mask(void) | |||
| 387 | cpuid_leaf1_edx_mask &= | 429 | cpuid_leaf1_edx_mask &= |
| 388 | ~((1 << X86_FEATURE_APIC) | /* disable local APIC */ | 430 | ~((1 << X86_FEATURE_APIC) | /* disable local APIC */ |
| 389 | (1 << X86_FEATURE_ACPI)); /* disable ACPI */ | 431 | (1 << X86_FEATURE_ACPI)); /* disable ACPI */ |
| 432 | |||
| 433 | cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_X2APIC % 32)); | ||
| 434 | |||
| 390 | ax = 1; | 435 | ax = 1; |
| 391 | cx = 0; | 436 | cx = 0; |
| 392 | xen_cpuid(&ax, &bx, &cx, &dx); | 437 | xen_cpuid(&ax, &bx, &cx, &dx); |
| @@ -1603,6 +1648,9 @@ void __ref xen_hvm_init_shared_info(void) | |||
| 1603 | * online but xen_hvm_init_shared_info is run at resume time too and | 1648 | * online but xen_hvm_init_shared_info is run at resume time too and |
| 1604 | * in that case multiple vcpus might be online. */ | 1649 | * in that case multiple vcpus might be online. */ |
| 1605 | for_each_online_cpu(cpu) { | 1650 | for_each_online_cpu(cpu) { |
| 1651 | /* Leave it to be NULL. */ | ||
| 1652 | if (cpu >= MAX_VIRT_CPUS) | ||
| 1653 | continue; | ||
| 1606 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; | 1654 | per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; |
| 1607 | } | 1655 | } |
| 1608 | } | 1656 | } |
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 8b54603ce816..3002ec1bb71a 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c | |||
| @@ -364,7 +364,7 @@ void __cpuinit xen_init_lock_cpu(int cpu) | |||
| 364 | int irq; | 364 | int irq; |
| 365 | const char *name; | 365 | const char *name; |
| 366 | 366 | ||
| 367 | WARN(per_cpu(lock_kicker_irq, cpu) > 0, "spinlock on CPU%d exists on IRQ%d!\n", | 367 | WARN(per_cpu(lock_kicker_irq, cpu) >= 0, "spinlock on CPU%d exists on IRQ%d!\n", |
| 368 | cpu, per_cpu(lock_kicker_irq, cpu)); | 368 | cpu, per_cpu(lock_kicker_irq, cpu)); |
| 369 | 369 | ||
| 370 | /* | 370 | /* |
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3a8f7e6db295..e7e92429d10f 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
| @@ -78,6 +78,10 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev) | |||
| 78 | { | 78 | { |
| 79 | struct drm_crtc *crtc; | 79 | struct drm_crtc *crtc; |
| 80 | 80 | ||
| 81 | /* Locking is currently fubar in the panic handler. */ | ||
| 82 | if (oops_in_progress) | ||
| 83 | return; | ||
| 84 | |||
| 81 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | 85 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
| 82 | WARN_ON(!mutex_is_locked(&crtc->mutex)); | 86 | WARN_ON(!mutex_is_locked(&crtc->mutex)); |
| 83 | 87 | ||
| @@ -246,6 +250,7 @@ char *drm_get_connector_status_name(enum drm_connector_status status) | |||
| 246 | else | 250 | else |
| 247 | return "unknown"; | 251 | return "unknown"; |
| 248 | } | 252 | } |
| 253 | EXPORT_SYMBOL(drm_get_connector_status_name); | ||
| 249 | 254 | ||
| 250 | /** | 255 | /** |
| 251 | * drm_mode_object_get - allocate a new modeset identifier | 256 | * drm_mode_object_get - allocate a new modeset identifier |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index e974f9309b72..ed1334e27c33 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -121,6 +121,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | |||
| 121 | connector->helper_private; | 121 | connector->helper_private; |
| 122 | int count = 0; | 122 | int count = 0; |
| 123 | int mode_flags = 0; | 123 | int mode_flags = 0; |
| 124 | bool verbose_prune = true; | ||
| 124 | 125 | ||
| 125 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, | 126 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, |
| 126 | drm_get_connector_name(connector)); | 127 | drm_get_connector_name(connector)); |
| @@ -149,6 +150,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | |||
| 149 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", | 150 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", |
| 150 | connector->base.id, drm_get_connector_name(connector)); | 151 | connector->base.id, drm_get_connector_name(connector)); |
| 151 | drm_mode_connector_update_edid_property(connector, NULL); | 152 | drm_mode_connector_update_edid_property(connector, NULL); |
| 153 | verbose_prune = false; | ||
| 152 | goto prune; | 154 | goto prune; |
| 153 | } | 155 | } |
| 154 | 156 | ||
| @@ -182,7 +184,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, | |||
| 182 | } | 184 | } |
| 183 | 185 | ||
| 184 | prune: | 186 | prune: |
| 185 | drm_mode_prune_invalid(dev, &connector->modes, true); | 187 | drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); |
| 186 | 188 | ||
| 187 | if (list_empty(&connector->modes)) | 189 | if (list_empty(&connector->modes)) |
| 188 | return 0; | 190 | return 0; |
| @@ -1005,12 +1007,20 @@ static void output_poll_execute(struct work_struct *work) | |||
| 1005 | continue; | 1007 | continue; |
| 1006 | 1008 | ||
| 1007 | connector->status = connector->funcs->detect(connector, false); | 1009 | connector->status = connector->funcs->detect(connector, false); |
| 1008 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", | 1010 | if (old_status != connector->status) { |
| 1009 | connector->base.id, | 1011 | const char *old, *new; |
| 1010 | drm_get_connector_name(connector), | 1012 | |
| 1011 | old_status, connector->status); | 1013 | old = drm_get_connector_status_name(old_status); |
| 1012 | if (old_status != connector->status) | 1014 | new = drm_get_connector_status_name(connector->status); |
| 1015 | |||
| 1016 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] " | ||
| 1017 | "status updated from %s to %s\n", | ||
| 1018 | connector->base.id, | ||
| 1019 | drm_get_connector_name(connector), | ||
| 1020 | old, new); | ||
| 1021 | |||
| 1013 | changed = true; | 1022 | changed = true; |
| 1023 | } | ||
| 1014 | } | 1024 | } |
| 1015 | 1025 | ||
| 1016 | mutex_unlock(&dev->mode_config.mutex); | 1026 | mutex_unlock(&dev->mode_config.mutex); |
| @@ -1083,10 +1093,11 @@ void drm_helper_hpd_irq_event(struct drm_device *dev) | |||
| 1083 | old_status = connector->status; | 1093 | old_status = connector->status; |
| 1084 | 1094 | ||
| 1085 | connector->status = connector->funcs->detect(connector, false); | 1095 | connector->status = connector->funcs->detect(connector, false); |
| 1086 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", | 1096 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", |
| 1087 | connector->base.id, | 1097 | connector->base.id, |
| 1088 | drm_get_connector_name(connector), | 1098 | drm_get_connector_name(connector), |
| 1089 | old_status, connector->status); | 1099 | drm_get_connector_status_name(old_status), |
| 1100 | drm_get_connector_status_name(connector->status)); | ||
| 1090 | if (old_status != connector->status) | 1101 | if (old_status != connector->status) |
| 1091 | changed = true; | 1102 | changed = true; |
| 1092 | } | 1103 | } |
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 8d4f29075af5..9cc247f55502 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
| @@ -57,7 +57,7 @@ static int drm_version(struct drm_device *dev, void *data, | |||
| 57 | struct drm_file *file_priv); | 57 | struct drm_file *file_priv); |
| 58 | 58 | ||
| 59 | #define DRM_IOCTL_DEF(ioctl, _func, _flags) \ | 59 | #define DRM_IOCTL_DEF(ioctl, _func, _flags) \ |
| 60 | [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0} | 60 | [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl} |
| 61 | 61 | ||
| 62 | /** Ioctl table */ | 62 | /** Ioctl table */ |
| 63 | static const struct drm_ioctl_desc drm_ioctls[] = { | 63 | static const struct drm_ioctl_desc drm_ioctls[] = { |
| @@ -375,7 +375,7 @@ long drm_ioctl(struct file *filp, | |||
| 375 | { | 375 | { |
| 376 | struct drm_file *file_priv = filp->private_data; | 376 | struct drm_file *file_priv = filp->private_data; |
| 377 | struct drm_device *dev; | 377 | struct drm_device *dev; |
| 378 | const struct drm_ioctl_desc *ioctl; | 378 | const struct drm_ioctl_desc *ioctl = NULL; |
| 379 | drm_ioctl_t *func; | 379 | drm_ioctl_t *func; |
| 380 | unsigned int nr = DRM_IOCTL_NR(cmd); | 380 | unsigned int nr = DRM_IOCTL_NR(cmd); |
| 381 | int retcode = -EINVAL; | 381 | int retcode = -EINVAL; |
| @@ -392,11 +392,6 @@ long drm_ioctl(struct file *filp, | |||
| 392 | atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); | 392 | atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); |
| 393 | ++file_priv->ioctl_count; | 393 | ++file_priv->ioctl_count; |
| 394 | 394 | ||
| 395 | DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", | ||
| 396 | task_pid_nr(current), cmd, nr, | ||
| 397 | (long)old_encode_dev(file_priv->minor->device), | ||
| 398 | file_priv->authenticated); | ||
| 399 | |||
| 400 | if ((nr >= DRM_CORE_IOCTL_COUNT) && | 395 | if ((nr >= DRM_CORE_IOCTL_COUNT) && |
| 401 | ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) | 396 | ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) |
| 402 | goto err_i1; | 397 | goto err_i1; |
| @@ -417,6 +412,11 @@ long drm_ioctl(struct file *filp, | |||
| 417 | } else | 412 | } else |
| 418 | goto err_i1; | 413 | goto err_i1; |
| 419 | 414 | ||
| 415 | DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", | ||
| 416 | task_pid_nr(current), | ||
| 417 | (long)old_encode_dev(file_priv->minor->device), | ||
| 418 | file_priv->authenticated, ioctl->name); | ||
| 419 | |||
| 420 | /* Do not trust userspace, use our own definition */ | 420 | /* Do not trust userspace, use our own definition */ |
| 421 | func = ioctl->func; | 421 | func = ioctl->func; |
| 422 | /* is there a local override? */ | 422 | /* is there a local override? */ |
| @@ -471,6 +471,12 @@ long drm_ioctl(struct file *filp, | |||
| 471 | } | 471 | } |
| 472 | 472 | ||
| 473 | err_i1: | 473 | err_i1: |
| 474 | if (!ioctl) | ||
| 475 | DRM_DEBUG("invalid iotcl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n", | ||
| 476 | task_pid_nr(current), | ||
| 477 | (long)old_encode_dev(file_priv->minor->device), | ||
| 478 | file_priv->authenticated, cmd, nr); | ||
| 479 | |||
| 474 | if (kdata != stack_kdata) | 480 | if (kdata != stack_kdata) |
| 475 | kfree(kdata); | 481 | kfree(kdata); |
| 476 | atomic_dec(&dev->ioctl_count); | 482 | atomic_dec(&dev->ioctl_count); |
diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c index 48c52f7df4e6..0cfb60f54766 100644 --- a/drivers/gpu/drm/drm_encoder_slave.c +++ b/drivers/gpu/drm/drm_encoder_slave.c | |||
| @@ -54,16 +54,12 @@ int drm_i2c_encoder_init(struct drm_device *dev, | |||
| 54 | struct i2c_adapter *adap, | 54 | struct i2c_adapter *adap, |
| 55 | const struct i2c_board_info *info) | 55 | const struct i2c_board_info *info) |
| 56 | { | 56 | { |
| 57 | char modalias[sizeof(I2C_MODULE_PREFIX) | ||
| 58 | + I2C_NAME_SIZE]; | ||
| 59 | struct module *module = NULL; | 57 | struct module *module = NULL; |
| 60 | struct i2c_client *client; | 58 | struct i2c_client *client; |
| 61 | struct drm_i2c_encoder_driver *encoder_drv; | 59 | struct drm_i2c_encoder_driver *encoder_drv; |
| 62 | int err = 0; | 60 | int err = 0; |
| 63 | 61 | ||
| 64 | snprintf(modalias, sizeof(modalias), | 62 | request_module("%s%s", I2C_MODULE_PREFIX, info->type); |
| 65 | "%s%s", I2C_MODULE_PREFIX, info->type); | ||
| 66 | request_module(modalias); | ||
| 67 | 63 | ||
| 68 | client = i2c_new_device(adap, info); | 64 | client = i2c_new_device(adap, info); |
| 69 | if (!client) { | 65 | if (!client) { |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index db1e2d6f90d7..07cf99cc8862 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
| @@ -755,33 +755,35 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) | |||
| 755 | EXPORT_SYMBOL(drm_mm_debug_table); | 755 | EXPORT_SYMBOL(drm_mm_debug_table); |
| 756 | 756 | ||
| 757 | #if defined(CONFIG_DEBUG_FS) | 757 | #if defined(CONFIG_DEBUG_FS) |
| 758 | int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) | 758 | static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry) |
| 759 | { | 759 | { |
| 760 | struct drm_mm_node *entry; | ||
| 761 | unsigned long total_used = 0, total_free = 0, total = 0; | ||
| 762 | unsigned long hole_start, hole_end, hole_size; | 760 | unsigned long hole_start, hole_end, hole_size; |
| 763 | 761 | ||
| 764 | hole_start = drm_mm_hole_node_start(&mm->head_node); | 762 | if (entry->hole_follows) { |
| 765 | hole_end = drm_mm_hole_node_end(&mm->head_node); | 763 | hole_start = drm_mm_hole_node_start(entry); |
| 766 | hole_size = hole_end - hole_start; | 764 | hole_end = drm_mm_hole_node_end(entry); |
| 767 | if (hole_size) | 765 | hole_size = hole_end - hole_start; |
| 768 | seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", | 766 | seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", |
| 769 | hole_start, hole_end, hole_size); | 767 | hole_start, hole_end, hole_size); |
| 770 | total_free += hole_size; | 768 | return hole_size; |
| 769 | } | ||
| 770 | |||
| 771 | return 0; | ||
| 772 | } | ||
| 773 | |||
| 774 | int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) | ||
| 775 | { | ||
| 776 | struct drm_mm_node *entry; | ||
| 777 | unsigned long total_used = 0, total_free = 0, total = 0; | ||
| 778 | |||
| 779 | total_free += drm_mm_dump_hole(m, &mm->head_node); | ||
| 771 | 780 | ||
| 772 | drm_mm_for_each_node(entry, mm) { | 781 | drm_mm_for_each_node(entry, mm) { |
| 773 | seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n", | 782 | seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n", |
| 774 | entry->start, entry->start + entry->size, | 783 | entry->start, entry->start + entry->size, |
| 775 | entry->size); | 784 | entry->size); |
| 776 | total_used += entry->size; | 785 | total_used += entry->size; |
| 777 | if (entry->hole_follows) { | 786 | total_free += drm_mm_dump_hole(m, entry); |
| 778 | hole_start = drm_mm_hole_node_start(entry); | ||
| 779 | hole_end = drm_mm_hole_node_end(entry); | ||
| 780 | hole_size = hole_end - hole_start; | ||
| 781 | seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", | ||
| 782 | hole_start, hole_end, hole_size); | ||
| 783 | total_free += hole_size; | ||
| 784 | } | ||
| 785 | } | 787 | } |
| 786 | total = total_free + total_used; | 788 | total = total_free + total_used; |
| 787 | 789 | ||
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index faa79df02648..a371ff865a88 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
| @@ -1143,6 +1143,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option, | |||
| 1143 | was_digit = false; | 1143 | was_digit = false; |
| 1144 | } else | 1144 | } else |
| 1145 | goto done; | 1145 | goto done; |
| 1146 | break; | ||
| 1146 | case '0' ... '9': | 1147 | case '0' ... '9': |
| 1147 | was_digit = true; | 1148 | was_digit = true; |
| 1148 | break; | 1149 | break; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6be940effefd..6165535d15f0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -1045,6 +1045,8 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, | |||
| 1045 | if (timeout) { | 1045 | if (timeout) { |
| 1046 | struct timespec sleep_time = timespec_sub(now, before); | 1046 | struct timespec sleep_time = timespec_sub(now, before); |
| 1047 | *timeout = timespec_sub(*timeout, sleep_time); | 1047 | *timeout = timespec_sub(*timeout, sleep_time); |
| 1048 | if (!timespec_valid(timeout)) /* i.e. negative time remains */ | ||
| 1049 | set_normalized_timespec(timeout, 0, 0); | ||
| 1048 | } | 1050 | } |
| 1049 | 1051 | ||
| 1050 | switch (end) { | 1052 | switch (end) { |
| @@ -1053,8 +1055,6 @@ static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, | |||
| 1053 | case -ERESTARTSYS: /* Signal */ | 1055 | case -ERESTARTSYS: /* Signal */ |
| 1054 | return (int)end; | 1056 | return (int)end; |
| 1055 | case 0: /* Timeout */ | 1057 | case 0: /* Timeout */ |
| 1056 | if (timeout) | ||
| 1057 | set_normalized_timespec(timeout, 0, 0); | ||
| 1058 | return -ETIME; | 1058 | return -ETIME; |
| 1059 | default: /* Completed */ | 1059 | default: /* Completed */ |
| 1060 | WARN_ON(end < 0); /* We're not aware of other errors */ | 1060 | WARN_ON(end < 0); /* We're not aware of other errors */ |
| @@ -2377,10 +2377,8 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file) | |||
| 2377 | mutex_unlock(&dev->struct_mutex); | 2377 | mutex_unlock(&dev->struct_mutex); |
| 2378 | 2378 | ||
| 2379 | ret = __wait_seqno(ring, seqno, reset_counter, true, timeout); | 2379 | ret = __wait_seqno(ring, seqno, reset_counter, true, timeout); |
| 2380 | if (timeout) { | 2380 | if (timeout) |
| 2381 | WARN_ON(!timespec_valid(timeout)); | ||
| 2382 | args->timeout_ns = timespec_to_ns(timeout); | 2381 | args->timeout_ns = timespec_to_ns(timeout); |
| 2383 | } | ||
| 2384 | return ret; | 2382 | return ret; |
| 2385 | 2383 | ||
| 2386 | out: | 2384 | out: |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index dca614de71b6..bdb0d7717bc7 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
| @@ -709,15 +709,6 @@ static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl) | |||
| 709 | return snb_gmch_ctl << 25; /* 32 MB units */ | 709 | return snb_gmch_ctl << 25; /* 32 MB units */ |
| 710 | } | 710 | } |
| 711 | 711 | ||
| 712 | static inline size_t gen7_get_stolen_size(u16 snb_gmch_ctl) | ||
| 713 | { | ||
| 714 | static const int stolen_decoder[] = { | ||
| 715 | 0, 0, 0, 0, 0, 32, 48, 64, 128, 256, 96, 160, 224, 352}; | ||
| 716 | snb_gmch_ctl >>= IVB_GMCH_GMS_SHIFT; | ||
| 717 | snb_gmch_ctl &= IVB_GMCH_GMS_MASK; | ||
| 718 | return stolen_decoder[snb_gmch_ctl] << 20; | ||
| 719 | } | ||
| 720 | |||
| 721 | static int gen6_gmch_probe(struct drm_device *dev, | 712 | static int gen6_gmch_probe(struct drm_device *dev, |
| 722 | size_t *gtt_total, | 713 | size_t *gtt_total, |
| 723 | size_t *stolen, | 714 | size_t *stolen, |
| @@ -747,11 +738,7 @@ static int gen6_gmch_probe(struct drm_device *dev, | |||
| 747 | pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); | 738 | pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); |
| 748 | gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); | 739 | gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl); |
| 749 | 740 | ||
| 750 | if (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) | 741 | *stolen = gen6_get_stolen_size(snb_gmch_ctl); |
| 751 | *stolen = gen7_get_stolen_size(snb_gmch_ctl); | ||
| 752 | else | ||
| 753 | *stolen = gen6_get_stolen_size(snb_gmch_ctl); | ||
| 754 | |||
| 755 | *gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT; | 742 | *gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT; |
| 756 | 743 | ||
| 757 | /* For Modern GENs the PTEs and register space are split in the BAR */ | 744 | /* For Modern GENs the PTEs and register space are split in the BAR */ |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 83f9c26e1adb..2d6b62e42daf 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -46,8 +46,6 @@ | |||
| 46 | #define SNB_GMCH_GGMS_MASK 0x3 | 46 | #define SNB_GMCH_GGMS_MASK 0x3 |
| 47 | #define SNB_GMCH_GMS_SHIFT 3 /* Graphics Mode Select */ | 47 | #define SNB_GMCH_GMS_SHIFT 3 /* Graphics Mode Select */ |
| 48 | #define SNB_GMCH_GMS_MASK 0x1f | 48 | #define SNB_GMCH_GMS_MASK 0x1f |
| 49 | #define IVB_GMCH_GMS_SHIFT 4 | ||
| 50 | #define IVB_GMCH_GMS_MASK 0xf | ||
| 51 | 49 | ||
| 52 | 50 | ||
| 53 | /* PCI config space */ | 51 | /* PCI config space */ |
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 26a0a570f92e..fb961bb81903 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
| @@ -1265,6 +1265,8 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder) | |||
| 1265 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); | 1265 | intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); |
| 1266 | intel_dp_start_link_train(intel_dp); | 1266 | intel_dp_start_link_train(intel_dp); |
| 1267 | intel_dp_complete_link_train(intel_dp); | 1267 | intel_dp_complete_link_train(intel_dp); |
| 1268 | if (port != PORT_A) | ||
| 1269 | intel_dp_stop_link_train(intel_dp); | ||
| 1268 | } | 1270 | } |
| 1269 | } | 1271 | } |
| 1270 | 1272 | ||
| @@ -1326,6 +1328,9 @@ static void intel_enable_ddi(struct intel_encoder *intel_encoder) | |||
| 1326 | } else if (type == INTEL_OUTPUT_EDP) { | 1328 | } else if (type == INTEL_OUTPUT_EDP) { |
| 1327 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 1329 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); |
| 1328 | 1330 | ||
| 1331 | if (port == PORT_A) | ||
| 1332 | intel_dp_stop_link_train(intel_dp); | ||
| 1333 | |||
| 1329 | ironlake_edp_backlight_on(intel_dp); | 1334 | ironlake_edp_backlight_on(intel_dp); |
| 1330 | } | 1335 | } |
| 1331 | 1336 | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index fb2fbc1e08b9..3d704b706a8d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -702,6 +702,9 @@ intel_dp_compute_config(struct intel_encoder *encoder, | |||
| 702 | /* Walk through all bpp values. Luckily they're all nicely spaced with 2 | 702 | /* Walk through all bpp values. Luckily they're all nicely spaced with 2 |
| 703 | * bpc in between. */ | 703 | * bpc in between. */ |
| 704 | bpp = min_t(int, 8*3, pipe_config->pipe_bpp); | 704 | bpp = min_t(int, 8*3, pipe_config->pipe_bpp); |
| 705 | if (is_edp(intel_dp) && dev_priv->edp.bpp) | ||
| 706 | bpp = min_t(int, bpp, dev_priv->edp.bpp); | ||
| 707 | |||
| 705 | for (; bpp >= 6*3; bpp -= 2*3) { | 708 | for (; bpp >= 6*3; bpp -= 2*3) { |
| 706 | mode_rate = intel_dp_link_required(target_clock, bpp); | 709 | mode_rate = intel_dp_link_required(target_clock, bpp); |
| 707 | 710 | ||
| @@ -739,6 +742,7 @@ found: | |||
| 739 | intel_dp->link_bw = bws[clock]; | 742 | intel_dp->link_bw = bws[clock]; |
| 740 | intel_dp->lane_count = lane_count; | 743 | intel_dp->lane_count = lane_count; |
| 741 | adjusted_mode->clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw); | 744 | adjusted_mode->clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw); |
| 745 | pipe_config->pipe_bpp = bpp; | ||
| 742 | pipe_config->pixel_target_clock = target_clock; | 746 | pipe_config->pixel_target_clock = target_clock; |
| 743 | 747 | ||
| 744 | DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n", | 748 | DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n", |
| @@ -751,20 +755,6 @@ found: | |||
| 751 | target_clock, adjusted_mode->clock, | 755 | target_clock, adjusted_mode->clock, |
| 752 | &pipe_config->dp_m_n); | 756 | &pipe_config->dp_m_n); |
| 753 | 757 | ||
| 754 | /* | ||
| 755 | * XXX: We have a strange regression where using the vbt edp bpp value | ||
| 756 | * for the link bw computation results in black screens, the panel only | ||
| 757 | * works when we do the computation at the usual 24bpp (but still | ||
| 758 | * requires us to use 18bpp). Until that's fully debugged, stay | ||
| 759 | * bug-for-bug compatible with the old code. | ||
| 760 | */ | ||
| 761 | if (is_edp(intel_dp) && dev_priv->edp.bpp) { | ||
| 762 | DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", | ||
| 763 | bpp, dev_priv->edp.bpp); | ||
| 764 | bpp = min_t(int, bpp, dev_priv->edp.bpp); | ||
| 765 | } | ||
| 766 | pipe_config->pipe_bpp = bpp; | ||
| 767 | |||
| 768 | return true; | 758 | return true; |
| 769 | } | 759 | } |
| 770 | 760 | ||
| @@ -1389,6 +1379,7 @@ static void intel_enable_dp(struct intel_encoder *encoder) | |||
| 1389 | ironlake_edp_panel_on(intel_dp); | 1379 | ironlake_edp_panel_on(intel_dp); |
| 1390 | ironlake_edp_panel_vdd_off(intel_dp, true); | 1380 | ironlake_edp_panel_vdd_off(intel_dp, true); |
| 1391 | intel_dp_complete_link_train(intel_dp); | 1381 | intel_dp_complete_link_train(intel_dp); |
| 1382 | intel_dp_stop_link_train(intel_dp); | ||
| 1392 | ironlake_edp_backlight_on(intel_dp); | 1383 | ironlake_edp_backlight_on(intel_dp); |
| 1393 | } | 1384 | } |
| 1394 | 1385 | ||
| @@ -1711,10 +1702,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
| 1711 | struct drm_i915_private *dev_priv = dev->dev_private; | 1702 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1712 | enum port port = intel_dig_port->port; | 1703 | enum port port = intel_dig_port->port; |
| 1713 | int ret; | 1704 | int ret; |
| 1714 | uint32_t temp; | ||
| 1715 | 1705 | ||
| 1716 | if (HAS_DDI(dev)) { | 1706 | if (HAS_DDI(dev)) { |
| 1717 | temp = I915_READ(DP_TP_CTL(port)); | 1707 | uint32_t temp = I915_READ(DP_TP_CTL(port)); |
| 1718 | 1708 | ||
| 1719 | if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) | 1709 | if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) |
| 1720 | temp |= DP_TP_CTL_SCRAMBLE_DISABLE; | 1710 | temp |= DP_TP_CTL_SCRAMBLE_DISABLE; |
| @@ -1724,18 +1714,6 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
| 1724 | temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; | 1714 | temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; |
| 1725 | switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { | 1715 | switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
| 1726 | case DP_TRAINING_PATTERN_DISABLE: | 1716 | case DP_TRAINING_PATTERN_DISABLE: |
| 1727 | |||
| 1728 | if (port != PORT_A) { | ||
| 1729 | temp |= DP_TP_CTL_LINK_TRAIN_IDLE; | ||
| 1730 | I915_WRITE(DP_TP_CTL(port), temp); | ||
| 1731 | |||
| 1732 | if (wait_for((I915_READ(DP_TP_STATUS(port)) & | ||
| 1733 | DP_TP_STATUS_IDLE_DONE), 1)) | ||
| 1734 | DRM_ERROR("Timed out waiting for DP idle patterns\n"); | ||
| 1735 | |||
| 1736 | temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; | 1717 | temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; |
| 1740 | 1718 | ||
| 1741 | break; | 1719 | break; |
| @@ -1811,6 +1789,37 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
| 1811 | return true; | 1789 | return true; |
| 1812 | } | 1790 | } |
| 1813 | 1791 | ||
| 1792 | static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) | ||
| 1793 | { | ||
| 1794 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | ||
| 1795 | struct drm_device *dev = intel_dig_port->base.base.dev; | ||
| 1796 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1797 | enum port port = intel_dig_port->port; | ||
| 1798 | uint32_t val; | ||
| 1799 | |||
| 1800 | if (!HAS_DDI(dev)) | ||
| 1801 | return; | ||
| 1802 | |||
| 1803 | val = I915_READ(DP_TP_CTL(port)); | ||
| 1804 | val &= ~DP_TP_CTL_LINK_TRAIN_MASK; | ||
| 1805 | val |= DP_TP_CTL_LINK_TRAIN_IDLE; | ||
| 1806 | I915_WRITE(DP_TP_CTL(port), val); | ||
| 1807 | |||
| 1808 | /* | ||
| 1809 | * On PORT_A we can have only eDP in SST mode. There the only reason | ||
| 1810 | * we need to set idle transmission mode is to work around a HW issue | ||
| 1811 | * where we enable the pipe while not in idle link-training mode. | ||
| 1812 | * In this case there is requirement to wait for a minimum number of | ||
| 1813 | * idle patterns to be sent. | ||
| 1814 | */ | ||
| 1815 | if (port == PORT_A) | ||
| 1816 | return; | ||
| 1817 | |||
| 1818 | if (wait_for((I915_READ(DP_TP_STATUS(port)) & DP_TP_STATUS_IDLE_DONE), | ||
| 1819 | 1)) | ||
| 1820 | DRM_ERROR("Timed out waiting for DP idle patterns\n"); | ||
| 1821 | } | ||
| 1822 | |||
| 1814 | /* Enable corresponding port and start training pattern 1 */ | 1823 | /* Enable corresponding port and start training pattern 1 */ |
| 1815 | void | 1824 | void |
| 1816 | intel_dp_start_link_train(struct intel_dp *intel_dp) | 1825 | intel_dp_start_link_train(struct intel_dp *intel_dp) |
| @@ -1953,10 +1962,19 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) | |||
| 1953 | ++tries; | 1962 | ++tries; |
| 1954 | } | 1963 | } |
| 1955 | 1964 | ||
| 1965 | intel_dp_set_idle_link_train(intel_dp); | ||
| 1966 | |||
| 1967 | intel_dp->DP = DP; | ||
| 1968 | |||
| 1956 | if (channel_eq) | 1969 | if (channel_eq) |
| 1957 | DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n"); | 1970 | DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n"); |
| 1958 | 1971 | ||
| 1959 | intel_dp_set_link_train(intel_dp, DP, DP_TRAINING_PATTERN_DISABLE); | 1972 | } |
| 1973 | |||
| 1974 | void intel_dp_stop_link_train(struct intel_dp *intel_dp) | ||
| 1975 | { | ||
| 1976 | intel_dp_set_link_train(intel_dp, intel_dp->DP, | ||
| 1977 | DP_TRAINING_PATTERN_DISABLE); | ||
| 1960 | } | 1978 | } |
| 1961 | 1979 | ||
| 1962 | static void | 1980 | static void |
| @@ -2164,6 +2182,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) | |||
| 2164 | drm_get_encoder_name(&intel_encoder->base)); | 2182 | drm_get_encoder_name(&intel_encoder->base)); |
| 2165 | intel_dp_start_link_train(intel_dp); | 2183 | intel_dp_start_link_train(intel_dp); |
| 2166 | intel_dp_complete_link_train(intel_dp); | 2184 | intel_dp_complete_link_train(intel_dp); |
| 2185 | intel_dp_stop_link_train(intel_dp); | ||
| 2167 | } | 2186 | } |
| 2168 | } | 2187 | } |
| 2169 | 2188 | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index b5b6d19e6dd3..624a9e6b8d71 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -499,6 +499,7 @@ extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 499 | extern void intel_dp_init_link_config(struct intel_dp *intel_dp); | 499 | extern void intel_dp_init_link_config(struct intel_dp *intel_dp); |
| 500 | extern void intel_dp_start_link_train(struct intel_dp *intel_dp); | 500 | extern void intel_dp_start_link_train(struct intel_dp *intel_dp); |
| 501 | extern void intel_dp_complete_link_train(struct intel_dp *intel_dp); | 501 | extern void intel_dp_complete_link_train(struct intel_dp *intel_dp); |
| 502 | extern void intel_dp_stop_link_train(struct intel_dp *intel_dp); | ||
| 502 | extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); | 503 | extern void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); |
| 503 | extern void intel_dp_encoder_destroy(struct drm_encoder *encoder); | 504 | extern void intel_dp_encoder_destroy(struct drm_encoder *encoder); |
| 504 | extern void intel_dp_check_link_status(struct intel_dp *intel_dp); | 505 | extern void intel_dp_check_link_status(struct intel_dp *intel_dp); |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 0e19e575a1b4..6b7c3ca2c035 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
| @@ -262,10 +262,22 @@ void intel_fbdev_fini(struct drm_device *dev) | |||
| 262 | void intel_fbdev_set_suspend(struct drm_device *dev, int state) | 262 | void intel_fbdev_set_suspend(struct drm_device *dev, int state) |
| 263 | { | 263 | { |
| 264 | drm_i915_private_t *dev_priv = dev->dev_private; | 264 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 265 | if (!dev_priv->fbdev) | 265 | struct intel_fbdev *ifbdev = dev_priv->fbdev; |
| 266 | struct fb_info *info; | ||
| 267 | |||
| 268 | if (!ifbdev) | ||
| 266 | return; | 269 | return; |
| 267 | 270 | ||
| 268 | fb_set_suspend(dev_priv->fbdev->helper.fbdev, state); | 271 | info = ifbdev->helper.fbdev; |
| 272 | |||
| 273 | /* On resume from hibernation: If the object is shmemfs backed, it has | ||
| 274 | * been restored from swap. If the object is stolen however, it will be | ||
| 275 | * full of whatever garbage was left in there. | ||
| 276 | */ | ||
| 277 | if (!state && ifbdev->ifb.obj->stolen) | ||
| 278 | memset_io(info->screen_base, 0, info->screen_size); | ||
| 279 | |||
| 280 | fb_set_suspend(info, state); | ||
| 269 | } | 281 | } |
| 270 | 282 | ||
| 271 | MODULE_LICENSE("GPL and additional rights"); | 283 | MODULE_LICENSE("GPL and additional rights"); |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index de3b0dc5658b..aa01128ff192 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -1301,17 +1301,17 @@ static void valleyview_update_wm(struct drm_device *dev) | |||
| 1301 | 1301 | ||
| 1302 | vlv_update_drain_latency(dev); | 1302 | vlv_update_drain_latency(dev); |
| 1303 | 1303 | ||
| 1304 | if (g4x_compute_wm0(dev, 0, | 1304 | if (g4x_compute_wm0(dev, PIPE_A, |
| 1305 | &valleyview_wm_info, latency_ns, | 1305 | &valleyview_wm_info, latency_ns, |
| 1306 | &valleyview_cursor_wm_info, latency_ns, | 1306 | &valleyview_cursor_wm_info, latency_ns, |
| 1307 | &planea_wm, &cursora_wm)) | 1307 | &planea_wm, &cursora_wm)) |
| 1308 | enabled |= 1; | 1308 | enabled |= 1 << PIPE_A; |
| 1309 | 1309 | ||
| 1310 | if (g4x_compute_wm0(dev, 1, | 1310 | if (g4x_compute_wm0(dev, PIPE_B, |
| 1311 | &valleyview_wm_info, latency_ns, | 1311 | &valleyview_wm_info, latency_ns, |
| 1312 | &valleyview_cursor_wm_info, latency_ns, | 1312 | &valleyview_cursor_wm_info, latency_ns, |
| 1313 | &planeb_wm, &cursorb_wm)) | 1313 | &planeb_wm, &cursorb_wm)) |
| 1314 | enabled |= 2; | 1314 | enabled |= 1 << PIPE_B; |
| 1315 | 1315 | ||
| 1316 | if (single_plane_enabled(enabled) && | 1316 | if (single_plane_enabled(enabled) && |
| 1317 | g4x_compute_srwm(dev, ffs(enabled) - 1, | 1317 | g4x_compute_srwm(dev, ffs(enabled) - 1, |
| @@ -1357,17 +1357,17 @@ static void g4x_update_wm(struct drm_device *dev) | |||
| 1357 | int plane_sr, cursor_sr; | 1357 | int plane_sr, cursor_sr; |
| 1358 | unsigned int enabled = 0; | 1358 | unsigned int enabled = 0; |
| 1359 | 1359 | ||
| 1360 | if (g4x_compute_wm0(dev, 0, | 1360 | if (g4x_compute_wm0(dev, PIPE_A, |
| 1361 | &g4x_wm_info, latency_ns, | 1361 | &g4x_wm_info, latency_ns, |
| 1362 | &g4x_cursor_wm_info, latency_ns, | 1362 | &g4x_cursor_wm_info, latency_ns, |
| 1363 | &planea_wm, &cursora_wm)) | 1363 | &planea_wm, &cursora_wm)) |
| 1364 | enabled |= 1; | 1364 | enabled |= 1 << PIPE_A; |
| 1365 | 1365 | ||
| 1366 | if (g4x_compute_wm0(dev, 1, | 1366 | if (g4x_compute_wm0(dev, PIPE_B, |
| 1367 | &g4x_wm_info, latency_ns, | 1367 | &g4x_wm_info, latency_ns, |
| 1368 | &g4x_cursor_wm_info, latency_ns, | 1368 | &g4x_cursor_wm_info, latency_ns, |
| 1369 | &planeb_wm, &cursorb_wm)) | 1369 | &planeb_wm, &cursorb_wm)) |
| 1370 | enabled |= 2; | 1370 | enabled |= 1 << PIPE_B; |
| 1371 | 1371 | ||
| 1372 | if (single_plane_enabled(enabled) && | 1372 | if (single_plane_enabled(enabled) && |
| 1373 | g4x_compute_srwm(dev, ffs(enabled) - 1, | 1373 | g4x_compute_srwm(dev, ffs(enabled) - 1, |
| @@ -1716,7 +1716,7 @@ static void ironlake_update_wm(struct drm_device *dev) | |||
| 1716 | unsigned int enabled; | 1716 | unsigned int enabled; |
| 1717 | 1717 | ||
| 1718 | enabled = 0; | 1718 | enabled = 0; |
| 1719 | if (g4x_compute_wm0(dev, 0, | 1719 | if (g4x_compute_wm0(dev, PIPE_A, |
| 1720 | &ironlake_display_wm_info, | 1720 | &ironlake_display_wm_info, |
| 1721 | ILK_LP0_PLANE_LATENCY, | 1721 | ILK_LP0_PLANE_LATENCY, |
| 1722 | &ironlake_cursor_wm_info, | 1722 | &ironlake_cursor_wm_info, |
| @@ -1727,10 +1727,10 @@ static void ironlake_update_wm(struct drm_device *dev) | |||
| 1727 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" | 1727 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" |
| 1728 | " plane %d, " "cursor: %d\n", | 1728 | " plane %d, " "cursor: %d\n", |
| 1729 | plane_wm, cursor_wm); | 1729 | plane_wm, cursor_wm); |
| 1730 | enabled |= 1; | 1730 | enabled |= 1 << PIPE_A; |
| 1731 | } | 1731 | } |
| 1732 | 1732 | ||
| 1733 | if (g4x_compute_wm0(dev, 1, | 1733 | if (g4x_compute_wm0(dev, PIPE_B, |
| 1734 | &ironlake_display_wm_info, | 1734 | &ironlake_display_wm_info, |
| 1735 | ILK_LP0_PLANE_LATENCY, | 1735 | ILK_LP0_PLANE_LATENCY, |
| 1736 | &ironlake_cursor_wm_info, | 1736 | &ironlake_cursor_wm_info, |
| @@ -1741,7 +1741,7 @@ static void ironlake_update_wm(struct drm_device *dev) | |||
| 1741 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" | 1741 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" |
| 1742 | " plane %d, cursor: %d\n", | 1742 | " plane %d, cursor: %d\n", |
| 1743 | plane_wm, cursor_wm); | 1743 | plane_wm, cursor_wm); |
| 1744 | enabled |= 2; | 1744 | enabled |= 1 << PIPE_B; |
| 1745 | } | 1745 | } |
| 1746 | 1746 | ||
| 1747 | /* | 1747 | /* |
| @@ -1801,7 +1801,7 @@ static void sandybridge_update_wm(struct drm_device *dev) | |||
| 1801 | unsigned int enabled; | 1801 | unsigned int enabled; |
| 1802 | 1802 | ||
| 1803 | enabled = 0; | 1803 | enabled = 0; |
| 1804 | if (g4x_compute_wm0(dev, 0, | 1804 | if (g4x_compute_wm0(dev, PIPE_A, |
| 1805 | &sandybridge_display_wm_info, latency, | 1805 | &sandybridge_display_wm_info, latency, |
| 1806 | &sandybridge_cursor_wm_info, latency, | 1806 | &sandybridge_cursor_wm_info, latency, |
| 1807 | &plane_wm, &cursor_wm)) { | 1807 | &plane_wm, &cursor_wm)) { |
| @@ -1812,10 +1812,10 @@ static void sandybridge_update_wm(struct drm_device *dev) | |||
| 1812 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" | 1812 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" |
| 1813 | " plane %d, " "cursor: %d\n", | 1813 | " plane %d, " "cursor: %d\n", |
| 1814 | plane_wm, cursor_wm); | 1814 | plane_wm, cursor_wm); |
| 1815 | enabled |= 1; | 1815 | enabled |= 1 << PIPE_A; |
| 1816 | } | 1816 | } |
| 1817 | 1817 | ||
| 1818 | if (g4x_compute_wm0(dev, 1, | 1818 | if (g4x_compute_wm0(dev, PIPE_B, |
| 1819 | &sandybridge_display_wm_info, latency, | 1819 | &sandybridge_display_wm_info, latency, |
| 1820 | &sandybridge_cursor_wm_info, latency, | 1820 | &sandybridge_cursor_wm_info, latency, |
| 1821 | &plane_wm, &cursor_wm)) { | 1821 | &plane_wm, &cursor_wm)) { |
| @@ -1826,7 +1826,7 @@ static void sandybridge_update_wm(struct drm_device *dev) | |||
| 1826 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" | 1826 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" |
| 1827 | " plane %d, cursor: %d\n", | 1827 | " plane %d, cursor: %d\n", |
| 1828 | plane_wm, cursor_wm); | 1828 | plane_wm, cursor_wm); |
| 1829 | enabled |= 2; | 1829 | enabled |= 1 << PIPE_B; |
| 1830 | } | 1830 | } |
| 1831 | 1831 | ||
| 1832 | /* | 1832 | /* |
| @@ -1904,7 +1904,7 @@ static void ivybridge_update_wm(struct drm_device *dev) | |||
| 1904 | unsigned int enabled; | 1904 | unsigned int enabled; |
| 1905 | 1905 | ||
| 1906 | enabled = 0; | 1906 | enabled = 0; |
| 1907 | if (g4x_compute_wm0(dev, 0, | 1907 | if (g4x_compute_wm0(dev, PIPE_A, |
| 1908 | &sandybridge_display_wm_info, latency, | 1908 | &sandybridge_display_wm_info, latency, |
| 1909 | &sandybridge_cursor_wm_info, latency, | 1909 | &sandybridge_cursor_wm_info, latency, |
| 1910 | &plane_wm, &cursor_wm)) { | 1910 | &plane_wm, &cursor_wm)) { |
| @@ -1915,10 +1915,10 @@ static void ivybridge_update_wm(struct drm_device *dev) | |||
| 1915 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" | 1915 | DRM_DEBUG_KMS("FIFO watermarks For pipe A -" |
| 1916 | " plane %d, " "cursor: %d\n", | 1916 | " plane %d, " "cursor: %d\n", |
| 1917 | plane_wm, cursor_wm); | 1917 | plane_wm, cursor_wm); |
| 1918 | enabled |= 1; | 1918 | enabled |= 1 << PIPE_A; |
| 1919 | } | 1919 | } |
| 1920 | 1920 | ||
| 1921 | if (g4x_compute_wm0(dev, 1, | 1921 | if (g4x_compute_wm0(dev, PIPE_B, |
| 1922 | &sandybridge_display_wm_info, latency, | 1922 | &sandybridge_display_wm_info, latency, |
| 1923 | &sandybridge_cursor_wm_info, latency, | 1923 | &sandybridge_cursor_wm_info, latency, |
| 1924 | &plane_wm, &cursor_wm)) { | 1924 | &plane_wm, &cursor_wm)) { |
| @@ -1929,10 +1929,10 @@ static void ivybridge_update_wm(struct drm_device *dev) | |||
| 1929 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" | 1929 | DRM_DEBUG_KMS("FIFO watermarks For pipe B -" |
| 1930 | " plane %d, cursor: %d\n", | 1930 | " plane %d, cursor: %d\n", |
| 1931 | plane_wm, cursor_wm); | 1931 | plane_wm, cursor_wm); |
| 1932 | enabled |= 2; | 1932 | enabled |= 1 << PIPE_B; |
| 1933 | } | 1933 | } |
| 1934 | 1934 | ||
| 1935 | if (g4x_compute_wm0(dev, 2, | 1935 | if (g4x_compute_wm0(dev, PIPE_C, |
| 1936 | &sandybridge_display_wm_info, latency, | 1936 | &sandybridge_display_wm_info, latency, |
| 1937 | &sandybridge_cursor_wm_info, latency, | 1937 | &sandybridge_cursor_wm_info, latency, |
| 1938 | &plane_wm, &cursor_wm)) { | 1938 | &plane_wm, &cursor_wm)) { |
| @@ -1943,7 +1943,7 @@ static void ivybridge_update_wm(struct drm_device *dev) | |||
| 1943 | DRM_DEBUG_KMS("FIFO watermarks For pipe C -" | 1943 | DRM_DEBUG_KMS("FIFO watermarks For pipe C -" |
| 1944 | " plane %d, cursor: %d\n", | 1944 | " plane %d, cursor: %d\n", |
| 1945 | plane_wm, cursor_wm); | 1945 | plane_wm, cursor_wm); |
| 1946 | enabled |= 3; | 1946 | enabled |= 1 << PIPE_C; |
| 1947 | } | 1947 | } |
| 1948 | 1948 | ||
| 1949 | /* | 1949 | /* |
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index f9889658329b..77b8a45fb10a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c | |||
| @@ -46,29 +46,26 @@ static void mga_crtc_load_lut(struct drm_crtc *crtc) | |||
| 46 | 46 | ||
| 47 | static inline void mga_wait_vsync(struct mga_device *mdev) | 47 | static inline void mga_wait_vsync(struct mga_device *mdev) |
| 48 | { | 48 | { |
| 49 | unsigned int count = 0; | 49 | unsigned long timeout = jiffies + HZ/10; |
| 50 | unsigned int status = 0; | 50 | unsigned int status = 0; |
| 51 | 51 | ||
| 52 | do { | 52 | do { |
| 53 | status = RREG32(MGAREG_Status); | 53 | status = RREG32(MGAREG_Status); |
| 54 | count++; | 54 | } while ((status & 0x08) && time_before(jiffies, timeout)); |
| 55 | } while ((status & 0x08) && (count < 250000)); | 55 | timeout = jiffies + HZ/10; |
| 56 | count = 0; | ||
| 57 | status = 0; | 56 | status = 0; |
| 58 | do { | 57 | do { |
| 59 | status = RREG32(MGAREG_Status); | 58 | status = RREG32(MGAREG_Status); |
| 60 | count++; | 59 | } while (!(status & 0x08) && time_before(jiffies, timeout)); |
| 61 | } while (!(status & 0x08) && (count < 250000)); | ||
| 62 | } | 60 | } |
| 63 | 61 | ||
| 64 | static inline void mga_wait_busy(struct mga_device *mdev) | 62 | static inline void mga_wait_busy(struct mga_device *mdev) |
| 65 | { | 63 | { |
| 66 | unsigned int count = 0; | 64 | unsigned long timeout = jiffies + HZ; |
| 67 | unsigned int status = 0; | 65 | unsigned int status = 0; |
| 68 | do { | 66 | do { |
| 69 | status = RREG8(MGAREG_Status + 2); | 67 | status = RREG8(MGAREG_Status + 2); |
| 70 | count++; | 68 | } while ((status & 0x01) && time_before(jiffies, timeout)); |
| 71 | } while ((status & 0x01) && (count < 500000)); | ||
| 72 | } | 69 | } |
| 73 | 70 | ||
| 74 | /* | 71 | /* |
| @@ -189,12 +186,12 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) | |||
| 189 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 186 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 190 | tmp = RREG8(DAC_DATA); | 187 | tmp = RREG8(DAC_DATA); |
| 191 | tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; | 188 | tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; |
| 192 | WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); | 189 | WREG8(DAC_DATA, tmp); |
| 193 | 190 | ||
| 194 | WREG8(DAC_INDEX, MGA1064_REMHEADCTL); | 191 | WREG8(DAC_INDEX, MGA1064_REMHEADCTL); |
| 195 | tmp = RREG8(DAC_DATA); | 192 | tmp = RREG8(DAC_DATA); |
| 196 | tmp |= MGA1064_REMHEADCTL_CLKDIS; | 193 | tmp |= MGA1064_REMHEADCTL_CLKDIS; |
| 197 | WREG_DAC(MGA1064_REMHEADCTL, tmp); | 194 | WREG8(DAC_DATA, tmp); |
| 198 | 195 | ||
| 199 | /* select PLL Set C */ | 196 | /* select PLL Set C */ |
| 200 | tmp = RREG8(MGAREG_MEM_MISC_READ); | 197 | tmp = RREG8(MGAREG_MEM_MISC_READ); |
| @@ -204,7 +201,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) | |||
| 204 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 201 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 205 | tmp = RREG8(DAC_DATA); | 202 | tmp = RREG8(DAC_DATA); |
| 206 | tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; | 203 | tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80; |
| 207 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 204 | WREG8(DAC_DATA, tmp); |
| 208 | 205 | ||
| 209 | udelay(500); | 206 | udelay(500); |
| 210 | 207 | ||
| @@ -212,7 +209,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) | |||
| 212 | WREG8(DAC_INDEX, MGA1064_VREF_CTL); | 209 | WREG8(DAC_INDEX, MGA1064_VREF_CTL); |
| 213 | tmp = RREG8(DAC_DATA); | 210 | tmp = RREG8(DAC_DATA); |
| 214 | tmp &= ~0x04; | 211 | tmp &= ~0x04; |
| 215 | WREG_DAC(MGA1064_VREF_CTL, tmp); | 212 | WREG8(DAC_DATA, tmp); |
| 216 | 213 | ||
| 217 | udelay(50); | 214 | udelay(50); |
| 218 | 215 | ||
| @@ -236,13 +233,13 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) | |||
| 236 | tmp = RREG8(DAC_DATA); | 233 | tmp = RREG8(DAC_DATA); |
| 237 | tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; | 234 | tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; |
| 238 | tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; | 235 | tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; |
| 239 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 236 | WREG8(DAC_DATA, tmp); |
| 240 | 237 | ||
| 241 | WREG8(DAC_INDEX, MGA1064_REMHEADCTL); | 238 | WREG8(DAC_INDEX, MGA1064_REMHEADCTL); |
| 242 | tmp = RREG8(DAC_DATA); | 239 | tmp = RREG8(DAC_DATA); |
| 243 | tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK; | 240 | tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK; |
| 244 | tmp |= MGA1064_REMHEADCTL_CLKSL_PLL; | 241 | tmp |= MGA1064_REMHEADCTL_CLKSL_PLL; |
| 245 | WREG_DAC(MGA1064_REMHEADCTL, tmp); | 242 | WREG8(DAC_DATA, tmp); |
| 246 | 243 | ||
| 247 | /* reset dotclock rate bit */ | 244 | /* reset dotclock rate bit */ |
| 248 | WREG8(MGAREG_SEQ_INDEX, 1); | 245 | WREG8(MGAREG_SEQ_INDEX, 1); |
| @@ -253,7 +250,7 @@ static int mga_g200wb_set_plls(struct mga_device *mdev, long clock) | |||
| 253 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 250 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 254 | tmp = RREG8(DAC_DATA); | 251 | tmp = RREG8(DAC_DATA); |
| 255 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; | 252 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; |
| 256 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 253 | WREG8(DAC_DATA, tmp); |
| 257 | 254 | ||
| 258 | vcount = RREG8(MGAREG_VCOUNT); | 255 | vcount = RREG8(MGAREG_VCOUNT); |
| 259 | 256 | ||
| @@ -318,7 +315,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) | |||
| 318 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 315 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 319 | tmp = RREG8(DAC_DATA); | 316 | tmp = RREG8(DAC_DATA); |
| 320 | tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; | 317 | tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; |
| 321 | WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); | 318 | WREG8(DAC_DATA, tmp); |
| 322 | 319 | ||
| 323 | tmp = RREG8(MGAREG_MEM_MISC_READ); | 320 | tmp = RREG8(MGAREG_MEM_MISC_READ); |
| 324 | tmp |= 0x3 << 2; | 321 | tmp |= 0x3 << 2; |
| @@ -326,12 +323,12 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) | |||
| 326 | 323 | ||
| 327 | WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); | 324 | WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); |
| 328 | tmp = RREG8(DAC_DATA); | 325 | tmp = RREG8(DAC_DATA); |
| 329 | WREG_DAC(MGA1064_PIX_PLL_STAT, tmp & ~0x40); | 326 | WREG8(DAC_DATA, tmp & ~0x40); |
| 330 | 327 | ||
| 331 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 328 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 332 | tmp = RREG8(DAC_DATA); | 329 | tmp = RREG8(DAC_DATA); |
| 333 | tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; | 330 | tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; |
| 334 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 331 | WREG8(DAC_DATA, tmp); |
| 335 | 332 | ||
| 336 | WREG_DAC(MGA1064_EV_PIX_PLLC_M, m); | 333 | WREG_DAC(MGA1064_EV_PIX_PLLC_M, m); |
| 337 | WREG_DAC(MGA1064_EV_PIX_PLLC_N, n); | 334 | WREG_DAC(MGA1064_EV_PIX_PLLC_N, n); |
| @@ -342,7 +339,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) | |||
| 342 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 339 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 343 | tmp = RREG8(DAC_DATA); | 340 | tmp = RREG8(DAC_DATA); |
| 344 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; | 341 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; |
| 345 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 342 | WREG8(DAC_DATA, tmp); |
| 346 | 343 | ||
| 347 | udelay(500); | 344 | udelay(500); |
| 348 | 345 | ||
| @@ -350,11 +347,11 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) | |||
| 350 | tmp = RREG8(DAC_DATA); | 347 | tmp = RREG8(DAC_DATA); |
| 351 | tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; | 348 | tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; |
| 352 | tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; | 349 | tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; |
| 353 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 350 | WREG8(DAC_DATA, tmp); |
| 354 | 351 | ||
| 355 | WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); | 352 | WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT); |
| 356 | tmp = RREG8(DAC_DATA); | 353 | tmp = RREG8(DAC_DATA); |
| 357 | WREG_DAC(MGA1064_PIX_PLL_STAT, tmp | 0x40); | 354 | WREG8(DAC_DATA, tmp | 0x40); |
| 358 | 355 | ||
| 359 | tmp = RREG8(MGAREG_MEM_MISC_READ); | 356 | tmp = RREG8(MGAREG_MEM_MISC_READ); |
| 360 | tmp |= (0x3 << 2); | 357 | tmp |= (0x3 << 2); |
| @@ -363,7 +360,7 @@ static int mga_g200ev_set_plls(struct mga_device *mdev, long clock) | |||
| 363 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 360 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 364 | tmp = RREG8(DAC_DATA); | 361 | tmp = RREG8(DAC_DATA); |
| 365 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; | 362 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; |
| 366 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 363 | WREG8(DAC_DATA, tmp); |
| 367 | 364 | ||
| 368 | return 0; | 365 | return 0; |
| 369 | } | 366 | } |
| @@ -416,7 +413,7 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock) | |||
| 416 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 413 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 417 | tmp = RREG8(DAC_DATA); | 414 | tmp = RREG8(DAC_DATA); |
| 418 | tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; | 415 | tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; |
| 419 | WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); | 416 | WREG8(DAC_DATA, tmp); |
| 420 | 417 | ||
| 421 | tmp = RREG8(MGAREG_MEM_MISC_READ); | 418 | tmp = RREG8(MGAREG_MEM_MISC_READ); |
| 422 | tmp |= 0x3 << 2; | 419 | tmp |= 0x3 << 2; |
| @@ -425,7 +422,7 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock) | |||
| 425 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 422 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 426 | tmp = RREG8(DAC_DATA); | 423 | tmp = RREG8(DAC_DATA); |
| 427 | tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; | 424 | tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; |
| 428 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 425 | WREG8(DAC_DATA, tmp); |
| 429 | 426 | ||
| 430 | udelay(500); | 427 | udelay(500); |
| 431 | 428 | ||
| @@ -439,13 +436,13 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock) | |||
| 439 | tmp = RREG8(DAC_DATA); | 436 | tmp = RREG8(DAC_DATA); |
| 440 | tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; | 437 | tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK; |
| 441 | tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; | 438 | tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL; |
| 442 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 439 | WREG8(DAC_DATA, tmp); |
| 443 | 440 | ||
| 444 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 441 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 445 | tmp = RREG8(DAC_DATA); | 442 | tmp = RREG8(DAC_DATA); |
| 446 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; | 443 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; |
| 447 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; | 444 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; |
| 448 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 445 | WREG8(DAC_DATA, tmp); |
| 449 | 446 | ||
| 450 | vcount = RREG8(MGAREG_VCOUNT); | 447 | vcount = RREG8(MGAREG_VCOUNT); |
| 451 | 448 | ||
| @@ -515,12 +512,12 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock) | |||
| 515 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); | 512 | WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL); |
| 516 | tmp = RREG8(DAC_DATA); | 513 | tmp = RREG8(DAC_DATA); |
| 517 | tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; | 514 | tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS; |
| 518 | WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp); | 515 | WREG8(DAC_DATA, tmp); |
| 519 | 516 | ||
| 520 | WREG8(DAC_INDEX, MGA1064_REMHEADCTL); | 517 | WREG8(DAC_INDEX, MGA1064_REMHEADCTL); |
| 521 | tmp = RREG8(DAC_DATA); | 518 | tmp = RREG8(DAC_DATA); |
| 522 | tmp |= MGA1064_REMHEADCTL_CLKDIS; | 519 | tmp |= MGA1064_REMHEADCTL_CLKDIS; |
| 523 | WREG_DAC(MGA1064_REMHEADCTL, tmp); | 520 | WREG8(DAC_DATA, tmp); |
| 524 | 521 | ||
| 525 | tmp = RREG8(MGAREG_MEM_MISC_READ); | 522 | tmp = RREG8(MGAREG_MEM_MISC_READ); |
| 526 | tmp |= (0x3<<2) | 0xc0; | 523 | tmp |= (0x3<<2) | 0xc0; |
| @@ -530,7 +527,7 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock) | |||
| 530 | tmp = RREG8(DAC_DATA); | 527 | tmp = RREG8(DAC_DATA); |
| 531 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; | 528 | tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS; |
| 532 | tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; | 529 | tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN; |
| 533 | WREG_DAC(MGA1064_PIX_CLK_CTL, tmp); | 530 | WREG8(DAC_DATA, tmp); |
| 534 | 531 | ||
| 535 | udelay(500); | 532 | udelay(500); |
| 536 | 533 | ||
| @@ -657,12 +654,26 @@ static void mga_g200wb_commit(struct drm_crtc *crtc) | |||
| 657 | WREG_DAC(MGA1064_GEN_IO_DATA, tmp); | 654 | WREG_DAC(MGA1064_GEN_IO_DATA, tmp); |
| 658 | } | 655 | } |
| 659 | 656 | ||
| 660 | 657 | /* | |
| 658 | This is how the framebuffer base address is stored in g200 cards: | ||
| 659 | * Assume @offset is the gpu_addr variable of the framebuffer object | ||
| 660 | * Then addr is the number of _pixels_ (not bytes) from the start of | ||
| 661 | VRAM to the first pixel we want to display. (divided by 2 for 32bit | ||
| 662 | framebuffers) | ||
| 663 | * addr is stored in the CRTCEXT0, CRTCC and CRTCD registers | ||
| 664 | addr<20> -> CRTCEXT0<6> | ||
| 665 | addr<19-16> -> CRTCEXT0<3-0> | ||
| 666 | addr<15-8> -> CRTCC<7-0> | ||
| 667 | addr<7-0> -> CRTCD<7-0> | ||
| 668 | CRTCEXT0 has to be programmed last to trigger an update and make the | ||
| 669 | new addr variable take effect. | ||
| 670 | */ | ||
| 661 | void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) | 671 | void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) |
| 662 | { | 672 | { |
| 663 | struct mga_device *mdev = crtc->dev->dev_private; | 673 | struct mga_device *mdev = crtc->dev->dev_private; |
| 664 | u32 addr; | 674 | u32 addr; |
| 665 | int count; | 675 | int count; |
| 676 | u8 crtcext0; | ||
| 666 | 677 | ||
| 667 | while (RREG8(0x1fda) & 0x08); | 678 | while (RREG8(0x1fda) & 0x08); |
| 668 | while (!(RREG8(0x1fda) & 0x08)); | 679 | while (!(RREG8(0x1fda) & 0x08)); |
| @@ -670,10 +681,17 @@ void mga_set_start_address(struct drm_crtc *crtc, unsigned offset) | |||
| 670 | count = RREG8(MGAREG_VCOUNT) + 2; | 681 | count = RREG8(MGAREG_VCOUNT) + 2; |
| 671 | while (RREG8(MGAREG_VCOUNT) < count); | 682 | while (RREG8(MGAREG_VCOUNT) < count); |
| 672 | 683 | ||
| 673 | addr = offset >> 2; | 684 | WREG8(MGAREG_CRTCEXT_INDEX, 0); |
| 685 | crtcext0 = RREG8(MGAREG_CRTCEXT_DATA); | ||
| 686 | crtcext0 &= 0xB0; | ||
| 687 | addr = offset / 8; | ||
| 688 | /* Can't store addresses any higher than that... | ||
| 689 | but we also don't have more than 16MB of memory, so it should be fine. */ | ||
| 690 | WARN_ON(addr > 0x1fffff); | ||
| 691 | crtcext0 |= (!!(addr & (1<<20)))<<6; | ||
| 674 | WREG_CRT(0x0d, (u8)(addr & 0xff)); | 692 | WREG_CRT(0x0d, (u8)(addr & 0xff)); |
| 675 | WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff); | 693 | WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff); |
| 676 | WREG_CRT(0xaf, (u8)(addr >> 16) & 0xf); | 694 | WREG_ECRT(0x0, ((u8)(addr >> 16) & 0xf) | crtcext0); |
| 677 | } | 695 | } |
| 678 | 696 | ||
| 679 | 697 | ||
| @@ -829,11 +847,7 @@ static int mga_crtc_mode_set(struct drm_crtc *crtc, | |||
| 829 | 847 | ||
| 830 | 848 | ||
| 831 | for (i = 0; i < sizeof(dacvalue); i++) { | 849 | for (i = 0; i < sizeof(dacvalue); i++) { |
| 832 | if ((i <= 0x03) || | 850 | if ((i <= 0x17) || |
| 833 | (i == 0x07) || | ||
| 834 | (i == 0x0b) || | ||
| 835 | (i == 0x0f) || | ||
| 836 | ((i >= 0x13) && (i <= 0x17)) || | ||
| 837 | (i == 0x1b) || | 851 | (i == 0x1b) || |
| 838 | (i == 0x1c) || | 852 | (i == 0x1c) || |
| 839 | ((i >= 0x1f) && (i <= 0x29)) || | 853 | ((i >= 0x1f) && (i <= 0x29)) || |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 0e8fab1913df..fa6964d8681a 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
| @@ -273,6 +273,27 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = { | |||
| 273 | .target_residency = 500, | 273 | .target_residency = 500, |
| 274 | .enter = &intel_idle }, | 274 | .enter = &intel_idle }, |
| 275 | { | 275 | { |
| 276 | .name = "C8-HSW", | ||
| 277 | .desc = "MWAIT 0x40", | ||
| 278 | .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
| 279 | .exit_latency = 300, | ||
| 280 | .target_residency = 900, | ||
| 281 | .enter = &intel_idle }, | ||
| 282 | { | ||
| 283 | .name = "C9-HSW", | ||
| 284 | .desc = "MWAIT 0x50", | ||
| 285 | .flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
| 286 | .exit_latency = 600, | ||
| 287 | .target_residency = 1800, | ||
| 288 | .enter = &intel_idle }, | ||
| 289 | { | ||
| 290 | .name = "C10-HSW", | ||
| 291 | .desc = "MWAIT 0x60", | ||
| 292 | .flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, | ||
| 293 | .exit_latency = 2600, | ||
| 294 | .target_residency = 7700, | ||
| 295 | .enter = &intel_idle }, | ||
| 296 | { | ||
| 276 | .enter = NULL } | 297 | .enter = NULL } |
| 277 | }; | 298 | }; |
| 278 | 299 | ||
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 699187ab3800..5b9ac32801c7 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c | |||
| @@ -1002,6 +1002,7 @@ void guest_set_pgd(struct lguest *lg, unsigned long gpgdir, u32 idx) | |||
| 1002 | kill_guest(&lg->cpus[0], | 1002 | kill_guest(&lg->cpus[0], |
| 1003 | "Cannot populate switcher mapping"); | 1003 | "Cannot populate switcher mapping"); |
| 1004 | } | 1004 | } |
| 1005 | lg->pgdirs[pgdir].last_host_cpu = -1; | ||
| 1005 | } | 1006 | } |
| 1006 | } | 1007 | } |
| 1007 | 1008 | ||
diff --git a/drivers/net/caif/Kconfig b/drivers/net/caif/Kconfig index 7ffc756131a2..547098086773 100644 --- a/drivers/net/caif/Kconfig +++ b/drivers/net/caif/Kconfig | |||
| @@ -43,7 +43,7 @@ config CAIF_HSI | |||
| 43 | 43 | ||
| 44 | config CAIF_VIRTIO | 44 | config CAIF_VIRTIO |
| 45 | tristate "CAIF virtio transport driver" | 45 | tristate "CAIF virtio transport driver" |
| 46 | depends on CAIF | 46 | depends on CAIF && HAS_DMA |
| 47 | select VHOST_RING | 47 | select VHOST_RING |
| 48 | select VIRTIO | 48 | select VIRTIO |
| 49 | select GENERIC_ALLOCATOR | 49 | select GENERIC_ALLOCATOR |
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index de570a8f8967..072c6f14e8fc 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c | |||
| @@ -632,7 +632,6 @@ struct vortex_private { | |||
| 632 | pm_state_valid:1, /* pci_dev->saved_config_space has sane contents */ | 632 | pm_state_valid:1, /* pci_dev->saved_config_space has sane contents */ |
| 633 | open:1, | 633 | open:1, |
| 634 | medialock:1, | 634 | medialock:1, |
| 635 | must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ | ||
| 636 | large_frames:1, /* accept large frames */ | 635 | large_frames:1, /* accept large frames */ |
| 637 | handling_irq:1; /* private in_irq indicator */ | 636 | handling_irq:1; /* private in_irq indicator */ |
| 638 | /* {get|set}_wol operations are already serialized by rtnl. | 637 | /* {get|set}_wol operations are already serialized by rtnl. |
| @@ -1012,6 +1011,12 @@ static int vortex_init_one(struct pci_dev *pdev, | |||
| 1012 | if (rc < 0) | 1011 | if (rc < 0) |
| 1013 | goto out; | 1012 | goto out; |
| 1014 | 1013 | ||
| 1014 | rc = pci_request_regions(pdev, DRV_NAME); | ||
| 1015 | if (rc < 0) { | ||
| 1016 | pci_disable_device(pdev); | ||
| 1017 | goto out; | ||
| 1018 | } | ||
| 1019 | |||
| 1015 | unit = vortex_cards_found; | 1020 | unit = vortex_cards_found; |
| 1016 | 1021 | ||
| 1017 | if (global_use_mmio < 0 && (unit >= MAX_UNITS || use_mmio[unit] < 0)) { | 1022 | if (global_use_mmio < 0 && (unit >= MAX_UNITS || use_mmio[unit] < 0)) { |
| @@ -1027,6 +1032,7 @@ static int vortex_init_one(struct pci_dev *pdev, | |||
| 1027 | if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */ | 1032 | if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */ |
| 1028 | ioaddr = pci_iomap(pdev, 0, 0); | 1033 | ioaddr = pci_iomap(pdev, 0, 0); |
| 1029 | if (!ioaddr) { | 1034 | if (!ioaddr) { |
| 1035 | pci_release_regions(pdev); | ||
| 1030 | pci_disable_device(pdev); | 1036 | pci_disable_device(pdev); |
| 1031 | rc = -ENOMEM; | 1037 | rc = -ENOMEM; |
| 1032 | goto out; | 1038 | goto out; |
| @@ -1036,6 +1042,7 @@ static int vortex_init_one(struct pci_dev *pdev, | |||
| 1036 | ent->driver_data, unit); | 1042 | ent->driver_data, unit); |
| 1037 | if (rc < 0) { | 1043 | if (rc < 0) { |
| 1038 | pci_iounmap(pdev, ioaddr); | 1044 | pci_iounmap(pdev, ioaddr); |
| 1045 | pci_release_regions(pdev); | ||
| 1039 | pci_disable_device(pdev); | 1046 | pci_disable_device(pdev); |
| 1040 | goto out; | 1047 | goto out; |
| 1041 | } | 1048 | } |
| @@ -1178,11 +1185,6 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq, | |||
| 1178 | 1185 | ||
| 1179 | /* PCI-only startup logic */ | 1186 | /* PCI-only startup logic */ |
| 1180 | if (pdev) { | 1187 | if (pdev) { |
| 1181 | /* EISA resources already marked, so only PCI needs to do this here */ | ||
| 1182 | /* Ignore return value, because Cardbus drivers already allocate for us */ | ||
| 1183 | if (request_region(dev->base_addr, vci->io_size, print_name) != NULL) | ||
| 1184 | vp->must_free_region = 1; | ||
| 1185 | |||
| 1186 | /* enable bus-mastering if necessary */ | 1188 | /* enable bus-mastering if necessary */ |
| 1187 | if (vci->flags & PCI_USES_MASTER) | 1189 | if (vci->flags & PCI_USES_MASTER) |
| 1188 | pci_set_master(pdev); | 1190 | pci_set_master(pdev); |
| @@ -1220,7 +1222,7 @@ static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq, | |||
| 1220 | &vp->rx_ring_dma); | 1222 | &vp->rx_ring_dma); |
| 1221 | retval = -ENOMEM; | 1223 | retval = -ENOMEM; |
| 1222 | if (!vp->rx_ring) | 1224 | if (!vp->rx_ring) |
| 1223 | goto free_region; | 1225 | goto free_device; |
| 1224 | 1226 | ||
| 1225 | vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE); | 1227 | vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE); |
| 1226 | vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE; | 1228 | vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE; |
| @@ -1484,9 +1486,7 @@ free_ring: | |||
| 1484 | + sizeof(struct boom_tx_desc) * TX_RING_SIZE, | 1486 | + sizeof(struct boom_tx_desc) * TX_RING_SIZE, |
| 1485 | vp->rx_ring, | 1487 | vp->rx_ring, |
| 1486 | vp->rx_ring_dma); | 1488 | vp->rx_ring_dma); |
| 1487 | free_region: | 1489 | free_device: |
| 1488 | if (vp->must_free_region) | ||
| 1489 | release_region(dev->base_addr, vci->io_size); | ||
| 1490 | free_netdev(dev); | 1490 | free_netdev(dev); |
| 1491 | pr_err(PFX "vortex_probe1 fails. Returns %d\n", retval); | 1491 | pr_err(PFX "vortex_probe1 fails. Returns %d\n", retval); |
| 1492 | out: | 1492 | out: |
| @@ -3254,8 +3254,9 @@ static void vortex_remove_one(struct pci_dev *pdev) | |||
| 3254 | + sizeof(struct boom_tx_desc) * TX_RING_SIZE, | 3254 | + sizeof(struct boom_tx_desc) * TX_RING_SIZE, |
| 3255 | vp->rx_ring, | 3255 | vp->rx_ring, |
| 3256 | vp->rx_ring_dma); | 3256 | vp->rx_ring_dma); |
| 3257 | if (vp->must_free_region) | 3257 | |
| 3258 | release_region(dev->base_addr, vp->io_size); | 3258 | pci_release_regions(pdev); |
| 3259 | |||
| 3259 | free_netdev(dev); | 3260 | free_netdev(dev); |
| 3260 | } | 3261 | } |
| 3261 | 3262 | ||
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index ce4a030d3d0c..07f7ef05c3f2 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c | |||
| @@ -3236,9 +3236,10 @@ bnad_init(struct bnad *bnad, | |||
| 3236 | 3236 | ||
| 3237 | sprintf(bnad->wq_name, "%s_wq_%d", BNAD_NAME, bnad->id); | 3237 | sprintf(bnad->wq_name, "%s_wq_%d", BNAD_NAME, bnad->id); |
| 3238 | bnad->work_q = create_singlethread_workqueue(bnad->wq_name); | 3238 | bnad->work_q = create_singlethread_workqueue(bnad->wq_name); |
| 3239 | 3239 | if (!bnad->work_q) { | |
| 3240 | if (!bnad->work_q) | 3240 | iounmap(bnad->bar0); |
| 3241 | return -ENOMEM; | 3241 | return -ENOMEM; |
| 3242 | } | ||
| 3242 | 3243 | ||
| 3243 | return 0; | 3244 | return 0; |
| 3244 | } | 3245 | } |
diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig index 1194446f859a..768285ec10f4 100644 --- a/drivers/net/ethernet/cadence/Kconfig +++ b/drivers/net/ethernet/cadence/Kconfig | |||
| @@ -22,7 +22,7 @@ if NET_CADENCE | |||
| 22 | 22 | ||
| 23 | config ARM_AT91_ETHER | 23 | config ARM_AT91_ETHER |
| 24 | tristate "AT91RM9200 Ethernet support" | 24 | tristate "AT91RM9200 Ethernet support" |
| 25 | depends on GENERIC_HARDIRQS | 25 | depends on GENERIC_HARDIRQS && HAS_DMA |
| 26 | select NET_CORE | 26 | select NET_CORE |
| 27 | select MACB | 27 | select MACB |
| 28 | ---help--- | 28 | ---help--- |
| @@ -31,6 +31,7 @@ config ARM_AT91_ETHER | |||
| 31 | 31 | ||
| 32 | config MACB | 32 | config MACB |
| 33 | tristate "Cadence MACB/GEM support" | 33 | tristate "Cadence MACB/GEM support" |
| 34 | depends on HAS_DMA | ||
| 34 | select PHYLIB | 35 | select PHYLIB |
| 35 | ---help--- | 36 | ---help--- |
| 36 | The Cadence MACB ethernet interface is found on many Atmel AT32 and | 37 | The Cadence MACB ethernet interface is found on many Atmel AT32 and |
diff --git a/drivers/net/ethernet/calxeda/Kconfig b/drivers/net/ethernet/calxeda/Kconfig index aba435c3d4ae..184a063bed5f 100644 --- a/drivers/net/ethernet/calxeda/Kconfig +++ b/drivers/net/ethernet/calxeda/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config NET_CALXEDA_XGMAC | 1 | config NET_CALXEDA_XGMAC |
| 2 | tristate "Calxeda 1G/10G XGMAC Ethernet driver" | 2 | tristate "Calxeda 1G/10G XGMAC Ethernet driver" |
| 3 | depends on HAS_IOMEM | 3 | depends on HAS_IOMEM && HAS_DMA |
| 4 | select CRC32 | 4 | select CRC32 |
| 5 | help | 5 | help |
| 6 | This is the driver for the XGMAC Ethernet IP block found on Calxeda | 6 | This is the driver for the XGMAC Ethernet IP block found on Calxeda |
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index aff0310a778b..ca9825ca88c9 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c | |||
| @@ -87,6 +87,8 @@ | |||
| 87 | #define FEC_QUIRK_HAS_GBIT (1 << 3) | 87 | #define FEC_QUIRK_HAS_GBIT (1 << 3) |
| 88 | /* Controller has extend desc buffer */ | 88 | /* Controller has extend desc buffer */ |
| 89 | #define FEC_QUIRK_HAS_BUFDESC_EX (1 << 4) | 89 | #define FEC_QUIRK_HAS_BUFDESC_EX (1 << 4) |
| 90 | /* Controller has hardware checksum support */ | ||
| 91 | #define FEC_QUIRK_HAS_CSUM (1 << 5) | ||
| 90 | 92 | ||
| 91 | static struct platform_device_id fec_devtype[] = { | 93 | static struct platform_device_id fec_devtype[] = { |
| 92 | { | 94 | { |
| @@ -105,7 +107,7 @@ static struct platform_device_id fec_devtype[] = { | |||
| 105 | }, { | 107 | }, { |
| 106 | .name = "imx6q-fec", | 108 | .name = "imx6q-fec", |
| 107 | .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | | 109 | .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | |
| 108 | FEC_QUIRK_HAS_BUFDESC_EX, | 110 | FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM, |
| 109 | }, { | 111 | }, { |
| 110 | .name = "mvf-fec", | 112 | .name = "mvf-fec", |
| 111 | .driver_data = FEC_QUIRK_ENET_MAC, | 113 | .driver_data = FEC_QUIRK_ENET_MAC, |
| @@ -1744,6 +1746,8 @@ static const struct net_device_ops fec_netdev_ops = { | |||
| 1744 | static int fec_enet_init(struct net_device *ndev) | 1746 | static int fec_enet_init(struct net_device *ndev) |
| 1745 | { | 1747 | { |
| 1746 | struct fec_enet_private *fep = netdev_priv(ndev); | 1748 | struct fec_enet_private *fep = netdev_priv(ndev); |
| 1749 | const struct platform_device_id *id_entry = | ||
| 1750 | platform_get_device_id(fep->pdev); | ||
| 1747 | struct bufdesc *cbd_base; | 1751 | struct bufdesc *cbd_base; |
| 1748 | 1752 | ||
| 1749 | /* Allocate memory for buffer descriptors. */ | 1753 | /* Allocate memory for buffer descriptors. */ |
| @@ -1775,12 +1779,14 @@ static int fec_enet_init(struct net_device *ndev) | |||
| 1775 | writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK); | 1779 | writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK); |
| 1776 | netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT); | 1780 | netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT); |
| 1777 | 1781 | ||
| 1778 | /* enable hw accelerator */ | 1782 | if (id_entry->driver_data & FEC_QUIRK_HAS_CSUM) { |
| 1779 | ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | 1783 | /* enable hw accelerator */ |
| 1780 | | NETIF_F_RXCSUM); | 1784 | ndev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
| 1781 | ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | 1785 | | NETIF_F_RXCSUM); |
| 1782 | | NETIF_F_RXCSUM); | 1786 | ndev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
| 1783 | fep->csum_flags |= FLAG_RX_CSUM_ENABLED; | 1787 | | NETIF_F_RXCSUM); |
| 1788 | fep->csum_flags |= FLAG_RX_CSUM_ENABLED; | ||
| 1789 | } | ||
| 1784 | 1790 | ||
| 1785 | fec_restart(ndev, 0); | 1791 | fec_restart(ndev, 0); |
| 1786 | 1792 | ||
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 4989481c19f0..d300a0c0eafc 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c | |||
| @@ -359,10 +359,26 @@ static int emac_reset(struct emac_instance *dev) | |||
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | #ifdef CONFIG_PPC_DCR_NATIVE | 361 | #ifdef CONFIG_PPC_DCR_NATIVE |
| 362 | /* Enable internal clock source */ | 362 | /* |
| 363 | if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) | 363 | * PPC460EX/GT Embedded Processor Advanced User's Manual |
| 364 | dcri_clrset(SDR0, SDR0_ETH_CFG, | 364 | * section 28.10.1 Mode Register 0 (EMACx_MR0) states: |
| 365 | 0, SDR0_ETH_CFG_ECS << dev->cell_index); | 365 | * Note: The PHY must provide a TX Clk in order to perform a soft reset |
| 366 | * of the EMAC. If none is present, select the internal clock | ||
| 367 | * (SDR0_ETH_CFG[EMACx_PHY_CLK] = 1). | ||
| 368 | * After a soft reset, select the external clock. | ||
| 369 | */ | ||
| 370 | if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) { | ||
| 371 | if (dev->phy_address == 0xffffffff && | ||
| 372 | dev->phy_map == 0xffffffff) { | ||
| 373 | /* No PHY: select internal loop clock before reset */ | ||
| 374 | dcri_clrset(SDR0, SDR0_ETH_CFG, | ||
| 375 | 0, SDR0_ETH_CFG_ECS << dev->cell_index); | ||
| 376 | } else { | ||
| 377 | /* PHY present: select external clock before reset */ | ||
| 378 | dcri_clrset(SDR0, SDR0_ETH_CFG, | ||
| 379 | SDR0_ETH_CFG_ECS << dev->cell_index, 0); | ||
| 380 | } | ||
| 381 | } | ||
| 366 | #endif | 382 | #endif |
| 367 | 383 | ||
| 368 | out_be32(&p->mr0, EMAC_MR0_SRST); | 384 | out_be32(&p->mr0, EMAC_MR0_SRST); |
| @@ -370,10 +386,14 @@ static int emac_reset(struct emac_instance *dev) | |||
| 370 | --n; | 386 | --n; |
| 371 | 387 | ||
| 372 | #ifdef CONFIG_PPC_DCR_NATIVE | 388 | #ifdef CONFIG_PPC_DCR_NATIVE |
| 373 | /* Enable external clock source */ | 389 | if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) { |
| 374 | if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX)) | 390 | if (dev->phy_address == 0xffffffff && |
| 375 | dcri_clrset(SDR0, SDR0_ETH_CFG, | 391 | dev->phy_map == 0xffffffff) { |
| 376 | SDR0_ETH_CFG_ECS << dev->cell_index, 0); | 392 | /* No PHY: restore external clock source after reset */ |
| 393 | dcri_clrset(SDR0, SDR0_ETH_CFG, | ||
| 394 | SDR0_ETH_CFG_ECS << dev->cell_index, 0); | ||
| 395 | } | ||
| 396 | } | ||
| 377 | #endif | 397 | #endif |
| 378 | 398 | ||
| 379 | if (n) { | 399 | if (n) { |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_resources.c b/drivers/net/ethernet/mellanox/mlx4/en_resources.c index 91f2b2c43c12..d3f508697a3d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_resources.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_resources.c | |||
| @@ -60,7 +60,7 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride, | |||
| 60 | context->pri_path.sched_queue = 0x83 | (priv->port - 1) << 6; | 60 | context->pri_path.sched_queue = 0x83 | (priv->port - 1) << 6; |
| 61 | if (user_prio >= 0) { | 61 | if (user_prio >= 0) { |
| 62 | context->pri_path.sched_queue |= user_prio << 3; | 62 | context->pri_path.sched_queue |= user_prio << 3; |
| 63 | context->pri_path.feup = 1 << 6; | 63 | context->pri_path.feup = MLX4_FEUP_FORCE_ETH_UP; |
| 64 | } | 64 | } |
| 65 | context->pri_path.counter_index = 0xff; | 65 | context->pri_path.counter_index = 0xff; |
| 66 | context->cqn_send = cpu_to_be32(cqn); | 66 | context->cqn_send = cpu_to_be32(cqn); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index b147bdd40768..58a8e535d698 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c | |||
| @@ -131,7 +131,9 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) | |||
| 131 | [2] = "RSS XOR Hash Function support", | 131 | [2] = "RSS XOR Hash Function support", |
| 132 | [3] = "Device manage flow steering support", | 132 | [3] = "Device manage flow steering support", |
| 133 | [4] = "Automatic MAC reassignment support", | 133 | [4] = "Automatic MAC reassignment support", |
| 134 | [5] = "Time stamping support" | 134 | [5] = "Time stamping support", |
| 135 | [6] = "VST (control vlan insertion/stripping) support", | ||
| 136 | [7] = "FSM (MAC anti-spoofing) support" | ||
| 135 | }; | 137 | }; |
| 136 | int i; | 138 | int i; |
| 137 | 139 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index e12e0d2e0ee0..1157f028a90f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
| @@ -372,24 +372,29 @@ static int update_vport_qp_param(struct mlx4_dev *dev, | |||
| 372 | if (MLX4_QP_ST_RC == qp_type) | 372 | if (MLX4_QP_ST_RC == qp_type) |
| 373 | return -EINVAL; | 373 | return -EINVAL; |
| 374 | 374 | ||
| 375 | /* force strip vlan by clear vsd */ | ||
| 376 | qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN); | ||
| 377 | if (0 != vp_oper->state.default_vlan) { | ||
| 378 | qpc->pri_path.vlan_control = | ||
| 379 | MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | | ||
| 380 | MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED | | ||
| 381 | MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED; | ||
| 382 | } else { /* priority tagged */ | ||
| 383 | qpc->pri_path.vlan_control = | ||
| 384 | MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED | | ||
| 385 | MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED; | ||
| 386 | } | ||
| 387 | |||
| 388 | qpc->pri_path.fvl_rx |= MLX4_FVL_RX_FORCE_ETH_VLAN; | ||
| 375 | qpc->pri_path.vlan_index = vp_oper->vlan_idx; | 389 | qpc->pri_path.vlan_index = vp_oper->vlan_idx; |
| 376 | qpc->pri_path.fl = (1 << 6) | (1 << 2); /* set cv bit and hide_cqe_vlan bit*/ | 390 | qpc->pri_path.fl |= MLX4_FL_CV | MLX4_FL_ETH_HIDE_CQE_VLAN; |
| 377 | qpc->pri_path.feup |= 1 << 3; /* set fvl bit */ | 391 | qpc->pri_path.feup |= MLX4_FEUP_FORCE_ETH_UP | MLX4_FVL_FORCE_ETH_VLAN; |
| 378 | qpc->pri_path.sched_queue &= 0xC7; | 392 | qpc->pri_path.sched_queue &= 0xC7; |
| 379 | qpc->pri_path.sched_queue |= (vp_oper->state.default_qos) << 3; | 393 | qpc->pri_path.sched_queue |= (vp_oper->state.default_qos) << 3; |
| 380 | mlx4_dbg(dev, "qp %d port %d Q 0x%x set vlan to %d vidx %d feup %x fl %x\n", | ||
| 381 | be32_to_cpu(qpc->local_qpn) & 0xffffff, port, | ||
| 382 | (int)(qpc->pri_path.sched_queue), vp_oper->state.default_vlan, | ||
| 383 | vp_oper->vlan_idx, (int)(qpc->pri_path.feup), | ||
| 384 | (int)(qpc->pri_path.fl)); | ||
| 385 | } | 394 | } |
| 386 | if (vp_oper->state.spoofchk) { | 395 | if (vp_oper->state.spoofchk) { |
| 387 | qpc->pri_path.feup |= 1 << 5; /* set fsm bit */; | 396 | qpc->pri_path.feup |= MLX4_FSM_FORCE_ETH_SRC_MAC; |
| 388 | qpc->pri_path.grh_mylmc = (0x80 & qpc->pri_path.grh_mylmc) + vp_oper->mac_idx; | 397 | qpc->pri_path.grh_mylmc = (0x80 & qpc->pri_path.grh_mylmc) + vp_oper->mac_idx; |
| 389 | mlx4_dbg(dev, "spoof qp %d port %d feup 0x%x, myLmc 0x%x mindx %d\n", | ||
| 390 | be32_to_cpu(qpc->local_qpn) & 0xffffff, port, | ||
| 391 | (int)qpc->pri_path.feup, (int)qpc->pri_path.grh_mylmc, | ||
| 392 | vp_oper->mac_idx); | ||
| 393 | } | 398 | } |
| 394 | return 0; | 399 | return 0; |
| 395 | } | 400 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 90c253b145ef..019c5f78732e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
| @@ -429,6 +429,7 @@ struct qlcnic_hardware_context { | |||
| 429 | 429 | ||
| 430 | u16 port_type; | 430 | u16 port_type; |
| 431 | u16 board_type; | 431 | u16 board_type; |
| 432 | u16 supported_type; | ||
| 432 | 433 | ||
| 433 | u16 link_speed; | 434 | u16 link_speed; |
| 434 | u16 link_duplex; | 435 | u16 link_duplex; |
| @@ -1514,6 +1515,7 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter); | |||
| 1514 | void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); | 1515 | void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); |
| 1515 | void qlcnic_82xx_add_sysfs(struct qlcnic_adapter *adapter); | 1516 | void qlcnic_82xx_add_sysfs(struct qlcnic_adapter *adapter); |
| 1516 | void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter); | 1517 | void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter); |
| 1518 | int qlcnic_82xx_get_settings(struct qlcnic_adapter *, struct ethtool_cmd *); | ||
| 1517 | 1519 | ||
| 1518 | int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); | 1520 | int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); |
| 1519 | int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); | 1521 | int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index ea790a93ee7c..b4ff1e35a11d 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | |||
| @@ -696,15 +696,14 @@ u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter) | |||
| 696 | return 1; | 696 | return 1; |
| 697 | } | 697 | } |
| 698 | 698 | ||
| 699 | u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter) | 699 | u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter, u32 *wait_time) |
| 700 | { | 700 | { |
| 701 | u32 data; | 701 | u32 data; |
| 702 | unsigned long wait_time = 0; | ||
| 703 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 702 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
| 704 | /* wait for mailbox completion */ | 703 | /* wait for mailbox completion */ |
| 705 | do { | 704 | do { |
| 706 | data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL); | 705 | data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL); |
| 707 | if (++wait_time > QLCNIC_MBX_TIMEOUT) { | 706 | if (++(*wait_time) > QLCNIC_MBX_TIMEOUT) { |
| 708 | data = QLCNIC_RCODE_TIMEOUT; | 707 | data = QLCNIC_RCODE_TIMEOUT; |
| 709 | break; | 708 | break; |
| 710 | } | 709 | } |
| @@ -720,8 +719,8 @@ int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter, | |||
| 720 | u16 opcode; | 719 | u16 opcode; |
| 721 | u8 mbx_err_code; | 720 | u8 mbx_err_code; |
| 722 | unsigned long flags; | 721 | unsigned long flags; |
| 723 | u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd; | ||
| 724 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 722 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
| 723 | u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, wait_time = 0; | ||
| 725 | 724 | ||
| 726 | opcode = LSW(cmd->req.arg[0]); | 725 | opcode = LSW(cmd->req.arg[0]); |
| 727 | if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) { | 726 | if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) { |
| @@ -754,15 +753,13 @@ int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter, | |||
| 754 | /* Signal FW about the impending command */ | 753 | /* Signal FW about the impending command */ |
| 755 | QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER); | 754 | QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER); |
| 756 | poll: | 755 | poll: |
| 757 | rsp = qlcnic_83xx_mbx_poll(adapter); | 756 | rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time); |
| 758 | if (rsp != QLCNIC_RCODE_TIMEOUT) { | 757 | if (rsp != QLCNIC_RCODE_TIMEOUT) { |
| 759 | /* Get the FW response data */ | 758 | /* Get the FW response data */ |
| 760 | fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); | 759 | fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); |
| 761 | if (fw_data & QLCNIC_MBX_ASYNC_EVENT) { | 760 | if (fw_data & QLCNIC_MBX_ASYNC_EVENT) { |
| 762 | __qlcnic_83xx_process_aen(adapter); | 761 | __qlcnic_83xx_process_aen(adapter); |
| 763 | mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | 762 | goto poll; |
| 764 | if (mbx_val) | ||
| 765 | goto poll; | ||
| 766 | } | 763 | } |
| 767 | mbx_err_code = QLCNIC_MBX_STATUS(fw_data); | 764 | mbx_err_code = QLCNIC_MBX_STATUS(fw_data); |
| 768 | rsp_num = QLCNIC_MBX_NUM_REGS(fw_data); | 765 | rsp_num = QLCNIC_MBX_NUM_REGS(fw_data); |
| @@ -1276,11 +1273,13 @@ out: | |||
| 1276 | return err; | 1273 | return err; |
| 1277 | } | 1274 | } |
| 1278 | 1275 | ||
| 1279 | static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test) | 1276 | static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test, |
| 1277 | int num_sds_ring) | ||
| 1280 | { | 1278 | { |
| 1281 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 1279 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
| 1282 | struct qlcnic_host_sds_ring *sds_ring; | 1280 | struct qlcnic_host_sds_ring *sds_ring; |
| 1283 | struct qlcnic_host_rds_ring *rds_ring; | 1281 | struct qlcnic_host_rds_ring *rds_ring; |
| 1282 | u16 adapter_state = adapter->is_up; | ||
| 1284 | u8 ring; | 1283 | u8 ring; |
| 1285 | int ret; | 1284 | int ret; |
| 1286 | 1285 | ||
| @@ -1304,6 +1303,10 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test) | |||
| 1304 | ret = qlcnic_fw_create_ctx(adapter); | 1303 | ret = qlcnic_fw_create_ctx(adapter); |
| 1305 | if (ret) { | 1304 | if (ret) { |
| 1306 | qlcnic_detach(adapter); | 1305 | qlcnic_detach(adapter); |
| 1306 | if (adapter_state == QLCNIC_ADAPTER_UP_MAGIC) { | ||
| 1307 | adapter->max_sds_rings = num_sds_ring; | ||
| 1308 | qlcnic_attach(adapter); | ||
| 1309 | } | ||
| 1307 | netif_device_attach(netdev); | 1310 | netif_device_attach(netdev); |
| 1308 | return ret; | 1311 | return ret; |
| 1309 | } | 1312 | } |
| @@ -1596,7 +1599,8 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) | |||
| 1596 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | 1599 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) |
| 1597 | return -EBUSY; | 1600 | return -EBUSY; |
| 1598 | 1601 | ||
| 1599 | ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST); | 1602 | ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST, |
| 1603 | max_sds_rings); | ||
| 1600 | if (ret) | 1604 | if (ret) |
| 1601 | goto fail_diag_alloc; | 1605 | goto fail_diag_alloc; |
| 1602 | 1606 | ||
| @@ -2830,6 +2834,23 @@ int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter) | |||
| 2830 | break; | 2834 | break; |
| 2831 | } | 2835 | } |
| 2832 | config = cmd.rsp.arg[3]; | 2836 | config = cmd.rsp.arg[3]; |
| 2837 | if (QLC_83XX_SFP_PRESENT(config)) { | ||
| 2838 | switch (ahw->module_type) { | ||
| 2839 | case LINKEVENT_MODULE_OPTICAL_UNKNOWN: | ||
| 2840 | case LINKEVENT_MODULE_OPTICAL_SRLR: | ||
| 2841 | case LINKEVENT_MODULE_OPTICAL_LRM: | ||
| 2842 | case LINKEVENT_MODULE_OPTICAL_SFP_1G: | ||
| 2843 | ahw->supported_type = PORT_FIBRE; | ||
| 2844 | break; | ||
| 2845 | case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE: | ||
| 2846 | case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN: | ||
| 2847 | case LINKEVENT_MODULE_TWINAX: | ||
| 2848 | ahw->supported_type = PORT_TP; | ||
| 2849 | break; | ||
| 2850 | default: | ||
| 2851 | ahw->supported_type = PORT_OTHER; | ||
| 2852 | } | ||
| 2853 | } | ||
| 2833 | if (config & 1) | 2854 | if (config & 1) |
| 2834 | err = 1; | 2855 | err = 1; |
| 2835 | } | 2856 | } |
| @@ -2838,7 +2859,8 @@ out: | |||
| 2838 | return config; | 2859 | return config; |
| 2839 | } | 2860 | } |
| 2840 | 2861 | ||
| 2841 | int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter) | 2862 | int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter, |
| 2863 | struct ethtool_cmd *ecmd) | ||
| 2842 | { | 2864 | { |
| 2843 | u32 config = 0; | 2865 | u32 config = 0; |
| 2844 | int status = 0; | 2866 | int status = 0; |
| @@ -2851,6 +2873,54 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter) | |||
| 2851 | ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config); | 2873 | ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config); |
| 2852 | /* hard code until there is a way to get it from flash */ | 2874 | /* hard code until there is a way to get it from flash */ |
| 2853 | ahw->board_type = QLCNIC_BRDTYPE_83XX_10G; | 2875 | ahw->board_type = QLCNIC_BRDTYPE_83XX_10G; |
| 2876 | |||
| 2877 | if (netif_running(adapter->netdev) && ahw->has_link_events) { | ||
| 2878 | ethtool_cmd_speed_set(ecmd, ahw->link_speed); | ||
| 2879 | ecmd->duplex = ahw->link_duplex; | ||
| 2880 | ecmd->autoneg = ahw->link_autoneg; | ||
| 2881 | } else { | ||
| 2882 | ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); | ||
| 2883 | ecmd->duplex = DUPLEX_UNKNOWN; | ||
| 2884 | ecmd->autoneg = AUTONEG_DISABLE; | ||
| 2885 | } | ||
| 2886 | |||
| 2887 | if (ahw->port_type == QLCNIC_XGBE) { | ||
| 2888 | ecmd->supported = SUPPORTED_1000baseT_Full; | ||
| 2889 | ecmd->advertising = ADVERTISED_1000baseT_Full; | ||
| 2890 | } else { | ||
| 2891 | ecmd->supported = (SUPPORTED_10baseT_Half | | ||
| 2892 | SUPPORTED_10baseT_Full | | ||
| 2893 | SUPPORTED_100baseT_Half | | ||
| 2894 | SUPPORTED_100baseT_Full | | ||
| 2895 | SUPPORTED_1000baseT_Half | | ||
| 2896 | SUPPORTED_1000baseT_Full); | ||
| 2897 | ecmd->advertising = (ADVERTISED_100baseT_Half | | ||
| 2898 | ADVERTISED_100baseT_Full | | ||
| 2899 | ADVERTISED_1000baseT_Half | | ||
| 2900 | ADVERTISED_1000baseT_Full); | ||
| 2901 | } | ||
| 2902 | |||
| 2903 | switch (ahw->supported_type) { | ||
| 2904 | case PORT_FIBRE: | ||
| 2905 | ecmd->supported |= SUPPORTED_FIBRE; | ||
| 2906 | ecmd->advertising |= ADVERTISED_FIBRE; | ||
| 2907 | ecmd->port = PORT_FIBRE; | ||
| 2908 | ecmd->transceiver = XCVR_EXTERNAL; | ||
| 2909 | break; | ||
| 2910 | case PORT_TP: | ||
| 2911 | ecmd->supported |= SUPPORTED_TP; | ||
| 2912 | ecmd->advertising |= ADVERTISED_TP; | ||
| 2913 | ecmd->port = PORT_TP; | ||
| 2914 | ecmd->transceiver = XCVR_INTERNAL; | ||
| 2915 | break; | ||
| 2916 | default: | ||
| 2917 | ecmd->supported |= SUPPORTED_FIBRE; | ||
| 2918 | ecmd->advertising |= ADVERTISED_FIBRE; | ||
| 2919 | ecmd->port = PORT_OTHER; | ||
| 2920 | ecmd->transceiver = XCVR_EXTERNAL; | ||
| 2921 | break; | ||
| 2922 | } | ||
| 2923 | ecmd->phy_address = ahw->physical_port; | ||
| 2854 | return status; | 2924 | return status; |
| 2855 | } | 2925 | } |
| 2856 | 2926 | ||
| @@ -3046,7 +3116,8 @@ int qlcnic_83xx_interrupt_test(struct net_device *netdev) | |||
| 3046 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | 3116 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) |
| 3047 | return -EIO; | 3117 | return -EIO; |
| 3048 | 3118 | ||
| 3049 | ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST); | 3119 | ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST, |
| 3120 | max_sds_rings); | ||
| 3050 | if (ret) | 3121 | if (ret) |
| 3051 | goto fail_diag_irq; | 3122 | goto fail_diag_irq; |
| 3052 | 3123 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index 1f1d85e6f2af..f5db67fc9f55 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | |||
| @@ -603,7 +603,7 @@ int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *); | |||
| 603 | 603 | ||
| 604 | void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *); | 604 | void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *); |
| 605 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data); | 605 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data); |
| 606 | int qlcnic_83xx_get_settings(struct qlcnic_adapter *); | 606 | int qlcnic_83xx_get_settings(struct qlcnic_adapter *, struct ethtool_cmd *); |
| 607 | int qlcnic_83xx_set_settings(struct qlcnic_adapter *, struct ethtool_cmd *); | 607 | int qlcnic_83xx_set_settings(struct qlcnic_adapter *, struct ethtool_cmd *); |
| 608 | void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *, | 608 | void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *, |
| 609 | struct ethtool_pauseparam *); | 609 | struct ethtool_pauseparam *); |
| @@ -620,7 +620,7 @@ int qlcnic_83xx_flash_test(struct qlcnic_adapter *); | |||
| 620 | int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *); | 620 | int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *); |
| 621 | int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *); | 621 | int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *); |
| 622 | u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *); | 622 | u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *); |
| 623 | u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *); | 623 | u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *); |
| 624 | void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *); | 624 | void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *); |
| 625 | void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *); | 625 | void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *); |
| 626 | #endif | 626 | #endif |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index ab1d8d99cbd5..c67d1eb35e8f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | |||
| @@ -435,10 +435,6 @@ static void qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter) | |||
| 435 | } | 435 | } |
| 436 | done: | 436 | done: |
| 437 | netif_device_attach(netdev); | 437 | netif_device_attach(netdev); |
| 438 | if (netif_running(netdev)) { | ||
| 439 | netif_carrier_on(netdev); | ||
| 440 | netif_wake_queue(netdev); | ||
| 441 | } | ||
| 442 | } | 438 | } |
| 443 | 439 | ||
| 444 | static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter, | 440 | static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter, |
| @@ -642,15 +638,21 @@ static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) | |||
| 642 | 638 | ||
| 643 | static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter) | 639 | static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter) |
| 644 | { | 640 | { |
| 641 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
| 642 | |||
| 645 | qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1); | 643 | qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1); |
| 646 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
| 647 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | 644 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); |
| 648 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); | 645 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); |
| 649 | set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); | 646 | set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); |
| 650 | adapter->ahw->idc.quiesce_req = 0; | 647 | |
| 651 | adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; | 648 | ahw->idc.quiesce_req = 0; |
| 652 | adapter->ahw->idc.err_code = 0; | 649 | ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; |
| 653 | adapter->ahw->idc.collect_dump = 0; | 650 | ahw->idc.err_code = 0; |
| 651 | ahw->idc.collect_dump = 0; | ||
| 652 | ahw->reset_context = 0; | ||
| 653 | adapter->tx_timeo_cnt = 0; | ||
| 654 | |||
| 655 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
| 654 | } | 656 | } |
| 655 | 657 | ||
| 656 | /** | 658 | /** |
| @@ -851,6 +853,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) | |||
| 851 | /* Check for soft reset request */ | 853 | /* Check for soft reset request */ |
| 852 | if (ahw->reset_context && | 854 | if (ahw->reset_context && |
| 853 | !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) { | 855 | !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) { |
| 856 | adapter->ahw->reset_context = 0; | ||
| 854 | qlcnic_83xx_idc_tx_soft_reset(adapter); | 857 | qlcnic_83xx_idc_tx_soft_reset(adapter); |
| 855 | return ret; | 858 | return ret; |
| 856 | } | 859 | } |
| @@ -914,6 +917,7 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter) | |||
| 914 | static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter) | 917 | static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter) |
| 915 | { | 918 | { |
| 916 | dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__); | 919 | dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__); |
| 920 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
| 917 | adapter->ahw->idc.err_code = -EIO; | 921 | adapter->ahw->idc.err_code = -EIO; |
| 918 | 922 | ||
| 919 | return 0; | 923 | return 0; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 08efb4635007..f67652de5a63 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | |||
| @@ -131,12 +131,13 @@ static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = { | |||
| 131 | "ctx_lro_pkt_cnt", | 131 | "ctx_lro_pkt_cnt", |
| 132 | "ctx_ip_csum_error", | 132 | "ctx_ip_csum_error", |
| 133 | "ctx_rx_pkts_wo_ctx", | 133 | "ctx_rx_pkts_wo_ctx", |
| 134 | "ctx_rx_pkts_dropped_wo_sts", | 134 | "ctx_rx_pkts_drop_wo_sds_on_card", |
| 135 | "ctx_rx_pkts_drop_wo_sds_on_host", | ||
| 135 | "ctx_rx_osized_pkts", | 136 | "ctx_rx_osized_pkts", |
| 136 | "ctx_rx_pkts_dropped_wo_rds", | 137 | "ctx_rx_pkts_dropped_wo_rds", |
| 137 | "ctx_rx_unexpected_mcast_pkts", | 138 | "ctx_rx_unexpected_mcast_pkts", |
| 138 | "ctx_invalid_mac_address", | 139 | "ctx_invalid_mac_address", |
| 139 | "ctx_rx_rds_ring_prim_attemoted", | 140 | "ctx_rx_rds_ring_prim_attempted", |
| 140 | "ctx_rx_rds_ring_prim_success", | 141 | "ctx_rx_rds_ring_prim_success", |
| 141 | "ctx_num_lro_flows_added", | 142 | "ctx_num_lro_flows_added", |
| 142 | "ctx_num_lro_flows_removed", | 143 | "ctx_num_lro_flows_removed", |
| @@ -251,6 +252,18 @@ static int | |||
| 251 | qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | 252 | qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) |
| 252 | { | 253 | { |
| 253 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 254 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
| 255 | |||
| 256 | if (qlcnic_82xx_check(adapter)) | ||
| 257 | return qlcnic_82xx_get_settings(adapter, ecmd); | ||
| 258 | else if (qlcnic_83xx_check(adapter)) | ||
| 259 | return qlcnic_83xx_get_settings(adapter, ecmd); | ||
| 260 | |||
| 261 | return -EIO; | ||
| 262 | } | ||
| 263 | |||
| 264 | int qlcnic_82xx_get_settings(struct qlcnic_adapter *adapter, | ||
| 265 | struct ethtool_cmd *ecmd) | ||
| 266 | { | ||
| 254 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 267 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
| 255 | u32 speed, reg; | 268 | u32 speed, reg; |
| 256 | int check_sfp_module = 0; | 269 | int check_sfp_module = 0; |
| @@ -276,10 +289,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
| 276 | 289 | ||
| 277 | } else if (adapter->ahw->port_type == QLCNIC_XGBE) { | 290 | } else if (adapter->ahw->port_type == QLCNIC_XGBE) { |
| 278 | u32 val = 0; | 291 | u32 val = 0; |
| 279 | if (qlcnic_83xx_check(adapter)) | 292 | val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR); |
| 280 | qlcnic_83xx_get_settings(adapter); | ||
| 281 | else | ||
| 282 | val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR); | ||
| 283 | 293 | ||
| 284 | if (val == QLCNIC_PORT_MODE_802_3_AP) { | 294 | if (val == QLCNIC_PORT_MODE_802_3_AP) { |
| 285 | ecmd->supported = SUPPORTED_1000baseT_Full; | 295 | ecmd->supported = SUPPORTED_1000baseT_Full; |
| @@ -289,16 +299,13 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
| 289 | ecmd->advertising = ADVERTISED_10000baseT_Full; | 299 | ecmd->advertising = ADVERTISED_10000baseT_Full; |
| 290 | } | 300 | } |
| 291 | 301 | ||
| 292 | if (netif_running(dev) && adapter->ahw->has_link_events) { | 302 | if (netif_running(adapter->netdev) && ahw->has_link_events) { |
| 293 | if (qlcnic_82xx_check(adapter)) { | 303 | reg = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn)); |
| 294 | reg = QLCRD32(adapter, | 304 | speed = P3P_LINK_SPEED_VAL(pcifn, reg); |
| 295 | P3P_LINK_SPEED_REG(pcifn)); | 305 | ahw->link_speed = speed * P3P_LINK_SPEED_MHZ; |
| 296 | speed = P3P_LINK_SPEED_VAL(pcifn, reg); | 306 | ethtool_cmd_speed_set(ecmd, ahw->link_speed); |
| 297 | ahw->link_speed = speed * P3P_LINK_SPEED_MHZ; | 307 | ecmd->autoneg = ahw->link_autoneg; |
| 298 | } | 308 | ecmd->duplex = ahw->link_duplex; |
| 299 | ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed); | ||
| 300 | ecmd->autoneg = adapter->ahw->link_autoneg; | ||
| 301 | ecmd->duplex = adapter->ahw->link_duplex; | ||
| 302 | goto skip; | 309 | goto skip; |
| 303 | } | 310 | } |
| 304 | 311 | ||
| @@ -340,8 +347,8 @@ skip: | |||
| 340 | case QLCNIC_BRDTYPE_P3P_10G_SFP_QT: | 347 | case QLCNIC_BRDTYPE_P3P_10G_SFP_QT: |
| 341 | ecmd->advertising |= ADVERTISED_TP; | 348 | ecmd->advertising |= ADVERTISED_TP; |
| 342 | ecmd->supported |= SUPPORTED_TP; | 349 | ecmd->supported |= SUPPORTED_TP; |
| 343 | check_sfp_module = netif_running(dev) && | 350 | check_sfp_module = netif_running(adapter->netdev) && |
| 344 | adapter->ahw->has_link_events; | 351 | ahw->has_link_events; |
| 345 | case QLCNIC_BRDTYPE_P3P_10G_XFP: | 352 | case QLCNIC_BRDTYPE_P3P_10G_XFP: |
| 346 | ecmd->supported |= SUPPORTED_FIBRE; | 353 | ecmd->supported |= SUPPORTED_FIBRE; |
| 347 | ecmd->advertising |= ADVERTISED_FIBRE; | 354 | ecmd->advertising |= ADVERTISED_FIBRE; |
| @@ -355,8 +362,8 @@ skip: | |||
| 355 | ecmd->advertising |= | 362 | ecmd->advertising |= |
| 356 | (ADVERTISED_FIBRE | ADVERTISED_TP); | 363 | (ADVERTISED_FIBRE | ADVERTISED_TP); |
| 357 | ecmd->port = PORT_FIBRE; | 364 | ecmd->port = PORT_FIBRE; |
| 358 | check_sfp_module = netif_running(dev) && | 365 | check_sfp_module = netif_running(adapter->netdev) && |
| 359 | adapter->ahw->has_link_events; | 366 | ahw->has_link_events; |
| 360 | } else { | 367 | } else { |
| 361 | ecmd->autoneg = AUTONEG_ENABLE; | 368 | ecmd->autoneg = AUTONEG_ENABLE; |
| 362 | ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg); | 369 | ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg); |
| @@ -365,13 +372,6 @@ skip: | |||
| 365 | ecmd->port = PORT_TP; | 372 | ecmd->port = PORT_TP; |
| 366 | } | 373 | } |
| 367 | break; | 374 | break; |
| 368 | case QLCNIC_BRDTYPE_83XX_10G: | ||
| 369 | ecmd->autoneg = AUTONEG_DISABLE; | ||
| 370 | ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP); | ||
| 371 | ecmd->advertising |= (ADVERTISED_FIBRE | ADVERTISED_TP); | ||
| 372 | ecmd->port = PORT_FIBRE; | ||
| 373 | check_sfp_module = netif_running(dev) && ahw->has_link_events; | ||
| 374 | break; | ||
| 375 | default: | 375 | default: |
| 376 | dev_err(&adapter->pdev->dev, "Unsupported board model %d\n", | 376 | dev_err(&adapter->pdev->dev, "Unsupported board model %d\n", |
| 377 | adapter->ahw->board_type); | 377 | adapter->ahw->board_type); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h index 95b1b5732838..b6818f4356b9 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | |||
| @@ -134,7 +134,7 @@ struct qlcnic_mailbox_metadata { | |||
| 134 | 134 | ||
| 135 | #define QLCNIC_SET_OWNER 1 | 135 | #define QLCNIC_SET_OWNER 1 |
| 136 | #define QLCNIC_CLR_OWNER 0 | 136 | #define QLCNIC_CLR_OWNER 0 |
| 137 | #define QLCNIC_MBX_TIMEOUT 10000 | 137 | #define QLCNIC_MBX_TIMEOUT 5000 |
| 138 | 138 | ||
| 139 | #define QLCNIC_MBX_RSP_OK 1 | 139 | #define QLCNIC_MBX_RSP_OK 1 |
| 140 | #define QLCNIC_MBX_PORT_RSP_OK 0x1a | 140 | #define QLCNIC_MBX_PORT_RSP_OK 0x1a |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 264d5a4f8153..8fb836d4129f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
| @@ -37,24 +37,24 @@ MODULE_PARM_DESC(qlcnic_mac_learn, | |||
| 37 | "Mac Filter (0=learning is disabled, 1=Driver learning is enabled, 2=FDB learning is enabled)"); | 37 | "Mac Filter (0=learning is disabled, 1=Driver learning is enabled, 2=FDB learning is enabled)"); |
| 38 | 38 | ||
| 39 | int qlcnic_use_msi = 1; | 39 | int qlcnic_use_msi = 1; |
| 40 | MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled"); | 40 | MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled)"); |
| 41 | module_param_named(use_msi, qlcnic_use_msi, int, 0444); | 41 | module_param_named(use_msi, qlcnic_use_msi, int, 0444); |
| 42 | 42 | ||
| 43 | int qlcnic_use_msi_x = 1; | 43 | int qlcnic_use_msi_x = 1; |
| 44 | MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled"); | 44 | MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled)"); |
| 45 | module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444); | 45 | module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444); |
| 46 | 46 | ||
| 47 | int qlcnic_auto_fw_reset = 1; | 47 | int qlcnic_auto_fw_reset = 1; |
| 48 | MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled"); | 48 | MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled)"); |
| 49 | module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644); | 49 | module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644); |
| 50 | 50 | ||
| 51 | int qlcnic_load_fw_file; | 51 | int qlcnic_load_fw_file; |
| 52 | MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file"); | 52 | MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file)"); |
| 53 | module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444); | 53 | module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444); |
| 54 | 54 | ||
| 55 | int qlcnic_config_npars; | 55 | int qlcnic_config_npars; |
| 56 | module_param(qlcnic_config_npars, int, 0444); | 56 | module_param(qlcnic_config_npars, int, 0444); |
| 57 | MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled"); | 57 | MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled)"); |
| 58 | 58 | ||
| 59 | static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); | 59 | static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); |
| 60 | static void qlcnic_remove(struct pci_dev *pdev); | 60 | static void qlcnic_remove(struct pci_dev *pdev); |
| @@ -308,6 +308,23 @@ int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) | |||
| 308 | return 0; | 308 | return 0; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | static void qlcnic_delete_adapter_mac(struct qlcnic_adapter *adapter) | ||
| 312 | { | ||
| 313 | struct qlcnic_mac_list_s *cur; | ||
| 314 | struct list_head *head; | ||
| 315 | |||
| 316 | list_for_each(head, &adapter->mac_list) { | ||
| 317 | cur = list_entry(head, struct qlcnic_mac_list_s, list); | ||
| 318 | if (!memcmp(adapter->mac_addr, cur->mac_addr, ETH_ALEN)) { | ||
| 319 | qlcnic_sre_macaddr_change(adapter, cur->mac_addr, | ||
| 320 | 0, QLCNIC_MAC_DEL); | ||
| 321 | list_del(&cur->list); | ||
| 322 | kfree(cur); | ||
| 323 | return; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | } | ||
| 327 | |||
| 311 | static int qlcnic_set_mac(struct net_device *netdev, void *p) | 328 | static int qlcnic_set_mac(struct net_device *netdev, void *p) |
| 312 | { | 329 | { |
| 313 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 330 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
| @@ -322,11 +339,15 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) | |||
| 322 | if (!is_valid_ether_addr(addr->sa_data)) | 339 | if (!is_valid_ether_addr(addr->sa_data)) |
| 323 | return -EINVAL; | 340 | return -EINVAL; |
| 324 | 341 | ||
| 342 | if (!memcmp(adapter->mac_addr, addr->sa_data, ETH_ALEN)) | ||
| 343 | return 0; | ||
| 344 | |||
| 325 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | 345 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { |
| 326 | netif_device_detach(netdev); | 346 | netif_device_detach(netdev); |
| 327 | qlcnic_napi_disable(adapter); | 347 | qlcnic_napi_disable(adapter); |
| 328 | } | 348 | } |
| 329 | 349 | ||
| 350 | qlcnic_delete_adapter_mac(adapter); | ||
| 330 | memcpy(adapter->mac_addr, addr->sa_data, netdev->addr_len); | 351 | memcpy(adapter->mac_addr, addr->sa_data, netdev->addr_len); |
| 331 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); | 352 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); |
| 332 | qlcnic_set_multi(adapter->netdev); | 353 | qlcnic_set_multi(adapter->netdev); |
| @@ -2481,12 +2502,17 @@ static void qlcnic_tx_timeout(struct net_device *netdev) | |||
| 2481 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) | 2502 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) |
| 2482 | return; | 2503 | return; |
| 2483 | 2504 | ||
| 2484 | dev_err(&netdev->dev, "transmit timeout, resetting.\n"); | 2505 | if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) { |
| 2485 | 2506 | netdev_info(netdev, "Tx timeout, reset the adapter.\n"); | |
| 2486 | if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) | 2507 | if (qlcnic_82xx_check(adapter)) |
| 2487 | adapter->need_fw_reset = 1; | 2508 | adapter->need_fw_reset = 1; |
| 2488 | else | 2509 | else if (qlcnic_83xx_check(adapter)) |
| 2510 | qlcnic_83xx_idc_request_reset(adapter, | ||
| 2511 | QLCNIC_FORCE_FW_DUMP_KEY); | ||
| 2512 | } else { | ||
| 2513 | netdev_info(netdev, "Tx timeout, reset adapter context.\n"); | ||
| 2489 | adapter->ahw->reset_context = 1; | 2514 | adapter->ahw->reset_context = 1; |
| 2515 | } | ||
| 2490 | } | 2516 | } |
| 2491 | 2517 | ||
| 2492 | static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) | 2518 | static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 44d547d78b84..3869c3864deb 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | |||
| @@ -280,9 +280,9 @@ void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter) | |||
| 280 | static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr, | 280 | static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr, |
| 281 | u32 *pay, u8 pci_func, u8 size) | 281 | u32 *pay, u8 pci_func, u8 size) |
| 282 | { | 282 | { |
| 283 | u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, val, wait_time = 0; | ||
| 283 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 284 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
| 284 | unsigned long flags; | 285 | unsigned long flags; |
| 285 | u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, val; | ||
| 286 | u16 opcode; | 286 | u16 opcode; |
| 287 | u8 mbx_err_code; | 287 | u8 mbx_err_code; |
| 288 | int i, j; | 288 | int i, j; |
| @@ -330,15 +330,13 @@ static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr, | |||
| 330 | * assume something is wrong. | 330 | * assume something is wrong. |
| 331 | */ | 331 | */ |
| 332 | poll: | 332 | poll: |
| 333 | rsp = qlcnic_83xx_mbx_poll(adapter); | 333 | rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time); |
| 334 | if (rsp != QLCNIC_RCODE_TIMEOUT) { | 334 | if (rsp != QLCNIC_RCODE_TIMEOUT) { |
| 335 | /* Get the FW response data */ | 335 | /* Get the FW response data */ |
| 336 | fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); | 336 | fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); |
| 337 | if (fw_data & QLCNIC_MBX_ASYNC_EVENT) { | 337 | if (fw_data & QLCNIC_MBX_ASYNC_EVENT) { |
| 338 | __qlcnic_83xx_process_aen(adapter); | 338 | __qlcnic_83xx_process_aen(adapter); |
| 339 | mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | 339 | goto poll; |
| 340 | if (mbx_val) | ||
| 341 | goto poll; | ||
| 342 | } | 340 | } |
| 343 | mbx_err_code = QLCNIC_MBX_STATUS(fw_data); | 341 | mbx_err_code = QLCNIC_MBX_STATUS(fw_data); |
| 344 | rsp_num = QLCNIC_MBX_NUM_REGS(fw_data); | 342 | rsp_num = QLCNIC_MBX_NUM_REGS(fw_data); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index c81be2da119b..1a66ccded235 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | |||
| @@ -1133,9 +1133,6 @@ static int qlcnic_sriov_validate_linkevent(struct qlcnic_vf_info *vf, | |||
| 1133 | if ((cmd->req.arg[1] >> 16) != vf->rx_ctx_id) | 1133 | if ((cmd->req.arg[1] >> 16) != vf->rx_ctx_id) |
| 1134 | return -EINVAL; | 1134 | return -EINVAL; |
| 1135 | 1135 | ||
| 1136 | if (!(cmd->req.arg[1] & BIT_8)) | ||
| 1137 | return -EINVAL; | ||
| 1138 | |||
| 1139 | return 0; | 1136 | return 0; |
| 1140 | } | 1137 | } |
| 1141 | 1138 | ||
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 87463bc701a6..50235d201592 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c | |||
| @@ -1106,6 +1106,7 @@ static int ql_get_next_chunk(struct ql_adapter *qdev, struct rx_ring *rx_ring, | |||
| 1106 | if (pci_dma_mapping_error(qdev->pdev, map)) { | 1106 | if (pci_dma_mapping_error(qdev->pdev, map)) { |
| 1107 | __free_pages(rx_ring->pg_chunk.page, | 1107 | __free_pages(rx_ring->pg_chunk.page, |
| 1108 | qdev->lbq_buf_order); | 1108 | qdev->lbq_buf_order); |
| 1109 | rx_ring->pg_chunk.page = NULL; | ||
| 1109 | netif_err(qdev, drv, qdev->ndev, | 1110 | netif_err(qdev, drv, qdev->ndev, |
| 1110 | "PCI mapping failed.\n"); | 1111 | "PCI mapping failed.\n"); |
| 1111 | return -ENOMEM; | 1112 | return -ENOMEM; |
| @@ -2777,6 +2778,12 @@ static void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring | |||
| 2777 | curr_idx = 0; | 2778 | curr_idx = 0; |
| 2778 | 2779 | ||
| 2779 | } | 2780 | } |
| 2781 | if (rx_ring->pg_chunk.page) { | ||
| 2782 | pci_unmap_page(qdev->pdev, rx_ring->pg_chunk.map, | ||
| 2783 | ql_lbq_block_size(qdev), PCI_DMA_FROMDEVICE); | ||
| 2784 | put_page(rx_ring->pg_chunk.page); | ||
| 2785 | rx_ring->pg_chunk.page = NULL; | ||
| 2786 | } | ||
| 2780 | } | 2787 | } |
| 2781 | 2788 | ||
| 2782 | static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring) | 2789 | static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring) |
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index f695a50bac47..43c1f3223322 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config STMMAC_ETH | 1 | config STMMAC_ETH |
| 2 | tristate "STMicroelectronics 10/100/1000 Ethernet driver" | 2 | tristate "STMicroelectronics 10/100/1000 Ethernet driver" |
| 3 | depends on HAS_IOMEM | 3 | depends on HAS_IOMEM && HAS_DMA |
| 4 | select NET_CORE | 4 | select NET_CORE |
| 5 | select MII | 5 | select MII |
| 6 | select PHYLIB | 6 | select PHYLIB |
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index d5a141c7c4e7..1c502bb0c916 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
| @@ -229,7 +229,8 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) | |||
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | if (port->passthru) | 231 | if (port->passthru) |
| 232 | vlan = list_first_entry(&port->vlans, struct macvlan_dev, list); | 232 | vlan = list_first_or_null_rcu(&port->vlans, |
| 233 | struct macvlan_dev, list); | ||
| 233 | else | 234 | else |
| 234 | vlan = macvlan_hash_lookup(port, eth->h_dest); | 235 | vlan = macvlan_hash_lookup(port, eth->h_dest); |
| 235 | if (vlan == NULL) | 236 | if (vlan == NULL) |
| @@ -814,7 +815,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, | |||
| 814 | if (err < 0) | 815 | if (err < 0) |
| 815 | goto upper_dev_unlink; | 816 | goto upper_dev_unlink; |
| 816 | 817 | ||
| 817 | list_add_tail(&vlan->list, &port->vlans); | 818 | list_add_tail_rcu(&vlan->list, &port->vlans); |
| 818 | netif_stacked_transfer_operstate(lowerdev, dev); | 819 | netif_stacked_transfer_operstate(lowerdev, dev); |
| 819 | 820 | ||
| 820 | return 0; | 821 | return 0; |
| @@ -842,7 +843,7 @@ void macvlan_dellink(struct net_device *dev, struct list_head *head) | |||
| 842 | { | 843 | { |
| 843 | struct macvlan_dev *vlan = netdev_priv(dev); | 844 | struct macvlan_dev *vlan = netdev_priv(dev); |
| 844 | 845 | ||
| 845 | list_del(&vlan->list); | 846 | list_del_rcu(&vlan->list); |
| 846 | unregister_netdevice_queue(dev, head); | 847 | unregister_netdevice_queue(dev, head); |
| 847 | netdev_upper_dev_unlink(vlan->lowerdev, dev); | 848 | netdev_upper_dev_unlink(vlan->lowerdev, dev); |
| 848 | } | 849 | } |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3c23fdc27bf0..655bb25eed2b 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/cpu.h> | 29 | #include <linux/cpu.h> |
| 30 | 30 | ||
| 31 | static int napi_weight = 128; | 31 | static int napi_weight = NAPI_POLL_WEIGHT; |
| 32 | module_param(napi_weight, int, 0444); | 32 | module_param(napi_weight, int, 0444); |
| 33 | 33 | ||
| 34 | static bool csum = true, gso = true; | 34 | static bool csum = true, gso = true; |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 9b20d9ee2719..7f702fe3ecc2 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
| @@ -2369,6 +2369,9 @@ ath5k_tx_complete_poll_work(struct work_struct *work) | |||
| 2369 | int i; | 2369 | int i; |
| 2370 | bool needreset = false; | 2370 | bool needreset = false; |
| 2371 | 2371 | ||
| 2372 | if (!test_bit(ATH_STAT_STARTED, ah->status)) | ||
| 2373 | return; | ||
| 2374 | |||
| 2372 | mutex_lock(&ah->lock); | 2375 | mutex_lock(&ah->lock); |
| 2373 | 2376 | ||
| 2374 | for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) { | 2377 | for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) { |
| @@ -2676,6 +2679,7 @@ done: | |||
| 2676 | mmiowb(); | 2679 | mmiowb(); |
| 2677 | mutex_unlock(&ah->lock); | 2680 | mutex_unlock(&ah->lock); |
| 2678 | 2681 | ||
| 2682 | set_bit(ATH_STAT_STARTED, ah->status); | ||
| 2679 | ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work, | 2683 | ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work, |
| 2680 | msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); | 2684 | msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); |
| 2681 | 2685 | ||
| @@ -2737,6 +2741,7 @@ void ath5k_stop(struct ieee80211_hw *hw) | |||
| 2737 | 2741 | ||
| 2738 | ath5k_stop_tasklets(ah); | 2742 | ath5k_stop_tasklets(ah); |
| 2739 | 2743 | ||
| 2744 | clear_bit(ATH_STAT_STARTED, ah->status); | ||
| 2740 | cancel_delayed_work_sync(&ah->tx_complete_work); | 2745 | cancel_delayed_work_sync(&ah->tx_complete_work); |
| 2741 | 2746 | ||
| 2742 | if (!ath5k_modparam_no_hw_rfkill_switch) | 2747 | if (!ath5k_modparam_no_hw_rfkill_switch) |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 17507dc8a1e7..f3dc124c60c7 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
| @@ -17,7 +17,7 @@ config ATH9K_BTCOEX_SUPPORT | |||
| 17 | 17 | ||
| 18 | config ATH9K | 18 | config ATH9K |
| 19 | tristate "Atheros 802.11n wireless cards support" | 19 | tristate "Atheros 802.11n wireless cards support" |
| 20 | depends on MAC80211 | 20 | depends on MAC80211 && HAS_DMA |
| 21 | select ATH9K_HW | 21 | select ATH9K_HW |
| 22 | select MAC80211_LEDS | 22 | select MAC80211_LEDS |
| 23 | select LEDS_CLASS | 23 | select LEDS_CLASS |
diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h index 0c2ac0c6dc89..e85a8b076c22 100644 --- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h | |||
| @@ -233,9 +233,9 @@ static const u32 ar9565_1p0_baseband_core[][2] = { | |||
| 233 | {0x00009d10, 0x01834061}, | 233 | {0x00009d10, 0x01834061}, |
| 234 | {0x00009d14, 0x00c00400}, | 234 | {0x00009d14, 0x00c00400}, |
| 235 | {0x00009d18, 0x00000000}, | 235 | {0x00009d18, 0x00000000}, |
| 236 | {0x00009e08, 0x0078230c}, | 236 | {0x00009e08, 0x0038230c}, |
| 237 | {0x00009e24, 0x990bb515}, | 237 | {0x00009e24, 0x9907b515}, |
| 238 | {0x00009e28, 0x126f0000}, | 238 | {0x00009e28, 0x126f0600}, |
| 239 | {0x00009e30, 0x06336f77}, | 239 | {0x00009e30, 0x06336f77}, |
| 240 | {0x00009e34, 0x6af6532f}, | 240 | {0x00009e34, 0x6af6532f}, |
| 241 | {0x00009e38, 0x0cc80c00}, | 241 | {0x00009e38, 0x0cc80c00}, |
| @@ -337,7 +337,7 @@ static const u32 ar9565_1p0_baseband_core[][2] = { | |||
| 337 | 337 | ||
| 338 | static const u32 ar9565_1p0_baseband_postamble[][5] = { | 338 | static const u32 ar9565_1p0_baseband_postamble[][5] = { |
| 339 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 339 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
| 340 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a800d}, | 340 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8009}, |
| 341 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, | 341 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae}, |
| 342 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, | 342 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x63c640da}, |
| 343 | {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x09143c81}, | 343 | {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x09143c81}, |
| @@ -345,9 +345,9 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = { | |||
| 345 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, | 345 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, |
| 346 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, | 346 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, |
| 347 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, | 347 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, |
| 348 | {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, | 348 | {0x00009e04, 0x00802020, 0x00802020, 0x00142020, 0x00142020}, |
| 349 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8}, | 349 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, |
| 350 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e}, | 350 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, |
| 351 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, | 351 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, |
| 352 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 352 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 353 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 353 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
| @@ -450,6 +450,8 @@ static const u32 ar9565_1p0_soc_postamble[][5] = { | |||
| 450 | 450 | ||
| 451 | static const u32 ar9565_1p0_Common_rx_gain_table[][2] = { | 451 | static const u32 ar9565_1p0_Common_rx_gain_table[][2] = { |
| 452 | /* Addr allmodes */ | 452 | /* Addr allmodes */ |
| 453 | {0x00004050, 0x00300300}, | ||
| 454 | {0x0000406c, 0x00100000}, | ||
| 453 | {0x0000a000, 0x00010000}, | 455 | {0x0000a000, 0x00010000}, |
| 454 | {0x0000a004, 0x00030002}, | 456 | {0x0000a004, 0x00030002}, |
| 455 | {0x0000a008, 0x00050004}, | 457 | {0x0000a008, 0x00050004}, |
| @@ -498,27 +500,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = { | |||
| 498 | {0x0000a0b4, 0x00000000}, | 500 | {0x0000a0b4, 0x00000000}, |
| 499 | {0x0000a0b8, 0x00000000}, | 501 | {0x0000a0b8, 0x00000000}, |
| 500 | {0x0000a0bc, 0x00000000}, | 502 | {0x0000a0bc, 0x00000000}, |
| 501 | {0x0000a0c0, 0x001f0000}, | 503 | {0x0000a0c0, 0x00bf00a0}, |
| 502 | {0x0000a0c4, 0x01000101}, | 504 | {0x0000a0c4, 0x11a011a1}, |
| 503 | {0x0000a0c8, 0x011e011f}, | 505 | {0x0000a0c8, 0x11be11bf}, |
| 504 | {0x0000a0cc, 0x011c011d}, | 506 | {0x0000a0cc, 0x11bc11bd}, |
| 505 | {0x0000a0d0, 0x02030204}, | 507 | {0x0000a0d0, 0x22632264}, |
| 506 | {0x0000a0d4, 0x02010202}, | 508 | {0x0000a0d4, 0x22612262}, |
| 507 | {0x0000a0d8, 0x021f0200}, | 509 | {0x0000a0d8, 0x227f2260}, |
| 508 | {0x0000a0dc, 0x0302021e}, | 510 | {0x0000a0dc, 0x4322227e}, |
| 509 | {0x0000a0e0, 0x03000301}, | 511 | {0x0000a0e0, 0x43204321}, |
| 510 | {0x0000a0e4, 0x031e031f}, | 512 | {0x0000a0e4, 0x433e433f}, |
| 511 | {0x0000a0e8, 0x0402031d}, | 513 | {0x0000a0e8, 0x4462433d}, |
| 512 | {0x0000a0ec, 0x04000401}, | 514 | {0x0000a0ec, 0x44604461}, |
| 513 | {0x0000a0f0, 0x041e041f}, | 515 | {0x0000a0f0, 0x447e447f}, |
| 514 | {0x0000a0f4, 0x0502041d}, | 516 | {0x0000a0f4, 0x5582447d}, |
| 515 | {0x0000a0f8, 0x05000501}, | 517 | {0x0000a0f8, 0x55805581}, |
| 516 | {0x0000a0fc, 0x051e051f}, | 518 | {0x0000a0fc, 0x559e559f}, |
| 517 | {0x0000a100, 0x06010602}, | 519 | {0x0000a100, 0x66816682}, |
| 518 | {0x0000a104, 0x061f0600}, | 520 | {0x0000a104, 0x669f6680}, |
| 519 | {0x0000a108, 0x061d061e}, | 521 | {0x0000a108, 0x669d669e}, |
| 520 | {0x0000a10c, 0x07020703}, | 522 | {0x0000a10c, 0x77627763}, |
| 521 | {0x0000a110, 0x07000701}, | 523 | {0x0000a110, 0x77607761}, |
| 522 | {0x0000a114, 0x00000000}, | 524 | {0x0000a114, 0x00000000}, |
| 523 | {0x0000a118, 0x00000000}, | 525 | {0x0000a118, 0x00000000}, |
| 524 | {0x0000a11c, 0x00000000}, | 526 | {0x0000a11c, 0x00000000}, |
| @@ -530,27 +532,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = { | |||
| 530 | {0x0000a134, 0x00000000}, | 532 | {0x0000a134, 0x00000000}, |
| 531 | {0x0000a138, 0x00000000}, | 533 | {0x0000a138, 0x00000000}, |
| 532 | {0x0000a13c, 0x00000000}, | 534 | {0x0000a13c, 0x00000000}, |
| 533 | {0x0000a140, 0x001f0000}, | 535 | {0x0000a140, 0x00bf00a0}, |
| 534 | {0x0000a144, 0x01000101}, | 536 | {0x0000a144, 0x11a011a1}, |
| 535 | {0x0000a148, 0x011e011f}, | 537 | {0x0000a148, 0x11be11bf}, |
| 536 | {0x0000a14c, 0x011c011d}, | 538 | {0x0000a14c, 0x11bc11bd}, |
| 537 | {0x0000a150, 0x02030204}, | 539 | {0x0000a150, 0x22632264}, |
| 538 | {0x0000a154, 0x02010202}, | 540 | {0x0000a154, 0x22612262}, |
| 539 | {0x0000a158, 0x021f0200}, | 541 | {0x0000a158, 0x227f2260}, |
| 540 | {0x0000a15c, 0x0302021e}, | 542 | {0x0000a15c, 0x4322227e}, |
| 541 | {0x0000a160, 0x03000301}, | 543 | {0x0000a160, 0x43204321}, |
| 542 | {0x0000a164, 0x031e031f}, | 544 | {0x0000a164, 0x433e433f}, |
| 543 | {0x0000a168, 0x0402031d}, | 545 | {0x0000a168, 0x4462433d}, |
| 544 | {0x0000a16c, 0x04000401}, | 546 | {0x0000a16c, 0x44604461}, |
| 545 | {0x0000a170, 0x041e041f}, | 547 | {0x0000a170, 0x447e447f}, |
| 546 | {0x0000a174, 0x0502041d}, | 548 | {0x0000a174, 0x5582447d}, |
| 547 | {0x0000a178, 0x05000501}, | 549 | {0x0000a178, 0x55805581}, |
| 548 | {0x0000a17c, 0x051e051f}, | 550 | {0x0000a17c, 0x559e559f}, |
| 549 | {0x0000a180, 0x06010602}, | 551 | {0x0000a180, 0x66816682}, |
| 550 | {0x0000a184, 0x061f0600}, | 552 | {0x0000a184, 0x669f6680}, |
| 551 | {0x0000a188, 0x061d061e}, | 553 | {0x0000a188, 0x669d669e}, |
| 552 | {0x0000a18c, 0x07020703}, | 554 | {0x0000a18c, 0x77e677e7}, |
| 553 | {0x0000a190, 0x07000701}, | 555 | {0x0000a190, 0x77e477e5}, |
| 554 | {0x0000a194, 0x00000000}, | 556 | {0x0000a194, 0x00000000}, |
| 555 | {0x0000a198, 0x00000000}, | 557 | {0x0000a198, 0x00000000}, |
| 556 | {0x0000a19c, 0x00000000}, | 558 | {0x0000a19c, 0x00000000}, |
| @@ -770,7 +772,7 @@ static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = { | |||
| 770 | 772 | ||
| 771 | static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = { | 773 | static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = { |
| 772 | /* Addr allmodes */ | 774 | /* Addr allmodes */ |
| 773 | {0x00018c00, 0x18213ede}, | 775 | {0x00018c00, 0x18212ede}, |
| 774 | {0x00018c04, 0x000801d8}, | 776 | {0x00018c04, 0x000801d8}, |
| 775 | {0x00018c08, 0x0003780c}, | 777 | {0x00018c08, 0x0003780c}, |
| 776 | }; | 778 | }; |
| @@ -889,8 +891,8 @@ static const u32 ar9565_1p0_common_wo_xlna_rx_gain_table[][2] = { | |||
| 889 | {0x0000a180, 0x66816682}, | 891 | {0x0000a180, 0x66816682}, |
| 890 | {0x0000a184, 0x669f6680}, | 892 | {0x0000a184, 0x669f6680}, |
| 891 | {0x0000a188, 0x669d669e}, | 893 | {0x0000a188, 0x669d669e}, |
| 892 | {0x0000a18c, 0x77627763}, | 894 | {0x0000a18c, 0x77e677e7}, |
| 893 | {0x0000a190, 0x77607761}, | 895 | {0x0000a190, 0x77e477e5}, |
| 894 | {0x0000a194, 0x00000000}, | 896 | {0x0000a194, 0x00000000}, |
| 895 | {0x0000a198, 0x00000000}, | 897 | {0x0000a198, 0x00000000}, |
| 896 | {0x0000a19c, 0x00000000}, | 898 | {0x0000a19c, 0x00000000}, |
| @@ -1114,7 +1116,7 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = { | |||
| 1114 | {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84}, | 1116 | {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84}, |
| 1115 | {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000}, | 1117 | {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000}, |
| 1116 | {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000}, | 1118 | {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000}, |
| 1117 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 1119 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df}, |
| 1118 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 1120 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
| 1119 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 1121 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, |
| 1120 | {0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004}, | 1122 | {0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004}, |
| @@ -1140,13 +1142,13 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = { | |||
| 1140 | {0x0000a558, 0x69027f56, 0x69027f56, 0x53001ce5, 0x53001ce5}, | 1142 | {0x0000a558, 0x69027f56, 0x69027f56, 0x53001ce5, 0x53001ce5}, |
| 1141 | {0x0000a55c, 0x6d029f56, 0x6d029f56, 0x57001ce9, 0x57001ce9}, | 1143 | {0x0000a55c, 0x6d029f56, 0x6d029f56, 0x57001ce9, 0x57001ce9}, |
| 1142 | {0x0000a560, 0x73049f56, 0x73049f56, 0x5b001ceb, 0x5b001ceb}, | 1144 | {0x0000a560, 0x73049f56, 0x73049f56, 0x5b001ceb, 0x5b001ceb}, |
| 1143 | {0x0000a564, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1145 | {0x0000a564, 0x7804ff56, 0x7804ff56, 0x60001cf0, 0x60001cf0}, |
| 1144 | {0x0000a568, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1146 | {0x0000a568, 0x7804ff56, 0x7804ff56, 0x61001cf1, 0x61001cf1}, |
| 1145 | {0x0000a56c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1147 | {0x0000a56c, 0x7804ff56, 0x7804ff56, 0x62001cf2, 0x62001cf2}, |
| 1146 | {0x0000a570, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1148 | {0x0000a570, 0x7804ff56, 0x7804ff56, 0x63001cf3, 0x63001cf3}, |
| 1147 | {0x0000a574, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1149 | {0x0000a574, 0x7804ff56, 0x7804ff56, 0x64001cf4, 0x64001cf4}, |
| 1148 | {0x0000a578, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1150 | {0x0000a578, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6}, |
| 1149 | {0x0000a57c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec}, | 1151 | {0x0000a57c, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6}, |
| 1150 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1152 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 1151 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1153 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 1152 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1154 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| @@ -1174,7 +1176,7 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = { | |||
| 1174 | {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84}, | 1176 | {0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84}, |
| 1175 | {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000}, | 1177 | {0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000}, |
| 1176 | {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000}, | 1178 | {0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000}, |
| 1177 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 1179 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df}, |
| 1178 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 1180 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
| 1179 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, | 1181 | {0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002}, |
| 1180 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, | 1182 | {0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004}, |
| @@ -1200,13 +1202,13 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = { | |||
| 1200 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, | 1202 | {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5}, |
| 1201 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, | 1203 | {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9}, |
| 1202 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, | 1204 | {0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb}, |
| 1203 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1205 | {0x0000a564, 0x7504ff56, 0x7504ff56, 0x59001cf0, 0x59001cf0}, |
| 1204 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1206 | {0x0000a568, 0x7504ff56, 0x7504ff56, 0x5a001cf1, 0x5a001cf1}, |
| 1205 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1207 | {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x5b001cf2, 0x5b001cf2}, |
| 1206 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1208 | {0x0000a570, 0x7504ff56, 0x7504ff56, 0x5c001cf3, 0x5c001cf3}, |
| 1207 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1209 | {0x0000a574, 0x7504ff56, 0x7504ff56, 0x5d001cf4, 0x5d001cf4}, |
| 1208 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1210 | {0x0000a578, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6}, |
| 1209 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec}, | 1211 | {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6}, |
| 1210 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1212 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 1211 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1213 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 1212 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1214 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 6963862a1872..a18414b5948b 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -227,13 +227,13 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
| 227 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) | 227 | if (!test_bit(SC_OP_BEACONS, &sc->sc_flags)) |
| 228 | goto work; | 228 | goto work; |
| 229 | 229 | ||
| 230 | ath9k_set_beacon(sc); | ||
| 231 | |||
| 232 | if (ah->opmode == NL80211_IFTYPE_STATION && | 230 | if (ah->opmode == NL80211_IFTYPE_STATION && |
| 233 | test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { | 231 | test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) { |
| 234 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 232 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
| 235 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; | 233 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; |
| 236 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 234 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
| 235 | } else { | ||
| 236 | ath9k_set_beacon(sc); | ||
| 237 | } | 237 | } |
| 238 | work: | 238 | work: |
| 239 | ath_restart_work(sc); | 239 | ath_restart_work(sc); |
| @@ -1332,6 +1332,7 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, | |||
| 1332 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1332 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 1333 | struct ath_node *an = (struct ath_node *) sta->drv_priv; | 1333 | struct ath_node *an = (struct ath_node *) sta->drv_priv; |
| 1334 | struct ieee80211_key_conf ps_key = { }; | 1334 | struct ieee80211_key_conf ps_key = { }; |
| 1335 | int key; | ||
| 1335 | 1336 | ||
| 1336 | ath_node_attach(sc, sta, vif); | 1337 | ath_node_attach(sc, sta, vif); |
| 1337 | 1338 | ||
| @@ -1339,7 +1340,9 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, | |||
| 1339 | vif->type != NL80211_IFTYPE_AP_VLAN) | 1340 | vif->type != NL80211_IFTYPE_AP_VLAN) |
| 1340 | return 0; | 1341 | return 0; |
| 1341 | 1342 | ||
| 1342 | an->ps_key = ath_key_config(common, vif, sta, &ps_key); | 1343 | key = ath_key_config(common, vif, sta, &ps_key); |
| 1344 | if (key > 0) | ||
| 1345 | an->ps_key = key; | ||
| 1343 | 1346 | ||
| 1344 | return 0; | 1347 | return 0; |
| 1345 | } | 1348 | } |
| @@ -1356,6 +1359,7 @@ static void ath9k_del_ps_key(struct ath_softc *sc, | |||
| 1356 | return; | 1359 | return; |
| 1357 | 1360 | ||
| 1358 | ath_key_delete(common, &ps_key); | 1361 | ath_key_delete(common, &ps_key); |
| 1362 | an->ps_key = 0; | ||
| 1359 | } | 1363 | } |
| 1360 | 1364 | ||
| 1361 | static int ath9k_sta_remove(struct ieee80211_hw *hw, | 1365 | static int ath9k_sta_remove(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 523355b87659..f7c70b3a6ea9 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
| @@ -1728,6 +1728,25 @@ drop_recycle_buffer: | |||
| 1728 | sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize); | 1728 | sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize); |
| 1729 | } | 1729 | } |
| 1730 | 1730 | ||
| 1731 | void b43_dma_handle_rx_overflow(struct b43_dmaring *ring) | ||
| 1732 | { | ||
| 1733 | int current_slot, previous_slot; | ||
| 1734 | |||
| 1735 | B43_WARN_ON(ring->tx); | ||
| 1736 | |||
| 1737 | /* Device has filled all buffers, drop all packets and let TCP | ||
| 1738 | * decrease speed. | ||
| 1739 | * Decrement RX index by one will let the device to see all slots | ||
| 1740 | * as free again | ||
| 1741 | */ | ||
| 1742 | /* | ||
| 1743 | *TODO: How to increase rx_drop in mac80211? | ||
| 1744 | */ | ||
| 1745 | current_slot = ring->ops->get_current_rxslot(ring); | ||
| 1746 | previous_slot = prev_slot(ring, current_slot); | ||
| 1747 | ring->ops->set_current_rxslot(ring, previous_slot); | ||
| 1748 | } | ||
| 1749 | |||
| 1731 | void b43_dma_rx(struct b43_dmaring *ring) | 1750 | void b43_dma_rx(struct b43_dmaring *ring) |
| 1732 | { | 1751 | { |
| 1733 | const struct b43_dma_ops *ops = ring->ops; | 1752 | const struct b43_dma_ops *ops = ring->ops; |
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 9fdd1983079c..df8c8cdcbdb5 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | /* DMA-Interrupt reasons. */ | 9 | /* DMA-Interrupt reasons. */ |
| 10 | #define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ | 10 | #define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ |
| 11 | | (1 << 14) | (1 << 15)) | 11 | | (1 << 14) | (1 << 15)) |
| 12 | #define B43_DMAIRQ_NONFATALMASK (1 << 13) | 12 | #define B43_DMAIRQ_RDESC_UFLOW (1 << 13) |
| 13 | #define B43_DMAIRQ_RX_DONE (1 << 16) | 13 | #define B43_DMAIRQ_RX_DONE (1 << 16) |
| 14 | 14 | ||
| 15 | /*** 32-bit DMA Engine. ***/ | 15 | /*** 32-bit DMA Engine. ***/ |
| @@ -295,6 +295,8 @@ int b43_dma_tx(struct b43_wldev *dev, | |||
| 295 | void b43_dma_handle_txstatus(struct b43_wldev *dev, | 295 | void b43_dma_handle_txstatus(struct b43_wldev *dev, |
| 296 | const struct b43_txstatus *status); | 296 | const struct b43_txstatus *status); |
| 297 | 297 | ||
| 298 | void b43_dma_handle_rx_overflow(struct b43_dmaring *ring); | ||
| 299 | |||
| 298 | void b43_dma_rx(struct b43_dmaring *ring); | 300 | void b43_dma_rx(struct b43_dmaring *ring); |
| 299 | 301 | ||
| 300 | void b43_dma_direct_fifo_rx(struct b43_wldev *dev, | 302 | void b43_dma_direct_fifo_rx(struct b43_wldev *dev, |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index d377f77d30b5..6dd07e2ec595 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -1902,30 +1902,18 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
| 1902 | } | 1902 | } |
| 1903 | } | 1903 | } |
| 1904 | 1904 | ||
| 1905 | if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK | | 1905 | if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) { |
| 1906 | B43_DMAIRQ_NONFATALMASK))) { | 1906 | b43err(dev->wl, |
| 1907 | if (merged_dma_reason & B43_DMAIRQ_FATALMASK) { | 1907 | "Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n", |
| 1908 | b43err(dev->wl, "Fatal DMA error: " | 1908 | dma_reason[0], dma_reason[1], |
| 1909 | "0x%08X, 0x%08X, 0x%08X, " | 1909 | dma_reason[2], dma_reason[3], |
| 1910 | "0x%08X, 0x%08X, 0x%08X\n", | 1910 | dma_reason[4], dma_reason[5]); |
| 1911 | dma_reason[0], dma_reason[1], | 1911 | b43err(dev->wl, "This device does not support DMA " |
| 1912 | dma_reason[2], dma_reason[3], | ||
| 1913 | dma_reason[4], dma_reason[5]); | ||
| 1914 | b43err(dev->wl, "This device does not support DMA " | ||
| 1915 | "on your system. It will now be switched to PIO.\n"); | 1912 | "on your system. It will now be switched to PIO.\n"); |
| 1916 | /* Fall back to PIO transfers if we get fatal DMA errors! */ | 1913 | /* Fall back to PIO transfers if we get fatal DMA errors! */ |
| 1917 | dev->use_pio = true; | 1914 | dev->use_pio = true; |
| 1918 | b43_controller_restart(dev, "DMA error"); | 1915 | b43_controller_restart(dev, "DMA error"); |
| 1919 | return; | 1916 | return; |
| 1920 | } | ||
| 1921 | if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { | ||
| 1922 | b43err(dev->wl, "DMA error: " | ||
| 1923 | "0x%08X, 0x%08X, 0x%08X, " | ||
| 1924 | "0x%08X, 0x%08X, 0x%08X\n", | ||
| 1925 | dma_reason[0], dma_reason[1], | ||
| 1926 | dma_reason[2], dma_reason[3], | ||
| 1927 | dma_reason[4], dma_reason[5]); | ||
| 1928 | } | ||
| 1929 | } | 1917 | } |
| 1930 | 1918 | ||
| 1931 | if (unlikely(reason & B43_IRQ_UCODE_DEBUG)) | 1919 | if (unlikely(reason & B43_IRQ_UCODE_DEBUG)) |
| @@ -1944,6 +1932,11 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
| 1944 | handle_irq_noise(dev); | 1932 | handle_irq_noise(dev); |
| 1945 | 1933 | ||
| 1946 | /* Check the DMA reason registers for received data. */ | 1934 | /* Check the DMA reason registers for received data. */ |
| 1935 | if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) { | ||
| 1936 | if (B43_DEBUG) | ||
| 1937 | b43warn(dev->wl, "RX descriptor underrun\n"); | ||
| 1938 | b43_dma_handle_rx_overflow(dev->dma.rx_ring); | ||
| 1939 | } | ||
| 1947 | if (dma_reason[0] & B43_DMAIRQ_RX_DONE) { | 1940 | if (dma_reason[0] & B43_DMAIRQ_RX_DONE) { |
| 1948 | if (b43_using_pio_transfers(dev)) | 1941 | if (b43_using_pio_transfers(dev)) |
| 1949 | b43_pio_rx(dev->pio.rx_queue); | 1942 | b43_pio_rx(dev->pio.rx_queue); |
| @@ -2001,7 +1994,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev) | |||
| 2001 | return IRQ_NONE; | 1994 | return IRQ_NONE; |
| 2002 | 1995 | ||
| 2003 | dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) | 1996 | dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) |
| 2004 | & 0x0001DC00; | 1997 | & 0x0001FC00; |
| 2005 | dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON) | 1998 | dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON) |
| 2006 | & 0x0000DC00; | 1999 | & 0x0000DC00; |
| 2007 | dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON) | 2000 | dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON) |
| @@ -3130,7 +3123,7 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
| 3130 | b43_write32(dev, 0x018C, 0x02000000); | 3123 | b43_write32(dev, 0x018C, 0x02000000); |
| 3131 | } | 3124 | } |
| 3132 | b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000); | 3125 | b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000); |
| 3133 | b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00); | 3126 | b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00); |
| 3134 | b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00); | 3127 | b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00); |
| 3135 | b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00); | 3128 | b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00); |
| 3136 | b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00); | 3129 | b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00); |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index b8f82e688c72..9a95045c97b6 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
| @@ -5741,8 +5741,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) | |||
| 5741 | hw->flags = | 5741 | hw->flags = |
| 5742 | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | | 5742 | IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | |
| 5743 | IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT | | 5743 | IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT | |
| 5744 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | | 5744 | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; |
| 5745 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | ||
| 5746 | if (il->cfg->sku & IL_SKU_N) | 5745 | if (il->cfg->sku & IL_SKU_N) |
| 5747 | hw->flags |= | 5746 | hw->flags |= |
| 5748 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 5747 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index d3c8ece980d8..e42b266a023a 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
| @@ -2234,9 +2234,6 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
| 2234 | if (wdev->netdev->reg_state == NETREG_REGISTERED) | 2234 | if (wdev->netdev->reg_state == NETREG_REGISTERED) |
| 2235 | unregister_netdevice(wdev->netdev); | 2235 | unregister_netdevice(wdev->netdev); |
| 2236 | 2236 | ||
| 2237 | if (wdev->netdev->reg_state == NETREG_UNREGISTERED) | ||
| 2238 | free_netdev(wdev->netdev); | ||
| 2239 | |||
| 2240 | /* Clear the priv in adapter */ | 2237 | /* Clear the priv in adapter */ |
| 2241 | priv->netdev = NULL; | 2238 | priv->netdev = NULL; |
| 2242 | 2239 | ||
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 74db0d24a579..26755d9acb55 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
| @@ -1191,6 +1191,7 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter) | |||
| 1191 | adapter->if_ops.wakeup(adapter); | 1191 | adapter->if_ops.wakeup(adapter); |
| 1192 | adapter->hs_activated = false; | 1192 | adapter->hs_activated = false; |
| 1193 | adapter->is_hs_configured = false; | 1193 | adapter->is_hs_configured = false; |
| 1194 | adapter->is_suspended = false; | ||
| 1194 | mwifiex_hs_activated_event(mwifiex_get_priv(adapter, | 1195 | mwifiex_hs_activated_event(mwifiex_get_priv(adapter, |
| 1195 | MWIFIEX_BSS_ROLE_ANY), | 1196 | MWIFIEX_BSS_ROLE_ANY), |
| 1196 | false); | 1197 | false); |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 121443a0f2a1..2eb88ea9acf7 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
| @@ -655,6 +655,7 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv, | |||
| 655 | struct net_device *dev) | 655 | struct net_device *dev) |
| 656 | { | 656 | { |
| 657 | dev->netdev_ops = &mwifiex_netdev_ops; | 657 | dev->netdev_ops = &mwifiex_netdev_ops; |
| 658 | dev->destructor = free_netdev; | ||
| 658 | /* Initialize private structure */ | 659 | /* Initialize private structure */ |
| 659 | priv->current_key_index = 0; | 660 | priv->current_key_index = 0; |
| 660 | priv->media_connected = false; | 661 | priv->media_connected = false; |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 311d0b26b81c..1a8a19dbd635 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
| @@ -96,7 +96,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
| 96 | } else { | 96 | } else { |
| 97 | /* Multicast */ | 97 | /* Multicast */ |
| 98 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; | 98 | priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; |
| 99 | if (mcast_list->mode == MWIFIEX_MULTICAST_MODE) { | 99 | if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) { |
| 100 | dev_dbg(priv->adapter->dev, | 100 | dev_dbg(priv->adapter->dev, |
| 101 | "info: Enabling All Multicast!\n"); | 101 | "info: Enabling All Multicast!\n"); |
| 102 | priv->curr_pkt_filter |= | 102 | priv->curr_pkt_filter |= |
| @@ -108,20 +108,11 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
| 108 | dev_dbg(priv->adapter->dev, | 108 | dev_dbg(priv->adapter->dev, |
| 109 | "info: Set multicast list=%d\n", | 109 | "info: Set multicast list=%d\n", |
| 110 | mcast_list->num_multicast_addr); | 110 | mcast_list->num_multicast_addr); |
| 111 | /* Set multicast addresses to firmware */ | 111 | /* Send multicast addresses to firmware */ |
| 112 | if (old_pkt_filter == priv->curr_pkt_filter) { | 112 | ret = mwifiex_send_cmd_async(priv, |
| 113 | /* Send request to firmware */ | 113 | HostCmd_CMD_MAC_MULTICAST_ADR, |
| 114 | ret = mwifiex_send_cmd_async(priv, | 114 | HostCmd_ACT_GEN_SET, 0, |
| 115 | HostCmd_CMD_MAC_MULTICAST_ADR, | 115 | mcast_list); |
| 116 | HostCmd_ACT_GEN_SET, 0, | ||
| 117 | mcast_list); | ||
| 118 | } else { | ||
| 119 | /* Send request to firmware */ | ||
| 120 | ret = mwifiex_send_cmd_async(priv, | ||
| 121 | HostCmd_CMD_MAC_MULTICAST_ADR, | ||
| 122 | HostCmd_ACT_GEN_SET, 0, | ||
| 123 | mcast_list); | ||
| 124 | } | ||
| 125 | } | 116 | } |
| 126 | } | 117 | } |
| 127 | } | 118 | } |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index db95c547c09d..86af29f53bbe 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -1353,6 +1353,8 @@ config SCSI_LPFC | |||
| 1353 | tristate "Emulex LightPulse Fibre Channel Support" | 1353 | tristate "Emulex LightPulse Fibre Channel Support" |
| 1354 | depends on PCI && SCSI | 1354 | depends on PCI && SCSI |
| 1355 | select SCSI_FC_ATTRS | 1355 | select SCSI_FC_ATTRS |
| 1356 | select GENERIC_CSUM | ||
| 1357 | select CRC_T10DIF | ||
| 1356 | help | 1358 | help |
| 1357 | This lpfc driver supports the Emulex LightPulse | 1359 | This lpfc driver supports the Emulex LightPulse |
| 1358 | Family of Fibre Channel PCI host adapters. | 1360 | Family of Fibre Channel PCI host adapters. |
diff --git a/drivers/scsi/aic94xx/aic94xx_dev.c b/drivers/scsi/aic94xx/aic94xx_dev.c index 64136c56e706..33072388ea16 100644 --- a/drivers/scsi/aic94xx/aic94xx_dev.c +++ b/drivers/scsi/aic94xx/aic94xx_dev.c | |||
| @@ -84,7 +84,7 @@ static void asd_set_ddb_type(struct domain_device *dev) | |||
| 84 | struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; | 84 | struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; |
| 85 | int ddb = (int) (unsigned long) dev->lldd_dev; | 85 | int ddb = (int) (unsigned long) dev->lldd_dev; |
| 86 | 86 | ||
| 87 | if (dev->dev_type == SATA_PM_PORT) | 87 | if (dev->dev_type == SAS_SATA_PM_PORT) |
| 88 | asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_PM_PORT); | 88 | asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_PM_PORT); |
| 89 | else if (dev->tproto) | 89 | else if (dev->tproto) |
| 90 | asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_TARGET); | 90 | asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_TARGET); |
| @@ -116,7 +116,7 @@ void asd_set_dmamode(struct domain_device *dev) | |||
| 116 | int ddb = (int) (unsigned long) dev->lldd_dev; | 116 | int ddb = (int) (unsigned long) dev->lldd_dev; |
| 117 | u32 qdepth = 0; | 117 | u32 qdepth = 0; |
| 118 | 118 | ||
| 119 | if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM_PORT) { | 119 | if (dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM_PORT) { |
| 120 | if (ata_id_has_ncq(ata_dev->id)) | 120 | if (ata_id_has_ncq(ata_dev->id)) |
| 121 | qdepth = ata_id_queue_depth(ata_dev->id); | 121 | qdepth = ata_id_queue_depth(ata_dev->id); |
| 122 | asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, | 122 | asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, |
| @@ -140,8 +140,8 @@ static int asd_init_sata(struct domain_device *dev) | |||
| 140 | int ddb = (int) (unsigned long) dev->lldd_dev; | 140 | int ddb = (int) (unsigned long) dev->lldd_dev; |
| 141 | 141 | ||
| 142 | asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF); | 142 | asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF); |
| 143 | if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM || | 143 | if (dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM || |
| 144 | dev->dev_type == SATA_PM_PORT) { | 144 | dev->dev_type == SAS_SATA_PM_PORT) { |
| 145 | struct dev_to_host_fis *fis = (struct dev_to_host_fis *) | 145 | struct dev_to_host_fis *fis = (struct dev_to_host_fis *) |
| 146 | dev->frame_rcvd; | 146 | dev->frame_rcvd; |
| 147 | asd_ddbsite_write_byte(asd_ha, ddb, SATA_STATUS, fis->status); | 147 | asd_ddbsite_write_byte(asd_ha, ddb, SATA_STATUS, fis->status); |
| @@ -174,7 +174,7 @@ static int asd_init_target_ddb(struct domain_device *dev) | |||
| 174 | asd_ddbsite_write_byte(asd_ha, ddb, CONN_MASK, dev->port->phy_mask); | 174 | asd_ddbsite_write_byte(asd_ha, ddb, CONN_MASK, dev->port->phy_mask); |
| 175 | if (dev->port->oob_mode != SATA_OOB_MODE) { | 175 | if (dev->port->oob_mode != SATA_OOB_MODE) { |
| 176 | flags |= OPEN_REQUIRED; | 176 | flags |= OPEN_REQUIRED; |
| 177 | if ((dev->dev_type == SATA_DEV) || | 177 | if ((dev->dev_type == SAS_SATA_DEV) || |
| 178 | (dev->tproto & SAS_PROTOCOL_STP)) { | 178 | (dev->tproto & SAS_PROTOCOL_STP)) { |
| 179 | struct smp_resp *rps_resp = &dev->sata_dev.rps_resp; | 179 | struct smp_resp *rps_resp = &dev->sata_dev.rps_resp; |
| 180 | if (rps_resp->frame_type == SMP_RESPONSE && | 180 | if (rps_resp->frame_type == SMP_RESPONSE && |
| @@ -188,8 +188,8 @@ static int asd_init_target_ddb(struct domain_device *dev) | |||
| 188 | } else { | 188 | } else { |
| 189 | flags |= CONCURRENT_CONN_SUPP; | 189 | flags |= CONCURRENT_CONN_SUPP; |
| 190 | if (!dev->parent && | 190 | if (!dev->parent && |
| 191 | (dev->dev_type == EDGE_DEV || | 191 | (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || |
| 192 | dev->dev_type == FANOUT_DEV)) | 192 | dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE)) |
| 193 | asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN, | 193 | asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN, |
| 194 | 4); | 194 | 4); |
| 195 | else | 195 | else |
| @@ -198,7 +198,7 @@ static int asd_init_target_ddb(struct domain_device *dev) | |||
| 198 | asd_ddbsite_write_byte(asd_ha, ddb, NUM_CTX, 1); | 198 | asd_ddbsite_write_byte(asd_ha, ddb, NUM_CTX, 1); |
| 199 | } | 199 | } |
| 200 | } | 200 | } |
| 201 | if (dev->dev_type == SATA_PM) | 201 | if (dev->dev_type == SAS_SATA_PM) |
| 202 | flags |= SATA_MULTIPORT; | 202 | flags |= SATA_MULTIPORT; |
| 203 | asd_ddbsite_write_byte(asd_ha, ddb, DDB_TARG_FLAGS, flags); | 203 | asd_ddbsite_write_byte(asd_ha, ddb, DDB_TARG_FLAGS, flags); |
| 204 | 204 | ||
| @@ -211,7 +211,7 @@ static int asd_init_target_ddb(struct domain_device *dev) | |||
| 211 | asd_ddbsite_write_word(asd_ha, ddb, SEND_QUEUE_TAIL, 0xFFFF); | 211 | asd_ddbsite_write_word(asd_ha, ddb, SEND_QUEUE_TAIL, 0xFFFF); |
| 212 | asd_ddbsite_write_word(asd_ha, ddb, SISTER_DDB, 0xFFFF); | 212 | asd_ddbsite_write_word(asd_ha, ddb, SISTER_DDB, 0xFFFF); |
| 213 | 213 | ||
| 214 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { | 214 | if (dev->dev_type == SAS_SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) { |
| 215 | i = asd_init_sata(dev); | 215 | i = asd_init_sata(dev); |
| 216 | if (i < 0) { | 216 | if (i < 0) { |
| 217 | asd_free_ddb(asd_ha, ddb); | 217 | asd_free_ddb(asd_ha, ddb); |
| @@ -219,7 +219,7 @@ static int asd_init_target_ddb(struct domain_device *dev) | |||
| 219 | } | 219 | } |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | if (dev->dev_type == SAS_END_DEV) { | 222 | if (dev->dev_type == SAS_END_DEVICE) { |
| 223 | struct sas_end_device *rdev = rphy_to_end_device(dev->rphy); | 223 | struct sas_end_device *rdev = rphy_to_end_device(dev->rphy); |
| 224 | if (rdev->I_T_nexus_loss_timeout > 0) | 224 | if (rdev->I_T_nexus_loss_timeout > 0) |
| 225 | asd_ddbsite_write_word(asd_ha, ddb, ITNL_TIMEOUT, | 225 | asd_ddbsite_write_word(asd_ha, ddb, ITNL_TIMEOUT, |
| @@ -328,10 +328,10 @@ int asd_dev_found(struct domain_device *dev) | |||
| 328 | 328 | ||
| 329 | spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); | 329 | spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); |
| 330 | switch (dev->dev_type) { | 330 | switch (dev->dev_type) { |
| 331 | case SATA_PM: | 331 | case SAS_SATA_PM: |
| 332 | res = asd_init_sata_pm_ddb(dev); | 332 | res = asd_init_sata_pm_ddb(dev); |
| 333 | break; | 333 | break; |
| 334 | case SATA_PM_PORT: | 334 | case SAS_SATA_PM_PORT: |
| 335 | res = asd_init_sata_pm_port_ddb(dev); | 335 | res = asd_init_sata_pm_port_ddb(dev); |
| 336 | break; | 336 | break; |
| 337 | default: | 337 | default: |
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index 81b736c76fff..4df867e07b20 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c | |||
| @@ -74,7 +74,7 @@ static void asd_init_phy_identify(struct asd_phy *phy) | |||
| 74 | 74 | ||
| 75 | memset(phy->identify_frame, 0, sizeof(*phy->identify_frame)); | 75 | memset(phy->identify_frame, 0, sizeof(*phy->identify_frame)); |
| 76 | 76 | ||
| 77 | phy->identify_frame->dev_type = SAS_END_DEV; | 77 | phy->identify_frame->dev_type = SAS_END_DEVICE; |
| 78 | if (phy->sas_phy.role & PHY_ROLE_INITIATOR) | 78 | if (phy->sas_phy.role & PHY_ROLE_INITIATOR) |
| 79 | phy->identify_frame->initiator_bits = phy->sas_phy.iproto; | 79 | phy->identify_frame->initiator_bits = phy->sas_phy.iproto; |
| 80 | if (phy->sas_phy.role & PHY_ROLE_TARGET) | 80 | if (phy->sas_phy.role & PHY_ROLE_TARGET) |
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c index cf9040933da6..d4c35df3d4ae 100644 --- a/drivers/scsi/aic94xx/aic94xx_tmf.c +++ b/drivers/scsi/aic94xx/aic94xx_tmf.c | |||
| @@ -184,7 +184,7 @@ int asd_I_T_nexus_reset(struct domain_device *dev) | |||
| 184 | struct sas_phy *phy = sas_get_local_phy(dev); | 184 | struct sas_phy *phy = sas_get_local_phy(dev); |
| 185 | /* Standard mandates link reset for ATA (type 0) and | 185 | /* Standard mandates link reset for ATA (type 0) and |
| 186 | * hard reset for SSP (type 1) */ | 186 | * hard reset for SSP (type 1) */ |
| 187 | int reset_type = (dev->dev_type == SATA_DEV || | 187 | int reset_type = (dev->dev_type == SAS_SATA_DEV || |
| 188 | (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; | 188 | (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; |
| 189 | 189 | ||
| 190 | asd_clear_nexus_I_T(dev, NEXUS_PHASE_PRE); | 190 | asd_clear_nexus_I_T(dev, NEXUS_PHASE_PRE); |
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h index f1733dfa3ae2..777e7c0bbb4b 100644 --- a/drivers/scsi/be2iscsi/be.h +++ b/drivers/scsi/be2iscsi/be.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2012 Emulex | 2 | * Copyright (C) 2005 - 2013 Emulex |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c index 5c87768c109c..e66aa7c11a8a 100644 --- a/drivers/scsi/be2iscsi/be_cmds.c +++ b/drivers/scsi/be2iscsi/be_cmds.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2012 Emulex | 2 | * Copyright (C) 2005 - 2013 Emulex |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -155,6 +155,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, | |||
| 155 | uint16_t status = 0, addl_status = 0, wrb_num = 0; | 155 | uint16_t status = 0, addl_status = 0, wrb_num = 0; |
| 156 | struct be_mcc_wrb *temp_wrb; | 156 | struct be_mcc_wrb *temp_wrb; |
| 157 | struct be_cmd_req_hdr *ioctl_hdr; | 157 | struct be_cmd_req_hdr *ioctl_hdr; |
| 158 | struct be_cmd_resp_hdr *ioctl_resp_hdr; | ||
| 158 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | 159 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; |
| 159 | 160 | ||
| 160 | if (beiscsi_error(phba)) | 161 | if (beiscsi_error(phba)) |
| @@ -204,6 +205,12 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, | |||
| 204 | ioctl_hdr->subsystem, | 205 | ioctl_hdr->subsystem, |
| 205 | ioctl_hdr->opcode, | 206 | ioctl_hdr->opcode, |
| 206 | status, addl_status); | 207 | status, addl_status); |
| 208 | |||
| 209 | if (status == MCC_STATUS_INSUFFICIENT_BUFFER) { | ||
| 210 | ioctl_resp_hdr = (struct be_cmd_resp_hdr *) ioctl_hdr; | ||
| 211 | if (ioctl_resp_hdr->response_length) | ||
| 212 | goto release_mcc_tag; | ||
| 213 | } | ||
| 207 | rc = -EAGAIN; | 214 | rc = -EAGAIN; |
| 208 | } | 215 | } |
| 209 | 216 | ||
| @@ -267,6 +274,7 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, | |||
| 267 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 274 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
| 268 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | 275 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); |
| 269 | struct be_cmd_req_hdr *hdr = embedded_payload(wrb); | 276 | struct be_cmd_req_hdr *hdr = embedded_payload(wrb); |
| 277 | struct be_cmd_resp_hdr *resp_hdr; | ||
| 270 | 278 | ||
| 271 | be_dws_le_to_cpu(compl, 4); | 279 | be_dws_le_to_cpu(compl, 4); |
| 272 | 280 | ||
| @@ -284,6 +292,11 @@ static int be_mcc_compl_process(struct be_ctrl_info *ctrl, | |||
| 284 | hdr->subsystem, hdr->opcode, | 292 | hdr->subsystem, hdr->opcode, |
| 285 | compl_status, extd_status); | 293 | compl_status, extd_status); |
| 286 | 294 | ||
| 295 | if (compl_status == MCC_STATUS_INSUFFICIENT_BUFFER) { | ||
| 296 | resp_hdr = (struct be_cmd_resp_hdr *) hdr; | ||
| 297 | if (resp_hdr->response_length) | ||
| 298 | return 0; | ||
| 299 | } | ||
| 287 | return -EBUSY; | 300 | return -EBUSY; |
| 288 | } | 301 | } |
| 289 | return 0; | 302 | return 0; |
| @@ -335,30 +348,26 @@ static void be2iscsi_fail_session(struct iscsi_cls_session *cls_session) | |||
| 335 | void beiscsi_async_link_state_process(struct beiscsi_hba *phba, | 348 | void beiscsi_async_link_state_process(struct beiscsi_hba *phba, |
| 336 | struct be_async_event_link_state *evt) | 349 | struct be_async_event_link_state *evt) |
| 337 | { | 350 | { |
| 338 | switch (evt->port_link_status) { | 351 | if ((evt->port_link_status == ASYNC_EVENT_LINK_DOWN) || |
| 339 | case ASYNC_EVENT_LINK_DOWN: | 352 | ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && |
| 353 | (evt->port_fault != BEISCSI_PHY_LINK_FAULT_NONE))) { | ||
| 354 | phba->state = BE_ADAPTER_LINK_DOWN; | ||
| 355 | |||
| 340 | beiscsi_log(phba, KERN_ERR, | 356 | beiscsi_log(phba, KERN_ERR, |
| 341 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, | 357 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, |
| 342 | "BC_%d : Link Down on Physical Port %d\n", | 358 | "BC_%d : Link Down on Port %d\n", |
| 343 | evt->physical_port); | 359 | evt->physical_port); |
| 344 | 360 | ||
| 345 | phba->state |= BE_ADAPTER_LINK_DOWN; | ||
| 346 | iscsi_host_for_each_session(phba->shost, | 361 | iscsi_host_for_each_session(phba->shost, |
| 347 | be2iscsi_fail_session); | 362 | be2iscsi_fail_session); |
| 348 | break; | 363 | } else if ((evt->port_link_status & ASYNC_EVENT_LINK_UP) || |
| 349 | case ASYNC_EVENT_LINK_UP: | 364 | ((evt->port_link_status & ASYNC_EVENT_LOGICAL) && |
| 365 | (evt->port_fault == BEISCSI_PHY_LINK_FAULT_NONE))) { | ||
| 350 | phba->state = BE_ADAPTER_UP; | 366 | phba->state = BE_ADAPTER_UP; |
| 367 | |||
| 351 | beiscsi_log(phba, KERN_ERR, | 368 | beiscsi_log(phba, KERN_ERR, |
| 352 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, | 369 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, |
| 353 | "BC_%d : Link UP on Physical Port %d\n", | 370 | "BC_%d : Link UP on Port %d\n", |
| 354 | evt->physical_port); | ||
| 355 | break; | ||
| 356 | default: | ||
| 357 | beiscsi_log(phba, KERN_ERR, | ||
| 358 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_INIT, | ||
| 359 | "BC_%d : Unexpected Async Notification %d on" | ||
| 360 | "Physical Port %d\n", | ||
| 361 | evt->port_link_status, | ||
| 362 | evt->physical_port); | 371 | evt->physical_port); |
| 363 | } | 372 | } |
| 364 | } | 373 | } |
| @@ -479,7 +488,7 @@ static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) | |||
| 479 | { | 488 | { |
| 480 | void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; | 489 | void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; |
| 481 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | 490 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); |
| 482 | int wait = 0; | 491 | uint32_t wait = 0; |
| 483 | u32 ready; | 492 | u32 ready; |
| 484 | 493 | ||
| 485 | do { | 494 | do { |
| @@ -527,6 +536,10 @@ int be_mbox_notify(struct be_ctrl_info *ctrl) | |||
| 527 | struct be_mcc_compl *compl = &mbox->compl; | 536 | struct be_mcc_compl *compl = &mbox->compl; |
| 528 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | 537 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); |
| 529 | 538 | ||
| 539 | status = be_mbox_db_ready_wait(ctrl); | ||
| 540 | if (status) | ||
| 541 | return status; | ||
| 542 | |||
| 530 | val &= ~MPU_MAILBOX_DB_RDY_MASK; | 543 | val &= ~MPU_MAILBOX_DB_RDY_MASK; |
| 531 | val |= MPU_MAILBOX_DB_HI_MASK; | 544 | val |= MPU_MAILBOX_DB_HI_MASK; |
| 532 | val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; | 545 | val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; |
| @@ -580,6 +593,10 @@ static int be_mbox_notify_wait(struct beiscsi_hba *phba) | |||
| 580 | struct be_mcc_compl *compl = &mbox->compl; | 593 | struct be_mcc_compl *compl = &mbox->compl; |
| 581 | struct be_ctrl_info *ctrl = &phba->ctrl; | 594 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 582 | 595 | ||
| 596 | status = be_mbox_db_ready_wait(ctrl); | ||
| 597 | if (status) | ||
| 598 | return status; | ||
| 599 | |||
| 583 | val |= MPU_MAILBOX_DB_HI_MASK; | 600 | val |= MPU_MAILBOX_DB_HI_MASK; |
| 584 | /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ | 601 | /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ |
| 585 | val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; | 602 | val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; |
| @@ -732,6 +749,16 @@ int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, | |||
| 732 | return status; | 749 | return status; |
| 733 | } | 750 | } |
| 734 | 751 | ||
| 752 | /** | ||
| 753 | * be_cmd_fw_initialize()- Initialize FW | ||
| 754 | * @ctrl: Pointer to function control structure | ||
| 755 | * | ||
| 756 | * Send FW initialize pattern for the function. | ||
| 757 | * | ||
| 758 | * return | ||
| 759 | * Success: 0 | ||
| 760 | * Failure: Non-Zero value | ||
| 761 | **/ | ||
| 735 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) | 762 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) |
| 736 | { | 763 | { |
| 737 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 764 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
| @@ -762,6 +789,47 @@ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) | |||
| 762 | return status; | 789 | return status; |
| 763 | } | 790 | } |
| 764 | 791 | ||
| 792 | /** | ||
| 793 | * be_cmd_fw_uninit()- Uinitialize FW | ||
| 794 | * @ctrl: Pointer to function control structure | ||
| 795 | * | ||
| 796 | * Send FW uninitialize pattern for the function | ||
| 797 | * | ||
| 798 | * return | ||
| 799 | * Success: 0 | ||
| 800 | * Failure: Non-Zero value | ||
| 801 | **/ | ||
| 802 | int be_cmd_fw_uninit(struct be_ctrl_info *ctrl) | ||
| 803 | { | ||
| 804 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
| 805 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | ||
| 806 | int status; | ||
| 807 | u8 *endian_check; | ||
| 808 | |||
| 809 | spin_lock(&ctrl->mbox_lock); | ||
| 810 | memset(wrb, 0, sizeof(*wrb)); | ||
| 811 | |||
| 812 | endian_check = (u8 *) wrb; | ||
| 813 | *endian_check++ = 0xFF; | ||
| 814 | *endian_check++ = 0xAA; | ||
| 815 | *endian_check++ = 0xBB; | ||
| 816 | *endian_check++ = 0xFF; | ||
| 817 | *endian_check++ = 0xFF; | ||
| 818 | *endian_check++ = 0xCC; | ||
| 819 | *endian_check++ = 0xDD; | ||
| 820 | *endian_check = 0xFF; | ||
| 821 | |||
| 822 | be_dws_cpu_to_le(wrb, sizeof(*wrb)); | ||
| 823 | |||
| 824 | status = be_mbox_notify(ctrl); | ||
| 825 | if (status) | ||
| 826 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 827 | "BC_%d : be_cmd_fw_uninit Failed\n"); | ||
| 828 | |||
| 829 | spin_unlock(&ctrl->mbox_lock); | ||
| 830 | return status; | ||
| 831 | } | ||
| 832 | |||
| 765 | int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, | 833 | int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, |
| 766 | struct be_queue_info *cq, struct be_queue_info *eq, | 834 | struct be_queue_info *cq, struct be_queue_info *eq, |
| 767 | bool sol_evts, bool no_delay, int coalesce_wm) | 835 | bool sol_evts, bool no_delay, int coalesce_wm) |
| @@ -783,20 +851,7 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
| 783 | OPCODE_COMMON_CQ_CREATE, sizeof(*req)); | 851 | OPCODE_COMMON_CQ_CREATE, sizeof(*req)); |
| 784 | 852 | ||
| 785 | req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); | 853 | req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); |
| 786 | if (chip_skh_r(ctrl->pdev)) { | 854 | if (is_chip_be2_be3r(phba)) { |
| 787 | req->hdr.version = MBX_CMD_VER2; | ||
| 788 | req->page_size = 1; | ||
| 789 | AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm, | ||
| 790 | ctxt, coalesce_wm); | ||
| 791 | AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, | ||
| 792 | ctxt, no_delay); | ||
| 793 | AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt, | ||
| 794 | __ilog2_u32(cq->len / 256)); | ||
| 795 | AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1); | ||
| 796 | AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1); | ||
| 797 | AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id); | ||
| 798 | AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1); | ||
| 799 | } else { | ||
| 800 | AMAP_SET_BITS(struct amap_cq_context, coalescwm, | 855 | AMAP_SET_BITS(struct amap_cq_context, coalescwm, |
| 801 | ctxt, coalesce_wm); | 856 | ctxt, coalesce_wm); |
| 802 | AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); | 857 | AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); |
| @@ -809,6 +864,19 @@ int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, | |||
| 809 | AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); | 864 | AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); |
| 810 | AMAP_SET_BITS(struct amap_cq_context, func, ctxt, | 865 | AMAP_SET_BITS(struct amap_cq_context, func, ctxt, |
| 811 | PCI_FUNC(ctrl->pdev->devfn)); | 866 | PCI_FUNC(ctrl->pdev->devfn)); |
| 867 | } else { | ||
| 868 | req->hdr.version = MBX_CMD_VER2; | ||
| 869 | req->page_size = 1; | ||
| 870 | AMAP_SET_BITS(struct amap_cq_context_v2, coalescwm, | ||
| 871 | ctxt, coalesce_wm); | ||
| 872 | AMAP_SET_BITS(struct amap_cq_context_v2, nodelay, | ||
| 873 | ctxt, no_delay); | ||
| 874 | AMAP_SET_BITS(struct amap_cq_context_v2, count, ctxt, | ||
| 875 | __ilog2_u32(cq->len / 256)); | ||
| 876 | AMAP_SET_BITS(struct amap_cq_context_v2, valid, ctxt, 1); | ||
| 877 | AMAP_SET_BITS(struct amap_cq_context_v2, eventable, ctxt, 1); | ||
| 878 | AMAP_SET_BITS(struct amap_cq_context_v2, eqid, ctxt, eq->id); | ||
| 879 | AMAP_SET_BITS(struct amap_cq_context_v2, armed, ctxt, 1); | ||
| 812 | } | 880 | } |
| 813 | 881 | ||
| 814 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | 882 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); |
| @@ -949,6 +1017,7 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | |||
| 949 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 1017 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); |
| 950 | struct be_defq_create_req *req = embedded_payload(wrb); | 1018 | struct be_defq_create_req *req = embedded_payload(wrb); |
| 951 | struct be_dma_mem *q_mem = &dq->dma_mem; | 1019 | struct be_dma_mem *q_mem = &dq->dma_mem; |
| 1020 | struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev); | ||
| 952 | void *ctxt = &req->context; | 1021 | void *ctxt = &req->context; |
| 953 | int status; | 1022 | int status; |
| 954 | 1023 | ||
| @@ -961,17 +1030,36 @@ int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | |||
| 961 | OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req)); | 1030 | OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req)); |
| 962 | 1031 | ||
| 963 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | 1032 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); |
| 964 | AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid, ctxt, 0); | 1033 | |
| 965 | AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid_valid, ctxt, | 1034 | if (is_chip_be2_be3r(phba)) { |
| 966 | 1); | 1035 | AMAP_SET_BITS(struct amap_be_default_pdu_context, |
| 967 | AMAP_SET_BITS(struct amap_be_default_pdu_context, pci_func_id, ctxt, | 1036 | rx_pdid, ctxt, 0); |
| 968 | PCI_FUNC(ctrl->pdev->devfn)); | 1037 | AMAP_SET_BITS(struct amap_be_default_pdu_context, |
| 969 | AMAP_SET_BITS(struct amap_be_default_pdu_context, ring_size, ctxt, | 1038 | rx_pdid_valid, ctxt, 1); |
| 970 | be_encoded_q_len(length / sizeof(struct phys_addr))); | 1039 | AMAP_SET_BITS(struct amap_be_default_pdu_context, |
| 971 | AMAP_SET_BITS(struct amap_be_default_pdu_context, default_buffer_size, | 1040 | pci_func_id, ctxt, PCI_FUNC(ctrl->pdev->devfn)); |
| 972 | ctxt, entry_size); | 1041 | AMAP_SET_BITS(struct amap_be_default_pdu_context, |
| 973 | AMAP_SET_BITS(struct amap_be_default_pdu_context, cq_id_recv, ctxt, | 1042 | ring_size, ctxt, |
| 974 | cq->id); | 1043 | be_encoded_q_len(length / |
| 1044 | sizeof(struct phys_addr))); | ||
| 1045 | AMAP_SET_BITS(struct amap_be_default_pdu_context, | ||
| 1046 | default_buffer_size, ctxt, entry_size); | ||
| 1047 | AMAP_SET_BITS(struct amap_be_default_pdu_context, | ||
| 1048 | cq_id_recv, ctxt, cq->id); | ||
| 1049 | } else { | ||
| 1050 | AMAP_SET_BITS(struct amap_default_pdu_context_ext, | ||
| 1051 | rx_pdid, ctxt, 0); | ||
| 1052 | AMAP_SET_BITS(struct amap_default_pdu_context_ext, | ||
| 1053 | rx_pdid_valid, ctxt, 1); | ||
| 1054 | AMAP_SET_BITS(struct amap_default_pdu_context_ext, | ||
| 1055 | ring_size, ctxt, | ||
| 1056 | be_encoded_q_len(length / | ||
| 1057 | sizeof(struct phys_addr))); | ||
| 1058 | AMAP_SET_BITS(struct amap_default_pdu_context_ext, | ||
| 1059 | default_buffer_size, ctxt, entry_size); | ||
| 1060 | AMAP_SET_BITS(struct amap_default_pdu_context_ext, | ||
| 1061 | cq_id_recv, ctxt, cq->id); | ||
| 1062 | } | ||
| 975 | 1063 | ||
| 976 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | 1064 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); |
| 977 | 1065 | ||
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 23397d51ac54..99073086dfe0 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2012 Emulex | 2 | * Copyright (C) 2005 - 2013 Emulex |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -52,6 +52,10 @@ struct be_mcc_wrb { | |||
| 52 | 52 | ||
| 53 | /* Completion Status */ | 53 | /* Completion Status */ |
| 54 | #define MCC_STATUS_SUCCESS 0x0 | 54 | #define MCC_STATUS_SUCCESS 0x0 |
| 55 | #define MCC_STATUS_FAILED 0x1 | ||
| 56 | #define MCC_STATUS_ILLEGAL_REQUEST 0x2 | ||
| 57 | #define MCC_STATUS_ILLEGAL_FIELD 0x3 | ||
| 58 | #define MCC_STATUS_INSUFFICIENT_BUFFER 0x4 | ||
| 55 | 59 | ||
| 56 | #define CQE_STATUS_COMPL_MASK 0xFFFF | 60 | #define CQE_STATUS_COMPL_MASK 0xFFFF |
| 57 | #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ | 61 | #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ |
| @@ -118,7 +122,8 @@ struct be_async_event_trailer { | |||
| 118 | 122 | ||
| 119 | enum { | 123 | enum { |
| 120 | ASYNC_EVENT_LINK_DOWN = 0x0, | 124 | ASYNC_EVENT_LINK_DOWN = 0x0, |
| 121 | ASYNC_EVENT_LINK_UP = 0x1 | 125 | ASYNC_EVENT_LINK_UP = 0x1, |
| 126 | ASYNC_EVENT_LOGICAL = 0x2 | ||
| 122 | }; | 127 | }; |
| 123 | 128 | ||
| 124 | /** | 129 | /** |
| @@ -130,6 +135,9 @@ struct be_async_event_link_state { | |||
| 130 | u8 port_link_status; | 135 | u8 port_link_status; |
| 131 | u8 port_duplex; | 136 | u8 port_duplex; |
| 132 | u8 port_speed; | 137 | u8 port_speed; |
| 138 | #define BEISCSI_PHY_LINK_FAULT_NONE 0x00 | ||
| 139 | #define BEISCSI_PHY_LINK_FAULT_LOCAL 0x01 | ||
| 140 | #define BEISCSI_PHY_LINK_FAULT_REMOTE 0x02 | ||
| 133 | u8 port_fault; | 141 | u8 port_fault; |
| 134 | u8 rsvd0[7]; | 142 | u8 rsvd0[7]; |
| 135 | struct be_async_event_trailer trailer; | 143 | struct be_async_event_trailer trailer; |
| @@ -697,6 +705,7 @@ int beiscsi_mccq_compl(struct beiscsi_hba *phba, | |||
| 697 | uint32_t tag, struct be_mcc_wrb **wrb, void *cmd_va); | 705 | uint32_t tag, struct be_mcc_wrb **wrb, void *cmd_va); |
| 698 | /*ISCSI Functuions */ | 706 | /*ISCSI Functuions */ |
| 699 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); | 707 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); |
| 708 | int be_cmd_fw_uninit(struct be_ctrl_info *ctrl); | ||
| 700 | 709 | ||
| 701 | struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem); | 710 | struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem); |
| 702 | struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba); | 711 | struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba); |
| @@ -751,6 +760,18 @@ struct amap_be_default_pdu_context { | |||
| 751 | u8 rsvd4[32]; /* dword 3 */ | 760 | u8 rsvd4[32]; /* dword 3 */ |
| 752 | } __packed; | 761 | } __packed; |
| 753 | 762 | ||
| 763 | struct amap_default_pdu_context_ext { | ||
| 764 | u8 rsvd0[16]; /* dword 0 */ | ||
| 765 | u8 ring_size[4]; /* dword 0 */ | ||
| 766 | u8 rsvd1[12]; /* dword 0 */ | ||
| 767 | u8 rsvd2[22]; /* dword 1 */ | ||
| 768 | u8 rx_pdid[9]; /* dword 1 */ | ||
| 769 | u8 rx_pdid_valid; /* dword 1 */ | ||
| 770 | u8 default_buffer_size[16]; /* dword 2 */ | ||
| 771 | u8 cq_id_recv[16]; /* dword 2 */ | ||
| 772 | u8 rsvd3[32]; /* dword 3 */ | ||
| 773 | } __packed; | ||
| 774 | |||
| 754 | struct be_defq_create_req { | 775 | struct be_defq_create_req { |
| 755 | struct be_cmd_req_hdr hdr; | 776 | struct be_cmd_req_hdr hdr; |
| 756 | u16 num_pages; | 777 | u16 num_pages; |
| @@ -896,7 +917,7 @@ struct amap_it_dmsg_cqe_v2 { | |||
| 896 | * stack to notify the | 917 | * stack to notify the |
| 897 | * controller of a posted Work Request Block | 918 | * controller of a posted Work Request Block |
| 898 | */ | 919 | */ |
| 899 | #define DB_WRB_POST_CID_MASK 0x3FF /* bits 0 - 9 */ | 920 | #define DB_WRB_POST_CID_MASK 0xFFFF /* bits 0 - 16 */ |
| 900 | #define DB_DEF_PDU_WRB_INDEX_MASK 0xFF /* bits 0 - 9 */ | 921 | #define DB_DEF_PDU_WRB_INDEX_MASK 0xFF /* bits 0 - 9 */ |
| 901 | 922 | ||
| 902 | #define DB_DEF_PDU_WRB_INDEX_SHIFT 16 | 923 | #define DB_DEF_PDU_WRB_INDEX_SHIFT 16 |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 9014690fe841..ef36be003f67 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2012 Emulex | 2 | * Copyright (C) 2005 - 2013 Emulex |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -161,7 +161,9 @@ static int beiscsi_bindconn_cid(struct beiscsi_hba *phba, | |||
| 161 | struct beiscsi_conn *beiscsi_conn, | 161 | struct beiscsi_conn *beiscsi_conn, |
| 162 | unsigned int cid) | 162 | unsigned int cid) |
| 163 | { | 163 | { |
| 164 | if (phba->conn_table[cid]) { | 164 | uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); |
| 165 | |||
| 166 | if (phba->conn_table[cri_index]) { | ||
| 165 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 167 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
| 166 | "BS_%d : Connection table already occupied. Detected clash\n"); | 168 | "BS_%d : Connection table already occupied. Detected clash\n"); |
| 167 | 169 | ||
| @@ -169,9 +171,9 @@ static int beiscsi_bindconn_cid(struct beiscsi_hba *phba, | |||
| 169 | } else { | 171 | } else { |
| 170 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | 172 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 171 | "BS_%d : phba->conn_table[%d]=%p(beiscsi_conn)\n", | 173 | "BS_%d : phba->conn_table[%d]=%p(beiscsi_conn)\n", |
| 172 | cid, beiscsi_conn); | 174 | cri_index, beiscsi_conn); |
| 173 | 175 | ||
| 174 | phba->conn_table[cid] = beiscsi_conn; | 176 | phba->conn_table[cri_index] = beiscsi_conn; |
| 175 | } | 177 | } |
| 176 | return 0; | 178 | return 0; |
| 177 | } | 179 | } |
| @@ -990,9 +992,27 @@ static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) | |||
| 990 | static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) | 992 | static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) |
| 991 | { | 993 | { |
| 992 | struct beiscsi_hba *phba = beiscsi_ep->phba; | 994 | struct beiscsi_hba *phba = beiscsi_ep->phba; |
| 995 | struct beiscsi_conn *beiscsi_conn; | ||
| 993 | 996 | ||
| 994 | beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | 997 | beiscsi_put_cid(phba, beiscsi_ep->ep_cid); |
| 995 | beiscsi_ep->phba = NULL; | 998 | beiscsi_ep->phba = NULL; |
| 999 | phba->ep_array[BE_GET_CRI_FROM_CID | ||
| 1000 | (beiscsi_ep->ep_cid)] = NULL; | ||
| 1001 | |||
| 1002 | /** | ||
| 1003 | * Check if any connection resource allocated by driver | ||
| 1004 | * is to be freed.This case occurs when target redirection | ||
| 1005 | * or connection retry is done. | ||
| 1006 | **/ | ||
| 1007 | if (!beiscsi_ep->conn) | ||
| 1008 | return; | ||
| 1009 | |||
| 1010 | beiscsi_conn = beiscsi_ep->conn; | ||
| 1011 | if (beiscsi_conn->login_in_progress) { | ||
| 1012 | beiscsi_free_mgmt_task_handles(beiscsi_conn, | ||
| 1013 | beiscsi_conn->task); | ||
| 1014 | beiscsi_conn->login_in_progress = 0; | ||
| 1015 | } | ||
| 996 | } | 1016 | } |
| 997 | 1017 | ||
| 998 | /** | 1018 | /** |
| @@ -1009,7 +1029,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, | |||
| 1009 | { | 1029 | { |
| 1010 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | 1030 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; |
| 1011 | struct beiscsi_hba *phba = beiscsi_ep->phba; | 1031 | struct beiscsi_hba *phba = beiscsi_ep->phba; |
| 1012 | struct be_mcc_wrb *wrb; | ||
| 1013 | struct tcp_connect_and_offload_out *ptcpcnct_out; | 1032 | struct tcp_connect_and_offload_out *ptcpcnct_out; |
| 1014 | struct be_dma_mem nonemb_cmd; | 1033 | struct be_dma_mem nonemb_cmd; |
| 1015 | unsigned int tag; | 1034 | unsigned int tag; |
| @@ -1029,15 +1048,8 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, | |||
| 1029 | "BS_%d : In beiscsi_open_conn, ep_cid=%d\n", | 1048 | "BS_%d : In beiscsi_open_conn, ep_cid=%d\n", |
| 1030 | beiscsi_ep->ep_cid); | 1049 | beiscsi_ep->ep_cid); |
| 1031 | 1050 | ||
| 1032 | phba->ep_array[beiscsi_ep->ep_cid - | 1051 | phba->ep_array[BE_GET_CRI_FROM_CID |
| 1033 | phba->fw_config.iscsi_cid_start] = ep; | 1052 | (beiscsi_ep->ep_cid)] = ep; |
| 1034 | if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start + | ||
| 1035 | phba->params.cxns_per_ctrl * 2)) { | ||
| 1036 | |||
| 1037 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | ||
| 1038 | "BS_%d : Failed in allocate iscsi cid\n"); | ||
| 1039 | goto free_ep; | ||
| 1040 | } | ||
| 1041 | 1053 | ||
| 1042 | beiscsi_ep->cid_vld = 0; | 1054 | beiscsi_ep->cid_vld = 0; |
| 1043 | nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, | 1055 | nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, |
| @@ -1049,24 +1061,24 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, | |||
| 1049 | "BS_%d : Failed to allocate memory for" | 1061 | "BS_%d : Failed to allocate memory for" |
| 1050 | " mgmt_open_connection\n"); | 1062 | " mgmt_open_connection\n"); |
| 1051 | 1063 | ||
| 1052 | beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | 1064 | beiscsi_free_ep(beiscsi_ep); |
| 1053 | return -ENOMEM; | 1065 | return -ENOMEM; |
| 1054 | } | 1066 | } |
| 1055 | nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in); | 1067 | nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in); |
| 1056 | memset(nonemb_cmd.va, 0, nonemb_cmd.size); | 1068 | memset(nonemb_cmd.va, 0, nonemb_cmd.size); |
| 1057 | tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd); | 1069 | tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd); |
| 1058 | if (!tag) { | 1070 | if (tag <= 0) { |
| 1059 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, | 1071 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, |
| 1060 | "BS_%d : mgmt_open_connection Failed for cid=%d\n", | 1072 | "BS_%d : mgmt_open_connection Failed for cid=%d\n", |
| 1061 | beiscsi_ep->ep_cid); | 1073 | beiscsi_ep->ep_cid); |
| 1062 | 1074 | ||
| 1063 | beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | ||
| 1064 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | 1075 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, |
| 1065 | nonemb_cmd.va, nonemb_cmd.dma); | 1076 | nonemb_cmd.va, nonemb_cmd.dma); |
| 1077 | beiscsi_free_ep(beiscsi_ep); | ||
| 1066 | return -EAGAIN; | 1078 | return -EAGAIN; |
| 1067 | } | 1079 | } |
| 1068 | 1080 | ||
| 1069 | ret = beiscsi_mccq_compl(phba, tag, &wrb, NULL); | 1081 | ret = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va); |
| 1070 | if (ret) { | 1082 | if (ret) { |
| 1071 | beiscsi_log(phba, KERN_ERR, | 1083 | beiscsi_log(phba, KERN_ERR, |
| 1072 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, | 1084 | BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX, |
| @@ -1074,10 +1086,11 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, | |||
| 1074 | 1086 | ||
| 1075 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | 1087 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, |
| 1076 | nonemb_cmd.va, nonemb_cmd.dma); | 1088 | nonemb_cmd.va, nonemb_cmd.dma); |
| 1077 | goto free_ep; | 1089 | beiscsi_free_ep(beiscsi_ep); |
| 1090 | return -EBUSY; | ||
| 1078 | } | 1091 | } |
| 1079 | 1092 | ||
| 1080 | ptcpcnct_out = embedded_payload(wrb); | 1093 | ptcpcnct_out = (struct tcp_connect_and_offload_out *)nonemb_cmd.va; |
| 1081 | beiscsi_ep = ep->dd_data; | 1094 | beiscsi_ep = ep->dd_data; |
| 1082 | beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; | 1095 | beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; |
| 1083 | beiscsi_ep->cid_vld = 1; | 1096 | beiscsi_ep->cid_vld = 1; |
| @@ -1087,10 +1100,6 @@ static int beiscsi_open_conn(struct iscsi_endpoint *ep, | |||
| 1087 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | 1100 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, |
| 1088 | nonemb_cmd.va, nonemb_cmd.dma); | 1101 | nonemb_cmd.va, nonemb_cmd.dma); |
| 1089 | return 0; | 1102 | return 0; |
| 1090 | |||
| 1091 | free_ep: | ||
| 1092 | beiscsi_free_ep(beiscsi_ep); | ||
| 1093 | return -EBUSY; | ||
| 1094 | } | 1103 | } |
| 1095 | 1104 | ||
| 1096 | /** | 1105 | /** |
| @@ -1119,6 +1128,13 @@ beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | |||
| 1119 | return ERR_PTR(ret); | 1128 | return ERR_PTR(ret); |
| 1120 | } | 1129 | } |
| 1121 | 1130 | ||
| 1131 | if (beiscsi_error(phba)) { | ||
| 1132 | ret = -EIO; | ||
| 1133 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | ||
| 1134 | "BS_%d : The FW state Not Stable!!!\n"); | ||
| 1135 | return ERR_PTR(ret); | ||
| 1136 | } | ||
| 1137 | |||
| 1122 | if (phba->state != BE_ADAPTER_UP) { | 1138 | if (phba->state != BE_ADAPTER_UP) { |
| 1123 | ret = -EBUSY; | 1139 | ret = -EBUSY; |
| 1124 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, | 1140 | beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, |
| @@ -1201,8 +1217,10 @@ static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag) | |||
| 1201 | static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba, | 1217 | static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba, |
| 1202 | unsigned int cid) | 1218 | unsigned int cid) |
| 1203 | { | 1219 | { |
| 1204 | if (phba->conn_table[cid]) | 1220 | uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); |
| 1205 | phba->conn_table[cid] = NULL; | 1221 | |
| 1222 | if (phba->conn_table[cri_index]) | ||
| 1223 | phba->conn_table[cri_index] = NULL; | ||
| 1206 | else { | 1224 | else { |
| 1207 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, | 1225 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, |
| 1208 | "BS_%d : Connection table Not occupied.\n"); | 1226 | "BS_%d : Connection table Not occupied.\n"); |
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h index 38eab7232159..31ddc8494398 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.h +++ b/drivers/scsi/be2iscsi/be_iscsi.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2012 Emulex | 2 | * Copyright (C) 2005 - 2013 Emulex |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 4e2733d23003..d24a2867bc21 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2012 Emulex | 2 | * Copyright (C) 2005 - 2013 Emulex |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -153,10 +153,14 @@ BEISCSI_RW_ATTR(log_enable, 0x00, | |||
| 153 | 153 | ||
| 154 | DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL); | 154 | DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL); |
| 155 | DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL); | 155 | DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL); |
| 156 | DEVICE_ATTR(beiscsi_fw_ver, S_IRUGO, beiscsi_fw_ver_disp, NULL); | ||
| 157 | DEVICE_ATTR(beiscsi_active_cid_count, S_IRUGO, beiscsi_active_cid_disp, NULL); | ||
| 156 | struct device_attribute *beiscsi_attrs[] = { | 158 | struct device_attribute *beiscsi_attrs[] = { |
| 157 | &dev_attr_beiscsi_log_enable, | 159 | &dev_attr_beiscsi_log_enable, |
| 158 | &dev_attr_beiscsi_drvr_ver, | 160 | &dev_attr_beiscsi_drvr_ver, |
| 159 | &dev_attr_beiscsi_adapter_family, | 161 | &dev_attr_beiscsi_adapter_family, |
| 162 | &dev_attr_beiscsi_fw_ver, | ||
| 163 | &dev_attr_beiscsi_active_cid_count, | ||
| 160 | NULL, | 164 | NULL, |
| 161 | }; | 165 | }; |
| 162 | 166 | ||
| @@ -702,7 +706,7 @@ static void beiscsi_get_params(struct beiscsi_hba *phba) | |||
| 702 | + BE2_TMFS | 706 | + BE2_TMFS |
| 703 | + BE2_NOPOUT_REQ)); | 707 | + BE2_NOPOUT_REQ)); |
| 704 | phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count; | 708 | phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count; |
| 705 | phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count * 2; | 709 | phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count; |
| 706 | phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count; | 710 | phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count; |
| 707 | phba->params.num_sge_per_io = BE2_SGE; | 711 | phba->params.num_sge_per_io = BE2_SGE; |
| 708 | phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; | 712 | phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; |
| @@ -1032,7 +1036,6 @@ static void hwi_ring_cq_db(struct beiscsi_hba *phba, | |||
| 1032 | static unsigned int | 1036 | static unsigned int |
| 1033 | beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, | 1037 | beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, |
| 1034 | struct beiscsi_hba *phba, | 1038 | struct beiscsi_hba *phba, |
| 1035 | unsigned short cid, | ||
| 1036 | struct pdu_base *ppdu, | 1039 | struct pdu_base *ppdu, |
| 1037 | unsigned long pdu_len, | 1040 | unsigned long pdu_len, |
| 1038 | void *pbuffer, unsigned long buf_len) | 1041 | void *pbuffer, unsigned long buf_len) |
| @@ -1144,9 +1147,10 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid) | |||
| 1144 | struct hwi_wrb_context *pwrb_context; | 1147 | struct hwi_wrb_context *pwrb_context; |
| 1145 | struct hwi_controller *phwi_ctrlr; | 1148 | struct hwi_controller *phwi_ctrlr; |
| 1146 | struct wrb_handle *pwrb_handle, *pwrb_handle_tmp; | 1149 | struct wrb_handle *pwrb_handle, *pwrb_handle_tmp; |
| 1150 | uint16_t cri_index = BE_GET_CRI_FROM_CID(cid); | ||
| 1147 | 1151 | ||
| 1148 | phwi_ctrlr = phba->phwi_ctrlr; | 1152 | phwi_ctrlr = phba->phwi_ctrlr; |
| 1149 | pwrb_context = &phwi_ctrlr->wrb_context[cid]; | 1153 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; |
| 1150 | if (pwrb_context->wrb_handles_available >= 2) { | 1154 | if (pwrb_context->wrb_handles_available >= 2) { |
| 1151 | pwrb_handle = pwrb_context->pwrb_handle_base[ | 1155 | pwrb_handle = pwrb_context->pwrb_handle_base[ |
| 1152 | pwrb_context->alloc_index]; | 1156 | pwrb_context->alloc_index]; |
| @@ -1322,8 +1326,9 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn, | |||
| 1322 | hdr->t2retain = 0; | 1326 | hdr->t2retain = 0; |
| 1323 | hdr->flags = csol_cqe->i_flags; | 1327 | hdr->flags = csol_cqe->i_flags; |
| 1324 | hdr->response = csol_cqe->i_resp; | 1328 | hdr->response = csol_cqe->i_resp; |
| 1325 | hdr->exp_cmdsn = csol_cqe->exp_cmdsn; | 1329 | hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); |
| 1326 | hdr->max_cmdsn = (csol_cqe->exp_cmdsn + csol_cqe->cmd_wnd - 1); | 1330 | hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn + |
| 1331 | csol_cqe->cmd_wnd - 1); | ||
| 1327 | 1332 | ||
| 1328 | hdr->dlength[0] = 0; | 1333 | hdr->dlength[0] = 0; |
| 1329 | hdr->dlength[1] = 0; | 1334 | hdr->dlength[1] = 0; |
| @@ -1346,9 +1351,9 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn, | |||
| 1346 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP; | 1351 | hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP; |
| 1347 | hdr->flags = csol_cqe->i_flags; | 1352 | hdr->flags = csol_cqe->i_flags; |
| 1348 | hdr->response = csol_cqe->i_resp; | 1353 | hdr->response = csol_cqe->i_resp; |
| 1349 | hdr->exp_cmdsn = csol_cqe->exp_cmdsn; | 1354 | hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); |
| 1350 | hdr->max_cmdsn = (csol_cqe->exp_cmdsn + | 1355 | hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn + |
| 1351 | csol_cqe->cmd_wnd - 1); | 1356 | csol_cqe->cmd_wnd - 1); |
| 1352 | 1357 | ||
| 1353 | hdr->itt = io_task->libiscsi_itt; | 1358 | hdr->itt = io_task->libiscsi_itt; |
| 1354 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); | 1359 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); |
| @@ -1363,35 +1368,29 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, | |||
| 1363 | struct hwi_controller *phwi_ctrlr; | 1368 | struct hwi_controller *phwi_ctrlr; |
| 1364 | struct iscsi_task *task; | 1369 | struct iscsi_task *task; |
| 1365 | struct beiscsi_io_task *io_task; | 1370 | struct beiscsi_io_task *io_task; |
| 1366 | struct iscsi_conn *conn = beiscsi_conn->conn; | 1371 | uint16_t wrb_index, cid, cri_index; |
| 1367 | struct iscsi_session *session = conn->session; | ||
| 1368 | uint16_t wrb_index, cid; | ||
| 1369 | 1372 | ||
| 1370 | phwi_ctrlr = phba->phwi_ctrlr; | 1373 | phwi_ctrlr = phba->phwi_ctrlr; |
| 1371 | if (chip_skh_r(phba->pcidev)) { | 1374 | if (is_chip_be2_be3r(phba)) { |
| 1372 | wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2, | 1375 | wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe, |
| 1373 | wrb_idx, psol); | 1376 | wrb_idx, psol); |
| 1374 | cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2, | 1377 | cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe, |
| 1375 | cid, psol); | 1378 | cid, psol); |
| 1376 | } else { | 1379 | } else { |
| 1377 | wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe, | 1380 | wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2, |
| 1378 | wrb_idx, psol); | 1381 | wrb_idx, psol); |
| 1379 | cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe, | 1382 | cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2, |
| 1380 | cid, psol); | 1383 | cid, psol); |
| 1381 | } | 1384 | } |
| 1382 | 1385 | ||
| 1383 | pwrb_context = &phwi_ctrlr->wrb_context[ | 1386 | cri_index = BE_GET_CRI_FROM_CID(cid); |
| 1384 | cid - phba->fw_config.iscsi_cid_start]; | 1387 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; |
| 1385 | pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index]; | 1388 | pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index]; |
| 1386 | task = pwrb_handle->pio_handle; | 1389 | task = pwrb_handle->pio_handle; |
| 1387 | 1390 | ||
| 1388 | io_task = task->dd_data; | 1391 | io_task = task->dd_data; |
| 1389 | spin_lock_bh(&phba->mgmt_sgl_lock); | 1392 | memset(io_task->pwrb_handle->pwrb, 0, sizeof(struct iscsi_wrb)); |
| 1390 | free_mgmt_sgl_handle(phba, io_task->psgl_handle); | 1393 | iscsi_put_task(task); |
| 1391 | spin_unlock_bh(&phba->mgmt_sgl_lock); | ||
| 1392 | spin_lock_bh(&session->lock); | ||
| 1393 | free_wrb_handle(phba, pwrb_context, pwrb_handle); | ||
| 1394 | spin_unlock_bh(&session->lock); | ||
| 1395 | } | 1394 | } |
| 1396 | 1395 | ||
| 1397 | static void | 1396 | static void |
| @@ -1406,8 +1405,8 @@ be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn, | |||
| 1406 | hdr = (struct iscsi_nopin *)task->hdr; | 1405 | hdr = (struct iscsi_nopin *)task->hdr; |
| 1407 | hdr->flags = csol_cqe->i_flags; | 1406 | hdr->flags = csol_cqe->i_flags; |
| 1408 | hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); | 1407 | hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); |
| 1409 | hdr->max_cmdsn = be32_to_cpu(hdr->exp_cmdsn + | 1408 | hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn + |
| 1410 | csol_cqe->cmd_wnd - 1); | 1409 | csol_cqe->cmd_wnd - 1); |
| 1411 | 1410 | ||
| 1412 | hdr->opcode = ISCSI_OP_NOOP_IN; | 1411 | hdr->opcode = ISCSI_OP_NOOP_IN; |
| 1413 | hdr->itt = io_task->libiscsi_itt; | 1412 | hdr->itt = io_task->libiscsi_itt; |
| @@ -1418,7 +1417,26 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba, | |||
| 1418 | struct sol_cqe *psol, | 1417 | struct sol_cqe *psol, |
| 1419 | struct common_sol_cqe *csol_cqe) | 1418 | struct common_sol_cqe *csol_cqe) |
| 1420 | { | 1419 | { |
| 1421 | if (chip_skh_r(phba->pcidev)) { | 1420 | if (is_chip_be2_be3r(phba)) { |
| 1421 | csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1422 | i_exp_cmd_sn, psol); | ||
| 1423 | csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1424 | i_res_cnt, psol); | ||
| 1425 | csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1426 | i_cmd_wnd, psol); | ||
| 1427 | csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1428 | wrb_index, psol); | ||
| 1429 | csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1430 | cid, psol); | ||
| 1431 | csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1432 | hw_sts, psol); | ||
| 1433 | csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1434 | i_resp, psol); | ||
| 1435 | csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1436 | i_sts, psol); | ||
| 1437 | csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1438 | i_flags, psol); | ||
| 1439 | } else { | ||
| 1422 | csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe_v2, | 1440 | csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe_v2, |
| 1423 | i_exp_cmd_sn, psol); | 1441 | i_exp_cmd_sn, psol); |
| 1424 | csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe_v2, | 1442 | csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe_v2, |
| @@ -1429,7 +1447,7 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba, | |||
| 1429 | cid, psol); | 1447 | cid, psol); |
| 1430 | csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2, | 1448 | csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2, |
| 1431 | hw_sts, psol); | 1449 | hw_sts, psol); |
| 1432 | csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe, | 1450 | csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe_v2, |
| 1433 | i_cmd_wnd, psol); | 1451 | i_cmd_wnd, psol); |
| 1434 | if (AMAP_GET_BITS(struct amap_sol_cqe_v2, | 1452 | if (AMAP_GET_BITS(struct amap_sol_cqe_v2, |
| 1435 | cmd_cmpl, psol)) | 1453 | cmd_cmpl, psol)) |
| @@ -1445,25 +1463,6 @@ static void adapter_get_sol_cqe(struct beiscsi_hba *phba, | |||
| 1445 | if (AMAP_GET_BITS(struct amap_sol_cqe_v2, | 1463 | if (AMAP_GET_BITS(struct amap_sol_cqe_v2, |
| 1446 | o, psol)) | 1464 | o, psol)) |
| 1447 | csol_cqe->i_flags |= ISCSI_FLAG_CMD_OVERFLOW; | 1465 | csol_cqe->i_flags |= ISCSI_FLAG_CMD_OVERFLOW; |
| 1448 | } else { | ||
| 1449 | csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1450 | i_exp_cmd_sn, psol); | ||
| 1451 | csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1452 | i_res_cnt, psol); | ||
| 1453 | csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1454 | i_cmd_wnd, psol); | ||
| 1455 | csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1456 | wrb_index, psol); | ||
| 1457 | csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1458 | cid, psol); | ||
| 1459 | csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1460 | hw_sts, psol); | ||
| 1461 | csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1462 | i_resp, psol); | ||
| 1463 | csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1464 | i_sts, psol); | ||
| 1465 | csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe, | ||
| 1466 | i_flags, psol); | ||
| 1467 | } | 1466 | } |
| 1468 | } | 1467 | } |
| 1469 | 1468 | ||
| @@ -1480,14 +1479,15 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, | |||
| 1480 | struct iscsi_conn *conn = beiscsi_conn->conn; | 1479 | struct iscsi_conn *conn = beiscsi_conn->conn; |
| 1481 | struct iscsi_session *session = conn->session; | 1480 | struct iscsi_session *session = conn->session; |
| 1482 | struct common_sol_cqe csol_cqe = {0}; | 1481 | struct common_sol_cqe csol_cqe = {0}; |
| 1482 | uint16_t cri_index = 0; | ||
| 1483 | 1483 | ||
| 1484 | phwi_ctrlr = phba->phwi_ctrlr; | 1484 | phwi_ctrlr = phba->phwi_ctrlr; |
| 1485 | 1485 | ||
| 1486 | /* Copy the elements to a common structure */ | 1486 | /* Copy the elements to a common structure */ |
| 1487 | adapter_get_sol_cqe(phba, psol, &csol_cqe); | 1487 | adapter_get_sol_cqe(phba, psol, &csol_cqe); |
| 1488 | 1488 | ||
| 1489 | pwrb_context = &phwi_ctrlr->wrb_context[ | 1489 | cri_index = BE_GET_CRI_FROM_CID(csol_cqe.cid); |
| 1490 | csol_cqe.cid - phba->fw_config.iscsi_cid_start]; | 1490 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; |
| 1491 | 1491 | ||
| 1492 | pwrb_handle = pwrb_context->pwrb_handle_basestd[ | 1492 | pwrb_handle = pwrb_context->pwrb_handle_basestd[ |
| 1493 | csol_cqe.wrb_index]; | 1493 | csol_cqe.wrb_index]; |
| @@ -1561,15 +1561,15 @@ hwi_get_async_handle(struct beiscsi_hba *phba, | |||
| 1561 | unsigned char is_header = 0; | 1561 | unsigned char is_header = 0; |
| 1562 | unsigned int index, dpl; | 1562 | unsigned int index, dpl; |
| 1563 | 1563 | ||
| 1564 | if (chip_skh_r(phba->pcidev)) { | 1564 | if (is_chip_be2_be3r(phba)) { |
| 1565 | dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, | 1565 | dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, |
| 1566 | dpl, pdpdu_cqe); | 1566 | dpl, pdpdu_cqe); |
| 1567 | index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, | 1567 | index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, |
| 1568 | index, pdpdu_cqe); | 1568 | index, pdpdu_cqe); |
| 1569 | } else { | 1569 | } else { |
| 1570 | dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, | 1570 | dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, |
| 1571 | dpl, pdpdu_cqe); | 1571 | dpl, pdpdu_cqe); |
| 1572 | index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, | 1572 | index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, |
| 1573 | index, pdpdu_cqe); | 1573 | index, pdpdu_cqe); |
| 1574 | } | 1574 | } |
| 1575 | 1575 | ||
| @@ -1613,8 +1613,8 @@ hwi_get_async_handle(struct beiscsi_hba *phba, | |||
| 1613 | 1613 | ||
| 1614 | WARN_ON(!pasync_handle); | 1614 | WARN_ON(!pasync_handle); |
| 1615 | 1615 | ||
| 1616 | pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid - | 1616 | pasync_handle->cri = |
| 1617 | phba->fw_config.iscsi_cid_start; | 1617 | BE_GET_CRI_FROM_CID(beiscsi_conn->beiscsi_conn_cid); |
| 1618 | pasync_handle->is_header = is_header; | 1618 | pasync_handle->is_header = is_header; |
| 1619 | pasync_handle->buffer_len = dpl; | 1619 | pasync_handle->buffer_len = dpl; |
| 1620 | *pcq_index = index; | 1620 | *pcq_index = index; |
| @@ -1856,8 +1856,6 @@ hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn, | |||
| 1856 | } | 1856 | } |
| 1857 | 1857 | ||
| 1858 | status = beiscsi_process_async_pdu(beiscsi_conn, phba, | 1858 | status = beiscsi_process_async_pdu(beiscsi_conn, phba, |
| 1859 | (beiscsi_conn->beiscsi_conn_cid - | ||
| 1860 | phba->fw_config.iscsi_cid_start), | ||
| 1861 | phdr, hdr_len, pfirst_buffer, | 1859 | phdr, hdr_len, pfirst_buffer, |
| 1862 | offset); | 1860 | offset); |
| 1863 | 1861 | ||
| @@ -2011,6 +2009,7 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) | |||
| 2011 | unsigned int num_processed = 0; | 2009 | unsigned int num_processed = 0; |
| 2012 | unsigned int tot_nump = 0; | 2010 | unsigned int tot_nump = 0; |
| 2013 | unsigned short code = 0, cid = 0; | 2011 | unsigned short code = 0, cid = 0; |
| 2012 | uint16_t cri_index = 0; | ||
| 2014 | struct beiscsi_conn *beiscsi_conn; | 2013 | struct beiscsi_conn *beiscsi_conn; |
| 2015 | struct beiscsi_endpoint *beiscsi_ep; | 2014 | struct beiscsi_endpoint *beiscsi_ep; |
| 2016 | struct iscsi_endpoint *ep; | 2015 | struct iscsi_endpoint *ep; |
| @@ -2028,7 +2027,9 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) | |||
| 2028 | 32] & CQE_CODE_MASK); | 2027 | 32] & CQE_CODE_MASK); |
| 2029 | 2028 | ||
| 2030 | /* Get the CID */ | 2029 | /* Get the CID */ |
| 2031 | if (chip_skh_r(phba->pcidev)) { | 2030 | if (is_chip_be2_be3r(phba)) { |
| 2031 | cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol); | ||
| 2032 | } else { | ||
| 2032 | if ((code == DRIVERMSG_NOTIFY) || | 2033 | if ((code == DRIVERMSG_NOTIFY) || |
| 2033 | (code == UNSOL_HDR_NOTIFY) || | 2034 | (code == UNSOL_HDR_NOTIFY) || |
| 2034 | (code == UNSOL_DATA_NOTIFY)) | 2035 | (code == UNSOL_DATA_NOTIFY)) |
| @@ -2038,10 +2039,10 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq) | |||
| 2038 | else | 2039 | else |
| 2039 | cid = AMAP_GET_BITS(struct amap_sol_cqe_v2, | 2040 | cid = AMAP_GET_BITS(struct amap_sol_cqe_v2, |
| 2040 | cid, sol); | 2041 | cid, sol); |
| 2041 | } else | 2042 | } |
| 2042 | cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol); | ||
| 2043 | 2043 | ||
| 2044 | ep = phba->ep_array[cid - phba->fw_config.iscsi_cid_start]; | 2044 | cri_index = BE_GET_CRI_FROM_CID(cid); |
| 2045 | ep = phba->ep_array[cri_index]; | ||
| 2045 | beiscsi_ep = ep->dd_data; | 2046 | beiscsi_ep = ep->dd_data; |
| 2046 | beiscsi_conn = beiscsi_ep->conn; | 2047 | beiscsi_conn = beiscsi_ep->conn; |
| 2047 | 2048 | ||
| @@ -2191,7 +2192,7 @@ void beiscsi_process_all_cqs(struct work_struct *work) | |||
| 2191 | 2192 | ||
| 2192 | static int be_iopoll(struct blk_iopoll *iop, int budget) | 2193 | static int be_iopoll(struct blk_iopoll *iop, int budget) |
| 2193 | { | 2194 | { |
| 2194 | static unsigned int ret; | 2195 | unsigned int ret; |
| 2195 | struct beiscsi_hba *phba; | 2196 | struct beiscsi_hba *phba; |
| 2196 | struct be_eq_obj *pbe_eq; | 2197 | struct be_eq_obj *pbe_eq; |
| 2197 | 2198 | ||
| @@ -2416,11 +2417,11 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) | |||
| 2416 | /* Check for the data_count */ | 2417 | /* Check for the data_count */ |
| 2417 | dsp_value = (task->data_count) ? 1 : 0; | 2418 | dsp_value = (task->data_count) ? 1 : 0; |
| 2418 | 2419 | ||
| 2419 | if (chip_skh_r(phba->pcidev)) | 2420 | if (is_chip_be2_be3r(phba)) |
| 2420 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, | 2421 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, |
| 2421 | pwrb, dsp_value); | 2422 | pwrb, dsp_value); |
| 2422 | else | 2423 | else |
| 2423 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, | 2424 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, |
| 2424 | pwrb, dsp_value); | 2425 | pwrb, dsp_value); |
| 2425 | 2426 | ||
| 2426 | /* Map addr only if there is data_count */ | 2427 | /* Map addr only if there is data_count */ |
| @@ -2538,8 +2539,9 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba) | |||
| 2538 | 2539 | ||
| 2539 | static int beiscsi_alloc_mem(struct beiscsi_hba *phba) | 2540 | static int beiscsi_alloc_mem(struct beiscsi_hba *phba) |
| 2540 | { | 2541 | { |
| 2541 | struct be_mem_descriptor *mem_descr; | ||
| 2542 | dma_addr_t bus_add; | 2542 | dma_addr_t bus_add; |
| 2543 | struct hwi_controller *phwi_ctrlr; | ||
| 2544 | struct be_mem_descriptor *mem_descr; | ||
| 2543 | struct mem_array *mem_arr, *mem_arr_orig; | 2545 | struct mem_array *mem_arr, *mem_arr_orig; |
| 2544 | unsigned int i, j, alloc_size, curr_alloc_size; | 2546 | unsigned int i, j, alloc_size, curr_alloc_size; |
| 2545 | 2547 | ||
| @@ -2547,9 +2549,18 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba) | |||
| 2547 | if (!phba->phwi_ctrlr) | 2549 | if (!phba->phwi_ctrlr) |
| 2548 | return -ENOMEM; | 2550 | return -ENOMEM; |
| 2549 | 2551 | ||
| 2552 | /* Allocate memory for wrb_context */ | ||
| 2553 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 2554 | phwi_ctrlr->wrb_context = kzalloc(sizeof(struct hwi_wrb_context) * | ||
| 2555 | phba->params.cxns_per_ctrl, | ||
| 2556 | GFP_KERNEL); | ||
| 2557 | if (!phwi_ctrlr->wrb_context) | ||
| 2558 | return -ENOMEM; | ||
| 2559 | |||
| 2550 | phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr), | 2560 | phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr), |
| 2551 | GFP_KERNEL); | 2561 | GFP_KERNEL); |
| 2552 | if (!phba->init_mem) { | 2562 | if (!phba->init_mem) { |
| 2563 | kfree(phwi_ctrlr->wrb_context); | ||
| 2553 | kfree(phba->phwi_ctrlr); | 2564 | kfree(phba->phwi_ctrlr); |
| 2554 | return -ENOMEM; | 2565 | return -ENOMEM; |
| 2555 | } | 2566 | } |
| @@ -2558,6 +2569,7 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba) | |||
| 2558 | GFP_KERNEL); | 2569 | GFP_KERNEL); |
| 2559 | if (!mem_arr_orig) { | 2570 | if (!mem_arr_orig) { |
| 2560 | kfree(phba->init_mem); | 2571 | kfree(phba->init_mem); |
| 2572 | kfree(phwi_ctrlr->wrb_context); | ||
| 2561 | kfree(phba->phwi_ctrlr); | 2573 | kfree(phba->phwi_ctrlr); |
| 2562 | return -ENOMEM; | 2574 | return -ENOMEM; |
| 2563 | } | 2575 | } |
| @@ -2628,6 +2640,7 @@ free_mem: | |||
| 2628 | } | 2640 | } |
| 2629 | kfree(mem_arr_orig); | 2641 | kfree(mem_arr_orig); |
| 2630 | kfree(phba->init_mem); | 2642 | kfree(phba->init_mem); |
| 2643 | kfree(phba->phwi_ctrlr->wrb_context); | ||
| 2631 | kfree(phba->phwi_ctrlr); | 2644 | kfree(phba->phwi_ctrlr); |
| 2632 | return -ENOMEM; | 2645 | return -ENOMEM; |
| 2633 | } | 2646 | } |
| @@ -2666,6 +2679,7 @@ static void iscsi_init_global_templates(struct beiscsi_hba *phba) | |||
| 2666 | static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | 2679 | static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba) |
| 2667 | { | 2680 | { |
| 2668 | struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb; | 2681 | struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb; |
| 2682 | struct hwi_context_memory *phwi_ctxt; | ||
| 2669 | struct wrb_handle *pwrb_handle = NULL; | 2683 | struct wrb_handle *pwrb_handle = NULL; |
| 2670 | struct hwi_controller *phwi_ctrlr; | 2684 | struct hwi_controller *phwi_ctrlr; |
| 2671 | struct hwi_wrb_context *pwrb_context; | 2685 | struct hwi_wrb_context *pwrb_context; |
| @@ -2680,7 +2694,18 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | |||
| 2680 | mem_descr_wrb += HWI_MEM_WRB; | 2694 | mem_descr_wrb += HWI_MEM_WRB; |
| 2681 | phwi_ctrlr = phba->phwi_ctrlr; | 2695 | phwi_ctrlr = phba->phwi_ctrlr; |
| 2682 | 2696 | ||
| 2683 | for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { | 2697 | /* Allocate memory for WRBQ */ |
| 2698 | phwi_ctxt = phwi_ctrlr->phwi_ctxt; | ||
| 2699 | phwi_ctxt->be_wrbq = kzalloc(sizeof(struct be_queue_info) * | ||
| 2700 | phba->fw_config.iscsi_cid_count, | ||
| 2701 | GFP_KERNEL); | ||
| 2702 | if (!phwi_ctxt->be_wrbq) { | ||
| 2703 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 2704 | "BM_%d : WRBQ Mem Alloc Failed\n"); | ||
| 2705 | return -ENOMEM; | ||
| 2706 | } | ||
| 2707 | |||
| 2708 | for (index = 0; index < phba->params.cxns_per_ctrl; index++) { | ||
| 2684 | pwrb_context = &phwi_ctrlr->wrb_context[index]; | 2709 | pwrb_context = &phwi_ctrlr->wrb_context[index]; |
| 2685 | pwrb_context->pwrb_handle_base = | 2710 | pwrb_context->pwrb_handle_base = |
| 2686 | kzalloc(sizeof(struct wrb_handle *) * | 2711 | kzalloc(sizeof(struct wrb_handle *) * |
| @@ -2723,7 +2748,7 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | |||
| 2723 | } | 2748 | } |
| 2724 | } | 2749 | } |
| 2725 | idx = 0; | 2750 | idx = 0; |
| 2726 | for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { | 2751 | for (index = 0; index < phba->params.cxns_per_ctrl; index++) { |
| 2727 | pwrb_context = &phwi_ctrlr->wrb_context[index]; | 2752 | pwrb_context = &phwi_ctrlr->wrb_context[index]; |
| 2728 | if (!num_cxn_wrb) { | 2753 | if (!num_cxn_wrb) { |
| 2729 | pwrb = mem_descr_wrb->mem_array[idx].virtual_address; | 2754 | pwrb = mem_descr_wrb->mem_array[idx].virtual_address; |
| @@ -2752,7 +2777,7 @@ init_wrb_hndl_failed: | |||
| 2752 | return -ENOMEM; | 2777 | return -ENOMEM; |
| 2753 | } | 2778 | } |
| 2754 | 2779 | ||
| 2755 | static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) | 2780 | static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) |
| 2756 | { | 2781 | { |
| 2757 | struct hwi_controller *phwi_ctrlr; | 2782 | struct hwi_controller *phwi_ctrlr; |
| 2758 | struct hba_parameters *p = &phba->params; | 2783 | struct hba_parameters *p = &phba->params; |
| @@ -2770,6 +2795,15 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) | |||
| 2770 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx; | 2795 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx; |
| 2771 | memset(pasync_ctx, 0, sizeof(*pasync_ctx)); | 2796 | memset(pasync_ctx, 0, sizeof(*pasync_ctx)); |
| 2772 | 2797 | ||
| 2798 | pasync_ctx->async_entry = kzalloc(sizeof(struct hwi_async_entry) * | ||
| 2799 | phba->fw_config.iscsi_cid_count, | ||
| 2800 | GFP_KERNEL); | ||
| 2801 | if (!pasync_ctx->async_entry) { | ||
| 2802 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 2803 | "BM_%d : hwi_init_async_pdu_ctx Mem Alloc Failed\n"); | ||
| 2804 | return -ENOMEM; | ||
| 2805 | } | ||
| 2806 | |||
| 2773 | pasync_ctx->num_entries = p->asyncpdus_per_ctrl; | 2807 | pasync_ctx->num_entries = p->asyncpdus_per_ctrl; |
| 2774 | pasync_ctx->buffer_size = p->defpdu_hdr_sz; | 2808 | pasync_ctx->buffer_size = p->defpdu_hdr_sz; |
| 2775 | 2809 | ||
| @@ -2934,6 +2968,8 @@ static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) | |||
| 2934 | pasync_ctx->async_header.ep_read_ptr = -1; | 2968 | pasync_ctx->async_header.ep_read_ptr = -1; |
| 2935 | pasync_ctx->async_data.host_write_ptr = 0; | 2969 | pasync_ctx->async_data.host_write_ptr = 0; |
| 2936 | pasync_ctx->async_data.ep_read_ptr = -1; | 2970 | pasync_ctx->async_data.ep_read_ptr = -1; |
| 2971 | |||
| 2972 | return 0; | ||
| 2937 | } | 2973 | } |
| 2938 | 2974 | ||
| 2939 | static int | 2975 | static int |
| @@ -3293,6 +3329,7 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba, | |||
| 3293 | void *wrb_vaddr; | 3329 | void *wrb_vaddr; |
| 3294 | struct be_dma_mem sgl; | 3330 | struct be_dma_mem sgl; |
| 3295 | struct be_mem_descriptor *mem_descr; | 3331 | struct be_mem_descriptor *mem_descr; |
| 3332 | struct hwi_wrb_context *pwrb_context; | ||
| 3296 | int status; | 3333 | int status; |
| 3297 | 3334 | ||
| 3298 | idx = 0; | 3335 | idx = 0; |
| @@ -3351,8 +3388,9 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba, | |||
| 3351 | kfree(pwrb_arr); | 3388 | kfree(pwrb_arr); |
| 3352 | return status; | 3389 | return status; |
| 3353 | } | 3390 | } |
| 3354 | phwi_ctrlr->wrb_context[i * 2].cid = phwi_context->be_wrbq[i]. | 3391 | pwrb_context = &phwi_ctrlr->wrb_context[i]; |
| 3355 | id; | 3392 | pwrb_context->cid = phwi_context->be_wrbq[i].id; |
| 3393 | BE_SET_CID_TO_CRI(i, pwrb_context->cid); | ||
| 3356 | } | 3394 | } |
| 3357 | kfree(pwrb_arr); | 3395 | kfree(pwrb_arr); |
| 3358 | return 0; | 3396 | return 0; |
| @@ -3365,7 +3403,7 @@ static void free_wrb_handles(struct beiscsi_hba *phba) | |||
| 3365 | struct hwi_wrb_context *pwrb_context; | 3403 | struct hwi_wrb_context *pwrb_context; |
| 3366 | 3404 | ||
| 3367 | phwi_ctrlr = phba->phwi_ctrlr; | 3405 | phwi_ctrlr = phba->phwi_ctrlr; |
| 3368 | for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { | 3406 | for (index = 0; index < phba->params.cxns_per_ctrl; index++) { |
| 3369 | pwrb_context = &phwi_ctrlr->wrb_context[index]; | 3407 | pwrb_context = &phwi_ctrlr->wrb_context[index]; |
| 3370 | kfree(pwrb_context->pwrb_handle_base); | 3408 | kfree(pwrb_context->pwrb_handle_base); |
| 3371 | kfree(pwrb_context->pwrb_handle_basestd); | 3409 | kfree(pwrb_context->pwrb_handle_basestd); |
| @@ -3394,6 +3432,7 @@ static void hwi_cleanup(struct beiscsi_hba *phba) | |||
| 3394 | struct be_ctrl_info *ctrl = &phba->ctrl; | 3432 | struct be_ctrl_info *ctrl = &phba->ctrl; |
| 3395 | struct hwi_controller *phwi_ctrlr; | 3433 | struct hwi_controller *phwi_ctrlr; |
| 3396 | struct hwi_context_memory *phwi_context; | 3434 | struct hwi_context_memory *phwi_context; |
| 3435 | struct hwi_async_pdu_context *pasync_ctx; | ||
| 3397 | int i, eq_num; | 3436 | int i, eq_num; |
| 3398 | 3437 | ||
| 3399 | phwi_ctrlr = phba->phwi_ctrlr; | 3438 | phwi_ctrlr = phba->phwi_ctrlr; |
| @@ -3403,6 +3442,7 @@ static void hwi_cleanup(struct beiscsi_hba *phba) | |||
| 3403 | if (q->created) | 3442 | if (q->created) |
| 3404 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ); | 3443 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ); |
| 3405 | } | 3444 | } |
| 3445 | kfree(phwi_context->be_wrbq); | ||
| 3406 | free_wrb_handles(phba); | 3446 | free_wrb_handles(phba); |
| 3407 | 3447 | ||
| 3408 | q = &phwi_context->be_def_hdrq; | 3448 | q = &phwi_context->be_def_hdrq; |
| @@ -3430,6 +3470,10 @@ static void hwi_cleanup(struct beiscsi_hba *phba) | |||
| 3430 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ); | 3470 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ); |
| 3431 | } | 3471 | } |
| 3432 | be_mcc_queues_destroy(phba); | 3472 | be_mcc_queues_destroy(phba); |
| 3473 | |||
| 3474 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx; | ||
| 3475 | kfree(pasync_ctx->async_entry); | ||
| 3476 | be_cmd_fw_uninit(ctrl); | ||
| 3433 | } | 3477 | } |
| 3434 | 3478 | ||
| 3435 | static int be_mcc_queues_create(struct beiscsi_hba *phba, | 3479 | static int be_mcc_queues_create(struct beiscsi_hba *phba, |
| @@ -3607,7 +3651,12 @@ static int hwi_init_controller(struct beiscsi_hba *phba) | |||
| 3607 | if (beiscsi_init_wrb_handle(phba)) | 3651 | if (beiscsi_init_wrb_handle(phba)) |
| 3608 | return -ENOMEM; | 3652 | return -ENOMEM; |
| 3609 | 3653 | ||
| 3610 | hwi_init_async_pdu_ctx(phba); | 3654 | if (hwi_init_async_pdu_ctx(phba)) { |
| 3655 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 3656 | "BM_%d : hwi_init_async_pdu_ctx failed\n"); | ||
| 3657 | return -ENOMEM; | ||
| 3658 | } | ||
| 3659 | |||
| 3611 | if (hwi_init_port(phba) != 0) { | 3660 | if (hwi_init_port(phba) != 0) { |
| 3612 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3661 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 3613 | "BM_%d : hwi_init_controller failed\n"); | 3662 | "BM_%d : hwi_init_controller failed\n"); |
| @@ -3637,6 +3686,7 @@ static void beiscsi_free_mem(struct beiscsi_hba *phba) | |||
| 3637 | mem_descr++; | 3686 | mem_descr++; |
| 3638 | } | 3687 | } |
| 3639 | kfree(phba->init_mem); | 3688 | kfree(phba->init_mem); |
| 3689 | kfree(phba->phwi_ctrlr->wrb_context); | ||
| 3640 | kfree(phba->phwi_ctrlr); | 3690 | kfree(phba->phwi_ctrlr); |
| 3641 | } | 3691 | } |
| 3642 | 3692 | ||
| @@ -3769,7 +3819,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) | |||
| 3769 | 3819 | ||
| 3770 | static int hba_setup_cid_tbls(struct beiscsi_hba *phba) | 3820 | static int hba_setup_cid_tbls(struct beiscsi_hba *phba) |
| 3771 | { | 3821 | { |
| 3772 | int i, new_cid; | 3822 | int i; |
| 3773 | 3823 | ||
| 3774 | phba->cid_array = kzalloc(sizeof(void *) * phba->params.cxns_per_ctrl, | 3824 | phba->cid_array = kzalloc(sizeof(void *) * phba->params.cxns_per_ctrl, |
| 3775 | GFP_KERNEL); | 3825 | GFP_KERNEL); |
| @@ -3780,19 +3830,33 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba) | |||
| 3780 | return -ENOMEM; | 3830 | return -ENOMEM; |
| 3781 | } | 3831 | } |
| 3782 | phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) * | 3832 | phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) * |
| 3783 | phba->params.cxns_per_ctrl * 2, GFP_KERNEL); | 3833 | phba->params.cxns_per_ctrl, GFP_KERNEL); |
| 3784 | if (!phba->ep_array) { | 3834 | if (!phba->ep_array) { |
| 3785 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 3835 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 3786 | "BM_%d : Failed to allocate memory in " | 3836 | "BM_%d : Failed to allocate memory in " |
| 3787 | "hba_setup_cid_tbls\n"); | 3837 | "hba_setup_cid_tbls\n"); |
| 3788 | kfree(phba->cid_array); | 3838 | kfree(phba->cid_array); |
| 3839 | phba->cid_array = NULL; | ||
| 3789 | return -ENOMEM; | 3840 | return -ENOMEM; |
| 3790 | } | 3841 | } |
| 3791 | new_cid = phba->fw_config.iscsi_cid_start; | 3842 | |
| 3792 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { | 3843 | phba->conn_table = kzalloc(sizeof(struct beiscsi_conn *) * |
| 3793 | phba->cid_array[i] = new_cid; | 3844 | phba->params.cxns_per_ctrl, GFP_KERNEL); |
| 3794 | new_cid += 2; | 3845 | if (!phba->conn_table) { |
| 3846 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | ||
| 3847 | "BM_%d : Failed to allocate memory in" | ||
| 3848 | "hba_setup_cid_tbls\n"); | ||
| 3849 | |||
| 3850 | kfree(phba->cid_array); | ||
| 3851 | kfree(phba->ep_array); | ||
| 3852 | phba->cid_array = NULL; | ||
| 3853 | phba->ep_array = NULL; | ||
| 3854 | return -ENOMEM; | ||
| 3795 | } | 3855 | } |
| 3856 | |||
| 3857 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) | ||
| 3858 | phba->cid_array[i] = phba->phwi_ctrlr->wrb_context[i].cid; | ||
| 3859 | |||
| 3796 | phba->avlbl_cids = phba->params.cxns_per_ctrl; | 3860 | phba->avlbl_cids = phba->params.cxns_per_ctrl; |
| 3797 | return 0; | 3861 | return 0; |
| 3798 | } | 3862 | } |
| @@ -4062,6 +4126,53 @@ static void beiscsi_clean_port(struct beiscsi_hba *phba) | |||
| 4062 | kfree(phba->eh_sgl_hndl_base); | 4126 | kfree(phba->eh_sgl_hndl_base); |
| 4063 | kfree(phba->cid_array); | 4127 | kfree(phba->cid_array); |
| 4064 | kfree(phba->ep_array); | 4128 | kfree(phba->ep_array); |
| 4129 | kfree(phba->conn_table); | ||
| 4130 | } | ||
| 4131 | |||
| 4132 | /** | ||
| 4133 | * beiscsi_free_mgmt_task_handles()- Free driver CXN resources | ||
| 4134 | * @beiscsi_conn: ptr to the conn to be cleaned up | ||
| 4135 | * @task: ptr to iscsi_task resource to be freed. | ||
| 4136 | * | ||
| 4137 | * Free driver mgmt resources binded to CXN. | ||
| 4138 | **/ | ||
| 4139 | void | ||
| 4140 | beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn, | ||
| 4141 | struct iscsi_task *task) | ||
| 4142 | { | ||
| 4143 | struct beiscsi_io_task *io_task; | ||
| 4144 | struct beiscsi_hba *phba = beiscsi_conn->phba; | ||
| 4145 | struct hwi_wrb_context *pwrb_context; | ||
| 4146 | struct hwi_controller *phwi_ctrlr; | ||
| 4147 | uint16_t cri_index = BE_GET_CRI_FROM_CID( | ||
| 4148 | beiscsi_conn->beiscsi_conn_cid); | ||
| 4149 | |||
| 4150 | phwi_ctrlr = phba->phwi_ctrlr; | ||
| 4151 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; | ||
| 4152 | |||
| 4153 | io_task = task->dd_data; | ||
| 4154 | |||
| 4155 | if (io_task->pwrb_handle) { | ||
| 4156 | memset(io_task->pwrb_handle->pwrb, 0, | ||
| 4157 | sizeof(struct iscsi_wrb)); | ||
| 4158 | free_wrb_handle(phba, pwrb_context, | ||
| 4159 | io_task->pwrb_handle); | ||
| 4160 | io_task->pwrb_handle = NULL; | ||
| 4161 | } | ||
| 4162 | |||
| 4163 | if (io_task->psgl_handle) { | ||
| 4164 | spin_lock_bh(&phba->mgmt_sgl_lock); | ||
| 4165 | free_mgmt_sgl_handle(phba, | ||
| 4166 | io_task->psgl_handle); | ||
| 4167 | io_task->psgl_handle = NULL; | ||
| 4168 | spin_unlock_bh(&phba->mgmt_sgl_lock); | ||
| 4169 | } | ||
| 4170 | |||
| 4171 | if (io_task->mtask_addr) | ||
| 4172 | pci_unmap_single(phba->pcidev, | ||
| 4173 | io_task->mtask_addr, | ||
| 4174 | io_task->mtask_data_count, | ||
| 4175 | PCI_DMA_TODEVICE); | ||
| 4065 | } | 4176 | } |
| 4066 | 4177 | ||
| 4067 | /** | 4178 | /** |
| @@ -4078,10 +4189,11 @@ static void beiscsi_cleanup_task(struct iscsi_task *task) | |||
| 4078 | struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess; | 4189 | struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess; |
| 4079 | struct hwi_wrb_context *pwrb_context; | 4190 | struct hwi_wrb_context *pwrb_context; |
| 4080 | struct hwi_controller *phwi_ctrlr; | 4191 | struct hwi_controller *phwi_ctrlr; |
| 4192 | uint16_t cri_index = BE_GET_CRI_FROM_CID( | ||
| 4193 | beiscsi_conn->beiscsi_conn_cid); | ||
| 4081 | 4194 | ||
| 4082 | phwi_ctrlr = phba->phwi_ctrlr; | 4195 | phwi_ctrlr = phba->phwi_ctrlr; |
| 4083 | pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid | 4196 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; |
| 4084 | - phba->fw_config.iscsi_cid_start]; | ||
| 4085 | 4197 | ||
| 4086 | if (io_task->cmd_bhs) { | 4198 | if (io_task->cmd_bhs) { |
| 4087 | pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, | 4199 | pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, |
| @@ -4103,27 +4215,8 @@ static void beiscsi_cleanup_task(struct iscsi_task *task) | |||
| 4103 | io_task->psgl_handle = NULL; | 4215 | io_task->psgl_handle = NULL; |
| 4104 | } | 4216 | } |
| 4105 | } else { | 4217 | } else { |
| 4106 | if (!beiscsi_conn->login_in_progress) { | 4218 | if (!beiscsi_conn->login_in_progress) |
| 4107 | if (io_task->pwrb_handle) { | 4219 | beiscsi_free_mgmt_task_handles(beiscsi_conn, task); |
| 4108 | free_wrb_handle(phba, pwrb_context, | ||
| 4109 | io_task->pwrb_handle); | ||
| 4110 | io_task->pwrb_handle = NULL; | ||
| 4111 | } | ||
| 4112 | if (io_task->psgl_handle) { | ||
| 4113 | spin_lock(&phba->mgmt_sgl_lock); | ||
| 4114 | free_mgmt_sgl_handle(phba, | ||
| 4115 | io_task->psgl_handle); | ||
| 4116 | spin_unlock(&phba->mgmt_sgl_lock); | ||
| 4117 | io_task->psgl_handle = NULL; | ||
| 4118 | } | ||
| 4119 | if (io_task->mtask_addr) { | ||
| 4120 | pci_unmap_single(phba->pcidev, | ||
| 4121 | io_task->mtask_addr, | ||
| 4122 | io_task->mtask_data_count, | ||
| 4123 | PCI_DMA_TODEVICE); | ||
| 4124 | io_task->mtask_addr = 0; | ||
| 4125 | } | ||
| 4126 | } | ||
| 4127 | } | 4220 | } |
| 4128 | } | 4221 | } |
| 4129 | 4222 | ||
| @@ -4146,15 +4239,14 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, | |||
| 4146 | beiscsi_cleanup_task(task); | 4239 | beiscsi_cleanup_task(task); |
| 4147 | spin_unlock_bh(&session->lock); | 4240 | spin_unlock_bh(&session->lock); |
| 4148 | 4241 | ||
| 4149 | pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid - | 4242 | pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid); |
| 4150 | phba->fw_config.iscsi_cid_start)); | ||
| 4151 | 4243 | ||
| 4152 | /* Check for the adapter family */ | 4244 | /* Check for the adapter family */ |
| 4153 | if (chip_skh_r(phba->pcidev)) | 4245 | if (is_chip_be2_be3r(phba)) |
| 4154 | beiscsi_offload_cxn_v2(params, pwrb_handle); | ||
| 4155 | else | ||
| 4156 | beiscsi_offload_cxn_v0(params, pwrb_handle, | 4246 | beiscsi_offload_cxn_v0(params, pwrb_handle, |
| 4157 | phba->init_mem); | 4247 | phba->init_mem); |
| 4248 | else | ||
| 4249 | beiscsi_offload_cxn_v2(params, pwrb_handle); | ||
| 4158 | 4250 | ||
| 4159 | be_dws_le_to_cpu(pwrb_handle->pwrb, | 4251 | be_dws_le_to_cpu(pwrb_handle->pwrb, |
| 4160 | sizeof(struct iscsi_target_context_update_wrb)); | 4252 | sizeof(struct iscsi_target_context_update_wrb)); |
| @@ -4194,6 +4286,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) | |||
| 4194 | struct hwi_wrb_context *pwrb_context; | 4286 | struct hwi_wrb_context *pwrb_context; |
| 4195 | struct hwi_controller *phwi_ctrlr; | 4287 | struct hwi_controller *phwi_ctrlr; |
| 4196 | itt_t itt; | 4288 | itt_t itt; |
| 4289 | uint16_t cri_index = 0; | ||
| 4197 | struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess; | 4290 | struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess; |
| 4198 | dma_addr_t paddr; | 4291 | dma_addr_t paddr; |
| 4199 | 4292 | ||
| @@ -4223,8 +4316,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) | |||
| 4223 | goto free_hndls; | 4316 | goto free_hndls; |
| 4224 | } | 4317 | } |
| 4225 | io_task->pwrb_handle = alloc_wrb_handle(phba, | 4318 | io_task->pwrb_handle = alloc_wrb_handle(phba, |
| 4226 | beiscsi_conn->beiscsi_conn_cid - | 4319 | beiscsi_conn->beiscsi_conn_cid); |
| 4227 | phba->fw_config.iscsi_cid_start); | ||
| 4228 | if (!io_task->pwrb_handle) { | 4320 | if (!io_task->pwrb_handle) { |
| 4229 | beiscsi_log(phba, KERN_ERR, | 4321 | beiscsi_log(phba, KERN_ERR, |
| 4230 | BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, | 4322 | BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, |
| @@ -4236,6 +4328,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) | |||
| 4236 | } else { | 4328 | } else { |
| 4237 | io_task->scsi_cmnd = NULL; | 4329 | io_task->scsi_cmnd = NULL; |
| 4238 | if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) { | 4330 | if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) { |
| 4331 | beiscsi_conn->task = task; | ||
| 4239 | if (!beiscsi_conn->login_in_progress) { | 4332 | if (!beiscsi_conn->login_in_progress) { |
| 4240 | spin_lock(&phba->mgmt_sgl_lock); | 4333 | spin_lock(&phba->mgmt_sgl_lock); |
| 4241 | io_task->psgl_handle = (struct sgl_handle *) | 4334 | io_task->psgl_handle = (struct sgl_handle *) |
| @@ -4257,8 +4350,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) | |||
| 4257 | io_task->psgl_handle; | 4350 | io_task->psgl_handle; |
| 4258 | io_task->pwrb_handle = | 4351 | io_task->pwrb_handle = |
| 4259 | alloc_wrb_handle(phba, | 4352 | alloc_wrb_handle(phba, |
| 4260 | beiscsi_conn->beiscsi_conn_cid - | 4353 | beiscsi_conn->beiscsi_conn_cid); |
| 4261 | phba->fw_config.iscsi_cid_start); | ||
| 4262 | if (!io_task->pwrb_handle) { | 4354 | if (!io_task->pwrb_handle) { |
| 4263 | beiscsi_log(phba, KERN_ERR, | 4355 | beiscsi_log(phba, KERN_ERR, |
| 4264 | BEISCSI_LOG_IO | | 4356 | BEISCSI_LOG_IO | |
| @@ -4278,7 +4370,6 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) | |||
| 4278 | io_task->pwrb_handle = | 4370 | io_task->pwrb_handle = |
| 4279 | beiscsi_conn->plogin_wrb_handle; | 4371 | beiscsi_conn->plogin_wrb_handle; |
| 4280 | } | 4372 | } |
| 4281 | beiscsi_conn->task = task; | ||
| 4282 | } else { | 4373 | } else { |
| 4283 | spin_lock(&phba->mgmt_sgl_lock); | 4374 | spin_lock(&phba->mgmt_sgl_lock); |
| 4284 | io_task->psgl_handle = alloc_mgmt_sgl_handle(phba); | 4375 | io_task->psgl_handle = alloc_mgmt_sgl_handle(phba); |
| @@ -4295,8 +4386,7 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) | |||
| 4295 | } | 4386 | } |
| 4296 | io_task->pwrb_handle = | 4387 | io_task->pwrb_handle = |
| 4297 | alloc_wrb_handle(phba, | 4388 | alloc_wrb_handle(phba, |
| 4298 | beiscsi_conn->beiscsi_conn_cid - | 4389 | beiscsi_conn->beiscsi_conn_cid); |
| 4299 | phba->fw_config.iscsi_cid_start); | ||
| 4300 | if (!io_task->pwrb_handle) { | 4390 | if (!io_task->pwrb_handle) { |
| 4301 | beiscsi_log(phba, KERN_ERR, | 4391 | beiscsi_log(phba, KERN_ERR, |
| 4302 | BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, | 4392 | BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, |
| @@ -4324,12 +4414,13 @@ free_io_hndls: | |||
| 4324 | free_mgmt_hndls: | 4414 | free_mgmt_hndls: |
| 4325 | spin_lock(&phba->mgmt_sgl_lock); | 4415 | spin_lock(&phba->mgmt_sgl_lock); |
| 4326 | free_mgmt_sgl_handle(phba, io_task->psgl_handle); | 4416 | free_mgmt_sgl_handle(phba, io_task->psgl_handle); |
| 4417 | io_task->psgl_handle = NULL; | ||
| 4327 | spin_unlock(&phba->mgmt_sgl_lock); | 4418 | spin_unlock(&phba->mgmt_sgl_lock); |
| 4328 | free_hndls: | 4419 | free_hndls: |
| 4329 | phwi_ctrlr = phba->phwi_ctrlr; | 4420 | phwi_ctrlr = phba->phwi_ctrlr; |
| 4330 | pwrb_context = &phwi_ctrlr->wrb_context[ | 4421 | cri_index = BE_GET_CRI_FROM_CID( |
| 4331 | beiscsi_conn->beiscsi_conn_cid - | 4422 | beiscsi_conn->beiscsi_conn_cid); |
| 4332 | phba->fw_config.iscsi_cid_start]; | 4423 | pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; |
| 4333 | if (io_task->pwrb_handle) | 4424 | if (io_task->pwrb_handle) |
| 4334 | free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); | 4425 | free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); |
| 4335 | io_task->pwrb_handle = NULL; | 4426 | io_task->pwrb_handle = NULL; |
| @@ -4351,7 +4442,6 @@ int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg, | |||
| 4351 | unsigned int doorbell = 0; | 4442 | unsigned int doorbell = 0; |
| 4352 | 4443 | ||
| 4353 | pwrb = io_task->pwrb_handle->pwrb; | 4444 | pwrb = io_task->pwrb_handle->pwrb; |
| 4354 | memset(pwrb, 0, sizeof(*pwrb)); | ||
| 4355 | 4445 | ||
| 4356 | io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; | 4446 | io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; |
| 4357 | io_task->bhs_len = sizeof(struct be_cmd_bhs); | 4447 | io_task->bhs_len = sizeof(struct be_cmd_bhs); |
| @@ -4465,19 +4555,7 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
| 4465 | pwrb = io_task->pwrb_handle->pwrb; | 4555 | pwrb = io_task->pwrb_handle->pwrb; |
| 4466 | memset(pwrb, 0, sizeof(*pwrb)); | 4556 | memset(pwrb, 0, sizeof(*pwrb)); |
| 4467 | 4557 | ||
| 4468 | if (chip_skh_r(phba->pcidev)) { | 4558 | if (is_chip_be2_be3r(phba)) { |
| 4469 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb, | ||
| 4470 | be32_to_cpu(task->cmdsn)); | ||
| 4471 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb, | ||
| 4472 | io_task->pwrb_handle->wrb_index); | ||
| 4473 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb, | ||
| 4474 | io_task->psgl_handle->sgl_index); | ||
| 4475 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, | ||
| 4476 | task->data_count); | ||
| 4477 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, | ||
| 4478 | io_task->pwrb_handle->nxt_wrb_index); | ||
| 4479 | pwrb_typeoffset = SKH_WRB_TYPE_OFFSET; | ||
| 4480 | } else { | ||
| 4481 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, | 4559 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, |
| 4482 | be32_to_cpu(task->cmdsn)); | 4560 | be32_to_cpu(task->cmdsn)); |
| 4483 | AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, | 4561 | AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, |
| @@ -4489,6 +4567,18 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
| 4489 | AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, | 4567 | AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, |
| 4490 | io_task->pwrb_handle->nxt_wrb_index); | 4568 | io_task->pwrb_handle->nxt_wrb_index); |
| 4491 | pwrb_typeoffset = BE_WRB_TYPE_OFFSET; | 4569 | pwrb_typeoffset = BE_WRB_TYPE_OFFSET; |
| 4570 | } else { | ||
| 4571 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb, | ||
| 4572 | be32_to_cpu(task->cmdsn)); | ||
| 4573 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb, | ||
| 4574 | io_task->pwrb_handle->wrb_index); | ||
| 4575 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb, | ||
| 4576 | io_task->psgl_handle->sgl_index); | ||
| 4577 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, | ||
| 4578 | task->data_count); | ||
| 4579 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, | ||
| 4580 | io_task->pwrb_handle->nxt_wrb_index); | ||
| 4581 | pwrb_typeoffset = SKH_WRB_TYPE_OFFSET; | ||
| 4492 | } | 4582 | } |
| 4493 | 4583 | ||
| 4494 | 4584 | ||
| @@ -4501,19 +4591,19 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
| 4501 | case ISCSI_OP_NOOP_OUT: | 4591 | case ISCSI_OP_NOOP_OUT: |
| 4502 | if (task->hdr->ttt != ISCSI_RESERVED_TAG) { | 4592 | if (task->hdr->ttt != ISCSI_RESERVED_TAG) { |
| 4503 | ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset); | 4593 | ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset); |
| 4504 | if (chip_skh_r(phba->pcidev)) | 4594 | if (is_chip_be2_be3r(phba)) |
| 4505 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, | 4595 | AMAP_SET_BITS(struct amap_iscsi_wrb, |
| 4506 | dmsg, pwrb, 1); | 4596 | dmsg, pwrb, 1); |
| 4507 | else | 4597 | else |
| 4508 | AMAP_SET_BITS(struct amap_iscsi_wrb, | 4598 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, |
| 4509 | dmsg, pwrb, 1); | 4599 | dmsg, pwrb, 1); |
| 4510 | } else { | 4600 | } else { |
| 4511 | ADAPTER_SET_WRB_TYPE(pwrb, INI_RD_CMD, pwrb_typeoffset); | 4601 | ADAPTER_SET_WRB_TYPE(pwrb, INI_RD_CMD, pwrb_typeoffset); |
| 4512 | if (chip_skh_r(phba->pcidev)) | 4602 | if (is_chip_be2_be3r(phba)) |
| 4513 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, | 4603 | AMAP_SET_BITS(struct amap_iscsi_wrb, |
| 4514 | dmsg, pwrb, 0); | 4604 | dmsg, pwrb, 0); |
| 4515 | else | 4605 | else |
| 4516 | AMAP_SET_BITS(struct amap_iscsi_wrb, | 4606 | AMAP_SET_BITS(struct amap_iscsi_wrb_v2, |
| 4517 | dmsg, pwrb, 0); | 4607 | dmsg, pwrb, 0); |
| 4518 | } | 4608 | } |
| 4519 | hwi_write_buffer(pwrb, task); | 4609 | hwi_write_buffer(pwrb, task); |
| @@ -4540,9 +4630,9 @@ static int beiscsi_mtask(struct iscsi_task *task) | |||
| 4540 | } | 4630 | } |
| 4541 | 4631 | ||
| 4542 | /* Set the task type */ | 4632 | /* Set the task type */ |
| 4543 | io_task->wrb_type = (chip_skh_r(phba->pcidev)) ? | 4633 | io_task->wrb_type = (is_chip_be2_be3r(phba)) ? |
| 4544 | AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb) : | 4634 | AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb) : |
| 4545 | AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb); | 4635 | AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb); |
| 4546 | 4636 | ||
| 4547 | doorbell |= cid & DB_WRB_POST_CID_MASK; | 4637 | doorbell |= cid & DB_WRB_POST_CID_MASK; |
| 4548 | doorbell |= (io_task->pwrb_handle->wrb_index & | 4638 | doorbell |= (io_task->pwrb_handle->wrb_index & |
| @@ -4834,6 +4924,7 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev, | |||
| 4834 | case OC_SKH_ID1: | 4924 | case OC_SKH_ID1: |
| 4835 | phba->generation = BE_GEN4; | 4925 | phba->generation = BE_GEN4; |
| 4836 | phba->iotask_fn = beiscsi_iotask_v2; | 4926 | phba->iotask_fn = beiscsi_iotask_v2; |
| 4927 | break; | ||
| 4837 | default: | 4928 | default: |
| 4838 | phba->generation = 0; | 4929 | phba->generation = 0; |
| 4839 | } | 4930 | } |
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index 5946577d79d6..2c06ef3c02ac 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2012 Emulex | 2 | * Copyright (C) 2005 - 2013 Emulex |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -36,7 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | #include "be.h" | 37 | #include "be.h" |
| 38 | #define DRV_NAME "be2iscsi" | 38 | #define DRV_NAME "be2iscsi" |
| 39 | #define BUILD_STR "10.0.272.0" | 39 | #define BUILD_STR "10.0.467.0" |
| 40 | #define BE_NAME "Emulex OneConnect" \ | 40 | #define BE_NAME "Emulex OneConnect" \ |
| 41 | "Open-iSCSI Driver version" BUILD_STR | 41 | "Open-iSCSI Driver version" BUILD_STR |
| 42 | #define DRV_DESC BE_NAME " " "Driver" | 42 | #define DRV_DESC BE_NAME " " "Driver" |
| @@ -66,8 +66,9 @@ | |||
| 66 | 66 | ||
| 67 | #define MAX_CPUS 64 | 67 | #define MAX_CPUS 64 |
| 68 | #define BEISCSI_MAX_NUM_CPUS 7 | 68 | #define BEISCSI_MAX_NUM_CPUS 7 |
| 69 | #define OC_SKH_MAX_NUM_CPUS 63 | 69 | #define OC_SKH_MAX_NUM_CPUS 31 |
| 70 | 70 | ||
| 71 | #define BEISCSI_VER_STRLEN 32 | ||
| 71 | 72 | ||
| 72 | #define BEISCSI_SGLIST_ELEMENTS 30 | 73 | #define BEISCSI_SGLIST_ELEMENTS 30 |
| 73 | 74 | ||
| @@ -265,7 +266,9 @@ struct invalidate_command_table { | |||
| 265 | unsigned short cid; | 266 | unsigned short cid; |
| 266 | } __packed; | 267 | } __packed; |
| 267 | 268 | ||
| 268 | #define chip_skh_r(pdev) (pdev->device == OC_SKH_ID1) | 269 | #define chip_be2(phba) (phba->generation == BE_GEN2) |
| 270 | #define chip_be3_r(phba) (phba->generation == BE_GEN3) | ||
| 271 | #define is_chip_be2_be3r(phba) (chip_be3_r(phba) || (chip_be2(phba))) | ||
| 269 | struct beiscsi_hba { | 272 | struct beiscsi_hba { |
| 270 | struct hba_parameters params; | 273 | struct hba_parameters params; |
| 271 | struct hwi_controller *phwi_ctrlr; | 274 | struct hwi_controller *phwi_ctrlr; |
| @@ -304,10 +307,15 @@ struct beiscsi_hba { | |||
| 304 | unsigned short avlbl_cids; | 307 | unsigned short avlbl_cids; |
| 305 | unsigned short cid_alloc; | 308 | unsigned short cid_alloc; |
| 306 | unsigned short cid_free; | 309 | unsigned short cid_free; |
| 307 | struct beiscsi_conn *conn_table[BE2_MAX_SESSIONS * 2]; | ||
| 308 | struct list_head hba_queue; | 310 | struct list_head hba_queue; |
| 311 | #define BE_MAX_SESSION 2048 | ||
| 312 | #define BE_SET_CID_TO_CRI(cri_index, cid) \ | ||
| 313 | (phba->cid_to_cri_map[cid] = cri_index) | ||
| 314 | #define BE_GET_CRI_FROM_CID(cid) (phba->cid_to_cri_map[cid]) | ||
| 315 | unsigned short cid_to_cri_map[BE_MAX_SESSION]; | ||
| 309 | unsigned short *cid_array; | 316 | unsigned short *cid_array; |
| 310 | struct iscsi_endpoint **ep_array; | 317 | struct iscsi_endpoint **ep_array; |
| 318 | struct beiscsi_conn **conn_table; | ||
| 311 | struct iscsi_boot_kset *boot_kset; | 319 | struct iscsi_boot_kset *boot_kset; |
| 312 | struct Scsi_Host *shost; | 320 | struct Scsi_Host *shost; |
| 313 | struct iscsi_iface *ipv4_iface; | 321 | struct iscsi_iface *ipv4_iface; |
| @@ -339,6 +347,7 @@ struct beiscsi_hba { | |||
| 339 | struct delayed_work beiscsi_hw_check_task; | 347 | struct delayed_work beiscsi_hw_check_task; |
| 340 | 348 | ||
| 341 | u8 mac_address[ETH_ALEN]; | 349 | u8 mac_address[ETH_ALEN]; |
| 350 | char fw_ver_str[BEISCSI_VER_STRLEN]; | ||
| 342 | char wq_name[20]; | 351 | char wq_name[20]; |
| 343 | struct workqueue_struct *wq; /* The actuak work queue */ | 352 | struct workqueue_struct *wq; /* The actuak work queue */ |
| 344 | struct be_ctrl_info ctrl; | 353 | struct be_ctrl_info ctrl; |
| @@ -563,7 +572,7 @@ struct hwi_async_pdu_context { | |||
| 563 | * This is a varying size list! Do not add anything | 572 | * This is a varying size list! Do not add anything |
| 564 | * after this entry!! | 573 | * after this entry!! |
| 565 | */ | 574 | */ |
| 566 | struct hwi_async_entry async_entry[BE2_MAX_SESSIONS * 2]; | 575 | struct hwi_async_entry *async_entry; |
| 567 | }; | 576 | }; |
| 568 | 577 | ||
| 569 | #define PDUCQE_CODE_MASK 0x0000003F | 578 | #define PDUCQE_CODE_MASK 0x0000003F |
| @@ -749,6 +758,8 @@ void | |||
| 749 | free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle); | 758 | free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle); |
| 750 | 759 | ||
| 751 | void beiscsi_process_all_cqs(struct work_struct *work); | 760 | void beiscsi_process_all_cqs(struct work_struct *work); |
| 761 | void beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn, | ||
| 762 | struct iscsi_task *task); | ||
| 752 | 763 | ||
| 753 | static inline bool beiscsi_error(struct beiscsi_hba *phba) | 764 | static inline bool beiscsi_error(struct beiscsi_hba *phba) |
| 754 | { | 765 | { |
| @@ -933,7 +944,7 @@ struct hwi_controller { | |||
| 933 | struct sgl_handle *psgl_handle_base; | 944 | struct sgl_handle *psgl_handle_base; |
| 934 | unsigned int wrb_mem_index; | 945 | unsigned int wrb_mem_index; |
| 935 | 946 | ||
| 936 | struct hwi_wrb_context wrb_context[BE2_MAX_SESSIONS * 2]; | 947 | struct hwi_wrb_context *wrb_context; |
| 937 | struct mcc_wrb *pmcc_wrb_base; | 948 | struct mcc_wrb *pmcc_wrb_base; |
| 938 | struct be_ring default_pdu_hdr; | 949 | struct be_ring default_pdu_hdr; |
| 939 | struct be_ring default_pdu_data; | 950 | struct be_ring default_pdu_data; |
| @@ -970,9 +981,7 @@ struct hwi_context_memory { | |||
| 970 | struct be_queue_info be_def_hdrq; | 981 | struct be_queue_info be_def_hdrq; |
| 971 | struct be_queue_info be_def_dataq; | 982 | struct be_queue_info be_def_dataq; |
| 972 | 983 | ||
| 973 | struct be_queue_info be_wrbq[BE2_MAX_SESSIONS]; | 984 | struct be_queue_info *be_wrbq; |
| 974 | struct be_mcc_wrb_context *pbe_mcc_context; | ||
| 975 | |||
| 976 | struct hwi_async_pdu_context *pasync_ctx; | 985 | struct hwi_async_pdu_context *pasync_ctx; |
| 977 | }; | 986 | }; |
| 978 | 987 | ||
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 55cc9902263d..245a9595a93a 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2012 Emulex | 2 | * Copyright (C) 2005 - 2013 Emulex |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -368,6 +368,8 @@ int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, | |||
| 368 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, | 368 | beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, |
| 369 | "BM_%d : phba->fw_config.iscsi_features = %d\n", | 369 | "BM_%d : phba->fw_config.iscsi_features = %d\n", |
| 370 | phba->fw_config.iscsi_features); | 370 | phba->fw_config.iscsi_features); |
| 371 | memcpy(phba->fw_ver_str, resp->params.hba_attribs. | ||
| 372 | firmware_version_string, BEISCSI_VER_STRLEN); | ||
| 371 | } else | 373 | } else |
| 372 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, | 374 | beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, |
| 373 | "BG_%d : Failed in mgmt_check_supported_fw\n"); | 375 | "BG_%d : Failed in mgmt_check_supported_fw\n"); |
| @@ -1260,6 +1262,45 @@ beiscsi_drvr_ver_disp(struct device *dev, struct device_attribute *attr, | |||
| 1260 | } | 1262 | } |
| 1261 | 1263 | ||
| 1262 | /** | 1264 | /** |
| 1265 | * beiscsi_fw_ver_disp()- Display Firmware Version | ||
| 1266 | * @dev: ptr to device not used. | ||
| 1267 | * @attr: device attribute, not used. | ||
| 1268 | * @buf: contains formatted text Firmware version | ||
| 1269 | * | ||
| 1270 | * return | ||
| 1271 | * size of the formatted string | ||
| 1272 | **/ | ||
| 1273 | ssize_t | ||
| 1274 | beiscsi_fw_ver_disp(struct device *dev, struct device_attribute *attr, | ||
| 1275 | char *buf) | ||
| 1276 | { | ||
| 1277 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 1278 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | ||
| 1279 | |||
| 1280 | return snprintf(buf, PAGE_SIZE, "%s\n", phba->fw_ver_str); | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | /** | ||
| 1284 | * beiscsi_active_cid_disp()- Display Sessions Active | ||
| 1285 | * @dev: ptr to device not used. | ||
| 1286 | * @attr: device attribute, not used. | ||
| 1287 | * @buf: contains formatted text Session Count | ||
| 1288 | * | ||
| 1289 | * return | ||
| 1290 | * size of the formatted string | ||
| 1291 | **/ | ||
| 1292 | ssize_t | ||
| 1293 | beiscsi_active_cid_disp(struct device *dev, struct device_attribute *attr, | ||
| 1294 | char *buf) | ||
| 1295 | { | ||
| 1296 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 1297 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | ||
| 1298 | |||
| 1299 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
| 1300 | (phba->params.cxns_per_ctrl - phba->avlbl_cids)); | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | /** | ||
| 1263 | * beiscsi_adap_family_disp()- Display adapter family. | 1304 | * beiscsi_adap_family_disp()- Display adapter family. |
| 1264 | * @dev: ptr to device to get priv structure | 1305 | * @dev: ptr to device to get priv structure |
| 1265 | * @attr: device attribute, not used. | 1306 | * @attr: device attribute, not used. |
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h index 2e4968add799..04af7e74fe48 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.h +++ b/drivers/scsi/be2iscsi/be_mgmt.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /** | 1 | /** |
| 2 | * Copyright (C) 2005 - 2012 Emulex | 2 | * Copyright (C) 2005 - 2013 Emulex |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
| @@ -156,25 +156,25 @@ union invalidate_commands_params { | |||
| 156 | } __packed; | 156 | } __packed; |
| 157 | 157 | ||
| 158 | struct mgmt_hba_attributes { | 158 | struct mgmt_hba_attributes { |
| 159 | u8 flashrom_version_string[32]; | 159 | u8 flashrom_version_string[BEISCSI_VER_STRLEN]; |
| 160 | u8 manufacturer_name[32]; | 160 | u8 manufacturer_name[BEISCSI_VER_STRLEN]; |
| 161 | u32 supported_modes; | 161 | u32 supported_modes; |
| 162 | u8 seeprom_version_lo; | 162 | u8 seeprom_version_lo; |
| 163 | u8 seeprom_version_hi; | 163 | u8 seeprom_version_hi; |
| 164 | u8 rsvd0[2]; | 164 | u8 rsvd0[2]; |
| 165 | u32 fw_cmd_data_struct_version; | 165 | u32 fw_cmd_data_struct_version; |
| 166 | u32 ep_fw_data_struct_version; | 166 | u32 ep_fw_data_struct_version; |
| 167 | u32 future_reserved[12]; | 167 | u8 ncsi_version_string[12]; |
| 168 | u32 default_extended_timeout; | 168 | u32 default_extended_timeout; |
| 169 | u8 controller_model_number[32]; | 169 | u8 controller_model_number[BEISCSI_VER_STRLEN]; |
| 170 | u8 controller_description[64]; | 170 | u8 controller_description[64]; |
| 171 | u8 controller_serial_number[32]; | 171 | u8 controller_serial_number[BEISCSI_VER_STRLEN]; |
| 172 | u8 ip_version_string[32]; | 172 | u8 ip_version_string[BEISCSI_VER_STRLEN]; |
| 173 | u8 firmware_version_string[32]; | 173 | u8 firmware_version_string[BEISCSI_VER_STRLEN]; |
| 174 | u8 bios_version_string[32]; | 174 | u8 bios_version_string[BEISCSI_VER_STRLEN]; |
| 175 | u8 redboot_version_string[32]; | 175 | u8 redboot_version_string[BEISCSI_VER_STRLEN]; |
| 176 | u8 driver_version_string[32]; | 176 | u8 driver_version_string[BEISCSI_VER_STRLEN]; |
| 177 | u8 fw_on_flash_version_string[32]; | 177 | u8 fw_on_flash_version_string[BEISCSI_VER_STRLEN]; |
| 178 | u32 functionalities_supported; | 178 | u32 functionalities_supported; |
| 179 | u16 max_cdblength; | 179 | u16 max_cdblength; |
| 180 | u8 asic_revision; | 180 | u8 asic_revision; |
| @@ -190,7 +190,8 @@ struct mgmt_hba_attributes { | |||
| 190 | u32 firmware_post_status; | 190 | u32 firmware_post_status; |
| 191 | u32 hba_mtu[8]; | 191 | u32 hba_mtu[8]; |
| 192 | u8 iscsi_features; | 192 | u8 iscsi_features; |
| 193 | u8 future_u8[3]; | 193 | u8 asic_generation; |
| 194 | u8 future_u8[2]; | ||
| 194 | u32 future_u32[3]; | 195 | u32 future_u32[3]; |
| 195 | } __packed; | 196 | } __packed; |
| 196 | 197 | ||
| @@ -207,7 +208,7 @@ struct mgmt_controller_attributes { | |||
| 207 | u64 unique_identifier; | 208 | u64 unique_identifier; |
| 208 | u8 netfilters; | 209 | u8 netfilters; |
| 209 | u8 rsvd0[3]; | 210 | u8 rsvd0[3]; |
| 210 | u8 future_u32[4]; | 211 | u32 future_u32[4]; |
| 211 | } __packed; | 212 | } __packed; |
| 212 | 213 | ||
| 213 | struct be_mgmt_controller_attributes { | 214 | struct be_mgmt_controller_attributes { |
| @@ -311,6 +312,12 @@ int mgmt_set_vlan(struct beiscsi_hba *phba, uint16_t vlan_tag); | |||
| 311 | ssize_t beiscsi_drvr_ver_disp(struct device *dev, | 312 | ssize_t beiscsi_drvr_ver_disp(struct device *dev, |
| 312 | struct device_attribute *attr, char *buf); | 313 | struct device_attribute *attr, char *buf); |
| 313 | 314 | ||
| 315 | ssize_t beiscsi_fw_ver_disp(struct device *dev, | ||
| 316 | struct device_attribute *attr, char *buf); | ||
| 317 | |||
| 318 | ssize_t beiscsi_active_cid_disp(struct device *dev, | ||
| 319 | struct device_attribute *attr, char *buf); | ||
| 320 | |||
| 314 | ssize_t beiscsi_adap_family_disp(struct device *dev, | 321 | ssize_t beiscsi_adap_family_disp(struct device *dev, |
| 315 | struct device_attribute *attr, char *buf); | 322 | struct device_attribute *attr, char *buf); |
| 316 | 323 | ||
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 11596b2c4702..08b22a901c25 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | #define _BNX2FC_H_ | 2 | #define _BNX2FC_H_ |
| 3 | /* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver. | 3 | /* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver. |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2008 - 2011 Broadcom Corporation | 5 | * Copyright (c) 2008 - 2013 Broadcom Corporation |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
| @@ -64,10 +64,12 @@ | |||
| 64 | #include "bnx2fc_constants.h" | 64 | #include "bnx2fc_constants.h" |
| 65 | 65 | ||
| 66 | #define BNX2FC_NAME "bnx2fc" | 66 | #define BNX2FC_NAME "bnx2fc" |
| 67 | #define BNX2FC_VERSION "1.0.13" | 67 | #define BNX2FC_VERSION "1.0.14" |
| 68 | 68 | ||
| 69 | #define PFX "bnx2fc: " | 69 | #define PFX "bnx2fc: " |
| 70 | 70 | ||
| 71 | #define BCM_CHIP_LEN 16 | ||
| 72 | |||
| 71 | #define BNX2X_DOORBELL_PCI_BAR 2 | 73 | #define BNX2X_DOORBELL_PCI_BAR 2 |
| 72 | 74 | ||
| 73 | #define BNX2FC_MAX_BD_LEN 0xffff | 75 | #define BNX2FC_MAX_BD_LEN 0xffff |
| @@ -241,6 +243,8 @@ struct bnx2fc_hba { | |||
| 241 | int wait_for_link_down; | 243 | int wait_for_link_down; |
| 242 | int num_ofld_sess; | 244 | int num_ofld_sess; |
| 243 | struct list_head vports; | 245 | struct list_head vports; |
| 246 | |||
| 247 | char chip_num[BCM_CHIP_LEN]; | ||
| 244 | }; | 248 | }; |
| 245 | 249 | ||
| 246 | struct bnx2fc_interface { | 250 | struct bnx2fc_interface { |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c index bdbbb13b8534..b1c9a4f8caee 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_els.c +++ b/drivers/scsi/bnx2fc/bnx2fc_els.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * This file contains helper routines that handle ELS requests | 3 | * This file contains helper routines that handle ELS requests |
| 4 | * and responses. | 4 | * and responses. |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2008 - 2011 Broadcom Corporation | 6 | * Copyright (c) 2008 - 2013 Broadcom Corporation |
| 7 | * | 7 | * |
| 8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 7dffec1e5715..69ac55495c1d 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * cnic modules to create FCoE instances, send/receive non-offloaded | 3 | * cnic modules to create FCoE instances, send/receive non-offloaded |
| 4 | * FIP/FCoE packets, listen to link events etc. | 4 | * FIP/FCoE packets, listen to link events etc. |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2008 - 2011 Broadcom Corporation | 6 | * Copyright (c) 2008 - 2013 Broadcom Corporation |
| 7 | * | 7 | * |
| 8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
| @@ -22,7 +22,7 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); | |||
| 22 | 22 | ||
| 23 | #define DRV_MODULE_NAME "bnx2fc" | 23 | #define DRV_MODULE_NAME "bnx2fc" |
| 24 | #define DRV_MODULE_VERSION BNX2FC_VERSION | 24 | #define DRV_MODULE_VERSION BNX2FC_VERSION |
| 25 | #define DRV_MODULE_RELDATE "Dec 21, 2012" | 25 | #define DRV_MODULE_RELDATE "Mar 08, 2013" |
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | static char version[] = | 28 | static char version[] = |
| @@ -679,6 +679,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev) | |||
| 679 | { | 679 | { |
| 680 | struct fcoe_port *port = lport_priv(lport); | 680 | struct fcoe_port *port = lport_priv(lport); |
| 681 | struct bnx2fc_interface *interface = port->priv; | 681 | struct bnx2fc_interface *interface = port->priv; |
| 682 | struct bnx2fc_hba *hba = interface->hba; | ||
| 682 | struct Scsi_Host *shost = lport->host; | 683 | struct Scsi_Host *shost = lport->host; |
| 683 | int rc = 0; | 684 | int rc = 0; |
| 684 | 685 | ||
| @@ -699,8 +700,9 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev) | |||
| 699 | } | 700 | } |
| 700 | if (!lport->vport) | 701 | if (!lport->vport) |
| 701 | fc_host_max_npiv_vports(lport->host) = USHRT_MAX; | 702 | fc_host_max_npiv_vports(lport->host) = USHRT_MAX; |
| 702 | sprintf(fc_host_symbolic_name(lport->host), "%s v%s over %s", | 703 | snprintf(fc_host_symbolic_name(lport->host), 256, |
| 703 | BNX2FC_NAME, BNX2FC_VERSION, | 704 | "%s (Broadcom %s) v%s over %s", |
| 705 | BNX2FC_NAME, hba->chip_num, BNX2FC_VERSION, | ||
| 704 | interface->netdev->name); | 706 | interface->netdev->name); |
| 705 | 707 | ||
| 706 | return 0; | 708 | return 0; |
| @@ -1656,23 +1658,60 @@ mem_err: | |||
| 1656 | static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba) | 1658 | static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba) |
| 1657 | { | 1659 | { |
| 1658 | struct cnic_dev *cnic; | 1660 | struct cnic_dev *cnic; |
| 1661 | struct pci_dev *pdev; | ||
| 1659 | 1662 | ||
| 1660 | if (!hba->cnic) { | 1663 | if (!hba->cnic) { |
| 1661 | printk(KERN_ERR PFX "cnic is NULL\n"); | 1664 | printk(KERN_ERR PFX "cnic is NULL\n"); |
| 1662 | return -ENODEV; | 1665 | return -ENODEV; |
| 1663 | } | 1666 | } |
| 1664 | cnic = hba->cnic; | 1667 | cnic = hba->cnic; |
| 1665 | hba->pcidev = cnic->pcidev; | 1668 | pdev = hba->pcidev = cnic->pcidev; |
| 1666 | if (hba->pcidev) | 1669 | if (!hba->pcidev) |
| 1667 | pci_dev_get(hba->pcidev); | 1670 | return -ENODEV; |
| 1668 | 1671 | ||
| 1672 | switch (pdev->device) { | ||
| 1673 | case PCI_DEVICE_ID_NX2_57710: | ||
| 1674 | strncpy(hba->chip_num, "BCM57710", BCM_CHIP_LEN); | ||
| 1675 | break; | ||
| 1676 | case PCI_DEVICE_ID_NX2_57711: | ||
| 1677 | strncpy(hba->chip_num, "BCM57711", BCM_CHIP_LEN); | ||
| 1678 | break; | ||
| 1679 | case PCI_DEVICE_ID_NX2_57712: | ||
| 1680 | case PCI_DEVICE_ID_NX2_57712_MF: | ||
| 1681 | case PCI_DEVICE_ID_NX2_57712_VF: | ||
| 1682 | strncpy(hba->chip_num, "BCM57712", BCM_CHIP_LEN); | ||
| 1683 | break; | ||
| 1684 | case PCI_DEVICE_ID_NX2_57800: | ||
| 1685 | case PCI_DEVICE_ID_NX2_57800_MF: | ||
| 1686 | case PCI_DEVICE_ID_NX2_57800_VF: | ||
| 1687 | strncpy(hba->chip_num, "BCM57800", BCM_CHIP_LEN); | ||
| 1688 | break; | ||
| 1689 | case PCI_DEVICE_ID_NX2_57810: | ||
| 1690 | case PCI_DEVICE_ID_NX2_57810_MF: | ||
| 1691 | case PCI_DEVICE_ID_NX2_57810_VF: | ||
| 1692 | strncpy(hba->chip_num, "BCM57810", BCM_CHIP_LEN); | ||
| 1693 | break; | ||
| 1694 | case PCI_DEVICE_ID_NX2_57840: | ||
| 1695 | case PCI_DEVICE_ID_NX2_57840_MF: | ||
| 1696 | case PCI_DEVICE_ID_NX2_57840_VF: | ||
| 1697 | case PCI_DEVICE_ID_NX2_57840_2_20: | ||
| 1698 | case PCI_DEVICE_ID_NX2_57840_4_10: | ||
| 1699 | strncpy(hba->chip_num, "BCM57840", BCM_CHIP_LEN); | ||
| 1700 | break; | ||
| 1701 | default: | ||
| 1702 | pr_err(PFX "Unknown device id 0x%x\n", pdev->device); | ||
| 1703 | break; | ||
| 1704 | } | ||
| 1705 | pci_dev_get(hba->pcidev); | ||
| 1669 | return 0; | 1706 | return 0; |
| 1670 | } | 1707 | } |
| 1671 | 1708 | ||
| 1672 | static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba) | 1709 | static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba) |
| 1673 | { | 1710 | { |
| 1674 | if (hba->pcidev) | 1711 | if (hba->pcidev) { |
| 1712 | hba->chip_num[0] = '\0'; | ||
| 1675 | pci_dev_put(hba->pcidev); | 1713 | pci_dev_put(hba->pcidev); |
| 1714 | } | ||
| 1676 | hba->pcidev = NULL; | 1715 | hba->pcidev = NULL; |
| 1677 | } | 1716 | } |
| 1678 | 1717 | ||
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index 50510ffe1bf5..c0d035a8f8f9 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * This file contains the code that low level functions that interact | 2 | * This file contains the code that low level functions that interact |
| 3 | * with 57712 FCoE firmware. | 3 | * with 57712 FCoE firmware. |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2008 - 2011 Broadcom Corporation | 5 | * Copyright (c) 2008 - 2013 Broadcom Corporation |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
| @@ -126,7 +126,11 @@ int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba) | |||
| 126 | fcoe_init3.error_bit_map_lo = 0xffffffff; | 126 | fcoe_init3.error_bit_map_lo = 0xffffffff; |
| 127 | fcoe_init3.error_bit_map_hi = 0xffffffff; | 127 | fcoe_init3.error_bit_map_hi = 0xffffffff; |
| 128 | 128 | ||
| 129 | fcoe_init3.perf_config = 1; | 129 | /* |
| 130 | * enable both cached connection and cached tasks | ||
| 131 | * 0 = none, 1 = cached connection, 2 = cached tasks, 3 = both | ||
| 132 | */ | ||
| 133 | fcoe_init3.perf_config = 3; | ||
| 130 | 134 | ||
| 131 | kwqe_arr[0] = (struct kwqe *) &fcoe_init1; | 135 | kwqe_arr[0] = (struct kwqe *) &fcoe_init1; |
| 132 | kwqe_arr[1] = (struct kwqe *) &fcoe_init2; | 136 | kwqe_arr[1] = (struct kwqe *) &fcoe_init2; |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 723a9a8ba5ee..575142e92d9c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver. | 1 | /* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver. |
| 2 | * IO manager and SCSI IO processing. | 2 | * IO manager and SCSI IO processing. |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2008 - 2011 Broadcom Corporation | 4 | * Copyright (c) 2008 - 2013 Broadcom Corporation |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
| @@ -1270,8 +1270,11 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd) | |||
| 1270 | 1270 | ||
| 1271 | spin_lock_bh(&tgt->tgt_lock); | 1271 | spin_lock_bh(&tgt->tgt_lock); |
| 1272 | io_req->wait_for_comp = 0; | 1272 | io_req->wait_for_comp = 0; |
| 1273 | if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE, | 1273 | if (test_bit(BNX2FC_FLAG_IO_COMPL, &io_req->req_flags)) { |
| 1274 | &io_req->req_flags))) { | 1274 | BNX2FC_IO_DBG(io_req, "IO completed in a different context\n"); |
| 1275 | rc = SUCCESS; | ||
| 1276 | } else if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE, | ||
| 1277 | &io_req->req_flags))) { | ||
| 1275 | /* Let the scsi-ml try to recover this command */ | 1278 | /* Let the scsi-ml try to recover this command */ |
| 1276 | printk(KERN_ERR PFX "abort failed, xid = 0x%x\n", | 1279 | printk(KERN_ERR PFX "abort failed, xid = 0x%x\n", |
| 1277 | io_req->xid); | 1280 | io_req->xid); |
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c index c57a3bb8a9fb..4d93177dfb53 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c +++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * Handles operations such as session offload/upload etc, and manages | 2 | * Handles operations such as session offload/upload etc, and manages |
| 3 | * session resources such as connection id and qp resources. | 3 | * session resources such as connection id and qp resources. |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2008 - 2011 Broadcom Corporation | 5 | * Copyright (c) 2008 - 2013 Broadcom Corporation |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
diff --git a/drivers/scsi/csiostor/csio_lnode.h b/drivers/scsi/csiostor/csio_lnode.h index 0f9c04175b11..372a67d122d3 100644 --- a/drivers/scsi/csiostor/csio_lnode.h +++ b/drivers/scsi/csiostor/csio_lnode.h | |||
| @@ -114,7 +114,7 @@ struct csio_lnode_stats { | |||
| 114 | uint32_t n_rnode_match; /* matched rnode */ | 114 | uint32_t n_rnode_match; /* matched rnode */ |
| 115 | uint32_t n_dev_loss_tmo; /* Device loss timeout */ | 115 | uint32_t n_dev_loss_tmo; /* Device loss timeout */ |
| 116 | uint32_t n_fdmi_err; /* fdmi err */ | 116 | uint32_t n_fdmi_err; /* fdmi err */ |
| 117 | uint32_t n_evt_fw[PROTO_ERR_IMPL_LOGO]; /* fw events */ | 117 | uint32_t n_evt_fw[PROTO_ERR_IMPL_LOGO + 1]; /* fw events */ |
| 118 | enum csio_ln_ev n_evt_sm[CSIO_LNE_MAX_EVENT]; /* State m/c events */ | 118 | enum csio_ln_ev n_evt_sm[CSIO_LNE_MAX_EVENT]; /* State m/c events */ |
| 119 | uint32_t n_rnode_alloc; /* rnode allocated */ | 119 | uint32_t n_rnode_alloc; /* rnode allocated */ |
| 120 | uint32_t n_rnode_free; /* rnode freed */ | 120 | uint32_t n_rnode_free; /* rnode freed */ |
diff --git a/drivers/scsi/csiostor/csio_rnode.h b/drivers/scsi/csiostor/csio_rnode.h index 65940096a80d..433434221222 100644 --- a/drivers/scsi/csiostor/csio_rnode.h +++ b/drivers/scsi/csiostor/csio_rnode.h | |||
| @@ -63,7 +63,7 @@ struct csio_rnode_stats { | |||
| 63 | uint32_t n_err_nomem; /* error nomem */ | 63 | uint32_t n_err_nomem; /* error nomem */ |
| 64 | uint32_t n_evt_unexp; /* unexpected event */ | 64 | uint32_t n_evt_unexp; /* unexpected event */ |
| 65 | uint32_t n_evt_drop; /* unexpected event */ | 65 | uint32_t n_evt_drop; /* unexpected event */ |
| 66 | uint32_t n_evt_fw[PROTO_ERR_IMPL_LOGO]; /* fw events */ | 66 | uint32_t n_evt_fw[PROTO_ERR_IMPL_LOGO + 1]; /* fw events */ |
| 67 | enum csio_rn_ev n_evt_sm[CSIO_RNFE_MAX_EVENT]; /* State m/c events */ | 67 | enum csio_rn_ev n_evt_sm[CSIO_RNFE_MAX_EVENT]; /* State m/c events */ |
| 68 | uint32_t n_lun_rst; /* Number of resets of | 68 | uint32_t n_lun_rst; /* Number of resets of |
| 69 | * of LUNs under this | 69 | * of LUNs under this |
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 98436c363035..b6d1f92ed33c 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | #define DRV_NAME "fnic" | 39 | #define DRV_NAME "fnic" |
| 40 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" | 40 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" |
| 41 | #define DRV_VERSION "1.5.0.2" | 41 | #define DRV_VERSION "1.5.0.22" |
| 42 | #define PFX DRV_NAME ": " | 42 | #define PFX DRV_NAME ": " |
| 43 | #define DFX DRV_NAME "%d: " | 43 | #define DFX DRV_NAME "%d: " |
| 44 | 44 | ||
| @@ -192,6 +192,18 @@ enum fnic_state { | |||
| 192 | 192 | ||
| 193 | struct mempool; | 193 | struct mempool; |
| 194 | 194 | ||
| 195 | enum fnic_evt { | ||
| 196 | FNIC_EVT_START_VLAN_DISC = 1, | ||
| 197 | FNIC_EVT_START_FCF_DISC = 2, | ||
| 198 | FNIC_EVT_MAX, | ||
| 199 | }; | ||
| 200 | |||
| 201 | struct fnic_event { | ||
| 202 | struct list_head list; | ||
| 203 | struct fnic *fnic; | ||
| 204 | enum fnic_evt event; | ||
| 205 | }; | ||
| 206 | |||
| 195 | /* Per-instance private data structure */ | 207 | /* Per-instance private data structure */ |
| 196 | struct fnic { | 208 | struct fnic { |
| 197 | struct fc_lport *lport; | 209 | struct fc_lport *lport; |
| @@ -254,6 +266,18 @@ struct fnic { | |||
| 254 | struct sk_buff_head frame_queue; | 266 | struct sk_buff_head frame_queue; |
| 255 | struct sk_buff_head tx_queue; | 267 | struct sk_buff_head tx_queue; |
| 256 | 268 | ||
| 269 | /*** FIP related data members -- start ***/ | ||
| 270 | void (*set_vlan)(struct fnic *, u16 vlan); | ||
| 271 | struct work_struct fip_frame_work; | ||
| 272 | struct sk_buff_head fip_frame_queue; | ||
| 273 | struct timer_list fip_timer; | ||
| 274 | struct list_head vlans; | ||
| 275 | spinlock_t vlans_lock; | ||
| 276 | |||
| 277 | struct work_struct event_work; | ||
| 278 | struct list_head evlist; | ||
| 279 | /*** FIP related data members -- end ***/ | ||
| 280 | |||
| 257 | /* copy work queue cache line section */ | 281 | /* copy work queue cache line section */ |
| 258 | ____cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX]; | 282 | ____cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX]; |
| 259 | /* completion queue cache line section */ | 283 | /* completion queue cache line section */ |
| @@ -278,6 +302,7 @@ static inline struct fnic *fnic_from_ctlr(struct fcoe_ctlr *fip) | |||
| 278 | } | 302 | } |
| 279 | 303 | ||
| 280 | extern struct workqueue_struct *fnic_event_queue; | 304 | extern struct workqueue_struct *fnic_event_queue; |
| 305 | extern struct workqueue_struct *fnic_fip_queue; | ||
| 281 | extern struct device_attribute *fnic_attrs[]; | 306 | extern struct device_attribute *fnic_attrs[]; |
| 282 | 307 | ||
| 283 | void fnic_clear_intr_mode(struct fnic *fnic); | 308 | void fnic_clear_intr_mode(struct fnic *fnic); |
| @@ -289,6 +314,7 @@ int fnic_send(struct fc_lport *, struct fc_frame *); | |||
| 289 | void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf); | 314 | void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf); |
| 290 | void fnic_handle_frame(struct work_struct *work); | 315 | void fnic_handle_frame(struct work_struct *work); |
| 291 | void fnic_handle_link(struct work_struct *work); | 316 | void fnic_handle_link(struct work_struct *work); |
| 317 | void fnic_handle_event(struct work_struct *work); | ||
| 292 | int fnic_rq_cmpl_handler(struct fnic *fnic, int); | 318 | int fnic_rq_cmpl_handler(struct fnic *fnic, int); |
| 293 | int fnic_alloc_rq_frame(struct vnic_rq *rq); | 319 | int fnic_alloc_rq_frame(struct vnic_rq *rq); |
| 294 | void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf); | 320 | void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf); |
| @@ -321,6 +347,12 @@ void fnic_handle_link_event(struct fnic *fnic); | |||
| 321 | 347 | ||
| 322 | int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *); | 348 | int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *); |
| 323 | 349 | ||
| 350 | void fnic_handle_fip_frame(struct work_struct *work); | ||
| 351 | void fnic_handle_fip_event(struct fnic *fnic); | ||
| 352 | void fnic_fcoe_reset_vlans(struct fnic *fnic); | ||
| 353 | void fnic_fcoe_evlist_free(struct fnic *fnic); | ||
| 354 | extern void fnic_handle_fip_timer(struct fnic *fnic); | ||
| 355 | |||
| 324 | static inline int | 356 | static inline int |
| 325 | fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags) | 357 | fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags) |
| 326 | { | 358 | { |
diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c index 483eb9dbe663..006fa92a02df 100644 --- a/drivers/scsi/fnic/fnic_fcs.c +++ b/drivers/scsi/fnic/fnic_fcs.c | |||
| @@ -31,12 +31,20 @@ | |||
| 31 | #include <scsi/libfc.h> | 31 | #include <scsi/libfc.h> |
| 32 | #include "fnic_io.h" | 32 | #include "fnic_io.h" |
| 33 | #include "fnic.h" | 33 | #include "fnic.h" |
| 34 | #include "fnic_fip.h" | ||
| 34 | #include "cq_enet_desc.h" | 35 | #include "cq_enet_desc.h" |
| 35 | #include "cq_exch_desc.h" | 36 | #include "cq_exch_desc.h" |
| 36 | 37 | ||
| 38 | static u8 fcoe_all_fcfs[ETH_ALEN]; | ||
| 39 | struct workqueue_struct *fnic_fip_queue; | ||
| 37 | struct workqueue_struct *fnic_event_queue; | 40 | struct workqueue_struct *fnic_event_queue; |
| 38 | 41 | ||
| 39 | static void fnic_set_eth_mode(struct fnic *); | 42 | static void fnic_set_eth_mode(struct fnic *); |
| 43 | static void fnic_fcoe_send_vlan_req(struct fnic *fnic); | ||
| 44 | static void fnic_fcoe_start_fcf_disc(struct fnic *fnic); | ||
| 45 | static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *); | ||
| 46 | static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag); | ||
| 47 | static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb); | ||
| 40 | 48 | ||
| 41 | void fnic_handle_link(struct work_struct *work) | 49 | void fnic_handle_link(struct work_struct *work) |
| 42 | { | 50 | { |
| @@ -69,6 +77,11 @@ void fnic_handle_link(struct work_struct *work) | |||
| 69 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | 77 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, |
| 70 | "link down\n"); | 78 | "link down\n"); |
| 71 | fcoe_ctlr_link_down(&fnic->ctlr); | 79 | fcoe_ctlr_link_down(&fnic->ctlr); |
| 80 | if (fnic->config.flags & VFCF_FIP_CAPABLE) { | ||
| 81 | /* start FCoE VLAN discovery */ | ||
| 82 | fnic_fcoe_send_vlan_req(fnic); | ||
| 83 | return; | ||
| 84 | } | ||
| 72 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | 85 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, |
| 73 | "link up\n"); | 86 | "link up\n"); |
| 74 | fcoe_ctlr_link_up(&fnic->ctlr); | 87 | fcoe_ctlr_link_up(&fnic->ctlr); |
| @@ -79,6 +92,11 @@ void fnic_handle_link(struct work_struct *work) | |||
| 79 | } else if (fnic->link_status) { | 92 | } else if (fnic->link_status) { |
| 80 | /* DOWN -> UP */ | 93 | /* DOWN -> UP */ |
| 81 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | 94 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); |
| 95 | if (fnic->config.flags & VFCF_FIP_CAPABLE) { | ||
| 96 | /* start FCoE VLAN discovery */ | ||
| 97 | fnic_fcoe_send_vlan_req(fnic); | ||
| 98 | return; | ||
| 99 | } | ||
| 82 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link up\n"); | 100 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link up\n"); |
| 83 | fcoe_ctlr_link_up(&fnic->ctlr); | 101 | fcoe_ctlr_link_up(&fnic->ctlr); |
| 84 | } else { | 102 | } else { |
| @@ -128,6 +146,441 @@ void fnic_handle_frame(struct work_struct *work) | |||
| 128 | } | 146 | } |
| 129 | } | 147 | } |
| 130 | 148 | ||
| 149 | void fnic_fcoe_evlist_free(struct fnic *fnic) | ||
| 150 | { | ||
| 151 | struct fnic_event *fevt = NULL; | ||
| 152 | struct fnic_event *next = NULL; | ||
| 153 | unsigned long flags; | ||
| 154 | |||
| 155 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
| 156 | if (list_empty(&fnic->evlist)) { | ||
| 157 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | |||
| 161 | list_for_each_entry_safe(fevt, next, &fnic->evlist, list) { | ||
| 162 | list_del(&fevt->list); | ||
| 163 | kfree(fevt); | ||
| 164 | } | ||
| 165 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 166 | } | ||
| 167 | |||
| 168 | void fnic_handle_event(struct work_struct *work) | ||
| 169 | { | ||
| 170 | struct fnic *fnic = container_of(work, struct fnic, event_work); | ||
| 171 | struct fnic_event *fevt = NULL; | ||
| 172 | struct fnic_event *next = NULL; | ||
| 173 | unsigned long flags; | ||
| 174 | |||
| 175 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
| 176 | if (list_empty(&fnic->evlist)) { | ||
| 177 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 178 | return; | ||
| 179 | } | ||
| 180 | |||
| 181 | list_for_each_entry_safe(fevt, next, &fnic->evlist, list) { | ||
| 182 | if (fnic->stop_rx_link_events) { | ||
| 183 | list_del(&fevt->list); | ||
| 184 | kfree(fevt); | ||
| 185 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 186 | return; | ||
| 187 | } | ||
| 188 | /* | ||
| 189 | * If we're in a transitional state, just re-queue and return. | ||
| 190 | * The queue will be serviced when we get to a stable state. | ||
| 191 | */ | ||
| 192 | if (fnic->state != FNIC_IN_FC_MODE && | ||
| 193 | fnic->state != FNIC_IN_ETH_MODE) { | ||
| 194 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 195 | return; | ||
| 196 | } | ||
| 197 | |||
| 198 | list_del(&fevt->list); | ||
| 199 | switch (fevt->event) { | ||
| 200 | case FNIC_EVT_START_VLAN_DISC: | ||
| 201 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 202 | fnic_fcoe_send_vlan_req(fnic); | ||
| 203 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
| 204 | break; | ||
| 205 | case FNIC_EVT_START_FCF_DISC: | ||
| 206 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | ||
| 207 | "Start FCF Discovery\n"); | ||
| 208 | fnic_fcoe_start_fcf_disc(fnic); | ||
| 209 | break; | ||
| 210 | default: | ||
| 211 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | ||
| 212 | "Unknown event 0x%x\n", fevt->event); | ||
| 213 | break; | ||
| 214 | } | ||
| 215 | kfree(fevt); | ||
| 216 | } | ||
| 217 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 218 | } | ||
| 219 | |||
| 220 | /** | ||
| 221 | * Check if the Received FIP FLOGI frame is rejected | ||
| 222 | * @fip: The FCoE controller that received the frame | ||
| 223 | * @skb: The received FIP frame | ||
| 224 | * | ||
| 225 | * Returns non-zero if the frame is rejected with unsupported cmd with | ||
| 226 | * insufficient resource els explanation. | ||
| 227 | */ | ||
| 228 | static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip, | ||
| 229 | struct sk_buff *skb) | ||
| 230 | { | ||
| 231 | struct fc_lport *lport = fip->lp; | ||
| 232 | struct fip_header *fiph; | ||
| 233 | struct fc_frame_header *fh = NULL; | ||
| 234 | struct fip_desc *desc; | ||
| 235 | struct fip_encaps *els; | ||
| 236 | enum fip_desc_type els_dtype = 0; | ||
| 237 | u16 op; | ||
| 238 | u8 els_op; | ||
| 239 | u8 sub; | ||
| 240 | |||
| 241 | size_t els_len = 0; | ||
| 242 | size_t rlen; | ||
| 243 | size_t dlen = 0; | ||
| 244 | |||
| 245 | if (skb_linearize(skb)) | ||
| 246 | return 0; | ||
| 247 | |||
| 248 | if (skb->len < sizeof(*fiph)) | ||
| 249 | return 0; | ||
| 250 | |||
| 251 | fiph = (struct fip_header *)skb->data; | ||
| 252 | op = ntohs(fiph->fip_op); | ||
| 253 | sub = fiph->fip_subcode; | ||
| 254 | |||
| 255 | if (op != FIP_OP_LS) | ||
| 256 | return 0; | ||
| 257 | |||
| 258 | if (sub != FIP_SC_REP) | ||
| 259 | return 0; | ||
| 260 | |||
| 261 | rlen = ntohs(fiph->fip_dl_len) * 4; | ||
| 262 | if (rlen + sizeof(*fiph) > skb->len) | ||
| 263 | return 0; | ||
| 264 | |||
| 265 | desc = (struct fip_desc *)(fiph + 1); | ||
| 266 | dlen = desc->fip_dlen * FIP_BPW; | ||
| 267 | |||
| 268 | if (desc->fip_dtype == FIP_DT_FLOGI) { | ||
| 269 | |||
| 270 | shost_printk(KERN_DEBUG, lport->host, | ||
| 271 | " FIP TYPE FLOGI: fab name:%llx " | ||
| 272 | "vfid:%d map:%x\n", | ||
| 273 | fip->sel_fcf->fabric_name, fip->sel_fcf->vfid, | ||
| 274 | fip->sel_fcf->fc_map); | ||
| 275 | if (dlen < sizeof(*els) + sizeof(*fh) + 1) | ||
| 276 | return 0; | ||
| 277 | |||
| 278 | els_len = dlen - sizeof(*els); | ||
| 279 | els = (struct fip_encaps *)desc; | ||
| 280 | fh = (struct fc_frame_header *)(els + 1); | ||
| 281 | els_dtype = desc->fip_dtype; | ||
| 282 | |||
| 283 | if (!fh) | ||
| 284 | return 0; | ||
| 285 | |||
| 286 | /* | ||
| 287 | * ELS command code, reason and explanation should be = Reject, | ||
| 288 | * unsupported command and insufficient resource | ||
| 289 | */ | ||
| 290 | els_op = *(u8 *)(fh + 1); | ||
| 291 | if (els_op == ELS_LS_RJT) { | ||
| 292 | shost_printk(KERN_INFO, lport->host, | ||
| 293 | "Flogi Request Rejected by Switch\n"); | ||
| 294 | return 1; | ||
| 295 | } | ||
| 296 | shost_printk(KERN_INFO, lport->host, | ||
| 297 | "Flogi Request Accepted by Switch\n"); | ||
| 298 | } | ||
| 299 | return 0; | ||
| 300 | } | ||
| 301 | |||
| 302 | static void fnic_fcoe_send_vlan_req(struct fnic *fnic) | ||
| 303 | { | ||
| 304 | struct fcoe_ctlr *fip = &fnic->ctlr; | ||
| 305 | struct sk_buff *skb; | ||
| 306 | char *eth_fr; | ||
| 307 | int fr_len; | ||
| 308 | struct fip_vlan *vlan; | ||
| 309 | u64 vlan_tov; | ||
| 310 | |||
| 311 | fnic_fcoe_reset_vlans(fnic); | ||
| 312 | fnic->set_vlan(fnic, 0); | ||
| 313 | FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, | ||
| 314 | "Sending VLAN request...\n"); | ||
| 315 | skb = dev_alloc_skb(sizeof(struct fip_vlan)); | ||
| 316 | if (!skb) | ||
| 317 | return; | ||
| 318 | |||
| 319 | fr_len = sizeof(*vlan); | ||
| 320 | eth_fr = (char *)skb->data; | ||
| 321 | vlan = (struct fip_vlan *)eth_fr; | ||
| 322 | |||
| 323 | memset(vlan, 0, sizeof(*vlan)); | ||
| 324 | memcpy(vlan->eth.h_source, fip->ctl_src_addr, ETH_ALEN); | ||
| 325 | memcpy(vlan->eth.h_dest, fcoe_all_fcfs, ETH_ALEN); | ||
| 326 | vlan->eth.h_proto = htons(ETH_P_FIP); | ||
| 327 | |||
| 328 | vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER); | ||
| 329 | vlan->fip.fip_op = htons(FIP_OP_VLAN); | ||
| 330 | vlan->fip.fip_subcode = FIP_SC_VL_REQ; | ||
| 331 | vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW); | ||
| 332 | |||
| 333 | vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC; | ||
| 334 | vlan->desc.mac.fd_desc.fip_dlen = sizeof(vlan->desc.mac) / FIP_BPW; | ||
| 335 | memcpy(&vlan->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); | ||
| 336 | |||
| 337 | vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME; | ||
| 338 | vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / FIP_BPW; | ||
| 339 | put_unaligned_be64(fip->lp->wwnn, &vlan->desc.wwnn.fd_wwn); | ||
| 340 | |||
| 341 | skb_put(skb, sizeof(*vlan)); | ||
| 342 | skb->protocol = htons(ETH_P_FIP); | ||
| 343 | skb_reset_mac_header(skb); | ||
| 344 | skb_reset_network_header(skb); | ||
| 345 | fip->send(fip, skb); | ||
| 346 | |||
| 347 | /* set a timer so that we can retry if there no response */ | ||
| 348 | vlan_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FIPVLAN_TOV); | ||
| 349 | mod_timer(&fnic->fip_timer, round_jiffies(vlan_tov)); | ||
| 350 | } | ||
| 351 | |||
| 352 | static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb) | ||
| 353 | { | ||
| 354 | struct fcoe_ctlr *fip = &fnic->ctlr; | ||
| 355 | struct fip_header *fiph; | ||
| 356 | struct fip_desc *desc; | ||
| 357 | u16 vid; | ||
| 358 | size_t rlen; | ||
| 359 | size_t dlen; | ||
| 360 | struct fcoe_vlan *vlan; | ||
| 361 | u64 sol_time; | ||
| 362 | unsigned long flags; | ||
| 363 | |||
| 364 | FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, | ||
| 365 | "Received VLAN response...\n"); | ||
| 366 | |||
| 367 | fiph = (struct fip_header *) skb->data; | ||
| 368 | |||
| 369 | FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, | ||
| 370 | "Received VLAN response... OP 0x%x SUB_OP 0x%x\n", | ||
| 371 | ntohs(fiph->fip_op), fiph->fip_subcode); | ||
| 372 | |||
| 373 | rlen = ntohs(fiph->fip_dl_len) * 4; | ||
| 374 | fnic_fcoe_reset_vlans(fnic); | ||
| 375 | spin_lock_irqsave(&fnic->vlans_lock, flags); | ||
| 376 | desc = (struct fip_desc *)(fiph + 1); | ||
| 377 | while (rlen > 0) { | ||
| 378 | dlen = desc->fip_dlen * FIP_BPW; | ||
| 379 | switch (desc->fip_dtype) { | ||
| 380 | case FIP_DT_VLAN: | ||
| 381 | vid = ntohs(((struct fip_vlan_desc *)desc)->fd_vlan); | ||
| 382 | shost_printk(KERN_INFO, fnic->lport->host, | ||
| 383 | "process_vlan_resp: FIP VLAN %d\n", vid); | ||
| 384 | vlan = kmalloc(sizeof(*vlan), | ||
| 385 | GFP_ATOMIC); | ||
| 386 | if (!vlan) { | ||
| 387 | /* retry from timer */ | ||
| 388 | spin_unlock_irqrestore(&fnic->vlans_lock, | ||
| 389 | flags); | ||
| 390 | goto out; | ||
| 391 | } | ||
| 392 | memset(vlan, 0, sizeof(struct fcoe_vlan)); | ||
| 393 | vlan->vid = vid & 0x0fff; | ||
| 394 | vlan->state = FIP_VLAN_AVAIL; | ||
| 395 | list_add_tail(&vlan->list, &fnic->vlans); | ||
| 396 | break; | ||
| 397 | } | ||
| 398 | desc = (struct fip_desc *)((char *)desc + dlen); | ||
| 399 | rlen -= dlen; | ||
| 400 | } | ||
| 401 | |||
| 402 | /* any VLAN descriptors present ? */ | ||
| 403 | if (list_empty(&fnic->vlans)) { | ||
| 404 | /* retry from timer */ | ||
| 405 | FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, | ||
| 406 | "No VLAN descriptors in FIP VLAN response\n"); | ||
| 407 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 408 | goto out; | ||
| 409 | } | ||
| 410 | |||
| 411 | vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list); | ||
| 412 | fnic->set_vlan(fnic, vlan->vid); | ||
| 413 | vlan->state = FIP_VLAN_SENT; /* sent now */ | ||
| 414 | vlan->sol_count++; | ||
| 415 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 416 | |||
| 417 | /* start the solicitation */ | ||
| 418 | fcoe_ctlr_link_up(fip); | ||
| 419 | |||
| 420 | sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY); | ||
| 421 | mod_timer(&fnic->fip_timer, round_jiffies(sol_time)); | ||
| 422 | out: | ||
| 423 | return; | ||
| 424 | } | ||
| 425 | |||
| 426 | static void fnic_fcoe_start_fcf_disc(struct fnic *fnic) | ||
| 427 | { | ||
| 428 | unsigned long flags; | ||
| 429 | struct fcoe_vlan *vlan; | ||
| 430 | u64 sol_time; | ||
| 431 | |||
| 432 | spin_lock_irqsave(&fnic->vlans_lock, flags); | ||
| 433 | vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list); | ||
| 434 | fnic->set_vlan(fnic, vlan->vid); | ||
| 435 | vlan->state = FIP_VLAN_SENT; /* sent now */ | ||
| 436 | vlan->sol_count = 1; | ||
| 437 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 438 | |||
| 439 | /* start the solicitation */ | ||
| 440 | fcoe_ctlr_link_up(&fnic->ctlr); | ||
| 441 | |||
| 442 | sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY); | ||
| 443 | mod_timer(&fnic->fip_timer, round_jiffies(sol_time)); | ||
| 444 | } | ||
| 445 | |||
| 446 | static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag) | ||
| 447 | { | ||
| 448 | unsigned long flags; | ||
| 449 | struct fcoe_vlan *fvlan; | ||
| 450 | |||
| 451 | spin_lock_irqsave(&fnic->vlans_lock, flags); | ||
| 452 | if (list_empty(&fnic->vlans)) { | ||
| 453 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 454 | return -EINVAL; | ||
| 455 | } | ||
| 456 | |||
| 457 | fvlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list); | ||
| 458 | if (fvlan->state == FIP_VLAN_USED) { | ||
| 459 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 460 | return 0; | ||
| 461 | } | ||
| 462 | |||
| 463 | if (fvlan->state == FIP_VLAN_SENT) { | ||
| 464 | fvlan->state = FIP_VLAN_USED; | ||
| 465 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 466 | return 0; | ||
| 467 | } | ||
| 468 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 469 | return -EINVAL; | ||
| 470 | } | ||
| 471 | |||
| 472 | static void fnic_event_enq(struct fnic *fnic, enum fnic_evt ev) | ||
| 473 | { | ||
| 474 | struct fnic_event *fevt; | ||
| 475 | unsigned long flags; | ||
| 476 | |||
| 477 | fevt = kmalloc(sizeof(*fevt), GFP_ATOMIC); | ||
| 478 | if (!fevt) | ||
| 479 | return; | ||
| 480 | |||
| 481 | fevt->fnic = fnic; | ||
| 482 | fevt->event = ev; | ||
| 483 | |||
| 484 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
| 485 | list_add_tail(&fevt->list, &fnic->evlist); | ||
| 486 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 487 | |||
| 488 | schedule_work(&fnic->event_work); | ||
| 489 | } | ||
| 490 | |||
| 491 | static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb) | ||
| 492 | { | ||
| 493 | struct fip_header *fiph; | ||
| 494 | int ret = 1; | ||
| 495 | u16 op; | ||
| 496 | u8 sub; | ||
| 497 | |||
| 498 | if (!skb || !(skb->data)) | ||
| 499 | return -1; | ||
| 500 | |||
| 501 | if (skb_linearize(skb)) | ||
| 502 | goto drop; | ||
| 503 | |||
| 504 | fiph = (struct fip_header *)skb->data; | ||
| 505 | op = ntohs(fiph->fip_op); | ||
| 506 | sub = fiph->fip_subcode; | ||
| 507 | |||
| 508 | if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER) | ||
| 509 | goto drop; | ||
| 510 | |||
| 511 | if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len) | ||
| 512 | goto drop; | ||
| 513 | |||
| 514 | if (op == FIP_OP_DISC && sub == FIP_SC_ADV) { | ||
| 515 | if (fnic_fcoe_vlan_check(fnic, ntohs(fiph->fip_flags))) | ||
| 516 | goto drop; | ||
| 517 | /* pass it on to fcoe */ | ||
| 518 | ret = 1; | ||
| 519 | } else if (op == FIP_OP_VLAN && sub == FIP_SC_VL_REP) { | ||
| 520 | /* set the vlan as used */ | ||
| 521 | fnic_fcoe_process_vlan_resp(fnic, skb); | ||
| 522 | ret = 0; | ||
| 523 | } else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) { | ||
| 524 | /* received CVL request, restart vlan disc */ | ||
| 525 | fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC); | ||
| 526 | /* pass it on to fcoe */ | ||
| 527 | ret = 1; | ||
| 528 | } | ||
| 529 | drop: | ||
| 530 | return ret; | ||
| 531 | } | ||
| 532 | |||
| 533 | void fnic_handle_fip_frame(struct work_struct *work) | ||
| 534 | { | ||
| 535 | struct fnic *fnic = container_of(work, struct fnic, fip_frame_work); | ||
| 536 | unsigned long flags; | ||
| 537 | struct sk_buff *skb; | ||
| 538 | struct ethhdr *eh; | ||
| 539 | |||
| 540 | while ((skb = skb_dequeue(&fnic->fip_frame_queue))) { | ||
| 541 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
| 542 | if (fnic->stop_rx_link_events) { | ||
| 543 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 544 | dev_kfree_skb(skb); | ||
| 545 | return; | ||
| 546 | } | ||
| 547 | /* | ||
| 548 | * If we're in a transitional state, just re-queue and return. | ||
| 549 | * The queue will be serviced when we get to a stable state. | ||
| 550 | */ | ||
| 551 | if (fnic->state != FNIC_IN_FC_MODE && | ||
| 552 | fnic->state != FNIC_IN_ETH_MODE) { | ||
| 553 | skb_queue_head(&fnic->fip_frame_queue, skb); | ||
| 554 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 555 | return; | ||
| 556 | } | ||
| 557 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 558 | eh = (struct ethhdr *)skb->data; | ||
| 559 | if (eh->h_proto == htons(ETH_P_FIP)) { | ||
| 560 | skb_pull(skb, sizeof(*eh)); | ||
| 561 | if (fnic_fcoe_handle_fip_frame(fnic, skb) <= 0) { | ||
| 562 | dev_kfree_skb(skb); | ||
| 563 | continue; | ||
| 564 | } | ||
| 565 | /* | ||
| 566 | * If there's FLOGI rejects - clear all | ||
| 567 | * fcf's & restart from scratch | ||
| 568 | */ | ||
| 569 | if (is_fnic_fip_flogi_reject(&fnic->ctlr, skb)) { | ||
| 570 | shost_printk(KERN_INFO, fnic->lport->host, | ||
| 571 | "Trigger a Link down - VLAN Disc\n"); | ||
| 572 | fcoe_ctlr_link_down(&fnic->ctlr); | ||
| 573 | /* start FCoE VLAN discovery */ | ||
| 574 | fnic_fcoe_send_vlan_req(fnic); | ||
| 575 | dev_kfree_skb(skb); | ||
| 576 | continue; | ||
| 577 | } | ||
| 578 | fcoe_ctlr_recv(&fnic->ctlr, skb); | ||
| 579 | continue; | ||
| 580 | } | ||
| 581 | } | ||
| 582 | } | ||
| 583 | |||
| 131 | /** | 584 | /** |
| 132 | * fnic_import_rq_eth_pkt() - handle received FCoE or FIP frame. | 585 | * fnic_import_rq_eth_pkt() - handle received FCoE or FIP frame. |
| 133 | * @fnic: fnic instance. | 586 | * @fnic: fnic instance. |
| @@ -150,8 +603,14 @@ static inline int fnic_import_rq_eth_pkt(struct fnic *fnic, struct sk_buff *skb) | |||
| 150 | skb_reset_mac_header(skb); | 603 | skb_reset_mac_header(skb); |
| 151 | } | 604 | } |
| 152 | if (eh->h_proto == htons(ETH_P_FIP)) { | 605 | if (eh->h_proto == htons(ETH_P_FIP)) { |
| 153 | skb_pull(skb, sizeof(*eh)); | 606 | if (!(fnic->config.flags & VFCF_FIP_CAPABLE)) { |
| 154 | fcoe_ctlr_recv(&fnic->ctlr, skb); | 607 | printk(KERN_ERR "Dropped FIP frame, as firmware " |
| 608 | "uses non-FIP mode, Enable FIP " | ||
| 609 | "using UCSM\n"); | ||
| 610 | goto drop; | ||
| 611 | } | ||
| 612 | skb_queue_tail(&fnic->fip_frame_queue, skb); | ||
| 613 | queue_work(fnic_fip_queue, &fnic->fip_frame_work); | ||
| 155 | return 1; /* let caller know packet was used */ | 614 | return 1; /* let caller know packet was used */ |
| 156 | } | 615 | } |
| 157 | if (eh->h_proto != htons(ETH_P_FCOE)) | 616 | if (eh->h_proto != htons(ETH_P_FCOE)) |
| @@ -720,3 +1179,104 @@ void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf) | |||
| 720 | dev_kfree_skb(fp_skb(fp)); | 1179 | dev_kfree_skb(fp_skb(fp)); |
| 721 | buf->os_buf = NULL; | 1180 | buf->os_buf = NULL; |
| 722 | } | 1181 | } |
| 1182 | |||
| 1183 | void fnic_fcoe_reset_vlans(struct fnic *fnic) | ||
| 1184 | { | ||
| 1185 | unsigned long flags; | ||
| 1186 | struct fcoe_vlan *vlan; | ||
| 1187 | struct fcoe_vlan *next; | ||
| 1188 | |||
| 1189 | /* | ||
| 1190 | * indicate a link down to fcoe so that all fcf's are free'd | ||
| 1191 | * might not be required since we did this before sending vlan | ||
| 1192 | * discovery request | ||
| 1193 | */ | ||
| 1194 | spin_lock_irqsave(&fnic->vlans_lock, flags); | ||
| 1195 | if (!list_empty(&fnic->vlans)) { | ||
| 1196 | list_for_each_entry_safe(vlan, next, &fnic->vlans, list) { | ||
| 1197 | list_del(&vlan->list); | ||
| 1198 | kfree(vlan); | ||
| 1199 | } | ||
| 1200 | } | ||
| 1201 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | void fnic_handle_fip_timer(struct fnic *fnic) | ||
| 1205 | { | ||
| 1206 | unsigned long flags; | ||
| 1207 | struct fcoe_vlan *vlan; | ||
| 1208 | u64 sol_time; | ||
| 1209 | |||
| 1210 | spin_lock_irqsave(&fnic->fnic_lock, flags); | ||
| 1211 | if (fnic->stop_rx_link_events) { | ||
| 1212 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 1213 | return; | ||
| 1214 | } | ||
| 1215 | spin_unlock_irqrestore(&fnic->fnic_lock, flags); | ||
| 1216 | |||
| 1217 | if (fnic->ctlr.mode == FIP_ST_NON_FIP) | ||
| 1218 | return; | ||
| 1219 | |||
| 1220 | spin_lock_irqsave(&fnic->vlans_lock, flags); | ||
| 1221 | if (list_empty(&fnic->vlans)) { | ||
| 1222 | /* no vlans available, try again */ | ||
| 1223 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | ||
| 1224 | "Start VLAN Discovery\n"); | ||
| 1225 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 1226 | fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC); | ||
| 1227 | return; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list); | ||
| 1231 | shost_printk(KERN_DEBUG, fnic->lport->host, | ||
| 1232 | "fip_timer: vlan %d state %d sol_count %d\n", | ||
| 1233 | vlan->vid, vlan->state, vlan->sol_count); | ||
| 1234 | switch (vlan->state) { | ||
| 1235 | case FIP_VLAN_USED: | ||
| 1236 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | ||
| 1237 | "FIP VLAN is selected for FC transaction\n"); | ||
| 1238 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 1239 | break; | ||
| 1240 | case FIP_VLAN_FAILED: | ||
| 1241 | /* if all vlans are in failed state, restart vlan disc */ | ||
| 1242 | FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, | ||
| 1243 | "Start VLAN Discovery\n"); | ||
| 1244 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 1245 | fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC); | ||
| 1246 | break; | ||
| 1247 | case FIP_VLAN_SENT: | ||
| 1248 | if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) { | ||
| 1249 | /* | ||
| 1250 | * no response on this vlan, remove from the list. | ||
| 1251 | * Try the next vlan | ||
| 1252 | */ | ||
| 1253 | shost_printk(KERN_INFO, fnic->lport->host, | ||
| 1254 | "Dequeue this VLAN ID %d from list\n", | ||
| 1255 | vlan->vid); | ||
| 1256 | list_del(&vlan->list); | ||
| 1257 | kfree(vlan); | ||
| 1258 | vlan = NULL; | ||
| 1259 | if (list_empty(&fnic->vlans)) { | ||
| 1260 | /* we exhausted all vlans, restart vlan disc */ | ||
| 1261 | spin_unlock_irqrestore(&fnic->vlans_lock, | ||
| 1262 | flags); | ||
| 1263 | shost_printk(KERN_INFO, fnic->lport->host, | ||
| 1264 | "fip_timer: vlan list empty, " | ||
| 1265 | "trigger vlan disc\n"); | ||
| 1266 | fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC); | ||
| 1267 | return; | ||
| 1268 | } | ||
| 1269 | /* check the next vlan */ | ||
| 1270 | vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, | ||
| 1271 | list); | ||
| 1272 | fnic->set_vlan(fnic, vlan->vid); | ||
| 1273 | vlan->state = FIP_VLAN_SENT; /* sent now */ | ||
| 1274 | } | ||
| 1275 | spin_unlock_irqrestore(&fnic->vlans_lock, flags); | ||
| 1276 | vlan->sol_count++; | ||
| 1277 | sol_time = jiffies + msecs_to_jiffies | ||
| 1278 | (FCOE_CTLR_START_DELAY); | ||
| 1279 | mod_timer(&fnic->fip_timer, round_jiffies(sol_time)); | ||
| 1280 | break; | ||
| 1281 | } | ||
| 1282 | } | ||
diff --git a/drivers/scsi/fnic/fnic_fip.h b/drivers/scsi/fnic/fnic_fip.h new file mode 100644 index 000000000000..87e74c2ab971 --- /dev/null +++ b/drivers/scsi/fnic/fnic_fip.h | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Cisco Systems, Inc. All rights reserved. | ||
| 3 | * Copyright 2007 Nuova Systems, Inc. All rights reserved. | ||
| 4 | * | ||
| 5 | * This program is free software; you may redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; version 2 of the License. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 10 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 11 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 12 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
| 13 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
| 15 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 16 | * SOFTWARE. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #ifndef _FNIC_FIP_H_ | ||
| 20 | #define _FNIC_FIP_H_ | ||
| 21 | |||
| 22 | |||
| 23 | #define FCOE_CTLR_START_DELAY 2000 /* ms after first adv. to choose FCF */ | ||
| 24 | #define FCOE_CTLR_FIPVLAN_TOV 2000 /* ms after FIP VLAN disc */ | ||
| 25 | #define FCOE_CTLR_MAX_SOL 8 | ||
| 26 | |||
| 27 | #define FINC_MAX_FLOGI_REJECTS 8 | ||
| 28 | |||
| 29 | /* | ||
| 30 | * FIP_DT_VLAN descriptor. | ||
| 31 | */ | ||
| 32 | struct fip_vlan_desc { | ||
| 33 | struct fip_desc fd_desc; | ||
| 34 | __be16 fd_vlan; | ||
| 35 | } __attribute__((packed)); | ||
| 36 | |||
| 37 | struct vlan { | ||
| 38 | __be16 vid; | ||
| 39 | __be16 type; | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* | ||
| 43 | * VLAN entry. | ||
| 44 | */ | ||
| 45 | struct fcoe_vlan { | ||
| 46 | struct list_head list; | ||
| 47 | u16 vid; /* vlan ID */ | ||
| 48 | u16 sol_count; /* no. of sols sent */ | ||
| 49 | u16 state; /* state */ | ||
| 50 | }; | ||
| 51 | |||
| 52 | enum fip_vlan_state { | ||
| 53 | FIP_VLAN_AVAIL = 0, /* don't do anything */ | ||
| 54 | FIP_VLAN_SENT = 1, /* sent */ | ||
| 55 | FIP_VLAN_USED = 2, /* succeed */ | ||
| 56 | FIP_VLAN_FAILED = 3, /* failed to response */ | ||
| 57 | }; | ||
| 58 | |||
| 59 | struct fip_vlan { | ||
| 60 | struct ethhdr eth; | ||
| 61 | struct fip_header fip; | ||
| 62 | struct { | ||
| 63 | struct fip_mac_desc mac; | ||
| 64 | struct fip_wwn_desc wwnn; | ||
| 65 | } desc; | ||
| 66 | }; | ||
| 67 | |||
| 68 | #endif /* __FINC_FIP_H_ */ | ||
diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index d601ac543c52..5f09d1814d26 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include "vnic_intr.h" | 39 | #include "vnic_intr.h" |
| 40 | #include "vnic_stats.h" | 40 | #include "vnic_stats.h" |
| 41 | #include "fnic_io.h" | 41 | #include "fnic_io.h" |
| 42 | #include "fnic_fip.h" | ||
| 42 | #include "fnic.h" | 43 | #include "fnic.h" |
| 43 | 44 | ||
| 44 | #define PCI_DEVICE_ID_CISCO_FNIC 0x0045 | 45 | #define PCI_DEVICE_ID_CISCO_FNIC 0x0045 |
| @@ -292,6 +293,13 @@ static void fnic_notify_timer(unsigned long data) | |||
| 292 | round_jiffies(jiffies + FNIC_NOTIFY_TIMER_PERIOD)); | 293 | round_jiffies(jiffies + FNIC_NOTIFY_TIMER_PERIOD)); |
| 293 | } | 294 | } |
| 294 | 295 | ||
| 296 | static void fnic_fip_notify_timer(unsigned long data) | ||
| 297 | { | ||
| 298 | struct fnic *fnic = (struct fnic *)data; | ||
| 299 | |||
| 300 | fnic_handle_fip_timer(fnic); | ||
| 301 | } | ||
| 302 | |||
| 295 | static void fnic_notify_timer_start(struct fnic *fnic) | 303 | static void fnic_notify_timer_start(struct fnic *fnic) |
| 296 | { | 304 | { |
| 297 | switch (vnic_dev_get_intr_mode(fnic->vdev)) { | 305 | switch (vnic_dev_get_intr_mode(fnic->vdev)) { |
| @@ -403,6 +411,12 @@ static u8 *fnic_get_mac(struct fc_lport *lport) | |||
| 403 | return fnic->data_src_addr; | 411 | return fnic->data_src_addr; |
| 404 | } | 412 | } |
| 405 | 413 | ||
| 414 | static void fnic_set_vlan(struct fnic *fnic, u16 vlan_id) | ||
| 415 | { | ||
| 416 | u16 old_vlan; | ||
| 417 | old_vlan = vnic_dev_set_default_vlan(fnic->vdev, vlan_id); | ||
| 418 | } | ||
| 419 | |||
| 406 | static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 420 | static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 407 | { | 421 | { |
| 408 | struct Scsi_Host *host; | 422 | struct Scsi_Host *host; |
| @@ -620,7 +634,29 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 620 | vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0); | 634 | vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0); |
| 621 | vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS); | 635 | vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS); |
| 622 | vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr); | 636 | vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr); |
| 637 | fnic->set_vlan = fnic_set_vlan; | ||
| 623 | fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO); | 638 | fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO); |
| 639 | setup_timer(&fnic->fip_timer, fnic_fip_notify_timer, | ||
| 640 | (unsigned long)fnic); | ||
| 641 | spin_lock_init(&fnic->vlans_lock); | ||
| 642 | INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame); | ||
| 643 | INIT_WORK(&fnic->event_work, fnic_handle_event); | ||
| 644 | skb_queue_head_init(&fnic->fip_frame_queue); | ||
| 645 | spin_lock_irqsave(&fnic_list_lock, flags); | ||
| 646 | if (!fnic_fip_queue) { | ||
| 647 | fnic_fip_queue = | ||
| 648 | create_singlethread_workqueue("fnic_fip_q"); | ||
| 649 | if (!fnic_fip_queue) { | ||
| 650 | spin_unlock_irqrestore(&fnic_list_lock, flags); | ||
| 651 | printk(KERN_ERR PFX "fnic FIP work queue " | ||
| 652 | "create failed\n"); | ||
| 653 | err = -ENOMEM; | ||
| 654 | goto err_out_free_max_pool; | ||
| 655 | } | ||
| 656 | } | ||
| 657 | spin_unlock_irqrestore(&fnic_list_lock, flags); | ||
| 658 | INIT_LIST_HEAD(&fnic->evlist); | ||
| 659 | INIT_LIST_HEAD(&fnic->vlans); | ||
| 624 | } else { | 660 | } else { |
| 625 | shost_printk(KERN_INFO, fnic->lport->host, | 661 | shost_printk(KERN_INFO, fnic->lport->host, |
| 626 | "firmware uses non-FIP mode\n"); | 662 | "firmware uses non-FIP mode\n"); |
| @@ -807,6 +843,13 @@ static void fnic_remove(struct pci_dev *pdev) | |||
| 807 | skb_queue_purge(&fnic->frame_queue); | 843 | skb_queue_purge(&fnic->frame_queue); |
| 808 | skb_queue_purge(&fnic->tx_queue); | 844 | skb_queue_purge(&fnic->tx_queue); |
| 809 | 845 | ||
| 846 | if (fnic->config.flags & VFCF_FIP_CAPABLE) { | ||
| 847 | del_timer_sync(&fnic->fip_timer); | ||
| 848 | skb_queue_purge(&fnic->fip_frame_queue); | ||
| 849 | fnic_fcoe_reset_vlans(fnic); | ||
| 850 | fnic_fcoe_evlist_free(fnic); | ||
| 851 | } | ||
| 852 | |||
| 810 | /* | 853 | /* |
| 811 | * Log off the fabric. This stops all remote ports, dns port, | 854 | * Log off the fabric. This stops all remote ports, dns port, |
| 812 | * logs off the fabric. This flushes all rport, disc, lport work | 855 | * logs off the fabric. This flushes all rport, disc, lport work |
| @@ -889,8 +932,8 @@ static int __init fnic_init_module(void) | |||
| 889 | len = sizeof(struct fnic_sgl_list); | 932 | len = sizeof(struct fnic_sgl_list); |
| 890 | fnic_sgl_cache[FNIC_SGL_CACHE_MAX] = kmem_cache_create | 933 | fnic_sgl_cache[FNIC_SGL_CACHE_MAX] = kmem_cache_create |
| 891 | ("fnic_sgl_max", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN, | 934 | ("fnic_sgl_max", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN, |
| 892 | SLAB_HWCACHE_ALIGN, | 935 | SLAB_HWCACHE_ALIGN, |
| 893 | NULL); | 936 | NULL); |
| 894 | if (!fnic_sgl_cache[FNIC_SGL_CACHE_MAX]) { | 937 | if (!fnic_sgl_cache[FNIC_SGL_CACHE_MAX]) { |
| 895 | printk(KERN_ERR PFX "failed to create fnic max sgl slab\n"); | 938 | printk(KERN_ERR PFX "failed to create fnic max sgl slab\n"); |
| 896 | err = -ENOMEM; | 939 | err = -ENOMEM; |
| @@ -951,6 +994,10 @@ static void __exit fnic_cleanup_module(void) | |||
| 951 | { | 994 | { |
| 952 | pci_unregister_driver(&fnic_driver); | 995 | pci_unregister_driver(&fnic_driver); |
| 953 | destroy_workqueue(fnic_event_queue); | 996 | destroy_workqueue(fnic_event_queue); |
| 997 | if (fnic_fip_queue) { | ||
| 998 | flush_workqueue(fnic_fip_queue); | ||
| 999 | destroy_workqueue(fnic_fip_queue); | ||
| 1000 | } | ||
| 954 | kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_MAX]); | 1001 | kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_MAX]); |
| 955 | kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]); | 1002 | kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]); |
| 956 | kmem_cache_destroy(fnic_io_req_cache); | 1003 | kmem_cache_destroy(fnic_io_req_cache); |
diff --git a/drivers/scsi/fnic/vnic_dev.c b/drivers/scsi/fnic/vnic_dev.c index b576be734e2e..9795d6f3e197 100644 --- a/drivers/scsi/fnic/vnic_dev.c +++ b/drivers/scsi/fnic/vnic_dev.c | |||
| @@ -584,6 +584,16 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg) | |||
| 584 | return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); | 584 | return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); |
| 585 | } | 585 | } |
| 586 | 586 | ||
| 587 | u16 vnic_dev_set_default_vlan(struct vnic_dev *vdev, u16 new_default_vlan) | ||
| 588 | { | ||
| 589 | u64 a0 = new_default_vlan, a1 = 0; | ||
| 590 | int wait = 1000; | ||
| 591 | int old_vlan = 0; | ||
| 592 | |||
| 593 | old_vlan = vnic_dev_cmd(vdev, CMD_SET_DEFAULT_VLAN, &a0, &a1, wait); | ||
| 594 | return (u16)old_vlan; | ||
| 595 | } | ||
| 596 | |||
| 587 | int vnic_dev_link_status(struct vnic_dev *vdev) | 597 | int vnic_dev_link_status(struct vnic_dev *vdev) |
| 588 | { | 598 | { |
| 589 | if (vdev->linkstatus) | 599 | if (vdev->linkstatus) |
diff --git a/drivers/scsi/fnic/vnic_dev.h b/drivers/scsi/fnic/vnic_dev.h index f9935a8a5a09..40d4195f562b 100644 --- a/drivers/scsi/fnic/vnic_dev.h +++ b/drivers/scsi/fnic/vnic_dev.h | |||
| @@ -148,6 +148,8 @@ int vnic_dev_disable(struct vnic_dev *vdev); | |||
| 148 | int vnic_dev_open(struct vnic_dev *vdev, int arg); | 148 | int vnic_dev_open(struct vnic_dev *vdev, int arg); |
| 149 | int vnic_dev_open_done(struct vnic_dev *vdev, int *done); | 149 | int vnic_dev_open_done(struct vnic_dev *vdev, int *done); |
| 150 | int vnic_dev_init(struct vnic_dev *vdev, int arg); | 150 | int vnic_dev_init(struct vnic_dev *vdev, int arg); |
| 151 | u16 vnic_dev_set_default_vlan(struct vnic_dev *vdev, | ||
| 152 | u16 new_default_vlan); | ||
| 151 | int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); | 153 | int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); |
| 152 | int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); | 154 | int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); |
| 153 | void vnic_dev_set_intr_mode(struct vnic_dev *vdev, | 155 | void vnic_dev_set_intr_mode(struct vnic_dev *vdev, |
diff --git a/drivers/scsi/fnic/vnic_devcmd.h b/drivers/scsi/fnic/vnic_devcmd.h index 7c9ccbd4134b..3e2fcbda6aed 100644 --- a/drivers/scsi/fnic/vnic_devcmd.h +++ b/drivers/scsi/fnic/vnic_devcmd.h | |||
| @@ -196,6 +196,73 @@ enum vnic_devcmd_cmd { | |||
| 196 | 196 | ||
| 197 | /* undo initialize of virtual link */ | 197 | /* undo initialize of virtual link */ |
| 198 | CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34), | 198 | CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34), |
| 199 | |||
| 200 | /* check fw capability of a cmd: | ||
| 201 | * in: (u32)a0=cmd | ||
| 202 | * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */ | ||
| 203 | CMD_CAPABILITY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36), | ||
| 204 | |||
| 205 | /* persistent binding info | ||
| 206 | * in: (u64)a0=paddr of arg | ||
| 207 | * (u32)a1=CMD_PERBI_XXX */ | ||
| 208 | CMD_PERBI = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37), | ||
| 209 | |||
| 210 | /* Interrupt Assert Register functionality | ||
| 211 | * in: (u16)a0=interrupt number to assert | ||
| 212 | */ | ||
| 213 | CMD_IAR = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 38), | ||
| 214 | |||
| 215 | /* initiate hangreset, like softreset after hang detected */ | ||
| 216 | CMD_HANG_RESET = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 39), | ||
| 217 | |||
| 218 | /* hangreset status: | ||
| 219 | * out: a0=0 reset complete, a0=1 reset in progress */ | ||
| 220 | CMD_HANG_RESET_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 40), | ||
| 221 | |||
| 222 | /* | ||
| 223 | * Set hw ingress packet vlan rewrite mode: | ||
| 224 | * in: (u32)a0=new vlan rewrite mode | ||
| 225 | * out: (u32)a0=old vlan rewrite mode */ | ||
| 226 | CMD_IG_VLAN_REWRITE_MODE = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 41), | ||
| 227 | |||
| 228 | /* | ||
| 229 | * in: (u16)a0=bdf of target vnic | ||
| 230 | * (u32)a1=cmd to proxy | ||
| 231 | * a2-a15=args to cmd in a1 | ||
| 232 | * out: (u32)a0=status of proxied cmd | ||
| 233 | * a1-a15=out args of proxied cmd */ | ||
| 234 | CMD_PROXY_BY_BDF = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42), | ||
| 235 | |||
| 236 | /* | ||
| 237 | * As for BY_BDF except a0 is index of hvnlink subordinate vnic | ||
| 238 | * or SR-IOV virtual vnic | ||
| 239 | */ | ||
| 240 | CMD_PROXY_BY_INDEX = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43), | ||
| 241 | |||
| 242 | /* | ||
| 243 | * For HPP toggle: | ||
| 244 | * adapter-info-get | ||
| 245 | * in: (u64)a0=phsical address of buffer passed in from caller. | ||
| 246 | * (u16)a1=size of buffer specified in a0. | ||
| 247 | * out: (u64)a0=phsical address of buffer passed in from caller. | ||
| 248 | * (u16)a1=actual bytes from VIF-CONFIG-INFO TLV, or | ||
| 249 | * 0 if no VIF-CONFIG-INFO TLV was ever received. */ | ||
| 250 | CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44), | ||
| 251 | |||
| 252 | /* | ||
| 253 | * INT13 API: (u64)a0=paddr to vnic_int13_params struct | ||
| 254 | * (u32)a1=INT13_CMD_xxx | ||
| 255 | */ | ||
| 256 | CMD_INT13_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 45), | ||
| 257 | |||
| 258 | /* | ||
| 259 | * Set default vlan: | ||
| 260 | * in: (u16)a0=new default vlan | ||
| 261 | * (u16)a1=zero for overriding vlan with param a0, | ||
| 262 | * non-zero for resetting vlan to the default | ||
| 263 | * out: (u16)a0=old default vlan | ||
| 264 | */ | ||
| 265 | CMD_SET_DEFAULT_VLAN = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 46) | ||
| 199 | }; | 266 | }; |
| 200 | 267 | ||
| 201 | /* flags for CMD_OPEN */ | 268 | /* flags for CMD_OPEN */ |
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index cc82d0f322b6..4e31caa21ddf 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c | |||
| @@ -2179,7 +2179,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) | |||
| 2179 | return 0; | 2179 | return 0; |
| 2180 | } | 2180 | } |
| 2181 | 2181 | ||
| 2182 | if (vhost->state == IBMVFC_ACTIVE) { | 2182 | if (vhost->logged_in) { |
| 2183 | evt = ibmvfc_get_event(vhost); | 2183 | evt = ibmvfc_get_event(vhost); |
| 2184 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT); | 2184 | ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT); |
| 2185 | 2185 | ||
| @@ -2190,7 +2190,12 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) | |||
| 2190 | tmf->common.length = sizeof(*tmf); | 2190 | tmf->common.length = sizeof(*tmf); |
| 2191 | tmf->scsi_id = rport->port_id; | 2191 | tmf->scsi_id = rport->port_id; |
| 2192 | int_to_scsilun(sdev->lun, &tmf->lun); | 2192 | int_to_scsilun(sdev->lun, &tmf->lun); |
| 2193 | tmf->flags = (type | IBMVFC_TMF_LUA_VALID); | 2193 | if (!(vhost->login_buf->resp.capabilities & IBMVFC_CAN_SUPPRESS_ABTS)) |
| 2194 | type &= ~IBMVFC_TMF_SUPPRESS_ABTS; | ||
| 2195 | if (vhost->state == IBMVFC_ACTIVE) | ||
| 2196 | tmf->flags = (type | IBMVFC_TMF_LUA_VALID); | ||
| 2197 | else | ||
| 2198 | tmf->flags = ((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID); | ||
| 2194 | tmf->cancel_key = (unsigned long)sdev->hostdata; | 2199 | tmf->cancel_key = (unsigned long)sdev->hostdata; |
| 2195 | tmf->my_cancel_key = (unsigned long)starget->hostdata; | 2200 | tmf->my_cancel_key = (unsigned long)starget->hostdata; |
| 2196 | 2201 | ||
| @@ -2327,7 +2332,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) | |||
| 2327 | timeout = wait_for_completion_timeout(&evt->comp, timeout); | 2332 | timeout = wait_for_completion_timeout(&evt->comp, timeout); |
| 2328 | 2333 | ||
| 2329 | if (!timeout) { | 2334 | if (!timeout) { |
| 2330 | rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | 2335 | rc = ibmvfc_cancel_all(sdev, 0); |
| 2331 | if (!rc) { | 2336 | if (!rc) { |
| 2332 | rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key); | 2337 | rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key); |
| 2333 | if (rc == SUCCESS) | 2338 | if (rc == SUCCESS) |
| @@ -2383,24 +2388,30 @@ out: | |||
| 2383 | * @cmd: scsi command to abort | 2388 | * @cmd: scsi command to abort |
| 2384 | * | 2389 | * |
| 2385 | * Returns: | 2390 | * Returns: |
| 2386 | * SUCCESS / FAILED | 2391 | * SUCCESS / FAST_IO_FAIL / FAILED |
| 2387 | **/ | 2392 | **/ |
| 2388 | static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd) | 2393 | static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd) |
| 2389 | { | 2394 | { |
| 2390 | struct scsi_device *sdev = cmd->device; | 2395 | struct scsi_device *sdev = cmd->device; |
| 2391 | struct ibmvfc_host *vhost = shost_priv(sdev->host); | 2396 | struct ibmvfc_host *vhost = shost_priv(sdev->host); |
| 2392 | int cancel_rc, abort_rc; | 2397 | int cancel_rc, block_rc; |
| 2393 | int rc = FAILED; | 2398 | int rc = FAILED; |
| 2394 | 2399 | ||
| 2395 | ENTER; | 2400 | ENTER; |
| 2396 | fc_block_scsi_eh(cmd); | 2401 | block_rc = fc_block_scsi_eh(cmd); |
| 2397 | ibmvfc_wait_while_resetting(vhost); | 2402 | ibmvfc_wait_while_resetting(vhost); |
| 2398 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | 2403 | if (block_rc != FAST_IO_FAIL) { |
| 2399 | abort_rc = ibmvfc_abort_task_set(sdev); | 2404 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); |
| 2405 | ibmvfc_abort_task_set(sdev); | ||
| 2406 | } else | ||
| 2407 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS); | ||
| 2400 | 2408 | ||
| 2401 | if (!cancel_rc && !abort_rc) | 2409 | if (!cancel_rc) |
| 2402 | rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun); | 2410 | rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun); |
| 2403 | 2411 | ||
| 2412 | if (block_rc == FAST_IO_FAIL && rc != FAILED) | ||
| 2413 | rc = FAST_IO_FAIL; | ||
| 2414 | |||
| 2404 | LEAVE; | 2415 | LEAVE; |
| 2405 | return rc; | 2416 | return rc; |
| 2406 | } | 2417 | } |
| @@ -2410,29 +2421,47 @@ static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd) | |||
| 2410 | * @cmd: scsi command struct | 2421 | * @cmd: scsi command struct |
| 2411 | * | 2422 | * |
| 2412 | * Returns: | 2423 | * Returns: |
| 2413 | * SUCCESS / FAILED | 2424 | * SUCCESS / FAST_IO_FAIL / FAILED |
| 2414 | **/ | 2425 | **/ |
| 2415 | static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) | 2426 | static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) |
| 2416 | { | 2427 | { |
| 2417 | struct scsi_device *sdev = cmd->device; | 2428 | struct scsi_device *sdev = cmd->device; |
| 2418 | struct ibmvfc_host *vhost = shost_priv(sdev->host); | 2429 | struct ibmvfc_host *vhost = shost_priv(sdev->host); |
| 2419 | int cancel_rc, reset_rc; | 2430 | int cancel_rc, block_rc, reset_rc = 0; |
| 2420 | int rc = FAILED; | 2431 | int rc = FAILED; |
| 2421 | 2432 | ||
| 2422 | ENTER; | 2433 | ENTER; |
| 2423 | fc_block_scsi_eh(cmd); | 2434 | block_rc = fc_block_scsi_eh(cmd); |
| 2424 | ibmvfc_wait_while_resetting(vhost); | 2435 | ibmvfc_wait_while_resetting(vhost); |
| 2425 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET); | 2436 | if (block_rc != FAST_IO_FAIL) { |
| 2426 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN"); | 2437 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET); |
| 2438 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN"); | ||
| 2439 | } else | ||
| 2440 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS); | ||
| 2427 | 2441 | ||
| 2428 | if (!cancel_rc && !reset_rc) | 2442 | if (!cancel_rc && !reset_rc) |
| 2429 | rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun); | 2443 | rc = ibmvfc_wait_for_ops(vhost, sdev, ibmvfc_match_lun); |
| 2430 | 2444 | ||
| 2445 | if (block_rc == FAST_IO_FAIL && rc != FAILED) | ||
| 2446 | rc = FAST_IO_FAIL; | ||
| 2447 | |||
| 2431 | LEAVE; | 2448 | LEAVE; |
| 2432 | return rc; | 2449 | return rc; |
| 2433 | } | 2450 | } |
| 2434 | 2451 | ||
| 2435 | /** | 2452 | /** |
| 2453 | * ibmvfc_dev_cancel_all_noreset - Device iterated cancel all function | ||
| 2454 | * @sdev: scsi device struct | ||
| 2455 | * @data: return code | ||
| 2456 | * | ||
| 2457 | **/ | ||
| 2458 | static void ibmvfc_dev_cancel_all_noreset(struct scsi_device *sdev, void *data) | ||
| 2459 | { | ||
| 2460 | unsigned long *rc = data; | ||
| 2461 | *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS); | ||
| 2462 | } | ||
| 2463 | |||
| 2464 | /** | ||
| 2436 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function | 2465 | * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function |
| 2437 | * @sdev: scsi device struct | 2466 | * @sdev: scsi device struct |
| 2438 | * @data: return code | 2467 | * @data: return code |
| @@ -2449,26 +2478,33 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data) | |||
| 2449 | * @cmd: scsi command struct | 2478 | * @cmd: scsi command struct |
| 2450 | * | 2479 | * |
| 2451 | * Returns: | 2480 | * Returns: |
| 2452 | * SUCCESS / FAILED | 2481 | * SUCCESS / FAST_IO_FAIL / FAILED |
| 2453 | **/ | 2482 | **/ |
| 2454 | static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) | 2483 | static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) |
| 2455 | { | 2484 | { |
| 2456 | struct scsi_device *sdev = cmd->device; | 2485 | struct scsi_device *sdev = cmd->device; |
| 2457 | struct ibmvfc_host *vhost = shost_priv(sdev->host); | 2486 | struct ibmvfc_host *vhost = shost_priv(sdev->host); |
| 2458 | struct scsi_target *starget = scsi_target(sdev); | 2487 | struct scsi_target *starget = scsi_target(sdev); |
| 2459 | int reset_rc; | 2488 | int block_rc; |
| 2489 | int reset_rc = 0; | ||
| 2460 | int rc = FAILED; | 2490 | int rc = FAILED; |
| 2461 | unsigned long cancel_rc = 0; | 2491 | unsigned long cancel_rc = 0; |
| 2462 | 2492 | ||
| 2463 | ENTER; | 2493 | ENTER; |
| 2464 | fc_block_scsi_eh(cmd); | 2494 | block_rc = fc_block_scsi_eh(cmd); |
| 2465 | ibmvfc_wait_while_resetting(vhost); | 2495 | ibmvfc_wait_while_resetting(vhost); |
| 2466 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset); | 2496 | if (block_rc != FAST_IO_FAIL) { |
| 2467 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target"); | 2497 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset); |
| 2498 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target"); | ||
| 2499 | } else | ||
| 2500 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_noreset); | ||
| 2468 | 2501 | ||
| 2469 | if (!cancel_rc && !reset_rc) | 2502 | if (!cancel_rc && !reset_rc) |
| 2470 | rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target); | 2503 | rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target); |
| 2471 | 2504 | ||
| 2505 | if (block_rc == FAST_IO_FAIL && rc != FAILED) | ||
| 2506 | rc = FAST_IO_FAIL; | ||
| 2507 | |||
| 2472 | LEAVE; | 2508 | LEAVE; |
| 2473 | return rc; | 2509 | return rc; |
| 2474 | } | 2510 | } |
| @@ -2480,12 +2516,16 @@ static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) | |||
| 2480 | **/ | 2516 | **/ |
| 2481 | static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) | 2517 | static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) |
| 2482 | { | 2518 | { |
| 2483 | int rc; | 2519 | int rc, block_rc; |
| 2484 | struct ibmvfc_host *vhost = shost_priv(cmd->device->host); | 2520 | struct ibmvfc_host *vhost = shost_priv(cmd->device->host); |
| 2485 | 2521 | ||
| 2486 | fc_block_scsi_eh(cmd); | 2522 | block_rc = fc_block_scsi_eh(cmd); |
| 2487 | dev_err(vhost->dev, "Resetting connection due to error recovery\n"); | 2523 | dev_err(vhost->dev, "Resetting connection due to error recovery\n"); |
| 2488 | rc = ibmvfc_issue_fc_host_lip(vhost->host); | 2524 | rc = ibmvfc_issue_fc_host_lip(vhost->host); |
| 2525 | |||
| 2526 | if (block_rc == FAST_IO_FAIL) | ||
| 2527 | return FAST_IO_FAIL; | ||
| 2528 | |||
| 2489 | return rc ? FAILED : SUCCESS; | 2529 | return rc ? FAILED : SUCCESS; |
| 2490 | } | 2530 | } |
| 2491 | 2531 | ||
| @@ -2509,8 +2549,7 @@ static void ibmvfc_terminate_rport_io(struct fc_rport *rport) | |||
| 2509 | dev_rport = starget_to_rport(scsi_target(sdev)); | 2549 | dev_rport = starget_to_rport(scsi_target(sdev)); |
| 2510 | if (dev_rport != rport) | 2550 | if (dev_rport != rport) |
| 2511 | continue; | 2551 | continue; |
| 2512 | ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | 2552 | ibmvfc_cancel_all(sdev, IBMVFC_TMF_SUPPRESS_ABTS); |
| 2513 | ibmvfc_abort_task_set(sdev); | ||
| 2514 | } | 2553 | } |
| 2515 | 2554 | ||
| 2516 | rc = ibmvfc_wait_for_ops(vhost, rport, ibmvfc_match_rport); | 2555 | rc = ibmvfc_wait_for_ops(vhost, rport, ibmvfc_match_rport); |
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 3be8af624e6f..017a5290e8c1 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h | |||
| @@ -29,8 +29,8 @@ | |||
| 29 | #include "viosrp.h" | 29 | #include "viosrp.h" |
| 30 | 30 | ||
| 31 | #define IBMVFC_NAME "ibmvfc" | 31 | #define IBMVFC_NAME "ibmvfc" |
| 32 | #define IBMVFC_DRIVER_VERSION "1.0.10" | 32 | #define IBMVFC_DRIVER_VERSION "1.0.11" |
| 33 | #define IBMVFC_DRIVER_DATE "(August 24, 2012)" | 33 | #define IBMVFC_DRIVER_DATE "(April 12, 2013)" |
| 34 | 34 | ||
| 35 | #define IBMVFC_DEFAULT_TIMEOUT 60 | 35 | #define IBMVFC_DEFAULT_TIMEOUT 60 |
| 36 | #define IBMVFC_ADISC_CANCEL_TIMEOUT 45 | 36 | #define IBMVFC_ADISC_CANCEL_TIMEOUT 45 |
| @@ -208,10 +208,10 @@ struct ibmvfc_npiv_login_resp { | |||
| 208 | u16 error; | 208 | u16 error; |
| 209 | u32 flags; | 209 | u32 flags; |
| 210 | #define IBMVFC_NATIVE_FC 0x01 | 210 | #define IBMVFC_NATIVE_FC 0x01 |
| 211 | #define IBMVFC_CAN_FLUSH_ON_HALT 0x08 | ||
| 212 | u32 reserved; | 211 | u32 reserved; |
| 213 | u64 capabilities; | 212 | u64 capabilities; |
| 214 | #define IBMVFC_CAN_FLUSH_ON_HALT 0x08 | 213 | #define IBMVFC_CAN_FLUSH_ON_HALT 0x08 |
| 214 | #define IBMVFC_CAN_SUPPRESS_ABTS 0x10 | ||
| 215 | u32 max_cmds; | 215 | u32 max_cmds; |
| 216 | u32 scsi_id_sz; | 216 | u32 scsi_id_sz; |
| 217 | u64 max_dma_len; | 217 | u64 max_dma_len; |
| @@ -351,6 +351,7 @@ struct ibmvfc_tmf { | |||
| 351 | #define IBMVFC_TMF_LUN_RESET 0x10 | 351 | #define IBMVFC_TMF_LUN_RESET 0x10 |
| 352 | #define IBMVFC_TMF_TGT_RESET 0x20 | 352 | #define IBMVFC_TMF_TGT_RESET 0x20 |
| 353 | #define IBMVFC_TMF_LUA_VALID 0x40 | 353 | #define IBMVFC_TMF_LUA_VALID 0x40 |
| 354 | #define IBMVFC_TMF_SUPPRESS_ABTS 0x80 | ||
| 354 | u32 cancel_key; | 355 | u32 cancel_key; |
| 355 | u32 my_cancel_key; | 356 | u32 my_cancel_key; |
| 356 | u32 pad; | 357 | u32 pad; |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 2197b57fb225..82a3c1ec8706 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
| @@ -4777,7 +4777,7 @@ static int ipr_eh_host_reset(struct scsi_cmnd *cmd) | |||
| 4777 | ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata; | 4777 | ioa_cfg = (struct ipr_ioa_cfg *) cmd->device->host->hostdata; |
| 4778 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | 4778 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); |
| 4779 | 4779 | ||
| 4780 | if (!ioa_cfg->in_reset_reload) { | 4780 | if (!ioa_cfg->in_reset_reload && !ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) { |
| 4781 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV); | 4781 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV); |
| 4782 | dev_err(&ioa_cfg->pdev->dev, | 4782 | dev_err(&ioa_cfg->pdev->dev, |
| 4783 | "Adapter being reset as a result of error recovery.\n"); | 4783 | "Adapter being reset as a result of error recovery.\n"); |
| @@ -6421,7 +6421,7 @@ static void ipr_build_ata_ioadl64(struct ipr_cmnd *ipr_cmd, | |||
| 6421 | { | 6421 | { |
| 6422 | u32 ioadl_flags = 0; | 6422 | u32 ioadl_flags = 0; |
| 6423 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; | 6423 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; |
| 6424 | struct ipr_ioadl64_desc *ioadl64 = ipr_cmd->i.ioadl64; | 6424 | struct ipr_ioadl64_desc *ioadl64 = ipr_cmd->i.ata_ioadl.ioadl64; |
| 6425 | struct ipr_ioadl64_desc *last_ioadl64 = NULL; | 6425 | struct ipr_ioadl64_desc *last_ioadl64 = NULL; |
| 6426 | int len = qc->nbytes; | 6426 | int len = qc->nbytes; |
| 6427 | struct scatterlist *sg; | 6427 | struct scatterlist *sg; |
| @@ -6441,7 +6441,7 @@ static void ipr_build_ata_ioadl64(struct ipr_cmnd *ipr_cmd, | |||
| 6441 | ioarcb->ioadl_len = | 6441 | ioarcb->ioadl_len = |
| 6442 | cpu_to_be32(sizeof(struct ipr_ioadl64_desc) * ipr_cmd->dma_use_sg); | 6442 | cpu_to_be32(sizeof(struct ipr_ioadl64_desc) * ipr_cmd->dma_use_sg); |
| 6443 | ioarcb->u.sis64_addr_data.data_ioadl_addr = | 6443 | ioarcb->u.sis64_addr_data.data_ioadl_addr = |
| 6444 | cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ata_ioadl)); | 6444 | cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ata_ioadl.ioadl64)); |
| 6445 | 6445 | ||
| 6446 | for_each_sg(qc->sg, sg, qc->n_elem, si) { | 6446 | for_each_sg(qc->sg, sg, qc->n_elem, si) { |
| 6447 | ioadl64->flags = cpu_to_be32(ioadl_flags); | 6447 | ioadl64->flags = cpu_to_be32(ioadl_flags); |
| @@ -6739,6 +6739,7 @@ static int ipr_invalid_adapter(struct ipr_ioa_cfg *ioa_cfg) | |||
| 6739 | static int ipr_ioa_bringdown_done(struct ipr_cmnd *ipr_cmd) | 6739 | static int ipr_ioa_bringdown_done(struct ipr_cmnd *ipr_cmd) |
| 6740 | { | 6740 | { |
| 6741 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 6741 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
| 6742 | int i; | ||
| 6742 | 6743 | ||
| 6743 | ENTER; | 6744 | ENTER; |
| 6744 | if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].removing_ioa) { | 6745 | if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].removing_ioa) { |
| @@ -6750,6 +6751,13 @@ static int ipr_ioa_bringdown_done(struct ipr_cmnd *ipr_cmd) | |||
| 6750 | 6751 | ||
| 6751 | ioa_cfg->in_reset_reload = 0; | 6752 | ioa_cfg->in_reset_reload = 0; |
| 6752 | ioa_cfg->reset_retries = 0; | 6753 | ioa_cfg->reset_retries = 0; |
| 6754 | for (i = 0; i < ioa_cfg->hrrq_num; i++) { | ||
| 6755 | spin_lock(&ioa_cfg->hrrq[i]._lock); | ||
| 6756 | ioa_cfg->hrrq[i].ioa_is_dead = 1; | ||
| 6757 | spin_unlock(&ioa_cfg->hrrq[i]._lock); | ||
| 6758 | } | ||
| 6759 | wmb(); | ||
| 6760 | |||
| 6753 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); | 6761 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); |
| 6754 | wake_up_all(&ioa_cfg->reset_wait_q); | 6762 | wake_up_all(&ioa_cfg->reset_wait_q); |
| 6755 | LEAVE; | 6763 | LEAVE; |
| @@ -8651,7 +8659,7 @@ static void ipr_pci_perm_failure(struct pci_dev *pdev) | |||
| 8651 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | 8659 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); |
| 8652 | if (ioa_cfg->sdt_state == WAIT_FOR_DUMP) | 8660 | if (ioa_cfg->sdt_state == WAIT_FOR_DUMP) |
| 8653 | ioa_cfg->sdt_state = ABORT_DUMP; | 8661 | ioa_cfg->sdt_state = ABORT_DUMP; |
| 8654 | ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES; | 8662 | ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES - 1; |
| 8655 | ioa_cfg->in_ioa_bringdown = 1; | 8663 | ioa_cfg->in_ioa_bringdown = 1; |
| 8656 | for (i = 0; i < ioa_cfg->hrrq_num; i++) { | 8664 | for (i = 0; i < ioa_cfg->hrrq_num; i++) { |
| 8657 | spin_lock(&ioa_cfg->hrrq[i]._lock); | 8665 | spin_lock(&ioa_cfg->hrrq[i]._lock); |
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 21a6ff1ed5c6..a1fb840596ef 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
| @@ -552,7 +552,7 @@ struct ipr_ioarcb_ata_regs { /* 22 bytes */ | |||
| 552 | u8 hob_lbam; | 552 | u8 hob_lbam; |
| 553 | u8 hob_lbah; | 553 | u8 hob_lbah; |
| 554 | u8 ctl; | 554 | u8 ctl; |
| 555 | }__attribute__ ((packed, aligned(4))); | 555 | }__attribute__ ((packed, aligned(2))); |
| 556 | 556 | ||
| 557 | struct ipr_ioadl_desc { | 557 | struct ipr_ioadl_desc { |
| 558 | __be32 flags_and_data_len; | 558 | __be32 flags_and_data_len; |
diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index c3aa6c5457b9..96a26f454673 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c | |||
| @@ -1085,7 +1085,7 @@ static void sci_remote_device_ready_state_enter(struct sci_base_state_machine *s | |||
| 1085 | struct isci_host *ihost = idev->owning_port->owning_controller; | 1085 | struct isci_host *ihost = idev->owning_port->owning_controller; |
| 1086 | struct domain_device *dev = idev->domain_dev; | 1086 | struct domain_device *dev = idev->domain_dev; |
| 1087 | 1087 | ||
| 1088 | if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) { | 1088 | if (dev->dev_type == SAS_SATA_DEV || (dev->tproto & SAS_PROTOCOL_SATA)) { |
| 1089 | sci_change_state(&idev->sm, SCI_STP_DEV_IDLE); | 1089 | sci_change_state(&idev->sm, SCI_STP_DEV_IDLE); |
| 1090 | } else if (dev_is_expander(dev)) { | 1090 | } else if (dev_is_expander(dev)) { |
| 1091 | sci_change_state(&idev->sm, SCI_SMP_DEV_IDLE); | 1091 | sci_change_state(&idev->sm, SCI_SMP_DEV_IDLE); |
| @@ -1098,7 +1098,7 @@ static void sci_remote_device_ready_state_exit(struct sci_base_state_machine *sm | |||
| 1098 | struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); | 1098 | struct isci_remote_device *idev = container_of(sm, typeof(*idev), sm); |
| 1099 | struct domain_device *dev = idev->domain_dev; | 1099 | struct domain_device *dev = idev->domain_dev; |
| 1100 | 1100 | ||
| 1101 | if (dev->dev_type == SAS_END_DEV) { | 1101 | if (dev->dev_type == SAS_END_DEVICE) { |
| 1102 | struct isci_host *ihost = idev->owning_port->owning_controller; | 1102 | struct isci_host *ihost = idev->owning_port->owning_controller; |
| 1103 | 1103 | ||
| 1104 | isci_remote_device_not_ready(ihost, idev, | 1104 | isci_remote_device_not_ready(ihost, idev, |
diff --git a/drivers/scsi/isci/remote_device.h b/drivers/scsi/isci/remote_device.h index 7674caae1d88..47a013fffae7 100644 --- a/drivers/scsi/isci/remote_device.h +++ b/drivers/scsi/isci/remote_device.h | |||
| @@ -297,7 +297,7 @@ static inline struct isci_remote_device *rnc_to_dev(struct sci_remote_node_conte | |||
| 297 | 297 | ||
| 298 | static inline bool dev_is_expander(struct domain_device *dev) | 298 | static inline bool dev_is_expander(struct domain_device *dev) |
| 299 | { | 299 | { |
| 300 | return dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV; | 300 | return dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE; |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | static inline void sci_remote_device_decrement_request_count(struct isci_remote_device *idev) | 303 | static inline void sci_remote_device_decrement_request_count(struct isci_remote_device *idev) |
diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 9594ab62702b..e3e3bcbd5a9f 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c | |||
| @@ -2978,7 +2978,7 @@ static void sci_request_started_state_enter(struct sci_base_state_machine *sm) | |||
| 2978 | /* all unaccelerated request types (non ssp or ncq) handled with | 2978 | /* all unaccelerated request types (non ssp or ncq) handled with |
| 2979 | * substates | 2979 | * substates |
| 2980 | */ | 2980 | */ |
| 2981 | if (!task && dev->dev_type == SAS_END_DEV) { | 2981 | if (!task && dev->dev_type == SAS_END_DEVICE) { |
| 2982 | state = SCI_REQ_TASK_WAIT_TC_COMP; | 2982 | state = SCI_REQ_TASK_WAIT_TC_COMP; |
| 2983 | } else if (task && task->task_proto == SAS_PROTOCOL_SMP) { | 2983 | } else if (task && task->task_proto == SAS_PROTOCOL_SMP) { |
| 2984 | state = SCI_REQ_SMP_WAIT_RESP; | 2984 | state = SCI_REQ_SMP_WAIT_RESP; |
| @@ -3101,7 +3101,7 @@ sci_io_request_construct(struct isci_host *ihost, | |||
| 3101 | if (idev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) | 3101 | if (idev->rnc.remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) |
| 3102 | return SCI_FAILURE_INVALID_REMOTE_DEVICE; | 3102 | return SCI_FAILURE_INVALID_REMOTE_DEVICE; |
| 3103 | 3103 | ||
| 3104 | if (dev->dev_type == SAS_END_DEV) | 3104 | if (dev->dev_type == SAS_END_DEVICE) |
| 3105 | /* pass */; | 3105 | /* pass */; |
| 3106 | else if (dev_is_sata(dev)) | 3106 | else if (dev_is_sata(dev)) |
| 3107 | memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd)); | 3107 | memset(&ireq->stp.cmd, 0, sizeof(ireq->stp.cmd)); |
| @@ -3125,7 +3125,7 @@ enum sci_status sci_task_request_construct(struct isci_host *ihost, | |||
| 3125 | /* Build the common part of the request */ | 3125 | /* Build the common part of the request */ |
| 3126 | sci_general_request_construct(ihost, idev, ireq); | 3126 | sci_general_request_construct(ihost, idev, ireq); |
| 3127 | 3127 | ||
| 3128 | if (dev->dev_type == SAS_END_DEV || dev_is_sata(dev)) { | 3128 | if (dev->dev_type == SAS_END_DEVICE || dev_is_sata(dev)) { |
| 3129 | set_bit(IREQ_TMF, &ireq->flags); | 3129 | set_bit(IREQ_TMF, &ireq->flags); |
| 3130 | memset(ireq->tc, 0, sizeof(struct scu_task_context)); | 3130 | memset(ireq->tc, 0, sizeof(struct scu_task_context)); |
| 3131 | 3131 | ||
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index b6f19a1db780..9bb020ac089c 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c | |||
| @@ -250,7 +250,7 @@ static struct isci_request *isci_task_request_build(struct isci_host *ihost, | |||
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | /* XXX convert to get this from task->tproto like other drivers */ | 252 | /* XXX convert to get this from task->tproto like other drivers */ |
| 253 | if (dev->dev_type == SAS_END_DEV) { | 253 | if (dev->dev_type == SAS_END_DEVICE) { |
| 254 | isci_tmf->proto = SAS_PROTOCOL_SSP; | 254 | isci_tmf->proto = SAS_PROTOCOL_SSP; |
| 255 | status = sci_task_request_construct_ssp(ireq); | 255 | status = sci_task_request_construct_ssp(ireq); |
| 256 | if (status != SCI_SUCCESS) | 256 | if (status != SCI_SUCCESS) |
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index bdb81cda8401..161c98efade9 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
| @@ -285,14 +285,14 @@ int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy) | |||
| 285 | if (phy->attached_tproto & SAS_PROTOCOL_STP) | 285 | if (phy->attached_tproto & SAS_PROTOCOL_STP) |
| 286 | dev->tproto = phy->attached_tproto; | 286 | dev->tproto = phy->attached_tproto; |
| 287 | if (phy->attached_sata_dev) | 287 | if (phy->attached_sata_dev) |
| 288 | dev->tproto |= SATA_DEV; | 288 | dev->tproto |= SAS_SATA_DEV; |
| 289 | 289 | ||
| 290 | if (phy->attached_dev_type == SATA_PENDING) | 290 | if (phy->attached_dev_type == SAS_SATA_PENDING) |
| 291 | dev->dev_type = SATA_PENDING; | 291 | dev->dev_type = SAS_SATA_PENDING; |
| 292 | else { | 292 | else { |
| 293 | int res; | 293 | int res; |
| 294 | 294 | ||
| 295 | dev->dev_type = SATA_DEV; | 295 | dev->dev_type = SAS_SATA_DEV; |
| 296 | res = sas_get_report_phy_sata(dev->parent, phy->phy_id, | 296 | res = sas_get_report_phy_sata(dev->parent, phy->phy_id, |
| 297 | &dev->sata_dev.rps_resp); | 297 | &dev->sata_dev.rps_resp); |
| 298 | if (res) { | 298 | if (res) { |
| @@ -314,7 +314,7 @@ static int sas_ata_clear_pending(struct domain_device *dev, struct ex_phy *phy) | |||
| 314 | int res; | 314 | int res; |
| 315 | 315 | ||
| 316 | /* we weren't pending, so successfully end the reset sequence now */ | 316 | /* we weren't pending, so successfully end the reset sequence now */ |
| 317 | if (dev->dev_type != SATA_PENDING) | 317 | if (dev->dev_type != SAS_SATA_PENDING) |
| 318 | return 1; | 318 | return 1; |
| 319 | 319 | ||
| 320 | /* hmmm, if this succeeds do we need to repost the domain_device to the | 320 | /* hmmm, if this succeeds do we need to repost the domain_device to the |
| @@ -348,9 +348,9 @@ static int smp_ata_check_ready(struct ata_link *link) | |||
| 348 | return 0; | 348 | return 0; |
| 349 | 349 | ||
| 350 | switch (ex_phy->attached_dev_type) { | 350 | switch (ex_phy->attached_dev_type) { |
| 351 | case SATA_PENDING: | 351 | case SAS_SATA_PENDING: |
| 352 | return 0; | 352 | return 0; |
| 353 | case SAS_END_DEV: | 353 | case SAS_END_DEVICE: |
| 354 | if (ex_phy->attached_sata_dev) | 354 | if (ex_phy->attached_sata_dev) |
| 355 | return sas_ata_clear_pending(dev, ex_phy); | 355 | return sas_ata_clear_pending(dev, ex_phy); |
| 356 | default: | 356 | default: |
| @@ -631,7 +631,7 @@ static void sas_get_ata_command_set(struct domain_device *dev) | |||
| 631 | struct dev_to_host_fis *fis = | 631 | struct dev_to_host_fis *fis = |
| 632 | (struct dev_to_host_fis *) dev->frame_rcvd; | 632 | (struct dev_to_host_fis *) dev->frame_rcvd; |
| 633 | 633 | ||
| 634 | if (dev->dev_type == SATA_PENDING) | 634 | if (dev->dev_type == SAS_SATA_PENDING) |
| 635 | return; | 635 | return; |
| 636 | 636 | ||
| 637 | if ((fis->sector_count == 1 && /* ATA */ | 637 | if ((fis->sector_count == 1 && /* ATA */ |
| @@ -797,7 +797,7 @@ int sas_discover_sata(struct domain_device *dev) | |||
| 797 | { | 797 | { |
| 798 | int res; | 798 | int res; |
| 799 | 799 | ||
| 800 | if (dev->dev_type == SATA_PM) | 800 | if (dev->dev_type == SAS_SATA_PM) |
| 801 | return -ENODEV; | 801 | return -ENODEV; |
| 802 | 802 | ||
| 803 | sas_get_ata_command_set(dev); | 803 | sas_get_ata_command_set(dev); |
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index a0c3003e0c7d..62b58d38ce2e 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c | |||
| @@ -39,11 +39,11 @@ | |||
| 39 | void sas_init_dev(struct domain_device *dev) | 39 | void sas_init_dev(struct domain_device *dev) |
| 40 | { | 40 | { |
| 41 | switch (dev->dev_type) { | 41 | switch (dev->dev_type) { |
| 42 | case SAS_END_DEV: | 42 | case SAS_END_DEVICE: |
| 43 | INIT_LIST_HEAD(&dev->ssp_dev.eh_list_node); | 43 | INIT_LIST_HEAD(&dev->ssp_dev.eh_list_node); |
| 44 | break; | 44 | break; |
| 45 | case EDGE_DEV: | 45 | case SAS_EDGE_EXPANDER_DEVICE: |
| 46 | case FANOUT_DEV: | 46 | case SAS_FANOUT_EXPANDER_DEVICE: |
| 47 | INIT_LIST_HEAD(&dev->ex_dev.children); | 47 | INIT_LIST_HEAD(&dev->ex_dev.children); |
| 48 | mutex_init(&dev->ex_dev.cmd_mutex); | 48 | mutex_init(&dev->ex_dev.cmd_mutex); |
| 49 | break; | 49 | break; |
| @@ -93,9 +93,9 @@ static int sas_get_port_device(struct asd_sas_port *port) | |||
| 93 | if (fis->interrupt_reason == 1 && fis->lbal == 1 && | 93 | if (fis->interrupt_reason == 1 && fis->lbal == 1 && |
| 94 | fis->byte_count_low==0x69 && fis->byte_count_high == 0x96 | 94 | fis->byte_count_low==0x69 && fis->byte_count_high == 0x96 |
| 95 | && (fis->device & ~0x10) == 0) | 95 | && (fis->device & ~0x10) == 0) |
| 96 | dev->dev_type = SATA_PM; | 96 | dev->dev_type = SAS_SATA_PM; |
| 97 | else | 97 | else |
| 98 | dev->dev_type = SATA_DEV; | 98 | dev->dev_type = SAS_SATA_DEV; |
| 99 | dev->tproto = SAS_PROTOCOL_SATA; | 99 | dev->tproto = SAS_PROTOCOL_SATA; |
| 100 | } else { | 100 | } else { |
| 101 | struct sas_identify_frame *id = | 101 | struct sas_identify_frame *id = |
| @@ -109,21 +109,21 @@ static int sas_get_port_device(struct asd_sas_port *port) | |||
| 109 | 109 | ||
| 110 | dev->port = port; | 110 | dev->port = port; |
| 111 | switch (dev->dev_type) { | 111 | switch (dev->dev_type) { |
| 112 | case SATA_DEV: | 112 | case SAS_SATA_DEV: |
| 113 | rc = sas_ata_init(dev); | 113 | rc = sas_ata_init(dev); |
| 114 | if (rc) { | 114 | if (rc) { |
| 115 | rphy = NULL; | 115 | rphy = NULL; |
| 116 | break; | 116 | break; |
| 117 | } | 117 | } |
| 118 | /* fall through */ | 118 | /* fall through */ |
| 119 | case SAS_END_DEV: | 119 | case SAS_END_DEVICE: |
| 120 | rphy = sas_end_device_alloc(port->port); | 120 | rphy = sas_end_device_alloc(port->port); |
| 121 | break; | 121 | break; |
| 122 | case EDGE_DEV: | 122 | case SAS_EDGE_EXPANDER_DEVICE: |
| 123 | rphy = sas_expander_alloc(port->port, | 123 | rphy = sas_expander_alloc(port->port, |
| 124 | SAS_EDGE_EXPANDER_DEVICE); | 124 | SAS_EDGE_EXPANDER_DEVICE); |
| 125 | break; | 125 | break; |
| 126 | case FANOUT_DEV: | 126 | case SAS_FANOUT_EXPANDER_DEVICE: |
| 127 | rphy = sas_expander_alloc(port->port, | 127 | rphy = sas_expander_alloc(port->port, |
| 128 | SAS_FANOUT_EXPANDER_DEVICE); | 128 | SAS_FANOUT_EXPANDER_DEVICE); |
| 129 | break; | 129 | break; |
| @@ -156,7 +156,7 @@ static int sas_get_port_device(struct asd_sas_port *port) | |||
| 156 | dev->rphy = rphy; | 156 | dev->rphy = rphy; |
| 157 | get_device(&dev->rphy->dev); | 157 | get_device(&dev->rphy->dev); |
| 158 | 158 | ||
| 159 | if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV) | 159 | if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEVICE) |
| 160 | list_add_tail(&dev->disco_list_node, &port->disco_list); | 160 | list_add_tail(&dev->disco_list_node, &port->disco_list); |
| 161 | else { | 161 | else { |
| 162 | spin_lock_irq(&port->dev_list_lock); | 162 | spin_lock_irq(&port->dev_list_lock); |
| @@ -315,7 +315,7 @@ void sas_free_device(struct kref *kref) | |||
| 315 | dev->phy = NULL; | 315 | dev->phy = NULL; |
| 316 | 316 | ||
| 317 | /* remove the phys and ports, everything else should be gone */ | 317 | /* remove the phys and ports, everything else should be gone */ |
| 318 | if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) | 318 | if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) |
| 319 | kfree(dev->ex_dev.ex_phy); | 319 | kfree(dev->ex_dev.ex_phy); |
| 320 | 320 | ||
| 321 | if (dev_is_sata(dev) && dev->sata_dev.ap) { | 321 | if (dev_is_sata(dev) && dev->sata_dev.ap) { |
| @@ -343,7 +343,7 @@ static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_d | |||
| 343 | spin_unlock_irq(&port->dev_list_lock); | 343 | spin_unlock_irq(&port->dev_list_lock); |
| 344 | 344 | ||
| 345 | spin_lock_irq(&ha->lock); | 345 | spin_lock_irq(&ha->lock); |
| 346 | if (dev->dev_type == SAS_END_DEV && | 346 | if (dev->dev_type == SAS_END_DEVICE && |
| 347 | !list_empty(&dev->ssp_dev.eh_list_node)) { | 347 | !list_empty(&dev->ssp_dev.eh_list_node)) { |
| 348 | list_del_init(&dev->ssp_dev.eh_list_node); | 348 | list_del_init(&dev->ssp_dev.eh_list_node); |
| 349 | ha->eh_active--; | 349 | ha->eh_active--; |
| @@ -457,15 +457,15 @@ static void sas_discover_domain(struct work_struct *work) | |||
| 457 | task_pid_nr(current)); | 457 | task_pid_nr(current)); |
| 458 | 458 | ||
| 459 | switch (dev->dev_type) { | 459 | switch (dev->dev_type) { |
| 460 | case SAS_END_DEV: | 460 | case SAS_END_DEVICE: |
| 461 | error = sas_discover_end_dev(dev); | 461 | error = sas_discover_end_dev(dev); |
| 462 | break; | 462 | break; |
| 463 | case EDGE_DEV: | 463 | case SAS_EDGE_EXPANDER_DEVICE: |
| 464 | case FANOUT_DEV: | 464 | case SAS_FANOUT_EXPANDER_DEVICE: |
| 465 | error = sas_discover_root_expander(dev); | 465 | error = sas_discover_root_expander(dev); |
| 466 | break; | 466 | break; |
| 467 | case SATA_DEV: | 467 | case SAS_SATA_DEV: |
| 468 | case SATA_PM: | 468 | case SAS_SATA_PM: |
| 469 | #ifdef CONFIG_SCSI_SAS_ATA | 469 | #ifdef CONFIG_SCSI_SAS_ATA |
| 470 | error = sas_discover_sata(dev); | 470 | error = sas_discover_sata(dev); |
| 471 | break; | 471 | break; |
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index f42b0e15410f..446b85110a1f 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
| @@ -183,21 +183,21 @@ static char sas_route_char(struct domain_device *dev, struct ex_phy *phy) | |||
| 183 | } | 183 | } |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | static enum sas_dev_type to_dev_type(struct discover_resp *dr) | 186 | static enum sas_device_type to_dev_type(struct discover_resp *dr) |
| 187 | { | 187 | { |
| 188 | /* This is detecting a failure to transmit initial dev to host | 188 | /* This is detecting a failure to transmit initial dev to host |
| 189 | * FIS as described in section J.5 of sas-2 r16 | 189 | * FIS as described in section J.5 of sas-2 r16 |
| 190 | */ | 190 | */ |
| 191 | if (dr->attached_dev_type == NO_DEVICE && dr->attached_sata_dev && | 191 | if (dr->attached_dev_type == SAS_PHY_UNUSED && dr->attached_sata_dev && |
| 192 | dr->linkrate >= SAS_LINK_RATE_1_5_GBPS) | 192 | dr->linkrate >= SAS_LINK_RATE_1_5_GBPS) |
| 193 | return SATA_PENDING; | 193 | return SAS_SATA_PENDING; |
| 194 | else | 194 | else |
| 195 | return dr->attached_dev_type; | 195 | return dr->attached_dev_type; |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) | 198 | static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) |
| 199 | { | 199 | { |
| 200 | enum sas_dev_type dev_type; | 200 | enum sas_device_type dev_type; |
| 201 | enum sas_linkrate linkrate; | 201 | enum sas_linkrate linkrate; |
| 202 | u8 sas_addr[SAS_ADDR_SIZE]; | 202 | u8 sas_addr[SAS_ADDR_SIZE]; |
| 203 | struct smp_resp *resp = rsp; | 203 | struct smp_resp *resp = rsp; |
| @@ -238,7 +238,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) | |||
| 238 | /* Handle vacant phy - rest of dr data is not valid so skip it */ | 238 | /* Handle vacant phy - rest of dr data is not valid so skip it */ |
| 239 | if (phy->phy_state == PHY_VACANT) { | 239 | if (phy->phy_state == PHY_VACANT) { |
| 240 | memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); | 240 | memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); |
| 241 | phy->attached_dev_type = NO_DEVICE; | 241 | phy->attached_dev_type = SAS_PHY_UNUSED; |
| 242 | if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) { | 242 | if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) { |
| 243 | phy->phy_id = phy_id; | 243 | phy->phy_id = phy_id; |
| 244 | goto skip; | 244 | goto skip; |
| @@ -259,7 +259,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) | |||
| 259 | /* help some expanders that fail to zero sas_address in the 'no | 259 | /* help some expanders that fail to zero sas_address in the 'no |
| 260 | * device' case | 260 | * device' case |
| 261 | */ | 261 | */ |
| 262 | if (phy->attached_dev_type == NO_DEVICE || | 262 | if (phy->attached_dev_type == SAS_PHY_UNUSED || |
| 263 | phy->linkrate < SAS_LINK_RATE_1_5_GBPS) | 263 | phy->linkrate < SAS_LINK_RATE_1_5_GBPS) |
| 264 | memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); | 264 | memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); |
| 265 | else | 265 | else |
| @@ -292,13 +292,13 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) | |||
| 292 | 292 | ||
| 293 | out: | 293 | out: |
| 294 | switch (phy->attached_dev_type) { | 294 | switch (phy->attached_dev_type) { |
| 295 | case SATA_PENDING: | 295 | case SAS_SATA_PENDING: |
| 296 | type = "stp pending"; | 296 | type = "stp pending"; |
| 297 | break; | 297 | break; |
| 298 | case NO_DEVICE: | 298 | case SAS_PHY_UNUSED: |
| 299 | type = "no device"; | 299 | type = "no device"; |
| 300 | break; | 300 | break; |
| 301 | case SAS_END_DEV: | 301 | case SAS_END_DEVICE: |
| 302 | if (phy->attached_iproto) { | 302 | if (phy->attached_iproto) { |
| 303 | if (phy->attached_tproto) | 303 | if (phy->attached_tproto) |
| 304 | type = "host+target"; | 304 | type = "host+target"; |
| @@ -311,8 +311,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) | |||
| 311 | type = "ssp"; | 311 | type = "ssp"; |
| 312 | } | 312 | } |
| 313 | break; | 313 | break; |
| 314 | case EDGE_DEV: | 314 | case SAS_EDGE_EXPANDER_DEVICE: |
| 315 | case FANOUT_DEV: | 315 | case SAS_FANOUT_EXPANDER_DEVICE: |
| 316 | type = "smp"; | 316 | type = "smp"; |
| 317 | break; | 317 | break; |
| 318 | default: | 318 | default: |
| @@ -833,7 +833,7 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
| 833 | } else | 833 | } else |
| 834 | #endif | 834 | #endif |
| 835 | if (phy->attached_tproto & SAS_PROTOCOL_SSP) { | 835 | if (phy->attached_tproto & SAS_PROTOCOL_SSP) { |
| 836 | child->dev_type = SAS_END_DEV; | 836 | child->dev_type = SAS_END_DEVICE; |
| 837 | rphy = sas_end_device_alloc(phy->port); | 837 | rphy = sas_end_device_alloc(phy->port); |
| 838 | /* FIXME: error handling */ | 838 | /* FIXME: error handling */ |
| 839 | if (unlikely(!rphy)) | 839 | if (unlikely(!rphy)) |
| @@ -932,11 +932,11 @@ static struct domain_device *sas_ex_discover_expander( | |||
| 932 | 932 | ||
| 933 | 933 | ||
| 934 | switch (phy->attached_dev_type) { | 934 | switch (phy->attached_dev_type) { |
| 935 | case EDGE_DEV: | 935 | case SAS_EDGE_EXPANDER_DEVICE: |
| 936 | rphy = sas_expander_alloc(phy->port, | 936 | rphy = sas_expander_alloc(phy->port, |
| 937 | SAS_EDGE_EXPANDER_DEVICE); | 937 | SAS_EDGE_EXPANDER_DEVICE); |
| 938 | break; | 938 | break; |
| 939 | case FANOUT_DEV: | 939 | case SAS_FANOUT_EXPANDER_DEVICE: |
| 940 | rphy = sas_expander_alloc(phy->port, | 940 | rphy = sas_expander_alloc(phy->port, |
| 941 | SAS_FANOUT_EXPANDER_DEVICE); | 941 | SAS_FANOUT_EXPANDER_DEVICE); |
| 942 | break; | 942 | break; |
| @@ -1013,7 +1013,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) | |||
| 1013 | if (sas_dev_present_in_domain(dev->port, ex_phy->attached_sas_addr)) | 1013 | if (sas_dev_present_in_domain(dev->port, ex_phy->attached_sas_addr)) |
| 1014 | sas_ex_disable_port(dev, ex_phy->attached_sas_addr); | 1014 | sas_ex_disable_port(dev, ex_phy->attached_sas_addr); |
| 1015 | 1015 | ||
| 1016 | if (ex_phy->attached_dev_type == NO_DEVICE) { | 1016 | if (ex_phy->attached_dev_type == SAS_PHY_UNUSED) { |
| 1017 | if (ex_phy->routing_attr == DIRECT_ROUTING) { | 1017 | if (ex_phy->routing_attr == DIRECT_ROUTING) { |
| 1018 | memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE); | 1018 | memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE); |
| 1019 | sas_configure_routing(dev, ex_phy->attached_sas_addr); | 1019 | sas_configure_routing(dev, ex_phy->attached_sas_addr); |
| @@ -1022,10 +1022,10 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) | |||
| 1022 | } else if (ex_phy->linkrate == SAS_LINK_RATE_UNKNOWN) | 1022 | } else if (ex_phy->linkrate == SAS_LINK_RATE_UNKNOWN) |
| 1023 | return 0; | 1023 | return 0; |
| 1024 | 1024 | ||
| 1025 | if (ex_phy->attached_dev_type != SAS_END_DEV && | 1025 | if (ex_phy->attached_dev_type != SAS_END_DEVICE && |
| 1026 | ex_phy->attached_dev_type != FANOUT_DEV && | 1026 | ex_phy->attached_dev_type != SAS_FANOUT_EXPANDER_DEVICE && |
| 1027 | ex_phy->attached_dev_type != EDGE_DEV && | 1027 | ex_phy->attached_dev_type != SAS_EDGE_EXPANDER_DEVICE && |
| 1028 | ex_phy->attached_dev_type != SATA_PENDING) { | 1028 | ex_phy->attached_dev_type != SAS_SATA_PENDING) { |
| 1029 | SAS_DPRINTK("unknown device type(0x%x) attached to ex %016llx " | 1029 | SAS_DPRINTK("unknown device type(0x%x) attached to ex %016llx " |
| 1030 | "phy 0x%x\n", ex_phy->attached_dev_type, | 1030 | "phy 0x%x\n", ex_phy->attached_dev_type, |
| 1031 | SAS_ADDR(dev->sas_addr), | 1031 | SAS_ADDR(dev->sas_addr), |
| @@ -1049,11 +1049,11 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) | |||
| 1049 | } | 1049 | } |
| 1050 | 1050 | ||
| 1051 | switch (ex_phy->attached_dev_type) { | 1051 | switch (ex_phy->attached_dev_type) { |
| 1052 | case SAS_END_DEV: | 1052 | case SAS_END_DEVICE: |
| 1053 | case SATA_PENDING: | 1053 | case SAS_SATA_PENDING: |
| 1054 | child = sas_ex_discover_end_dev(dev, phy_id); | 1054 | child = sas_ex_discover_end_dev(dev, phy_id); |
| 1055 | break; | 1055 | break; |
| 1056 | case FANOUT_DEV: | 1056 | case SAS_FANOUT_EXPANDER_DEVICE: |
| 1057 | if (SAS_ADDR(dev->port->disc.fanout_sas_addr)) { | 1057 | if (SAS_ADDR(dev->port->disc.fanout_sas_addr)) { |
| 1058 | SAS_DPRINTK("second fanout expander %016llx phy 0x%x " | 1058 | SAS_DPRINTK("second fanout expander %016llx phy 0x%x " |
| 1059 | "attached to ex %016llx phy 0x%x\n", | 1059 | "attached to ex %016llx phy 0x%x\n", |
| @@ -1067,7 +1067,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) | |||
| 1067 | memcpy(dev->port->disc.fanout_sas_addr, | 1067 | memcpy(dev->port->disc.fanout_sas_addr, |
| 1068 | ex_phy->attached_sas_addr, SAS_ADDR_SIZE); | 1068 | ex_phy->attached_sas_addr, SAS_ADDR_SIZE); |
| 1069 | /* fallthrough */ | 1069 | /* fallthrough */ |
| 1070 | case EDGE_DEV: | 1070 | case SAS_EDGE_EXPANDER_DEVICE: |
| 1071 | child = sas_ex_discover_expander(dev, phy_id); | 1071 | child = sas_ex_discover_expander(dev, phy_id); |
| 1072 | break; | 1072 | break; |
| 1073 | default: | 1073 | default: |
| @@ -1111,8 +1111,8 @@ static int sas_find_sub_addr(struct domain_device *dev, u8 *sub_addr) | |||
| 1111 | phy->phy_state == PHY_NOT_PRESENT) | 1111 | phy->phy_state == PHY_NOT_PRESENT) |
| 1112 | continue; | 1112 | continue; |
| 1113 | 1113 | ||
| 1114 | if ((phy->attached_dev_type == EDGE_DEV || | 1114 | if ((phy->attached_dev_type == SAS_EDGE_EXPANDER_DEVICE || |
| 1115 | phy->attached_dev_type == FANOUT_DEV) && | 1115 | phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE) && |
| 1116 | phy->routing_attr == SUBTRACTIVE_ROUTING) { | 1116 | phy->routing_attr == SUBTRACTIVE_ROUTING) { |
| 1117 | 1117 | ||
| 1118 | memcpy(sub_addr, phy->attached_sas_addr,SAS_ADDR_SIZE); | 1118 | memcpy(sub_addr, phy->attached_sas_addr,SAS_ADDR_SIZE); |
| @@ -1130,8 +1130,8 @@ static int sas_check_level_subtractive_boundary(struct domain_device *dev) | |||
| 1130 | u8 sub_addr[8] = {0, }; | 1130 | u8 sub_addr[8] = {0, }; |
| 1131 | 1131 | ||
| 1132 | list_for_each_entry(child, &ex->children, siblings) { | 1132 | list_for_each_entry(child, &ex->children, siblings) { |
| 1133 | if (child->dev_type != EDGE_DEV && | 1133 | if (child->dev_type != SAS_EDGE_EXPANDER_DEVICE && |
| 1134 | child->dev_type != FANOUT_DEV) | 1134 | child->dev_type != SAS_FANOUT_EXPANDER_DEVICE) |
| 1135 | continue; | 1135 | continue; |
| 1136 | if (sub_addr[0] == 0) { | 1136 | if (sub_addr[0] == 0) { |
| 1137 | sas_find_sub_addr(child, sub_addr); | 1137 | sas_find_sub_addr(child, sub_addr); |
| @@ -1208,7 +1208,7 @@ static int sas_check_ex_subtractive_boundary(struct domain_device *dev) | |||
| 1208 | int i; | 1208 | int i; |
| 1209 | u8 *sub_sas_addr = NULL; | 1209 | u8 *sub_sas_addr = NULL; |
| 1210 | 1210 | ||
| 1211 | if (dev->dev_type != EDGE_DEV) | 1211 | if (dev->dev_type != SAS_EDGE_EXPANDER_DEVICE) |
| 1212 | return 0; | 1212 | return 0; |
| 1213 | 1213 | ||
| 1214 | for (i = 0; i < ex->num_phys; i++) { | 1214 | for (i = 0; i < ex->num_phys; i++) { |
| @@ -1218,8 +1218,8 @@ static int sas_check_ex_subtractive_boundary(struct domain_device *dev) | |||
| 1218 | phy->phy_state == PHY_NOT_PRESENT) | 1218 | phy->phy_state == PHY_NOT_PRESENT) |
| 1219 | continue; | 1219 | continue; |
| 1220 | 1220 | ||
| 1221 | if ((phy->attached_dev_type == FANOUT_DEV || | 1221 | if ((phy->attached_dev_type == SAS_FANOUT_EXPANDER_DEVICE || |
| 1222 | phy->attached_dev_type == EDGE_DEV) && | 1222 | phy->attached_dev_type == SAS_EDGE_EXPANDER_DEVICE) && |
| 1223 | phy->routing_attr == SUBTRACTIVE_ROUTING) { | 1223 | phy->routing_attr == SUBTRACTIVE_ROUTING) { |
| 1224 | 1224 | ||
| 1225 | if (!sub_sas_addr) | 1225 | if (!sub_sas_addr) |
| @@ -1245,8 +1245,8 @@ static void sas_print_parent_topology_bug(struct domain_device *child, | |||
| 1245 | struct ex_phy *child_phy) | 1245 | struct ex_phy *child_phy) |
| 1246 | { | 1246 | { |
| 1247 | static const char *ex_type[] = { | 1247 | static const char *ex_type[] = { |
| 1248 | [EDGE_DEV] = "edge", | 1248 | [SAS_EDGE_EXPANDER_DEVICE] = "edge", |
| 1249 | [FANOUT_DEV] = "fanout", | 1249 | [SAS_FANOUT_EXPANDER_DEVICE] = "fanout", |
| 1250 | }; | 1250 | }; |
| 1251 | struct domain_device *parent = child->parent; | 1251 | struct domain_device *parent = child->parent; |
| 1252 | 1252 | ||
| @@ -1321,8 +1321,8 @@ static int sas_check_parent_topology(struct domain_device *child) | |||
| 1321 | if (!child->parent) | 1321 | if (!child->parent) |
| 1322 | return 0; | 1322 | return 0; |
| 1323 | 1323 | ||
| 1324 | if (child->parent->dev_type != EDGE_DEV && | 1324 | if (child->parent->dev_type != SAS_EDGE_EXPANDER_DEVICE && |
| 1325 | child->parent->dev_type != FANOUT_DEV) | 1325 | child->parent->dev_type != SAS_FANOUT_EXPANDER_DEVICE) |
| 1326 | return 0; | 1326 | return 0; |
| 1327 | 1327 | ||
| 1328 | parent_ex = &child->parent->ex_dev; | 1328 | parent_ex = &child->parent->ex_dev; |
| @@ -1341,8 +1341,8 @@ static int sas_check_parent_topology(struct domain_device *child) | |||
| 1341 | child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id]; | 1341 | child_phy = &child_ex->ex_phy[parent_phy->attached_phy_id]; |
| 1342 | 1342 | ||
| 1343 | switch (child->parent->dev_type) { | 1343 | switch (child->parent->dev_type) { |
| 1344 | case EDGE_DEV: | 1344 | case SAS_EDGE_EXPANDER_DEVICE: |
| 1345 | if (child->dev_type == FANOUT_DEV) { | 1345 | if (child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { |
| 1346 | if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING || | 1346 | if (parent_phy->routing_attr != SUBTRACTIVE_ROUTING || |
| 1347 | child_phy->routing_attr != TABLE_ROUTING) { | 1347 | child_phy->routing_attr != TABLE_ROUTING) { |
| 1348 | sas_print_parent_topology_bug(child, parent_phy, child_phy); | 1348 | sas_print_parent_topology_bug(child, parent_phy, child_phy); |
| @@ -1366,7 +1366,7 @@ static int sas_check_parent_topology(struct domain_device *child) | |||
| 1366 | } | 1366 | } |
| 1367 | } | 1367 | } |
| 1368 | break; | 1368 | break; |
| 1369 | case FANOUT_DEV: | 1369 | case SAS_FANOUT_EXPANDER_DEVICE: |
| 1370 | if (parent_phy->routing_attr != TABLE_ROUTING || | 1370 | if (parent_phy->routing_attr != TABLE_ROUTING || |
| 1371 | child_phy->routing_attr != SUBTRACTIVE_ROUTING) { | 1371 | child_phy->routing_attr != SUBTRACTIVE_ROUTING) { |
| 1372 | sas_print_parent_topology_bug(child, parent_phy, child_phy); | 1372 | sas_print_parent_topology_bug(child, parent_phy, child_phy); |
| @@ -1619,8 +1619,8 @@ static int sas_ex_level_discovery(struct asd_sas_port *port, const int level) | |||
| 1619 | struct domain_device *dev; | 1619 | struct domain_device *dev; |
| 1620 | 1620 | ||
| 1621 | list_for_each_entry(dev, &port->dev_list, dev_list_node) { | 1621 | list_for_each_entry(dev, &port->dev_list, dev_list_node) { |
| 1622 | if (dev->dev_type == EDGE_DEV || | 1622 | if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || |
| 1623 | dev->dev_type == FANOUT_DEV) { | 1623 | dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { |
| 1624 | struct sas_expander_device *ex = | 1624 | struct sas_expander_device *ex = |
| 1625 | rphy_to_expander_device(dev->rphy); | 1625 | rphy_to_expander_device(dev->rphy); |
| 1626 | 1626 | ||
| @@ -1720,7 +1720,7 @@ static int sas_get_phy_change_count(struct domain_device *dev, | |||
| 1720 | } | 1720 | } |
| 1721 | 1721 | ||
| 1722 | static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id, | 1722 | static int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id, |
| 1723 | u8 *sas_addr, enum sas_dev_type *type) | 1723 | u8 *sas_addr, enum sas_device_type *type) |
| 1724 | { | 1724 | { |
| 1725 | int res; | 1725 | int res; |
| 1726 | struct smp_resp *disc_resp; | 1726 | struct smp_resp *disc_resp; |
| @@ -1849,7 +1849,7 @@ static int sas_find_bcast_dev(struct domain_device *dev, | |||
| 1849 | SAS_DPRINTK("Expander phys DID NOT change\n"); | 1849 | SAS_DPRINTK("Expander phys DID NOT change\n"); |
| 1850 | } | 1850 | } |
| 1851 | list_for_each_entry(ch, &ex->children, siblings) { | 1851 | list_for_each_entry(ch, &ex->children, siblings) { |
| 1852 | if (ch->dev_type == EDGE_DEV || ch->dev_type == FANOUT_DEV) { | 1852 | if (ch->dev_type == SAS_EDGE_EXPANDER_DEVICE || ch->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { |
| 1853 | res = sas_find_bcast_dev(ch, src_dev); | 1853 | res = sas_find_bcast_dev(ch, src_dev); |
| 1854 | if (*src_dev) | 1854 | if (*src_dev) |
| 1855 | return res; | 1855 | return res; |
| @@ -1866,8 +1866,8 @@ static void sas_unregister_ex_tree(struct asd_sas_port *port, struct domain_devi | |||
| 1866 | 1866 | ||
| 1867 | list_for_each_entry_safe(child, n, &ex->children, siblings) { | 1867 | list_for_each_entry_safe(child, n, &ex->children, siblings) { |
| 1868 | set_bit(SAS_DEV_GONE, &child->state); | 1868 | set_bit(SAS_DEV_GONE, &child->state); |
| 1869 | if (child->dev_type == EDGE_DEV || | 1869 | if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || |
| 1870 | child->dev_type == FANOUT_DEV) | 1870 | child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) |
| 1871 | sas_unregister_ex_tree(port, child); | 1871 | sas_unregister_ex_tree(port, child); |
| 1872 | else | 1872 | else |
| 1873 | sas_unregister_dev(port, child); | 1873 | sas_unregister_dev(port, child); |
| @@ -1887,8 +1887,8 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent, | |||
| 1887 | if (SAS_ADDR(child->sas_addr) == | 1887 | if (SAS_ADDR(child->sas_addr) == |
| 1888 | SAS_ADDR(phy->attached_sas_addr)) { | 1888 | SAS_ADDR(phy->attached_sas_addr)) { |
| 1889 | set_bit(SAS_DEV_GONE, &child->state); | 1889 | set_bit(SAS_DEV_GONE, &child->state); |
| 1890 | if (child->dev_type == EDGE_DEV || | 1890 | if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || |
| 1891 | child->dev_type == FANOUT_DEV) | 1891 | child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) |
| 1892 | sas_unregister_ex_tree(parent->port, child); | 1892 | sas_unregister_ex_tree(parent->port, child); |
| 1893 | else | 1893 | else |
| 1894 | sas_unregister_dev(parent->port, child); | 1894 | sas_unregister_dev(parent->port, child); |
| @@ -1916,8 +1916,8 @@ static int sas_discover_bfs_by_root_level(struct domain_device *root, | |||
| 1916 | int res = 0; | 1916 | int res = 0; |
| 1917 | 1917 | ||
| 1918 | list_for_each_entry(child, &ex_root->children, siblings) { | 1918 | list_for_each_entry(child, &ex_root->children, siblings) { |
| 1919 | if (child->dev_type == EDGE_DEV || | 1919 | if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || |
| 1920 | child->dev_type == FANOUT_DEV) { | 1920 | child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { |
| 1921 | struct sas_expander_device *ex = | 1921 | struct sas_expander_device *ex = |
| 1922 | rphy_to_expander_device(child->rphy); | 1922 | rphy_to_expander_device(child->rphy); |
| 1923 | 1923 | ||
| @@ -1970,8 +1970,8 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) | |||
| 1970 | list_for_each_entry(child, &dev->ex_dev.children, siblings) { | 1970 | list_for_each_entry(child, &dev->ex_dev.children, siblings) { |
| 1971 | if (SAS_ADDR(child->sas_addr) == | 1971 | if (SAS_ADDR(child->sas_addr) == |
| 1972 | SAS_ADDR(ex_phy->attached_sas_addr)) { | 1972 | SAS_ADDR(ex_phy->attached_sas_addr)) { |
| 1973 | if (child->dev_type == EDGE_DEV || | 1973 | if (child->dev_type == SAS_EDGE_EXPANDER_DEVICE || |
| 1974 | child->dev_type == FANOUT_DEV) | 1974 | child->dev_type == SAS_FANOUT_EXPANDER_DEVICE) |
| 1975 | res = sas_discover_bfs_by_root(child); | 1975 | res = sas_discover_bfs_by_root(child); |
| 1976 | break; | 1976 | break; |
| 1977 | } | 1977 | } |
| @@ -1979,16 +1979,16 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) | |||
| 1979 | return res; | 1979 | return res; |
| 1980 | } | 1980 | } |
| 1981 | 1981 | ||
| 1982 | static bool dev_type_flutter(enum sas_dev_type new, enum sas_dev_type old) | 1982 | static bool dev_type_flutter(enum sas_device_type new, enum sas_device_type old) |
| 1983 | { | 1983 | { |
| 1984 | if (old == new) | 1984 | if (old == new) |
| 1985 | return true; | 1985 | return true; |
| 1986 | 1986 | ||
| 1987 | /* treat device directed resets as flutter, if we went | 1987 | /* treat device directed resets as flutter, if we went |
| 1988 | * SAS_END_DEV to SATA_PENDING the link needs recovery | 1988 | * SAS_END_DEVICE to SAS_SATA_PENDING the link needs recovery |
| 1989 | */ | 1989 | */ |
| 1990 | if ((old == SATA_PENDING && new == SAS_END_DEV) || | 1990 | if ((old == SAS_SATA_PENDING && new == SAS_END_DEVICE) || |
| 1991 | (old == SAS_END_DEV && new == SATA_PENDING)) | 1991 | (old == SAS_END_DEVICE && new == SAS_SATA_PENDING)) |
| 1992 | return true; | 1992 | return true; |
| 1993 | 1993 | ||
| 1994 | return false; | 1994 | return false; |
| @@ -1998,7 +1998,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last) | |||
| 1998 | { | 1998 | { |
| 1999 | struct expander_device *ex = &dev->ex_dev; | 1999 | struct expander_device *ex = &dev->ex_dev; |
| 2000 | struct ex_phy *phy = &ex->ex_phy[phy_id]; | 2000 | struct ex_phy *phy = &ex->ex_phy[phy_id]; |
| 2001 | enum sas_dev_type type = NO_DEVICE; | 2001 | enum sas_device_type type = SAS_PHY_UNUSED; |
| 2002 | u8 sas_addr[8]; | 2002 | u8 sas_addr[8]; |
| 2003 | int res; | 2003 | int res; |
| 2004 | 2004 | ||
| @@ -2032,7 +2032,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last) | |||
| 2032 | 2032 | ||
| 2033 | sas_ex_phy_discover(dev, phy_id); | 2033 | sas_ex_phy_discover(dev, phy_id); |
| 2034 | 2034 | ||
| 2035 | if (ata_dev && phy->attached_dev_type == SATA_PENDING) | 2035 | if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING) |
| 2036 | action = ", needs recovery"; | 2036 | action = ", needs recovery"; |
| 2037 | SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter%s\n", | 2037 | SAS_DPRINTK("ex %016llx phy 0x%x broadcast flutter%s\n", |
| 2038 | SAS_ADDR(dev->sas_addr), phy_id, action); | 2038 | SAS_ADDR(dev->sas_addr), phy_id, action); |
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h index 1de67964e5a1..7e7ba83f0a21 100644 --- a/drivers/scsi/libsas/sas_internal.h +++ b/drivers/scsi/libsas/sas_internal.h | |||
| @@ -131,16 +131,16 @@ static inline void sas_fill_in_rphy(struct domain_device *dev, | |||
| 131 | rphy->identify.initiator_port_protocols = dev->iproto; | 131 | rphy->identify.initiator_port_protocols = dev->iproto; |
| 132 | rphy->identify.target_port_protocols = dev->tproto; | 132 | rphy->identify.target_port_protocols = dev->tproto; |
| 133 | switch (dev->dev_type) { | 133 | switch (dev->dev_type) { |
| 134 | case SATA_DEV: | 134 | case SAS_SATA_DEV: |
| 135 | /* FIXME: need sata device type */ | 135 | /* FIXME: need sata device type */ |
| 136 | case SAS_END_DEV: | 136 | case SAS_END_DEVICE: |
| 137 | case SATA_PENDING: | 137 | case SAS_SATA_PENDING: |
| 138 | rphy->identify.device_type = SAS_END_DEVICE; | 138 | rphy->identify.device_type = SAS_END_DEVICE; |
| 139 | break; | 139 | break; |
| 140 | case EDGE_DEV: | 140 | case SAS_EDGE_EXPANDER_DEVICE: |
| 141 | rphy->identify.device_type = SAS_EDGE_EXPANDER_DEVICE; | 141 | rphy->identify.device_type = SAS_EDGE_EXPANDER_DEVICE; |
| 142 | break; | 142 | break; |
| 143 | case FANOUT_DEV: | 143 | case SAS_FANOUT_EXPANDER_DEVICE: |
| 144 | rphy->identify.device_type = SAS_FANOUT_EXPANDER_DEVICE; | 144 | rphy->identify.device_type = SAS_FANOUT_EXPANDER_DEVICE; |
| 145 | break; | 145 | break; |
| 146 | default: | 146 | default: |
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index 1398b714c018..d3c5297c6c89 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c | |||
| @@ -69,7 +69,7 @@ static void sas_resume_port(struct asd_sas_phy *phy) | |||
| 69 | continue; | 69 | continue; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) { | 72 | if (dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) { |
| 73 | dev->ex_dev.ex_change_count = -1; | 73 | dev->ex_dev.ex_change_count = -1; |
| 74 | for (i = 0; i < dev->ex_dev.num_phys; i++) { | 74 | for (i = 0; i < dev->ex_dev.num_phys; i++) { |
| 75 | struct ex_phy *phy = &dev->ex_dev.ex_phy[i]; | 75 | struct ex_phy *phy = &dev->ex_dev.ex_phy[i]; |
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 7706c99ec8bb..bcc56cac4fd8 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
| @@ -46,10 +46,15 @@ struct lpfc_sli2_slim; | |||
| 46 | #define LPFC_DEFAULT_MENLO_SG_SEG_CNT 128 /* sg element count per scsi | 46 | #define LPFC_DEFAULT_MENLO_SG_SEG_CNT 128 /* sg element count per scsi |
| 47 | cmnd for menlo needs nearly twice as for firmware | 47 | cmnd for menlo needs nearly twice as for firmware |
| 48 | downloads using bsg */ | 48 | downloads using bsg */ |
| 49 | #define LPFC_DEFAULT_PROT_SG_SEG_CNT 4096 /* sg protection elements count */ | 49 | |
| 50 | #define LPFC_MIN_SG_SLI4_BUF_SZ 0x800 /* based on LPFC_DEFAULT_SG_SEG_CNT */ | ||
| 51 | #define LPFC_MAX_SG_SLI4_SEG_CNT_DIF 128 /* sg element count per scsi cmnd */ | ||
| 52 | #define LPFC_MAX_SG_SEG_CNT_DIF 512 /* sg element count per scsi cmnd */ | ||
| 50 | #define LPFC_MAX_SG_SEG_CNT 4096 /* sg element count per scsi cmnd */ | 53 | #define LPFC_MAX_SG_SEG_CNT 4096 /* sg element count per scsi cmnd */ |
| 54 | #define LPFC_MAX_SGL_SEG_CNT 512 /* SGL element count per scsi cmnd */ | ||
| 55 | #define LPFC_MAX_BPL_SEG_CNT 4096 /* BPL element count per scsi cmnd */ | ||
| 56 | |||
| 51 | #define LPFC_MAX_SGE_SIZE 0x80000000 /* Maximum data allowed in a SGE */ | 57 | #define LPFC_MAX_SGE_SIZE 0x80000000 /* Maximum data allowed in a SGE */ |
| 52 | #define LPFC_MAX_PROT_SG_SEG_CNT 4096 /* prot sg element count per scsi cmd*/ | ||
| 53 | #define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */ | 58 | #define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */ |
| 54 | #define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */ | 59 | #define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */ |
| 55 | #define LPFC_VNAME_LEN 100 /* vport symbolic name length */ | 60 | #define LPFC_VNAME_LEN 100 /* vport symbolic name length */ |
| @@ -66,8 +71,10 @@ struct lpfc_sli2_slim; | |||
| 66 | * queue depths when there are driver resource error or Firmware | 71 | * queue depths when there are driver resource error or Firmware |
| 67 | * resource error. | 72 | * resource error. |
| 68 | */ | 73 | */ |
| 69 | #define QUEUE_RAMP_DOWN_INTERVAL (1 * HZ) /* 1 Second */ | 74 | /* 1 Second */ |
| 70 | #define QUEUE_RAMP_UP_INTERVAL (300 * HZ) /* 5 minutes */ | 75 | #define QUEUE_RAMP_DOWN_INTERVAL (msecs_to_jiffies(1000 * 1)) |
| 76 | /* 5 minutes */ | ||
| 77 | #define QUEUE_RAMP_UP_INTERVAL (msecs_to_jiffies(1000 * 300)) | ||
| 71 | 78 | ||
| 72 | /* Number of exchanges reserved for discovery to complete */ | 79 | /* Number of exchanges reserved for discovery to complete */ |
| 73 | #define LPFC_DISC_IOCB_BUFF_COUNT 20 | 80 | #define LPFC_DISC_IOCB_BUFF_COUNT 20 |
| @@ -671,6 +678,7 @@ struct lpfc_hba { | |||
| 671 | uint32_t lmt; | 678 | uint32_t lmt; |
| 672 | 679 | ||
| 673 | uint32_t fc_topology; /* link topology, from LINK INIT */ | 680 | uint32_t fc_topology; /* link topology, from LINK INIT */ |
| 681 | uint32_t fc_topology_changed; /* link topology, from LINK INIT */ | ||
| 674 | 682 | ||
| 675 | struct lpfc_stats fc_stat; | 683 | struct lpfc_stats fc_stat; |
| 676 | 684 | ||
| @@ -701,9 +709,11 @@ struct lpfc_hba { | |||
| 701 | uint32_t cfg_poll_tmo; | 709 | uint32_t cfg_poll_tmo; |
| 702 | uint32_t cfg_use_msi; | 710 | uint32_t cfg_use_msi; |
| 703 | uint32_t cfg_fcp_imax; | 711 | uint32_t cfg_fcp_imax; |
| 712 | uint32_t cfg_fcp_cpu_map; | ||
| 704 | uint32_t cfg_fcp_wq_count; | 713 | uint32_t cfg_fcp_wq_count; |
| 705 | uint32_t cfg_fcp_eq_count; | 714 | uint32_t cfg_fcp_eq_count; |
| 706 | uint32_t cfg_fcp_io_channel; | 715 | uint32_t cfg_fcp_io_channel; |
| 716 | uint32_t cfg_total_seg_cnt; | ||
| 707 | uint32_t cfg_sg_seg_cnt; | 717 | uint32_t cfg_sg_seg_cnt; |
| 708 | uint32_t cfg_prot_sg_seg_cnt; | 718 | uint32_t cfg_prot_sg_seg_cnt; |
| 709 | uint32_t cfg_sg_dma_buf_size; | 719 | uint32_t cfg_sg_dma_buf_size; |
| @@ -804,8 +814,10 @@ struct lpfc_hba { | |||
| 804 | uint64_t bg_reftag_err_cnt; | 814 | uint64_t bg_reftag_err_cnt; |
| 805 | 815 | ||
| 806 | /* fastpath list. */ | 816 | /* fastpath list. */ |
| 807 | spinlock_t scsi_buf_list_lock; | 817 | spinlock_t scsi_buf_list_get_lock; /* SCSI buf alloc list lock */ |
| 808 | struct list_head lpfc_scsi_buf_list; | 818 | spinlock_t scsi_buf_list_put_lock; /* SCSI buf free list lock */ |
| 819 | struct list_head lpfc_scsi_buf_list_get; | ||
| 820 | struct list_head lpfc_scsi_buf_list_put; | ||
| 809 | uint32_t total_scsi_bufs; | 821 | uint32_t total_scsi_bufs; |
| 810 | struct list_head lpfc_iocb_list; | 822 | struct list_head lpfc_iocb_list; |
| 811 | uint32_t total_iocbq_bufs; | 823 | uint32_t total_iocbq_bufs; |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 9290713af253..3c5625b8b1f4 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
| @@ -674,6 +674,9 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) | |||
| 674 | int i; | 674 | int i; |
| 675 | int rc; | 675 | int rc; |
| 676 | 676 | ||
| 677 | if (phba->pport->fc_flag & FC_OFFLINE_MODE) | ||
| 678 | return 0; | ||
| 679 | |||
| 677 | init_completion(&online_compl); | 680 | init_completion(&online_compl); |
| 678 | rc = lpfc_workq_post_event(phba, &status, &online_compl, | 681 | rc = lpfc_workq_post_event(phba, &status, &online_compl, |
| 679 | LPFC_EVT_OFFLINE_PREP); | 682 | LPFC_EVT_OFFLINE_PREP); |
| @@ -741,7 +744,8 @@ lpfc_selective_reset(struct lpfc_hba *phba) | |||
| 741 | int status = 0; | 744 | int status = 0; |
| 742 | int rc; | 745 | int rc; |
| 743 | 746 | ||
| 744 | if (!phba->cfg_enable_hba_reset) | 747 | if ((!phba->cfg_enable_hba_reset) || |
| 748 | (phba->pport->fc_flag & FC_OFFLINE_MODE)) | ||
| 745 | return -EACCES; | 749 | return -EACCES; |
| 746 | 750 | ||
| 747 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); | 751 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); |
| @@ -895,6 +899,7 @@ lpfc_sli4_pdev_reg_request(struct lpfc_hba *phba, uint32_t opcode) | |||
| 895 | pci_disable_sriov(pdev); | 899 | pci_disable_sriov(pdev); |
| 896 | phba->cfg_sriov_nr_virtfn = 0; | 900 | phba->cfg_sriov_nr_virtfn = 0; |
| 897 | } | 901 | } |
| 902 | |||
| 898 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); | 903 | status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE); |
| 899 | 904 | ||
| 900 | if (status != 0) | 905 | if (status != 0) |
| @@ -2801,6 +2806,8 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr, | |||
| 2801 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, | 2806 | lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT, |
| 2802 | "3054 lpfc_topology changed from %d to %d\n", | 2807 | "3054 lpfc_topology changed from %d to %d\n", |
| 2803 | prev_val, val); | 2808 | prev_val, val); |
| 2809 | if (prev_val != val && phba->sli_rev == LPFC_SLI_REV4) | ||
| 2810 | phba->fc_topology_changed = 1; | ||
| 2804 | err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport)); | 2811 | err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport)); |
| 2805 | if (err) { | 2812 | if (err) { |
| 2806 | phba->cfg_topology = prev_val; | 2813 | phba->cfg_topology = prev_val; |
| @@ -3792,6 +3799,141 @@ lpfc_fcp_imax_init(struct lpfc_hba *phba, int val) | |||
| 3792 | static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR, | 3799 | static DEVICE_ATTR(lpfc_fcp_imax, S_IRUGO | S_IWUSR, |
| 3793 | lpfc_fcp_imax_show, lpfc_fcp_imax_store); | 3800 | lpfc_fcp_imax_show, lpfc_fcp_imax_store); |
| 3794 | 3801 | ||
| 3802 | /** | ||
| 3803 | * lpfc_state_show - Display current driver CPU affinity | ||
| 3804 | * @dev: class converted to a Scsi_host structure. | ||
| 3805 | * @attr: device attribute, not used. | ||
| 3806 | * @buf: on return contains text describing the state of the link. | ||
| 3807 | * | ||
| 3808 | * Returns: size of formatted string. | ||
| 3809 | **/ | ||
| 3810 | static ssize_t | ||
| 3811 | lpfc_fcp_cpu_map_show(struct device *dev, struct device_attribute *attr, | ||
| 3812 | char *buf) | ||
| 3813 | { | ||
| 3814 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 3815 | struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata; | ||
| 3816 | struct lpfc_hba *phba = vport->phba; | ||
| 3817 | struct lpfc_vector_map_info *cpup; | ||
| 3818 | int idx, len = 0; | ||
| 3819 | |||
| 3820 | if ((phba->sli_rev != LPFC_SLI_REV4) || | ||
| 3821 | (phba->intr_type != MSIX)) | ||
| 3822 | return len; | ||
| 3823 | |||
| 3824 | switch (phba->cfg_fcp_cpu_map) { | ||
| 3825 | case 0: | ||
| 3826 | len += snprintf(buf + len, PAGE_SIZE-len, | ||
| 3827 | "fcp_cpu_map: No mapping (%d)\n", | ||
| 3828 | phba->cfg_fcp_cpu_map); | ||
| 3829 | return len; | ||
| 3830 | case 1: | ||
| 3831 | len += snprintf(buf + len, PAGE_SIZE-len, | ||
| 3832 | "fcp_cpu_map: HBA centric mapping (%d): " | ||
| 3833 | "%d online CPUs\n", | ||
| 3834 | phba->cfg_fcp_cpu_map, | ||
| 3835 | phba->sli4_hba.num_online_cpu); | ||
| 3836 | break; | ||
| 3837 | case 2: | ||
| 3838 | len += snprintf(buf + len, PAGE_SIZE-len, | ||
| 3839 | "fcp_cpu_map: Driver centric mapping (%d): " | ||
| 3840 | "%d online CPUs\n", | ||
| 3841 | phba->cfg_fcp_cpu_map, | ||
| 3842 | phba->sli4_hba.num_online_cpu); | ||
| 3843 | break; | ||
| 3844 | } | ||
| 3845 | |||
| 3846 | cpup = phba->sli4_hba.cpu_map; | ||
| 3847 | for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) { | ||
| 3848 | if (cpup->irq == LPFC_VECTOR_MAP_EMPTY) | ||
| 3849 | len += snprintf(buf + len, PAGE_SIZE-len, | ||
| 3850 | "CPU %02d io_chan %02d " | ||
| 3851 | "physid %d coreid %d\n", | ||
| 3852 | idx, cpup->channel_id, cpup->phys_id, | ||
| 3853 | cpup->core_id); | ||
| 3854 | else | ||
| 3855 | len += snprintf(buf + len, PAGE_SIZE-len, | ||
| 3856 | "CPU %02d io_chan %02d " | ||
| 3857 | "physid %d coreid %d IRQ %d\n", | ||
| 3858 | idx, cpup->channel_id, cpup->phys_id, | ||
| 3859 | cpup->core_id, cpup->irq); | ||
| 3860 | |||
| 3861 | cpup++; | ||
| 3862 | } | ||
| 3863 | return len; | ||
| 3864 | } | ||
| 3865 | |||
| 3866 | /** | ||
| 3867 | * lpfc_fcp_cpu_map_store - Change CPU affinity of driver vectors | ||
| 3868 | * @dev: class device that is converted into a Scsi_host. | ||
| 3869 | * @attr: device attribute, not used. | ||
| 3870 | * @buf: one or more lpfc_polling_flags values. | ||
| 3871 | * @count: not used. | ||
| 3872 | * | ||
| 3873 | * Returns: | ||
| 3874 | * -EINVAL - Not implemented yet. | ||
| 3875 | **/ | ||
| 3876 | static ssize_t | ||
| 3877 | lpfc_fcp_cpu_map_store(struct device *dev, struct device_attribute *attr, | ||
| 3878 | const char *buf, size_t count) | ||
| 3879 | { | ||
| 3880 | int status = -EINVAL; | ||
| 3881 | return status; | ||
| 3882 | } | ||
| 3883 | |||
| 3884 | /* | ||
| 3885 | # lpfc_fcp_cpu_map: Defines how to map CPUs to IRQ vectors | ||
| 3886 | # for the HBA. | ||
| 3887 | # | ||
| 3888 | # Value range is [0 to 2]. Default value is LPFC_DRIVER_CPU_MAP (2). | ||
| 3889 | # 0 - Do not affinitze IRQ vectors | ||
| 3890 | # 1 - Affintize HBA vectors with respect to each HBA | ||
| 3891 | # (start with CPU0 for each HBA) | ||
| 3892 | # 2 - Affintize HBA vectors with respect to the entire driver | ||
| 3893 | # (round robin thru all CPUs across all HBAs) | ||
| 3894 | */ | ||
| 3895 | static int lpfc_fcp_cpu_map = LPFC_DRIVER_CPU_MAP; | ||
| 3896 | module_param(lpfc_fcp_cpu_map, int, S_IRUGO|S_IWUSR); | ||
| 3897 | MODULE_PARM_DESC(lpfc_fcp_cpu_map, | ||
| 3898 | "Defines how to map CPUs to IRQ vectors per HBA"); | ||
| 3899 | |||
| 3900 | /** | ||
| 3901 | * lpfc_fcp_cpu_map_init - Set the initial sr-iov virtual function enable | ||
| 3902 | * @phba: lpfc_hba pointer. | ||
| 3903 | * @val: link speed value. | ||
| 3904 | * | ||
| 3905 | * Description: | ||
| 3906 | * If val is in a valid range [0-2], then affinitze the adapter's | ||
| 3907 | * MSIX vectors. | ||
| 3908 | * | ||
| 3909 | * Returns: | ||
| 3910 | * zero if val saved. | ||
| 3911 | * -EINVAL val out of range | ||
| 3912 | **/ | ||
| 3913 | static int | ||
| 3914 | lpfc_fcp_cpu_map_init(struct lpfc_hba *phba, int val) | ||
| 3915 | { | ||
| 3916 | if (phba->sli_rev != LPFC_SLI_REV4) { | ||
| 3917 | phba->cfg_fcp_cpu_map = 0; | ||
| 3918 | return 0; | ||
| 3919 | } | ||
| 3920 | |||
| 3921 | if (val >= LPFC_MIN_CPU_MAP && val <= LPFC_MAX_CPU_MAP) { | ||
| 3922 | phba->cfg_fcp_cpu_map = val; | ||
| 3923 | return 0; | ||
| 3924 | } | ||
| 3925 | |||
| 3926 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 3927 | "3326 fcp_cpu_map: %d out of range, using default\n", | ||
| 3928 | val); | ||
| 3929 | phba->cfg_fcp_cpu_map = LPFC_DRIVER_CPU_MAP; | ||
| 3930 | |||
| 3931 | return 0; | ||
| 3932 | } | ||
| 3933 | |||
| 3934 | static DEVICE_ATTR(lpfc_fcp_cpu_map, S_IRUGO | S_IWUSR, | ||
| 3935 | lpfc_fcp_cpu_map_show, lpfc_fcp_cpu_map_store); | ||
| 3936 | |||
| 3795 | /* | 3937 | /* |
| 3796 | # lpfc_fcp_class: Determines FC class to use for the FCP protocol. | 3938 | # lpfc_fcp_class: Determines FC class to use for the FCP protocol. |
| 3797 | # Value range is [2,3]. Default value is 3. | 3939 | # Value range is [2,3]. Default value is 3. |
| @@ -4009,12 +4151,11 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); | |||
| 4009 | # 0 = disabled (default) | 4151 | # 0 = disabled (default) |
| 4010 | # 1 = enabled | 4152 | # 1 = enabled |
| 4011 | # Value range is [0,1]. Default value is 0. | 4153 | # Value range is [0,1]. Default value is 0. |
| 4154 | # | ||
| 4155 | # This feature in under investigation and may be supported in the future. | ||
| 4012 | */ | 4156 | */ |
| 4013 | unsigned int lpfc_fcp_look_ahead = LPFC_LOOK_AHEAD_OFF; | 4157 | unsigned int lpfc_fcp_look_ahead = LPFC_LOOK_AHEAD_OFF; |
| 4014 | 4158 | ||
| 4015 | module_param(lpfc_fcp_look_ahead, uint, S_IRUGO); | ||
| 4016 | MODULE_PARM_DESC(lpfc_fcp_look_ahead, "Look ahead for completions"); | ||
| 4017 | |||
| 4018 | /* | 4159 | /* |
| 4019 | # lpfc_prot_mask: i | 4160 | # lpfc_prot_mask: i |
| 4020 | # - Bit mask of host protection capabilities used to register with the | 4161 | # - Bit mask of host protection capabilities used to register with the |
| @@ -4071,16 +4212,23 @@ MODULE_PARM_DESC(lpfc_delay_discovery, | |||
| 4071 | 4212 | ||
| 4072 | /* | 4213 | /* |
| 4073 | * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count | 4214 | * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count |
| 4074 | * This value can be set to values between 64 and 256. The default value is | 4215 | * This value can be set to values between 64 and 4096. The default value is |
| 4075 | * 64, but may be increased to allow for larger Max I/O sizes. The scsi layer | 4216 | * 64, but may be increased to allow for larger Max I/O sizes. The scsi layer |
| 4076 | * will be allowed to request I/Os of sizes up to (MAX_SEG_COUNT * SEG_SIZE). | 4217 | * will be allowed to request I/Os of sizes up to (MAX_SEG_COUNT * SEG_SIZE). |
| 4218 | * Because of the additional overhead involved in setting up T10-DIF, | ||
| 4219 | * this parameter will be limited to 128 if BlockGuard is enabled under SLI4 | ||
| 4220 | * and will be limited to 512 if BlockGuard is enabled under SLI3. | ||
| 4077 | */ | 4221 | */ |
| 4078 | LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT, | 4222 | LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT, |
| 4079 | LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count"); | 4223 | LPFC_MAX_SG_SEG_CNT, "Max Scatter Gather Segment Count"); |
| 4080 | 4224 | ||
| 4081 | LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_PROT_SG_SEG_CNT, | 4225 | /* |
| 4082 | LPFC_DEFAULT_PROT_SG_SEG_CNT, LPFC_MAX_PROT_SG_SEG_CNT, | 4226 | * This parameter will be depricated, the driver cannot limit the |
| 4083 | "Max Protection Scatter Gather Segment Count"); | 4227 | * protection data s/g list. |
| 4228 | */ | ||
| 4229 | LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, | ||
| 4230 | LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT, | ||
| 4231 | "Max Protection Scatter Gather Segment Count"); | ||
| 4084 | 4232 | ||
| 4085 | struct device_attribute *lpfc_hba_attrs[] = { | 4233 | struct device_attribute *lpfc_hba_attrs[] = { |
| 4086 | &dev_attr_bg_info, | 4234 | &dev_attr_bg_info, |
| @@ -4141,6 +4289,7 @@ struct device_attribute *lpfc_hba_attrs[] = { | |||
| 4141 | &dev_attr_lpfc_poll_tmo, | 4289 | &dev_attr_lpfc_poll_tmo, |
| 4142 | &dev_attr_lpfc_use_msi, | 4290 | &dev_attr_lpfc_use_msi, |
| 4143 | &dev_attr_lpfc_fcp_imax, | 4291 | &dev_attr_lpfc_fcp_imax, |
| 4292 | &dev_attr_lpfc_fcp_cpu_map, | ||
| 4144 | &dev_attr_lpfc_fcp_wq_count, | 4293 | &dev_attr_lpfc_fcp_wq_count, |
| 4145 | &dev_attr_lpfc_fcp_eq_count, | 4294 | &dev_attr_lpfc_fcp_eq_count, |
| 4146 | &dev_attr_lpfc_fcp_io_channel, | 4295 | &dev_attr_lpfc_fcp_io_channel, |
| @@ -5123,6 +5272,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
| 5123 | lpfc_enable_rrq_init(phba, lpfc_enable_rrq); | 5272 | lpfc_enable_rrq_init(phba, lpfc_enable_rrq); |
| 5124 | lpfc_use_msi_init(phba, lpfc_use_msi); | 5273 | lpfc_use_msi_init(phba, lpfc_use_msi); |
| 5125 | lpfc_fcp_imax_init(phba, lpfc_fcp_imax); | 5274 | lpfc_fcp_imax_init(phba, lpfc_fcp_imax); |
| 5275 | lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map); | ||
| 5126 | lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count); | 5276 | lpfc_fcp_wq_count_init(phba, lpfc_fcp_wq_count); |
| 5127 | lpfc_fcp_eq_count_init(phba, lpfc_fcp_eq_count); | 5277 | lpfc_fcp_eq_count_init(phba, lpfc_fcp_eq_count); |
| 5128 | lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel); | 5278 | lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel); |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 888666892004..094be2cad65b 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
| @@ -219,26 +219,35 @@ lpfc_bsg_copy_data(struct lpfc_dmabuf *dma_buffers, | |||
| 219 | unsigned int transfer_bytes, bytes_copied = 0; | 219 | unsigned int transfer_bytes, bytes_copied = 0; |
| 220 | unsigned int sg_offset, dma_offset; | 220 | unsigned int sg_offset, dma_offset; |
| 221 | unsigned char *dma_address, *sg_address; | 221 | unsigned char *dma_address, *sg_address; |
| 222 | struct scatterlist *sgel; | ||
| 223 | LIST_HEAD(temp_list); | 222 | LIST_HEAD(temp_list); |
| 224 | 223 | struct sg_mapping_iter miter; | |
| 224 | unsigned long flags; | ||
| 225 | unsigned int sg_flags = SG_MITER_ATOMIC; | ||
| 226 | bool sg_valid; | ||
| 225 | 227 | ||
| 226 | list_splice_init(&dma_buffers->list, &temp_list); | 228 | list_splice_init(&dma_buffers->list, &temp_list); |
| 227 | list_add(&dma_buffers->list, &temp_list); | 229 | list_add(&dma_buffers->list, &temp_list); |
| 228 | sg_offset = 0; | 230 | sg_offset = 0; |
| 229 | sgel = bsg_buffers->sg_list; | 231 | if (to_buffers) |
| 232 | sg_flags |= SG_MITER_FROM_SG; | ||
| 233 | else | ||
| 234 | sg_flags |= SG_MITER_TO_SG; | ||
| 235 | sg_miter_start(&miter, bsg_buffers->sg_list, bsg_buffers->sg_cnt, | ||
| 236 | sg_flags); | ||
| 237 | local_irq_save(flags); | ||
| 238 | sg_valid = sg_miter_next(&miter); | ||
| 230 | list_for_each_entry(mp, &temp_list, list) { | 239 | list_for_each_entry(mp, &temp_list, list) { |
| 231 | dma_offset = 0; | 240 | dma_offset = 0; |
| 232 | while (bytes_to_transfer && sgel && | 241 | while (bytes_to_transfer && sg_valid && |
| 233 | (dma_offset < LPFC_BPL_SIZE)) { | 242 | (dma_offset < LPFC_BPL_SIZE)) { |
| 234 | dma_address = mp->virt + dma_offset; | 243 | dma_address = mp->virt + dma_offset; |
| 235 | if (sg_offset) { | 244 | if (sg_offset) { |
| 236 | /* Continue previous partial transfer of sg */ | 245 | /* Continue previous partial transfer of sg */ |
| 237 | sg_address = sg_virt(sgel) + sg_offset; | 246 | sg_address = miter.addr + sg_offset; |
| 238 | transfer_bytes = sgel->length - sg_offset; | 247 | transfer_bytes = miter.length - sg_offset; |
| 239 | } else { | 248 | } else { |
| 240 | sg_address = sg_virt(sgel); | 249 | sg_address = miter.addr; |
| 241 | transfer_bytes = sgel->length; | 250 | transfer_bytes = miter.length; |
| 242 | } | 251 | } |
| 243 | if (bytes_to_transfer < transfer_bytes) | 252 | if (bytes_to_transfer < transfer_bytes) |
| 244 | transfer_bytes = bytes_to_transfer; | 253 | transfer_bytes = bytes_to_transfer; |
| @@ -252,12 +261,14 @@ lpfc_bsg_copy_data(struct lpfc_dmabuf *dma_buffers, | |||
| 252 | sg_offset += transfer_bytes; | 261 | sg_offset += transfer_bytes; |
| 253 | bytes_to_transfer -= transfer_bytes; | 262 | bytes_to_transfer -= transfer_bytes; |
| 254 | bytes_copied += transfer_bytes; | 263 | bytes_copied += transfer_bytes; |
| 255 | if (sg_offset >= sgel->length) { | 264 | if (sg_offset >= miter.length) { |
| 256 | sg_offset = 0; | 265 | sg_offset = 0; |
| 257 | sgel = sg_next(sgel); | 266 | sg_valid = sg_miter_next(&miter); |
| 258 | } | 267 | } |
| 259 | } | 268 | } |
| 260 | } | 269 | } |
| 270 | sg_miter_stop(&miter); | ||
| 271 | local_irq_restore(flags); | ||
| 261 | list_del_init(&dma_buffers->list); | 272 | list_del_init(&dma_buffers->list); |
| 262 | list_splice(&temp_list, &dma_buffers->list); | 273 | list_splice(&temp_list, &dma_buffers->list); |
| 263 | return bytes_copied; | 274 | return bytes_copied; |
| @@ -471,6 +482,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job) | |||
| 471 | cmdiocbq->context1 = dd_data; | 482 | cmdiocbq->context1 = dd_data; |
| 472 | cmdiocbq->context2 = cmp; | 483 | cmdiocbq->context2 = cmp; |
| 473 | cmdiocbq->context3 = bmp; | 484 | cmdiocbq->context3 = bmp; |
| 485 | cmdiocbq->context_un.ndlp = ndlp; | ||
| 474 | dd_data->type = TYPE_IOCB; | 486 | dd_data->type = TYPE_IOCB; |
| 475 | dd_data->set_job = job; | 487 | dd_data->set_job = job; |
| 476 | dd_data->context_un.iocb.cmdiocbq = cmdiocbq; | 488 | dd_data->context_un.iocb.cmdiocbq = cmdiocbq; |
| @@ -1508,6 +1520,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag, | |||
| 1508 | ctiocb->context1 = dd_data; | 1520 | ctiocb->context1 = dd_data; |
| 1509 | ctiocb->context2 = cmp; | 1521 | ctiocb->context2 = cmp; |
| 1510 | ctiocb->context3 = bmp; | 1522 | ctiocb->context3 = bmp; |
| 1523 | ctiocb->context_un.ndlp = ndlp; | ||
| 1511 | ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp; | 1524 | ctiocb->iocb_cmpl = lpfc_issue_ct_rsp_cmp; |
| 1512 | 1525 | ||
| 1513 | dd_data->type = TYPE_IOCB; | 1526 | dd_data->type = TYPE_IOCB; |
| @@ -2576,7 +2589,8 @@ static int lpfcdiag_loop_get_xri(struct lpfc_hba *phba, uint16_t rpi, | |||
| 2576 | evt->wait_time_stamp = jiffies; | 2589 | evt->wait_time_stamp = jiffies; |
| 2577 | time_left = wait_event_interruptible_timeout( | 2590 | time_left = wait_event_interruptible_timeout( |
| 2578 | evt->wq, !list_empty(&evt->events_to_see), | 2591 | evt->wq, !list_empty(&evt->events_to_see), |
| 2579 | ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ); | 2592 | msecs_to_jiffies(1000 * |
| 2593 | ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT))); | ||
| 2580 | if (list_empty(&evt->events_to_see)) | 2594 | if (list_empty(&evt->events_to_see)) |
| 2581 | ret_val = (time_left) ? -EINTR : -ETIMEDOUT; | 2595 | ret_val = (time_left) ? -EINTR : -ETIMEDOUT; |
| 2582 | else { | 2596 | else { |
| @@ -3151,7 +3165,8 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
| 3151 | evt->waiting = 1; | 3165 | evt->waiting = 1; |
| 3152 | time_left = wait_event_interruptible_timeout( | 3166 | time_left = wait_event_interruptible_timeout( |
| 3153 | evt->wq, !list_empty(&evt->events_to_see), | 3167 | evt->wq, !list_empty(&evt->events_to_see), |
| 3154 | ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT) * HZ); | 3168 | msecs_to_jiffies(1000 * |
| 3169 | ((phba->fc_ratov * 2) + LPFC_DRVR_TIMEOUT))); | ||
| 3155 | evt->waiting = 0; | 3170 | evt->waiting = 0; |
| 3156 | if (list_empty(&evt->events_to_see)) { | 3171 | if (list_empty(&evt->events_to_see)) { |
| 3157 | rc = (time_left) ? -EINTR : -ETIMEDOUT; | 3172 | rc = (time_left) ? -EINTR : -ETIMEDOUT; |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 7631893ae005..d41456e5f814 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
| @@ -470,3 +470,4 @@ int lpfc_sli4_xri_sgl_update(struct lpfc_hba *); | |||
| 470 | void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *); | 470 | void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *); |
| 471 | uint32_t lpfc_sli_port_speed_get(struct lpfc_hba *); | 471 | uint32_t lpfc_sli_port_speed_get(struct lpfc_hba *); |
| 472 | int lpfc_sli4_request_firmware_update(struct lpfc_hba *, uint8_t); | 472 | int lpfc_sli4_request_firmware_update(struct lpfc_hba *, uint8_t); |
| 473 | void lpfc_sli4_offline_eratt(struct lpfc_hba *); | ||
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 7bff3a19af56..ae1a07c57cae 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
| @@ -1811,7 +1811,8 @@ lpfc_fdmi_timeout_handler(struct lpfc_vport *vport) | |||
| 1811 | if (init_utsname()->nodename[0] != '\0') | 1811 | if (init_utsname()->nodename[0] != '\0') |
| 1812 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA); | 1812 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA); |
| 1813 | else | 1813 | else |
| 1814 | mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60); | 1814 | mod_timer(&vport->fc_fdmitmo, jiffies + |
| 1815 | msecs_to_jiffies(1000 * 60)); | ||
| 1815 | } | 1816 | } |
| 1816 | return; | 1817 | return; |
| 1817 | } | 1818 | } |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index bbed8471bf0b..3cae0a92e8bd 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <scsi/scsi_host.h> | 29 | #include <scsi/scsi_host.h> |
| 30 | #include <scsi/scsi_transport_fc.h> | 30 | #include <scsi/scsi_transport_fc.h> |
| 31 | 31 | ||
| 32 | |||
| 32 | #include "lpfc_hw4.h" | 33 | #include "lpfc_hw4.h" |
| 33 | #include "lpfc_hw.h" | 34 | #include "lpfc_hw.h" |
| 34 | #include "lpfc_sli.h" | 35 | #include "lpfc_sli.h" |
| @@ -238,7 +239,10 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
| 238 | 239 | ||
| 239 | icmd->un.elsreq64.remoteID = did; /* DID */ | 240 | icmd->un.elsreq64.remoteID = did; /* DID */ |
| 240 | icmd->ulpCommand = CMD_ELS_REQUEST64_CR; | 241 | icmd->ulpCommand = CMD_ELS_REQUEST64_CR; |
| 241 | icmd->ulpTimeout = phba->fc_ratov * 2; | 242 | if (elscmd == ELS_CMD_FLOGI) |
| 243 | icmd->ulpTimeout = FF_DEF_RATOV * 2; | ||
| 244 | else | ||
| 245 | icmd->ulpTimeout = phba->fc_ratov * 2; | ||
| 242 | } else { | 246 | } else { |
| 243 | icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys); | 247 | icmd->un.xseq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys); |
| 244 | icmd->un.xseq64.bdl.addrLow = putPaddrLow(pbuflist->phys); | 248 | icmd->un.xseq64.bdl.addrLow = putPaddrLow(pbuflist->phys); |
| @@ -308,16 +312,20 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp, | |||
| 308 | /* Xmit ELS command <elsCmd> to remote NPORT <did> */ | 312 | /* Xmit ELS command <elsCmd> to remote NPORT <did> */ |
| 309 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 313 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
| 310 | "0116 Xmit ELS command x%x to remote " | 314 | "0116 Xmit ELS command x%x to remote " |
| 311 | "NPORT x%x I/O tag: x%x, port state: x%x\n", | 315 | "NPORT x%x I/O tag: x%x, port state:x%x" |
| 316 | " fc_flag:x%x\n", | ||
| 312 | elscmd, did, elsiocb->iotag, | 317 | elscmd, did, elsiocb->iotag, |
| 313 | vport->port_state); | 318 | vport->port_state, |
| 319 | vport->fc_flag); | ||
| 314 | } else { | 320 | } else { |
| 315 | /* Xmit ELS response <elsCmd> to remote NPORT <did> */ | 321 | /* Xmit ELS response <elsCmd> to remote NPORT <did> */ |
| 316 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 322 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
| 317 | "0117 Xmit ELS response x%x to remote " | 323 | "0117 Xmit ELS response x%x to remote " |
| 318 | "NPORT x%x I/O tag: x%x, size: x%x\n", | 324 | "NPORT x%x I/O tag: x%x, size: x%x " |
| 325 | "port_state x%x fc_flag x%x\n", | ||
| 319 | elscmd, ndlp->nlp_DID, elsiocb->iotag, | 326 | elscmd, ndlp->nlp_DID, elsiocb->iotag, |
| 320 | cmdSize); | 327 | cmdSize, vport->port_state, |
| 328 | vport->fc_flag); | ||
| 321 | } | 329 | } |
| 322 | return elsiocb; | 330 | return elsiocb; |
| 323 | 331 | ||
| @@ -909,6 +917,23 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 909 | spin_lock_irq(shost->host_lock); | 917 | spin_lock_irq(shost->host_lock); |
| 910 | vport->fc_flag |= FC_PT2PT; | 918 | vport->fc_flag |= FC_PT2PT; |
| 911 | spin_unlock_irq(shost->host_lock); | 919 | spin_unlock_irq(shost->host_lock); |
| 920 | /* If physical FC port changed, unreg VFI and ALL VPIs / RPIs */ | ||
| 921 | if ((phba->sli_rev == LPFC_SLI_REV4) && phba->fc_topology_changed) { | ||
| 922 | lpfc_unregister_fcf_prep(phba); | ||
| 923 | |||
| 924 | /* The FC_VFI_REGISTERED flag will get clear in the cmpl | ||
| 925 | * handler for unreg_vfi, but if we don't force the | ||
| 926 | * FC_VFI_REGISTERED flag then the reg_vfi mailbox could be | ||
| 927 | * built with the update bit set instead of just the vp bit to | ||
| 928 | * change the Nport ID. We need to have the vp set and the | ||
| 929 | * Upd cleared on topology changes. | ||
| 930 | */ | ||
| 931 | spin_lock_irq(shost->host_lock); | ||
| 932 | vport->fc_flag &= ~FC_VFI_REGISTERED; | ||
| 933 | spin_unlock_irq(shost->host_lock); | ||
| 934 | phba->fc_topology_changed = 0; | ||
| 935 | lpfc_issue_reg_vfi(vport); | ||
| 936 | } | ||
| 912 | 937 | ||
| 913 | /* Start discovery - this should just do CLEAR_LA */ | 938 | /* Start discovery - this should just do CLEAR_LA */ |
| 914 | lpfc_disc_start(vport); | 939 | lpfc_disc_start(vport); |
| @@ -1030,9 +1055,19 @@ stop_rr_fcf_flogi: | |||
| 1030 | vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; | 1055 | vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS; |
| 1031 | if ((phba->sli_rev == LPFC_SLI_REV4) && | 1056 | if ((phba->sli_rev == LPFC_SLI_REV4) && |
| 1032 | (!(vport->fc_flag & FC_VFI_REGISTERED) || | 1057 | (!(vport->fc_flag & FC_VFI_REGISTERED) || |
| 1033 | (vport->fc_prevDID != vport->fc_myDID))) { | 1058 | (vport->fc_prevDID != vport->fc_myDID) || |
| 1034 | if (vport->fc_flag & FC_VFI_REGISTERED) | 1059 | phba->fc_topology_changed)) { |
| 1035 | lpfc_sli4_unreg_all_rpis(vport); | 1060 | if (vport->fc_flag & FC_VFI_REGISTERED) { |
| 1061 | if (phba->fc_topology_changed) { | ||
| 1062 | lpfc_unregister_fcf_prep(phba); | ||
| 1063 | spin_lock_irq(shost->host_lock); | ||
| 1064 | vport->fc_flag &= ~FC_VFI_REGISTERED; | ||
| 1065 | spin_unlock_irq(shost->host_lock); | ||
| 1066 | phba->fc_topology_changed = 0; | ||
| 1067 | } else { | ||
| 1068 | lpfc_sli4_unreg_all_rpis(vport); | ||
| 1069 | } | ||
| 1070 | } | ||
| 1036 | lpfc_issue_reg_vfi(vport); | 1071 | lpfc_issue_reg_vfi(vport); |
| 1037 | lpfc_nlp_put(ndlp); | 1072 | lpfc_nlp_put(ndlp); |
| 1038 | goto out; | 1073 | goto out; |
| @@ -1054,10 +1089,11 @@ stop_rr_fcf_flogi: | |||
| 1054 | 1089 | ||
| 1055 | /* FLOGI completes successfully */ | 1090 | /* FLOGI completes successfully */ |
| 1056 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 1091 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
| 1057 | "0101 FLOGI completes successfully " | 1092 | "0101 FLOGI completes successfully, I/O tag:x%x, " |
| 1058 | "Data: x%x x%x x%x x%x\n", | 1093 | "Data: x%x x%x x%x x%x x%x x%x\n", cmdiocb->iotag, |
| 1059 | irsp->un.ulpWord[4], sp->cmn.e_d_tov, | 1094 | irsp->un.ulpWord[4], sp->cmn.e_d_tov, |
| 1060 | sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution); | 1095 | sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution, |
| 1096 | vport->port_state, vport->fc_flag); | ||
| 1061 | 1097 | ||
| 1062 | if (vport->port_state == LPFC_FLOGI) { | 1098 | if (vport->port_state == LPFC_FLOGI) { |
| 1063 | /* | 1099 | /* |
| @@ -5047,6 +5083,8 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 5047 | struct ls_rjt stat; | 5083 | struct ls_rjt stat; |
| 5048 | uint32_t cmd, did; | 5084 | uint32_t cmd, did; |
| 5049 | int rc; | 5085 | int rc; |
| 5086 | uint32_t fc_flag = 0; | ||
| 5087 | uint32_t port_state = 0; | ||
| 5050 | 5088 | ||
| 5051 | cmd = *lp++; | 5089 | cmd = *lp++; |
| 5052 | sp = (struct serv_parm *) lp; | 5090 | sp = (struct serv_parm *) lp; |
| @@ -5113,16 +5151,25 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
| 5113 | * will be. | 5151 | * will be. |
| 5114 | */ | 5152 | */ |
| 5115 | vport->fc_myDID = PT2PT_LocalID; | 5153 | vport->fc_myDID = PT2PT_LocalID; |
| 5116 | } | 5154 | } else |
| 5155 | vport->fc_myDID = PT2PT_RemoteID; | ||
| 5117 | 5156 | ||
| 5118 | /* | 5157 | /* |
| 5119 | * The vport state should go to LPFC_FLOGI only | 5158 | * The vport state should go to LPFC_FLOGI only |
| 5120 | * AFTER we issue a FLOGI, not receive one. | 5159 | * AFTER we issue a FLOGI, not receive one. |
| 5121 | */ | 5160 | */ |
| 5122 | spin_lock_irq(shost->host_lock); | 5161 | spin_lock_irq(shost->host_lock); |
| 5162 | fc_flag = vport->fc_flag; | ||
| 5163 | port_state = vport->port_state; | ||
| 5123 | vport->fc_flag |= FC_PT2PT; | 5164 | vport->fc_flag |= FC_PT2PT; |
| 5124 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 5165 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
| 5166 | vport->port_state = LPFC_FLOGI; | ||
| 5125 | spin_unlock_irq(shost->host_lock); | 5167 | spin_unlock_irq(shost->host_lock); |
| 5168 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
| 5169 | "3311 Rcv Flogi PS x%x new PS x%x " | ||
| 5170 | "fc_flag x%x new fc_flag x%x\n", | ||
| 5171 | port_state, vport->port_state, | ||
| 5172 | fc_flag, vport->fc_flag); | ||
| 5126 | 5173 | ||
| 5127 | /* | 5174 | /* |
| 5128 | * We temporarily set fc_myDID to make it look like we are | 5175 | * We temporarily set fc_myDID to make it look like we are |
| @@ -6241,7 +6288,8 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) | |||
| 6241 | } | 6288 | } |
| 6242 | 6289 | ||
| 6243 | if (!list_empty(&phba->sli.ring[LPFC_ELS_RING].txcmplq)) | 6290 | if (!list_empty(&phba->sli.ring[LPFC_ELS_RING].txcmplq)) |
| 6244 | mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); | 6291 | mod_timer(&vport->els_tmofunc, |
| 6292 | jiffies + msecs_to_jiffies(1000 * timeout)); | ||
| 6245 | } | 6293 | } |
| 6246 | 6294 | ||
| 6247 | /** | 6295 | /** |
| @@ -6612,7 +6660,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 6612 | /* ELS command <elsCmd> received from NPORT <did> */ | 6660 | /* ELS command <elsCmd> received from NPORT <did> */ |
| 6613 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 6661 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
| 6614 | "0112 ELS command x%x received from NPORT x%x " | 6662 | "0112 ELS command x%x received from NPORT x%x " |
| 6615 | "Data: x%x\n", cmd, did, vport->port_state); | 6663 | "Data: x%x x%x x%x x%x\n", |
| 6664 | cmd, did, vport->port_state, vport->fc_flag, | ||
| 6665 | vport->fc_myDID, vport->fc_prevDID); | ||
| 6616 | switch (cmd) { | 6666 | switch (cmd) { |
| 6617 | case ELS_CMD_PLOGI: | 6667 | case ELS_CMD_PLOGI: |
| 6618 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, | 6668 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
| @@ -6621,6 +6671,19 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 6621 | 6671 | ||
| 6622 | phba->fc_stat.elsRcvPLOGI++; | 6672 | phba->fc_stat.elsRcvPLOGI++; |
| 6623 | ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp); | 6673 | ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp); |
| 6674 | if (phba->sli_rev == LPFC_SLI_REV4 && | ||
| 6675 | (phba->pport->fc_flag & FC_PT2PT)) { | ||
| 6676 | vport->fc_prevDID = vport->fc_myDID; | ||
| 6677 | /* Our DID needs to be updated before registering | ||
| 6678 | * the vfi. This is done in lpfc_rcv_plogi but | ||
| 6679 | * that is called after the reg_vfi. | ||
| 6680 | */ | ||
| 6681 | vport->fc_myDID = elsiocb->iocb.un.rcvels.parmRo; | ||
| 6682 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
| 6683 | "3312 Remote port assigned DID x%x " | ||
| 6684 | "%x\n", vport->fc_myDID, | ||
| 6685 | vport->fc_prevDID); | ||
| 6686 | } | ||
| 6624 | 6687 | ||
| 6625 | lpfc_send_els_event(vport, ndlp, payload); | 6688 | lpfc_send_els_event(vport, ndlp, payload); |
| 6626 | 6689 | ||
| @@ -6630,6 +6693,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 6630 | rjt_exp = LSEXP_NOTHING_MORE; | 6693 | rjt_exp = LSEXP_NOTHING_MORE; |
| 6631 | break; | 6694 | break; |
| 6632 | } | 6695 | } |
| 6696 | shost = lpfc_shost_from_vport(vport); | ||
| 6633 | if (vport->port_state < LPFC_DISC_AUTH) { | 6697 | if (vport->port_state < LPFC_DISC_AUTH) { |
| 6634 | if (!(phba->pport->fc_flag & FC_PT2PT) || | 6698 | if (!(phba->pport->fc_flag & FC_PT2PT) || |
| 6635 | (phba->pport->fc_flag & FC_PT2PT_PLOGI)) { | 6699 | (phba->pport->fc_flag & FC_PT2PT_PLOGI)) { |
| @@ -6641,9 +6705,18 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 6641 | * another NPort and the other side has initiated | 6705 | * another NPort and the other side has initiated |
| 6642 | * the PLOGI before responding to our FLOGI. | 6706 | * the PLOGI before responding to our FLOGI. |
| 6643 | */ | 6707 | */ |
| 6708 | if (phba->sli_rev == LPFC_SLI_REV4 && | ||
| 6709 | (phba->fc_topology_changed || | ||
| 6710 | vport->fc_myDID != vport->fc_prevDID)) { | ||
| 6711 | lpfc_unregister_fcf_prep(phba); | ||
| 6712 | spin_lock_irq(shost->host_lock); | ||
| 6713 | vport->fc_flag &= ~FC_VFI_REGISTERED; | ||
| 6714 | spin_unlock_irq(shost->host_lock); | ||
| 6715 | phba->fc_topology_changed = 0; | ||
| 6716 | lpfc_issue_reg_vfi(vport); | ||
| 6717 | } | ||
| 6644 | } | 6718 | } |
| 6645 | 6719 | ||
| 6646 | shost = lpfc_shost_from_vport(vport); | ||
| 6647 | spin_lock_irq(shost->host_lock); | 6720 | spin_lock_irq(shost->host_lock); |
| 6648 | ndlp->nlp_flag &= ~NLP_TARGET_REMOVE; | 6721 | ndlp->nlp_flag &= ~NLP_TARGET_REMOVE; |
| 6649 | spin_unlock_irq(shost->host_lock); | 6722 | spin_unlock_irq(shost->host_lock); |
| @@ -7002,8 +7075,11 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) | |||
| 7002 | spin_lock_irq(shost->host_lock); | 7075 | spin_lock_irq(shost->host_lock); |
| 7003 | if (vport->fc_flag & FC_DISC_DELAYED) { | 7076 | if (vport->fc_flag & FC_DISC_DELAYED) { |
| 7004 | spin_unlock_irq(shost->host_lock); | 7077 | spin_unlock_irq(shost->host_lock); |
| 7078 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, | ||
| 7079 | "3334 Delay fc port discovery for %d seconds\n", | ||
| 7080 | phba->fc_ratov); | ||
| 7005 | mod_timer(&vport->delayed_disc_tmo, | 7081 | mod_timer(&vport->delayed_disc_tmo, |
| 7006 | jiffies + HZ * phba->fc_ratov); | 7082 | jiffies + msecs_to_jiffies(1000 * phba->fc_ratov)); |
| 7007 | return; | 7083 | return; |
| 7008 | } | 7084 | } |
| 7009 | spin_unlock_irq(shost->host_lock); | 7085 | spin_unlock_irq(shost->host_lock); |
| @@ -7287,7 +7363,7 @@ lpfc_retry_pport_discovery(struct lpfc_hba *phba) | |||
| 7287 | return; | 7363 | return; |
| 7288 | 7364 | ||
| 7289 | shost = lpfc_shost_from_vport(phba->pport); | 7365 | shost = lpfc_shost_from_vport(phba->pport); |
| 7290 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 7366 | mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000)); |
| 7291 | spin_lock_irq(shost->host_lock); | 7367 | spin_lock_irq(shost->host_lock); |
| 7292 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 7368 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
| 7293 | spin_unlock_irq(shost->host_lock); | 7369 | spin_unlock_irq(shost->host_lock); |
| @@ -7791,7 +7867,8 @@ lpfc_block_fabric_iocbs(struct lpfc_hba *phba) | |||
| 7791 | blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags); | 7867 | blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags); |
| 7792 | /* Start a timer to unblock fabric iocbs after 100ms */ | 7868 | /* Start a timer to unblock fabric iocbs after 100ms */ |
| 7793 | if (!blocked) | 7869 | if (!blocked) |
| 7794 | mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 ); | 7870 | mod_timer(&phba->fabric_block_timer, |
| 7871 | jiffies + msecs_to_jiffies(100)); | ||
| 7795 | 7872 | ||
| 7796 | return; | 7873 | return; |
| 7797 | } | 7874 | } |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 326e05a65a73..0f6e2548f35d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
| @@ -160,11 +160,12 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
| 160 | if (!list_empty(&evtp->evt_listp)) | 160 | if (!list_empty(&evtp->evt_listp)) |
| 161 | return; | 161 | return; |
| 162 | 162 | ||
| 163 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); | ||
| 164 | |||
| 163 | spin_lock_irq(&phba->hbalock); | 165 | spin_lock_irq(&phba->hbalock); |
| 164 | /* We need to hold the node by incrementing the reference | 166 | /* We need to hold the node by incrementing the reference |
| 165 | * count until this queued work is done | 167 | * count until this queued work is done |
| 166 | */ | 168 | */ |
| 167 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); | ||
| 168 | if (evtp->evt_arg1) { | 169 | if (evtp->evt_arg1) { |
| 169 | evtp->evt = LPFC_EVT_DEV_LOSS; | 170 | evtp->evt = LPFC_EVT_DEV_LOSS; |
| 170 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 171 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
| @@ -1008,9 +1009,6 @@ lpfc_linkup(struct lpfc_hba *phba) | |||
| 1008 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) | 1009 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) |
| 1009 | lpfc_linkup_port(vports[i]); | 1010 | lpfc_linkup_port(vports[i]); |
| 1010 | lpfc_destroy_vport_work_array(phba, vports); | 1011 | lpfc_destroy_vport_work_array(phba, vports); |
| 1011 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && | ||
| 1012 | (phba->sli_rev < LPFC_SLI_REV4)) | ||
| 1013 | lpfc_issue_clear_la(phba, phba->pport); | ||
| 1014 | 1012 | ||
| 1015 | return 0; | 1013 | return 0; |
| 1016 | } | 1014 | } |
| @@ -1436,7 +1434,8 @@ lpfc_register_fcf(struct lpfc_hba *phba) | |||
| 1436 | if (phba->fcf.fcf_flag & FCF_REGISTERED) { | 1434 | if (phba->fcf.fcf_flag & FCF_REGISTERED) { |
| 1437 | phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE); | 1435 | phba->fcf.fcf_flag |= (FCF_SCAN_DONE | FCF_IN_USE); |
| 1438 | phba->hba_flag &= ~FCF_TS_INPROG; | 1436 | phba->hba_flag &= ~FCF_TS_INPROG; |
| 1439 | if (phba->pport->port_state != LPFC_FLOGI) { | 1437 | if (phba->pport->port_state != LPFC_FLOGI && |
| 1438 | phba->pport->fc_flag & FC_FABRIC) { | ||
| 1440 | phba->hba_flag |= FCF_RR_INPROG; | 1439 | phba->hba_flag |= FCF_RR_INPROG; |
| 1441 | spin_unlock_irq(&phba->hbalock); | 1440 | spin_unlock_irq(&phba->hbalock); |
| 1442 | lpfc_initial_flogi(phba->pport); | 1441 | lpfc_initial_flogi(phba->pport); |
| @@ -2270,8 +2269,11 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 2270 | spin_unlock_irq(&phba->hbalock); | 2269 | spin_unlock_irq(&phba->hbalock); |
| 2271 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP, | 2270 | lpfc_printf_log(phba, KERN_INFO, LOG_FIP, |
| 2272 | "2836 New FCF matches in-use " | 2271 | "2836 New FCF matches in-use " |
| 2273 | "FCF (x%x)\n", | 2272 | "FCF (x%x), port_state:x%x, " |
| 2274 | phba->fcf.current_rec.fcf_indx); | 2273 | "fc_flag:x%x\n", |
| 2274 | phba->fcf.current_rec.fcf_indx, | ||
| 2275 | phba->pport->port_state, | ||
| 2276 | phba->pport->fc_flag); | ||
| 2275 | goto out; | 2277 | goto out; |
| 2276 | } else | 2278 | } else |
| 2277 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP, | 2279 | lpfc_printf_log(phba, KERN_ERR, LOG_FIP, |
| @@ -2796,7 +2798,19 @@ void | |||
| 2796 | lpfc_issue_init_vpi(struct lpfc_vport *vport) | 2798 | lpfc_issue_init_vpi(struct lpfc_vport *vport) |
| 2797 | { | 2799 | { |
| 2798 | LPFC_MBOXQ_t *mboxq; | 2800 | LPFC_MBOXQ_t *mboxq; |
| 2799 | int rc; | 2801 | int rc, vpi; |
| 2802 | |||
| 2803 | if ((vport->port_type != LPFC_PHYSICAL_PORT) && (!vport->vpi)) { | ||
| 2804 | vpi = lpfc_alloc_vpi(vport->phba); | ||
| 2805 | if (!vpi) { | ||
| 2806 | lpfc_printf_vlog(vport, KERN_ERR, | ||
| 2807 | LOG_MBOX, | ||
| 2808 | "3303 Failed to obtain vport vpi\n"); | ||
| 2809 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | ||
| 2810 | return; | ||
| 2811 | } | ||
| 2812 | vport->vpi = vpi; | ||
| 2813 | } | ||
| 2800 | 2814 | ||
| 2801 | mboxq = mempool_alloc(vport->phba->mbox_mem_pool, GFP_KERNEL); | 2815 | mboxq = mempool_alloc(vport->phba->mbox_mem_pool, GFP_KERNEL); |
| 2802 | if (!mboxq) { | 2816 | if (!mboxq) { |
| @@ -2894,9 +2908,14 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 2894 | goto out_free_mem; | 2908 | goto out_free_mem; |
| 2895 | } | 2909 | } |
| 2896 | 2910 | ||
| 2897 | /* If the VFI is already registered, there is nothing else to do */ | 2911 | /* If the VFI is already registered, there is nothing else to do |
| 2912 | * Unless this was a VFI update and we are in PT2PT mode, then | ||
| 2913 | * we should drop through to set the port state to ready. | ||
| 2914 | */ | ||
| 2898 | if (vport->fc_flag & FC_VFI_REGISTERED) | 2915 | if (vport->fc_flag & FC_VFI_REGISTERED) |
| 2899 | goto out_free_mem; | 2916 | if (!(phba->sli_rev == LPFC_SLI_REV4 && |
| 2917 | vport->fc_flag & FC_PT2PT)) | ||
| 2918 | goto out_free_mem; | ||
| 2900 | 2919 | ||
| 2901 | /* The VPI is implicitly registered when the VFI is registered */ | 2920 | /* The VPI is implicitly registered when the VFI is registered */ |
| 2902 | spin_lock_irq(shost->host_lock); | 2921 | spin_lock_irq(shost->host_lock); |
| @@ -2913,6 +2932,13 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 2913 | goto out_free_mem; | 2932 | goto out_free_mem; |
| 2914 | } | 2933 | } |
| 2915 | 2934 | ||
| 2935 | lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, | ||
| 2936 | "3313 cmpl reg vfi port_state:%x fc_flag:%x myDid:%x " | ||
| 2937 | "alpacnt:%d LinkState:%x topology:%x\n", | ||
| 2938 | vport->port_state, vport->fc_flag, vport->fc_myDID, | ||
| 2939 | vport->phba->alpa_map[0], | ||
| 2940 | phba->link_state, phba->fc_topology); | ||
| 2941 | |||
| 2916 | if (vport->port_state == LPFC_FABRIC_CFG_LINK) { | 2942 | if (vport->port_state == LPFC_FABRIC_CFG_LINK) { |
| 2917 | /* | 2943 | /* |
| 2918 | * For private loop or for NPort pt2pt, | 2944 | * For private loop or for NPort pt2pt, |
| @@ -2925,7 +2951,10 @@ lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | |||
| 2925 | /* Use loop map to make discovery list */ | 2951 | /* Use loop map to make discovery list */ |
| 2926 | lpfc_disc_list_loopmap(vport); | 2952 | lpfc_disc_list_loopmap(vport); |
| 2927 | /* Start discovery */ | 2953 | /* Start discovery */ |
| 2928 | lpfc_disc_start(vport); | 2954 | if (vport->fc_flag & FC_PT2PT) |
| 2955 | vport->port_state = LPFC_VPORT_READY; | ||
| 2956 | else | ||
| 2957 | lpfc_disc_start(vport); | ||
| 2929 | } else { | 2958 | } else { |
| 2930 | lpfc_start_fdiscs(phba); | 2959 | lpfc_start_fdiscs(phba); |
| 2931 | lpfc_do_scr_ns_plogi(phba, vport); | 2960 | lpfc_do_scr_ns_plogi(phba, vport); |
| @@ -3007,6 +3036,15 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) | |||
| 3007 | break; | 3036 | break; |
| 3008 | } | 3037 | } |
| 3009 | 3038 | ||
| 3039 | if (phba->fc_topology && | ||
| 3040 | phba->fc_topology != bf_get(lpfc_mbx_read_top_topology, la)) { | ||
| 3041 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, | ||
| 3042 | "3314 Toplogy changed was 0x%x is 0x%x\n", | ||
| 3043 | phba->fc_topology, | ||
| 3044 | bf_get(lpfc_mbx_read_top_topology, la)); | ||
| 3045 | phba->fc_topology_changed = 1; | ||
| 3046 | } | ||
| 3047 | |||
| 3010 | phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la); | 3048 | phba->fc_topology = bf_get(lpfc_mbx_read_top_topology, la); |
| 3011 | phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; | 3049 | phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED; |
| 3012 | 3050 | ||
| @@ -4235,7 +4273,7 @@ lpfc_set_disctmo(struct lpfc_vport *vport) | |||
| 4235 | tmo, vport->port_state, vport->fc_flag); | 4273 | tmo, vport->port_state, vport->fc_flag); |
| 4236 | } | 4274 | } |
| 4237 | 4275 | ||
| 4238 | mod_timer(&vport->fc_disctmo, jiffies + HZ * tmo); | 4276 | mod_timer(&vport->fc_disctmo, jiffies + msecs_to_jiffies(1000 * tmo)); |
| 4239 | spin_lock_irq(shost->host_lock); | 4277 | spin_lock_irq(shost->host_lock); |
| 4240 | vport->fc_flag |= FC_DISC_TMO; | 4278 | vport->fc_flag |= FC_DISC_TMO; |
| 4241 | spin_unlock_irq(shost->host_lock); | 4279 | spin_unlock_irq(shost->host_lock); |
| @@ -4949,8 +4987,12 @@ lpfc_disc_start(struct lpfc_vport *vport) | |||
| 4949 | uint32_t clear_la_pending; | 4987 | uint32_t clear_la_pending; |
| 4950 | int did_changed; | 4988 | int did_changed; |
| 4951 | 4989 | ||
| 4952 | if (!lpfc_is_link_up(phba)) | 4990 | if (!lpfc_is_link_up(phba)) { |
| 4991 | lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, | ||
| 4992 | "3315 Link is not up %x\n", | ||
| 4993 | phba->link_state); | ||
| 4953 | return; | 4994 | return; |
| 4995 | } | ||
| 4954 | 4996 | ||
| 4955 | if (phba->link_state == LPFC_CLEAR_LA) | 4997 | if (phba->link_state == LPFC_CLEAR_LA) |
| 4956 | clear_la_pending = 1; | 4998 | clear_la_pending = 1; |
| @@ -4983,11 +5025,13 @@ lpfc_disc_start(struct lpfc_vport *vport) | |||
| 4983 | if (num_sent) | 5025 | if (num_sent) |
| 4984 | return; | 5026 | return; |
| 4985 | 5027 | ||
| 4986 | /* Register the VPI for SLI3, NON-NPIV only. */ | 5028 | /* Register the VPI for SLI3, NPIV only. */ |
| 4987 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && | 5029 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && |
| 4988 | !(vport->fc_flag & FC_PT2PT) && | 5030 | !(vport->fc_flag & FC_PT2PT) && |
| 4989 | !(vport->fc_flag & FC_RSCN_MODE) && | 5031 | !(vport->fc_flag & FC_RSCN_MODE) && |
| 4990 | (phba->sli_rev < LPFC_SLI_REV4)) { | 5032 | (phba->sli_rev < LPFC_SLI_REV4)) { |
| 5033 | if (vport->port_type == LPFC_PHYSICAL_PORT) | ||
| 5034 | lpfc_issue_clear_la(phba, vport); | ||
| 4991 | lpfc_issue_reg_vpi(phba, vport); | 5035 | lpfc_issue_reg_vpi(phba, vport); |
| 4992 | return; | 5036 | return; |
| 4993 | } | 5037 | } |
| @@ -5410,7 +5454,8 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
| 5410 | if (vport->cfg_fdmi_on == 1) | 5454 | if (vport->cfg_fdmi_on == 1) |
| 5411 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA); | 5455 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA); |
| 5412 | else | 5456 | else |
| 5413 | mod_timer(&vport->fc_fdmitmo, jiffies + HZ * 60); | 5457 | mod_timer(&vport->fc_fdmitmo, |
| 5458 | jiffies + msecs_to_jiffies(1000 * 60)); | ||
| 5414 | 5459 | ||
| 5415 | /* decrement the node reference count held for this callback | 5460 | /* decrement the node reference count held for this callback |
| 5416 | * function. | 5461 | * function. |
| @@ -5855,7 +5900,7 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba) | |||
| 5855 | struct lpfc_vport **vports; | 5900 | struct lpfc_vport **vports; |
| 5856 | struct lpfc_nodelist *ndlp; | 5901 | struct lpfc_nodelist *ndlp; |
| 5857 | struct Scsi_Host *shost; | 5902 | struct Scsi_Host *shost; |
| 5858 | int i, rc; | 5903 | int i = 0, rc; |
| 5859 | 5904 | ||
| 5860 | /* Unregister RPIs */ | 5905 | /* Unregister RPIs */ |
| 5861 | if (lpfc_fcf_inuse(phba)) | 5906 | if (lpfc_fcf_inuse(phba)) |
| @@ -5883,6 +5928,20 @@ lpfc_unregister_fcf_prep(struct lpfc_hba *phba) | |||
| 5883 | spin_unlock_irq(shost->host_lock); | 5928 | spin_unlock_irq(shost->host_lock); |
| 5884 | } | 5929 | } |
| 5885 | lpfc_destroy_vport_work_array(phba, vports); | 5930 | lpfc_destroy_vport_work_array(phba, vports); |
| 5931 | if (i == 0 && (!(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED))) { | ||
| 5932 | ndlp = lpfc_findnode_did(phba->pport, Fabric_DID); | ||
| 5933 | if (ndlp) | ||
| 5934 | lpfc_cancel_retry_delay_tmo(phba->pport, ndlp); | ||
| 5935 | lpfc_cleanup_pending_mbox(phba->pport); | ||
| 5936 | if (phba->sli_rev == LPFC_SLI_REV4) | ||
| 5937 | lpfc_sli4_unreg_all_rpis(phba->pport); | ||
| 5938 | lpfc_mbx_unreg_vpi(phba->pport); | ||
| 5939 | shost = lpfc_shost_from_vport(phba->pport); | ||
| 5940 | spin_lock_irq(shost->host_lock); | ||
| 5941 | phba->pport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | ||
| 5942 | phba->pport->vpi_state &= ~LPFC_VPI_REGISTERED; | ||
| 5943 | spin_unlock_irq(shost->host_lock); | ||
| 5944 | } | ||
| 5886 | 5945 | ||
| 5887 | /* Cleanup any outstanding ELS commands */ | 5946 | /* Cleanup any outstanding ELS commands */ |
| 5888 | lpfc_els_flush_all_cmd(phba); | 5947 | lpfc_els_flush_all_cmd(phba); |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index e8c476031703..83700c18f468 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
| @@ -1667,6 +1667,7 @@ enum lpfc_protgrp_type { | |||
| 1667 | #define BG_OP_IN_CSUM_OUT_CSUM 0x5 | 1667 | #define BG_OP_IN_CSUM_OUT_CSUM 0x5 |
| 1668 | #define BG_OP_IN_CRC_OUT_CSUM 0x6 | 1668 | #define BG_OP_IN_CRC_OUT_CSUM 0x6 |
| 1669 | #define BG_OP_IN_CSUM_OUT_CRC 0x7 | 1669 | #define BG_OP_IN_CSUM_OUT_CRC 0x7 |
| 1670 | #define BG_OP_RAW_MODE 0x8 | ||
| 1670 | 1671 | ||
| 1671 | struct lpfc_pde5 { | 1672 | struct lpfc_pde5 { |
| 1672 | uint32_t word0; | 1673 | uint32_t word0; |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 1dd2f6f0a127..713a4613ec3a 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
| @@ -200,6 +200,11 @@ struct lpfc_sli_intf { | |||
| 200 | #define LPFC_MAX_IMAX 5000000 | 200 | #define LPFC_MAX_IMAX 5000000 |
| 201 | #define LPFC_DEF_IMAX 50000 | 201 | #define LPFC_DEF_IMAX 50000 |
| 202 | 202 | ||
| 203 | #define LPFC_MIN_CPU_MAP 0 | ||
| 204 | #define LPFC_MAX_CPU_MAP 2 | ||
| 205 | #define LPFC_HBA_CPU_MAP 1 | ||
| 206 | #define LPFC_DRIVER_CPU_MAP 2 /* Default */ | ||
| 207 | |||
| 203 | /* PORT_CAPABILITIES constants. */ | 208 | /* PORT_CAPABILITIES constants. */ |
| 204 | #define LPFC_MAX_SUPPORTED_PAGES 8 | 209 | #define LPFC_MAX_SUPPORTED_PAGES 8 |
| 205 | 210 | ||
| @@ -621,7 +626,7 @@ struct lpfc_register { | |||
| 621 | #define lpfc_sliport_status_rdy_SHIFT 23 | 626 | #define lpfc_sliport_status_rdy_SHIFT 23 |
| 622 | #define lpfc_sliport_status_rdy_MASK 0x1 | 627 | #define lpfc_sliport_status_rdy_MASK 0x1 |
| 623 | #define lpfc_sliport_status_rdy_WORD word0 | 628 | #define lpfc_sliport_status_rdy_WORD word0 |
| 624 | #define MAX_IF_TYPE_2_RESETS 1000 | 629 | #define MAX_IF_TYPE_2_RESETS 6 |
| 625 | 630 | ||
| 626 | #define LPFC_CTL_PORT_CTL_OFFSET 0x408 | 631 | #define LPFC_CTL_PORT_CTL_OFFSET 0x408 |
| 627 | #define lpfc_sliport_ctrl_end_SHIFT 30 | 632 | #define lpfc_sliport_ctrl_end_SHIFT 30 |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 90b8b0515e23..cb465b253910 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | #include <linux/firmware.h> | 34 | #include <linux/firmware.h> |
| 35 | #include <linux/miscdevice.h> | 35 | #include <linux/miscdevice.h> |
| 36 | #include <linux/percpu.h> | ||
| 36 | 37 | ||
| 37 | #include <scsi/scsi.h> | 38 | #include <scsi/scsi.h> |
| 38 | #include <scsi/scsi_device.h> | 39 | #include <scsi/scsi_device.h> |
| @@ -58,6 +59,9 @@ char *_dump_buf_dif; | |||
| 58 | unsigned long _dump_buf_dif_order; | 59 | unsigned long _dump_buf_dif_order; |
| 59 | spinlock_t _dump_buf_lock; | 60 | spinlock_t _dump_buf_lock; |
| 60 | 61 | ||
| 62 | /* Used when mapping IRQ vectors in a driver centric manner */ | ||
| 63 | uint16_t lpfc_used_cpu[LPFC_MAX_CPU]; | ||
| 64 | |||
| 61 | static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *); | 65 | static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *); |
| 62 | static int lpfc_post_rcv_buf(struct lpfc_hba *); | 66 | static int lpfc_post_rcv_buf(struct lpfc_hba *); |
| 63 | static int lpfc_sli4_queue_verify(struct lpfc_hba *); | 67 | static int lpfc_sli4_queue_verify(struct lpfc_hba *); |
| @@ -541,13 +545,16 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
| 541 | 545 | ||
| 542 | /* Set up ring-0 (ELS) timer */ | 546 | /* Set up ring-0 (ELS) timer */ |
| 543 | timeout = phba->fc_ratov * 2; | 547 | timeout = phba->fc_ratov * 2; |
| 544 | mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); | 548 | mod_timer(&vport->els_tmofunc, |
| 549 | jiffies + msecs_to_jiffies(1000 * timeout)); | ||
| 545 | /* Set up heart beat (HB) timer */ | 550 | /* Set up heart beat (HB) timer */ |
| 546 | mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | 551 | mod_timer(&phba->hb_tmofunc, |
| 552 | jiffies + msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL)); | ||
| 547 | phba->hb_outstanding = 0; | 553 | phba->hb_outstanding = 0; |
| 548 | phba->last_completion_time = jiffies; | 554 | phba->last_completion_time = jiffies; |
| 549 | /* Set up error attention (ERATT) polling timer */ | 555 | /* Set up error attention (ERATT) polling timer */ |
| 550 | mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL); | 556 | mod_timer(&phba->eratt_poll, |
| 557 | jiffies + msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL)); | ||
| 551 | 558 | ||
| 552 | if (phba->hba_flag & LINK_DISABLED) { | 559 | if (phba->hba_flag & LINK_DISABLED) { |
| 553 | lpfc_printf_log(phba, | 560 | lpfc_printf_log(phba, |
| @@ -908,9 +915,9 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba) | |||
| 908 | psb->pCmd = NULL; | 915 | psb->pCmd = NULL; |
| 909 | psb->status = IOSTAT_SUCCESS; | 916 | psb->status = IOSTAT_SUCCESS; |
| 910 | } | 917 | } |
| 911 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | 918 | spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag); |
| 912 | list_splice(&aborts, &phba->lpfc_scsi_buf_list); | 919 | list_splice(&aborts, &phba->lpfc_scsi_buf_list_put); |
| 913 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | 920 | spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag); |
| 914 | return 0; | 921 | return 0; |
| 915 | } | 922 | } |
| 916 | 923 | ||
| @@ -1021,7 +1028,8 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) | |||
| 1021 | !(phba->link_state == LPFC_HBA_ERROR) && | 1028 | !(phba->link_state == LPFC_HBA_ERROR) && |
| 1022 | !(phba->pport->load_flag & FC_UNLOADING)) | 1029 | !(phba->pport->load_flag & FC_UNLOADING)) |
| 1023 | mod_timer(&phba->hb_tmofunc, | 1030 | mod_timer(&phba->hb_tmofunc, |
| 1024 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | 1031 | jiffies + |
| 1032 | msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL)); | ||
| 1025 | return; | 1033 | return; |
| 1026 | } | 1034 | } |
| 1027 | 1035 | ||
| @@ -1064,15 +1072,18 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
| 1064 | 1072 | ||
| 1065 | spin_lock_irq(&phba->pport->work_port_lock); | 1073 | spin_lock_irq(&phba->pport->work_port_lock); |
| 1066 | 1074 | ||
| 1067 | if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ, | 1075 | if (time_after(phba->last_completion_time + |
| 1068 | jiffies)) { | 1076 | msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL), |
| 1077 | jiffies)) { | ||
| 1069 | spin_unlock_irq(&phba->pport->work_port_lock); | 1078 | spin_unlock_irq(&phba->pport->work_port_lock); |
| 1070 | if (!phba->hb_outstanding) | 1079 | if (!phba->hb_outstanding) |
| 1071 | mod_timer(&phba->hb_tmofunc, | 1080 | mod_timer(&phba->hb_tmofunc, |
| 1072 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | 1081 | jiffies + |
| 1082 | msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL)); | ||
| 1073 | else | 1083 | else |
| 1074 | mod_timer(&phba->hb_tmofunc, | 1084 | mod_timer(&phba->hb_tmofunc, |
| 1075 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); | 1085 | jiffies + |
| 1086 | msecs_to_jiffies(1000 * LPFC_HB_MBOX_TIMEOUT)); | ||
| 1076 | return; | 1087 | return; |
| 1077 | } | 1088 | } |
| 1078 | spin_unlock_irq(&phba->pport->work_port_lock); | 1089 | spin_unlock_irq(&phba->pport->work_port_lock); |
| @@ -1104,7 +1115,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
| 1104 | if (!pmboxq) { | 1115 | if (!pmboxq) { |
| 1105 | mod_timer(&phba->hb_tmofunc, | 1116 | mod_timer(&phba->hb_tmofunc, |
| 1106 | jiffies + | 1117 | jiffies + |
| 1107 | HZ * LPFC_HB_MBOX_INTERVAL); | 1118 | msecs_to_jiffies(1000 * |
| 1119 | LPFC_HB_MBOX_INTERVAL)); | ||
| 1108 | return; | 1120 | return; |
| 1109 | } | 1121 | } |
| 1110 | 1122 | ||
| @@ -1120,7 +1132,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
| 1120 | phba->mbox_mem_pool); | 1132 | phba->mbox_mem_pool); |
| 1121 | mod_timer(&phba->hb_tmofunc, | 1133 | mod_timer(&phba->hb_tmofunc, |
| 1122 | jiffies + | 1134 | jiffies + |
| 1123 | HZ * LPFC_HB_MBOX_INTERVAL); | 1135 | msecs_to_jiffies(1000 * |
| 1136 | LPFC_HB_MBOX_INTERVAL)); | ||
| 1124 | return; | 1137 | return; |
| 1125 | } | 1138 | } |
| 1126 | phba->skipped_hb = 0; | 1139 | phba->skipped_hb = 0; |
| @@ -1136,7 +1149,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
| 1136 | phba->skipped_hb = jiffies; | 1149 | phba->skipped_hb = jiffies; |
| 1137 | 1150 | ||
| 1138 | mod_timer(&phba->hb_tmofunc, | 1151 | mod_timer(&phba->hb_tmofunc, |
| 1139 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); | 1152 | jiffies + |
| 1153 | msecs_to_jiffies(1000 * LPFC_HB_MBOX_TIMEOUT)); | ||
| 1140 | return; | 1154 | return; |
| 1141 | } else { | 1155 | } else { |
| 1142 | /* | 1156 | /* |
| @@ -1150,7 +1164,8 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
| 1150 | jiffies_to_msecs(jiffies | 1164 | jiffies_to_msecs(jiffies |
| 1151 | - phba->last_completion_time)); | 1165 | - phba->last_completion_time)); |
| 1152 | mod_timer(&phba->hb_tmofunc, | 1166 | mod_timer(&phba->hb_tmofunc, |
| 1153 | jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); | 1167 | jiffies + |
| 1168 | msecs_to_jiffies(1000 * LPFC_HB_MBOX_TIMEOUT)); | ||
| 1154 | } | 1169 | } |
| 1155 | } | 1170 | } |
| 1156 | } | 1171 | } |
| @@ -1191,7 +1206,7 @@ lpfc_offline_eratt(struct lpfc_hba *phba) | |||
| 1191 | * This routine is called to bring a SLI4 HBA offline when HBA hardware error | 1206 | * This routine is called to bring a SLI4 HBA offline when HBA hardware error |
| 1192 | * other than Port Error 6 has been detected. | 1207 | * other than Port Error 6 has been detected. |
| 1193 | **/ | 1208 | **/ |
| 1194 | static void | 1209 | void |
| 1195 | lpfc_sli4_offline_eratt(struct lpfc_hba *phba) | 1210 | lpfc_sli4_offline_eratt(struct lpfc_hba *phba) |
| 1196 | { | 1211 | { |
| 1197 | lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT); | 1212 | lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT); |
| @@ -2633,6 +2648,7 @@ lpfc_online(struct lpfc_hba *phba) | |||
| 2633 | struct lpfc_vport *vport; | 2648 | struct lpfc_vport *vport; |
| 2634 | struct lpfc_vport **vports; | 2649 | struct lpfc_vport **vports; |
| 2635 | int i; | 2650 | int i; |
| 2651 | bool vpis_cleared = false; | ||
| 2636 | 2652 | ||
| 2637 | if (!phba) | 2653 | if (!phba) |
| 2638 | return 0; | 2654 | return 0; |
| @@ -2656,6 +2672,10 @@ lpfc_online(struct lpfc_hba *phba) | |||
| 2656 | lpfc_unblock_mgmt_io(phba); | 2672 | lpfc_unblock_mgmt_io(phba); |
| 2657 | return 1; | 2673 | return 1; |
| 2658 | } | 2674 | } |
| 2675 | spin_lock_irq(&phba->hbalock); | ||
| 2676 | if (!phba->sli4_hba.max_cfg_param.vpi_used) | ||
| 2677 | vpis_cleared = true; | ||
| 2678 | spin_unlock_irq(&phba->hbalock); | ||
| 2659 | } else { | 2679 | } else { |
| 2660 | if (lpfc_sli_hba_setup(phba)) { /* Initialize SLI2/SLI3 HBA */ | 2680 | if (lpfc_sli_hba_setup(phba)) { /* Initialize SLI2/SLI3 HBA */ |
| 2661 | lpfc_unblock_mgmt_io(phba); | 2681 | lpfc_unblock_mgmt_io(phba); |
| @@ -2672,8 +2692,13 @@ lpfc_online(struct lpfc_hba *phba) | |||
| 2672 | vports[i]->fc_flag &= ~FC_OFFLINE_MODE; | 2692 | vports[i]->fc_flag &= ~FC_OFFLINE_MODE; |
| 2673 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) | 2693 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) |
| 2674 | vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; | 2694 | vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI; |
| 2675 | if (phba->sli_rev == LPFC_SLI_REV4) | 2695 | if (phba->sli_rev == LPFC_SLI_REV4) { |
| 2676 | vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; | 2696 | vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; |
| 2697 | if ((vpis_cleared) && | ||
| 2698 | (vports[i]->port_type != | ||
| 2699 | LPFC_PHYSICAL_PORT)) | ||
| 2700 | vports[i]->vpi = 0; | ||
| 2701 | } | ||
| 2677 | spin_unlock_irq(shost->host_lock); | 2702 | spin_unlock_irq(shost->host_lock); |
| 2678 | } | 2703 | } |
| 2679 | lpfc_destroy_vport_work_array(phba, vports); | 2704 | lpfc_destroy_vport_work_array(phba, vports); |
| @@ -2833,16 +2858,30 @@ lpfc_scsi_free(struct lpfc_hba *phba) | |||
| 2833 | struct lpfc_iocbq *io, *io_next; | 2858 | struct lpfc_iocbq *io, *io_next; |
| 2834 | 2859 | ||
| 2835 | spin_lock_irq(&phba->hbalock); | 2860 | spin_lock_irq(&phba->hbalock); |
| 2861 | |||
| 2836 | /* Release all the lpfc_scsi_bufs maintained by this host. */ | 2862 | /* Release all the lpfc_scsi_bufs maintained by this host. */ |
| 2837 | spin_lock(&phba->scsi_buf_list_lock); | 2863 | |
| 2838 | list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) { | 2864 | spin_lock(&phba->scsi_buf_list_put_lock); |
| 2865 | list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list_put, | ||
| 2866 | list) { | ||
| 2839 | list_del(&sb->list); | 2867 | list_del(&sb->list); |
| 2840 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data, | 2868 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data, |
| 2841 | sb->dma_handle); | 2869 | sb->dma_handle); |
| 2842 | kfree(sb); | 2870 | kfree(sb); |
| 2843 | phba->total_scsi_bufs--; | 2871 | phba->total_scsi_bufs--; |
| 2844 | } | 2872 | } |
| 2845 | spin_unlock(&phba->scsi_buf_list_lock); | 2873 | spin_unlock(&phba->scsi_buf_list_put_lock); |
| 2874 | |||
| 2875 | spin_lock(&phba->scsi_buf_list_get_lock); | ||
| 2876 | list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list_get, | ||
| 2877 | list) { | ||
| 2878 | list_del(&sb->list); | ||
| 2879 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data, | ||
| 2880 | sb->dma_handle); | ||
| 2881 | kfree(sb); | ||
| 2882 | phba->total_scsi_bufs--; | ||
| 2883 | } | ||
| 2884 | spin_unlock(&phba->scsi_buf_list_get_lock); | ||
| 2846 | 2885 | ||
| 2847 | /* Release all the lpfc_iocbq entries maintained by this host. */ | 2886 | /* Release all the lpfc_iocbq entries maintained by this host. */ |
| 2848 | list_for_each_entry_safe(io, io_next, &phba->lpfc_iocb_list, list) { | 2887 | list_for_each_entry_safe(io, io_next, &phba->lpfc_iocb_list, list) { |
| @@ -2978,9 +3017,12 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba) | |||
| 2978 | phba->sli4_hba.scsi_xri_cnt, | 3017 | phba->sli4_hba.scsi_xri_cnt, |
| 2979 | phba->sli4_hba.scsi_xri_max); | 3018 | phba->sli4_hba.scsi_xri_max); |
| 2980 | 3019 | ||
| 2981 | spin_lock_irq(&phba->scsi_buf_list_lock); | 3020 | spin_lock_irq(&phba->scsi_buf_list_get_lock); |
| 2982 | list_splice_init(&phba->lpfc_scsi_buf_list, &scsi_sgl_list); | 3021 | spin_lock_irq(&phba->scsi_buf_list_put_lock); |
| 2983 | spin_unlock_irq(&phba->scsi_buf_list_lock); | 3022 | list_splice_init(&phba->lpfc_scsi_buf_list_get, &scsi_sgl_list); |
| 3023 | list_splice(&phba->lpfc_scsi_buf_list_put, &scsi_sgl_list); | ||
| 3024 | spin_unlock_irq(&phba->scsi_buf_list_put_lock); | ||
| 3025 | spin_unlock_irq(&phba->scsi_buf_list_get_lock); | ||
| 2984 | 3026 | ||
| 2985 | if (phba->sli4_hba.scsi_xri_cnt > phba->sli4_hba.scsi_xri_max) { | 3027 | if (phba->sli4_hba.scsi_xri_cnt > phba->sli4_hba.scsi_xri_max) { |
| 2986 | /* max scsi xri shrinked below the allocated scsi buffers */ | 3028 | /* max scsi xri shrinked below the allocated scsi buffers */ |
| @@ -2994,9 +3036,9 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba) | |||
| 2994 | psb->dma_handle); | 3036 | psb->dma_handle); |
| 2995 | kfree(psb); | 3037 | kfree(psb); |
| 2996 | } | 3038 | } |
| 2997 | spin_lock_irq(&phba->scsi_buf_list_lock); | 3039 | spin_lock_irq(&phba->scsi_buf_list_get_lock); |
| 2998 | phba->sli4_hba.scsi_xri_cnt -= scsi_xri_cnt; | 3040 | phba->sli4_hba.scsi_xri_cnt -= scsi_xri_cnt; |
| 2999 | spin_unlock_irq(&phba->scsi_buf_list_lock); | 3041 | spin_unlock_irq(&phba->scsi_buf_list_get_lock); |
| 3000 | } | 3042 | } |
| 3001 | 3043 | ||
| 3002 | /* update xris associated to remaining allocated scsi buffers */ | 3044 | /* update xris associated to remaining allocated scsi buffers */ |
| @@ -3014,9 +3056,12 @@ lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba) | |||
| 3014 | psb->cur_iocbq.sli4_lxritag = lxri; | 3056 | psb->cur_iocbq.sli4_lxritag = lxri; |
| 3015 | psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri]; | 3057 | psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri]; |
| 3016 | } | 3058 | } |
| 3017 | spin_lock_irq(&phba->scsi_buf_list_lock); | 3059 | spin_lock_irq(&phba->scsi_buf_list_get_lock); |
| 3018 | list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list); | 3060 | spin_lock_irq(&phba->scsi_buf_list_put_lock); |
| 3019 | spin_unlock_irq(&phba->scsi_buf_list_lock); | 3061 | list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list_get); |
| 3062 | INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put); | ||
| 3063 | spin_unlock_irq(&phba->scsi_buf_list_put_lock); | ||
| 3064 | spin_unlock_irq(&phba->scsi_buf_list_get_lock); | ||
| 3020 | 3065 | ||
| 3021 | return 0; | 3066 | return 0; |
| 3022 | 3067 | ||
| @@ -3197,14 +3242,15 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) | |||
| 3197 | stat = 1; | 3242 | stat = 1; |
| 3198 | goto finished; | 3243 | goto finished; |
| 3199 | } | 3244 | } |
| 3200 | if (time >= 30 * HZ) { | 3245 | if (time >= msecs_to_jiffies(30 * 1000)) { |
| 3201 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 3246 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 3202 | "0461 Scanning longer than 30 " | 3247 | "0461 Scanning longer than 30 " |
| 3203 | "seconds. Continuing initialization\n"); | 3248 | "seconds. Continuing initialization\n"); |
| 3204 | stat = 1; | 3249 | stat = 1; |
| 3205 | goto finished; | 3250 | goto finished; |
| 3206 | } | 3251 | } |
| 3207 | if (time >= 15 * HZ && phba->link_state <= LPFC_LINK_DOWN) { | 3252 | if (time >= msecs_to_jiffies(15 * 1000) && |
| 3253 | phba->link_state <= LPFC_LINK_DOWN) { | ||
| 3208 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 3254 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 3209 | "0465 Link down longer than 15 " | 3255 | "0465 Link down longer than 15 " |
| 3210 | "seconds. Continuing initialization\n"); | 3256 | "seconds. Continuing initialization\n"); |
| @@ -3216,7 +3262,7 @@ int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time) | |||
| 3216 | goto finished; | 3262 | goto finished; |
| 3217 | if (vport->num_disc_nodes || vport->fc_prli_sent) | 3263 | if (vport->num_disc_nodes || vport->fc_prli_sent) |
| 3218 | goto finished; | 3264 | goto finished; |
| 3219 | if (vport->fc_map_cnt == 0 && time < 2 * HZ) | 3265 | if (vport->fc_map_cnt == 0 && time < msecs_to_jiffies(2 * 1000)) |
| 3220 | goto finished; | 3266 | goto finished; |
| 3221 | if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0) | 3267 | if ((phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) != 0) |
| 3222 | goto finished; | 3268 | goto finished; |
| @@ -4215,7 +4261,8 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba, | |||
| 4215 | * If there are other active VLinks present, | 4261 | * If there are other active VLinks present, |
| 4216 | * re-instantiate the Vlink using FDISC. | 4262 | * re-instantiate the Vlink using FDISC. |
| 4217 | */ | 4263 | */ |
| 4218 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 4264 | mod_timer(&ndlp->nlp_delayfunc, |
| 4265 | jiffies + msecs_to_jiffies(1000)); | ||
| 4219 | shost = lpfc_shost_from_vport(vport); | 4266 | shost = lpfc_shost_from_vport(vport); |
| 4220 | spin_lock_irq(shost->host_lock); | 4267 | spin_lock_irq(shost->host_lock); |
| 4221 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 4268 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
| @@ -4707,23 +4754,52 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4707 | return -ENOMEM; | 4754 | return -ENOMEM; |
| 4708 | 4755 | ||
| 4709 | /* | 4756 | /* |
| 4710 | * Since the sg_tablesize is module parameter, the sg_dma_buf_size | 4757 | * Since lpfc_sg_seg_cnt is module parameter, the sg_dma_buf_size |
| 4711 | * used to create the sg_dma_buf_pool must be dynamically calculated. | 4758 | * used to create the sg_dma_buf_pool must be dynamically calculated. |
| 4712 | * 2 segments are added since the IOCB needs a command and response bde. | ||
| 4713 | */ | 4759 | */ |
| 4714 | phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + | ||
| 4715 | sizeof(struct fcp_rsp) + | ||
| 4716 | ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct ulp_bde64)); | ||
| 4717 | 4760 | ||
| 4761 | /* Initialize the host templates the configured values. */ | ||
| 4762 | lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt; | ||
| 4763 | lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt; | ||
| 4764 | |||
| 4765 | /* There are going to be 2 reserved BDEs: 1 FCP cmnd + 1 FCP rsp */ | ||
| 4718 | if (phba->cfg_enable_bg) { | 4766 | if (phba->cfg_enable_bg) { |
| 4719 | phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SEG_CNT; | 4767 | /* |
| 4720 | phba->cfg_sg_dma_buf_size += | 4768 | * The scsi_buf for a T10-DIF I/O will hold the FCP cmnd, |
| 4721 | phba->cfg_prot_sg_seg_cnt * sizeof(struct ulp_bde64); | 4769 | * the FCP rsp, and a BDE for each. Sice we have no control |
| 4770 | * over how many protection data segments the SCSI Layer | ||
| 4771 | * will hand us (ie: there could be one for every block | ||
| 4772 | * in the IO), we just allocate enough BDEs to accomidate | ||
| 4773 | * our max amount and we need to limit lpfc_sg_seg_cnt to | ||
| 4774 | * minimize the risk of running out. | ||
| 4775 | */ | ||
| 4776 | phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + | ||
| 4777 | sizeof(struct fcp_rsp) + | ||
| 4778 | (LPFC_MAX_SG_SEG_CNT * sizeof(struct ulp_bde64)); | ||
| 4779 | |||
| 4780 | if (phba->cfg_sg_seg_cnt > LPFC_MAX_SG_SEG_CNT_DIF) | ||
| 4781 | phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SEG_CNT_DIF; | ||
| 4782 | |||
| 4783 | /* Total BDEs in BPL for scsi_sg_list and scsi_sg_prot_list */ | ||
| 4784 | phba->cfg_total_seg_cnt = LPFC_MAX_SG_SEG_CNT; | ||
| 4785 | } else { | ||
| 4786 | /* | ||
| 4787 | * The scsi_buf for a regular I/O will hold the FCP cmnd, | ||
| 4788 | * the FCP rsp, a BDE for each, and a BDE for up to | ||
| 4789 | * cfg_sg_seg_cnt data segments. | ||
| 4790 | */ | ||
| 4791 | phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + | ||
| 4792 | sizeof(struct fcp_rsp) + | ||
| 4793 | ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct ulp_bde64)); | ||
| 4794 | |||
| 4795 | /* Total BDEs in BPL for scsi_sg_list */ | ||
| 4796 | phba->cfg_total_seg_cnt = phba->cfg_sg_seg_cnt + 2; | ||
| 4722 | } | 4797 | } |
| 4723 | 4798 | ||
| 4724 | /* Also reinitialize the host templates with new values. */ | 4799 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP, |
| 4725 | lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt; | 4800 | "9088 sg_tablesize:%d dmabuf_size:%d total_bde:%d\n", |
| 4726 | lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt; | 4801 | phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size, |
| 4802 | phba->cfg_total_seg_cnt); | ||
| 4727 | 4803 | ||
| 4728 | phba->max_vpi = LPFC_MAX_VPI; | 4804 | phba->max_vpi = LPFC_MAX_VPI; |
| 4729 | /* This will be set to correct value after config_port mbox */ | 4805 | /* This will be set to correct value after config_port mbox */ |
| @@ -4789,13 +4865,13 @@ lpfc_sli_driver_resource_unset(struct lpfc_hba *phba) | |||
| 4789 | static int | 4865 | static int |
| 4790 | lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | 4866 | lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) |
| 4791 | { | 4867 | { |
| 4868 | struct lpfc_vector_map_info *cpup; | ||
| 4792 | struct lpfc_sli *psli; | 4869 | struct lpfc_sli *psli; |
| 4793 | LPFC_MBOXQ_t *mboxq; | 4870 | LPFC_MBOXQ_t *mboxq; |
| 4794 | int rc, i, hbq_count, buf_size, dma_buf_size, max_buf_size; | 4871 | int rc, i, hbq_count, max_buf_size; |
| 4795 | uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0}; | 4872 | uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0}; |
| 4796 | struct lpfc_mqe *mqe; | 4873 | struct lpfc_mqe *mqe; |
| 4797 | int longs, sli_family; | 4874 | int longs; |
| 4798 | int sges_per_segment; | ||
| 4799 | 4875 | ||
| 4800 | /* Before proceed, wait for POST done and device ready */ | 4876 | /* Before proceed, wait for POST done and device ready */ |
| 4801 | rc = lpfc_sli4_post_status_check(phba); | 4877 | rc = lpfc_sli4_post_status_check(phba); |
| @@ -4863,11 +4939,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4863 | phba->fc_map[1] = LPFC_FCOE_FCF_MAP1; | 4939 | phba->fc_map[1] = LPFC_FCOE_FCF_MAP1; |
| 4864 | phba->fc_map[2] = LPFC_FCOE_FCF_MAP2; | 4940 | phba->fc_map[2] = LPFC_FCOE_FCF_MAP2; |
| 4865 | 4941 | ||
| 4866 | /* With BlockGuard we can have multiple SGEs per Data Segemnt */ | ||
| 4867 | sges_per_segment = 1; | ||
| 4868 | if (phba->cfg_enable_bg) | ||
| 4869 | sges_per_segment = 2; | ||
| 4870 | |||
| 4871 | /* | 4942 | /* |
| 4872 | * For SLI4, instead of using ring 0 (LPFC_FCP_RING) for FCP commands | 4943 | * For SLI4, instead of using ring 0 (LPFC_FCP_RING) for FCP commands |
| 4873 | * we will associate a new ring, for each FCP fastpath EQ/CQ/WQ tuple. | 4944 | * we will associate a new ring, for each FCP fastpath EQ/CQ/WQ tuple. |
| @@ -4878,43 +4949,71 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 4878 | sizeof(struct lpfc_sli_ring), GFP_KERNEL); | 4949 | sizeof(struct lpfc_sli_ring), GFP_KERNEL); |
| 4879 | if (!phba->sli.ring) | 4950 | if (!phba->sli.ring) |
| 4880 | return -ENOMEM; | 4951 | return -ENOMEM; |
| 4952 | |||
| 4881 | /* | 4953 | /* |
| 4882 | * Since the sg_tablesize is module parameter, the sg_dma_buf_size | 4954 | * It doesn't matter what family our adapter is in, we are |
| 4955 | * limited to 2 Pages, 512 SGEs, for our SGL. | ||
| 4956 | * There are going to be 2 reserved SGEs: 1 FCP cmnd + 1 FCP rsp | ||
| 4957 | */ | ||
| 4958 | max_buf_size = (2 * SLI4_PAGE_SIZE); | ||
| 4959 | if (phba->cfg_sg_seg_cnt > LPFC_MAX_SGL_SEG_CNT - 2) | ||
| 4960 | phba->cfg_sg_seg_cnt = LPFC_MAX_SGL_SEG_CNT - 2; | ||
| 4961 | |||
| 4962 | /* | ||
| 4963 | * Since lpfc_sg_seg_cnt is module parameter, the sg_dma_buf_size | ||
| 4883 | * used to create the sg_dma_buf_pool must be dynamically calculated. | 4964 | * used to create the sg_dma_buf_pool must be dynamically calculated. |
| 4884 | * 2 segments are added since the IOCB needs a command and response bde. | ||
| 4885 | * To insure that the scsi sgl does not cross a 4k page boundary only | ||
| 4886 | * sgl sizes of must be a power of 2. | ||
| 4887 | */ | 4965 | */ |
| 4888 | buf_size = (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp) + | 4966 | |
| 4889 | (((phba->cfg_sg_seg_cnt * sges_per_segment) + 2) * | 4967 | if (phba->cfg_enable_bg) { |
| 4890 | sizeof(struct sli4_sge))); | 4968 | /* |
| 4891 | 4969 | * The scsi_buf for a T10-DIF I/O will hold the FCP cmnd, | |
| 4892 | sli_family = bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf); | 4970 | * the FCP rsp, and a SGE for each. Sice we have no control |
| 4893 | max_buf_size = LPFC_SLI4_MAX_BUF_SIZE; | 4971 | * over how many protection data segments the SCSI Layer |
| 4894 | switch (sli_family) { | 4972 | * will hand us (ie: there could be one for every block |
| 4895 | case LPFC_SLI_INTF_FAMILY_BE2: | 4973 | * in the IO), we just allocate enough SGEs to accomidate |
| 4896 | case LPFC_SLI_INTF_FAMILY_BE3: | 4974 | * our max amount and we need to limit lpfc_sg_seg_cnt to |
| 4897 | /* There is a single hint for BE - 2 pages per BPL. */ | 4975 | * minimize the risk of running out. |
| 4898 | if (bf_get(lpfc_sli_intf_sli_hint1, &phba->sli4_hba.sli_intf) == | 4976 | */ |
| 4899 | LPFC_SLI_INTF_SLI_HINT1_1) | 4977 | phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + |
| 4900 | max_buf_size = LPFC_SLI4_FL1_MAX_BUF_SIZE; | 4978 | sizeof(struct fcp_rsp) + max_buf_size; |
| 4901 | break; | 4979 | |
| 4902 | case LPFC_SLI_INTF_FAMILY_LNCR_A0: | 4980 | /* Total SGEs for scsi_sg_list and scsi_sg_prot_list */ |
| 4903 | case LPFC_SLI_INTF_FAMILY_LNCR_B0: | 4981 | phba->cfg_total_seg_cnt = LPFC_MAX_SGL_SEG_CNT; |
| 4904 | default: | 4982 | |
| 4905 | break; | 4983 | if (phba->cfg_sg_seg_cnt > LPFC_MAX_SG_SLI4_SEG_CNT_DIF) |
| 4984 | phba->cfg_sg_seg_cnt = LPFC_MAX_SG_SLI4_SEG_CNT_DIF; | ||
| 4985 | } else { | ||
| 4986 | /* | ||
| 4987 | * The scsi_buf for a regular I/O will hold the FCP cmnd, | ||
| 4988 | * the FCP rsp, a SGE for each, and a SGE for up to | ||
| 4989 | * cfg_sg_seg_cnt data segments. | ||
| 4990 | */ | ||
| 4991 | phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) + | ||
| 4992 | sizeof(struct fcp_rsp) + | ||
| 4993 | ((phba->cfg_sg_seg_cnt + 2) * sizeof(struct sli4_sge)); | ||
| 4994 | |||
| 4995 | /* Total SGEs for scsi_sg_list */ | ||
| 4996 | phba->cfg_total_seg_cnt = phba->cfg_sg_seg_cnt + 2; | ||
| 4997 | /* | ||
| 4998 | * NOTE: if (phba->cfg_sg_seg_cnt + 2) <= 256 we only need | ||
| 4999 | * to post 1 page for the SGL. | ||
| 5000 | */ | ||
| 4906 | } | 5001 | } |
| 4907 | 5002 | ||
| 4908 | for (dma_buf_size = LPFC_SLI4_MIN_BUF_SIZE; | 5003 | /* Initialize the host templates with the updated values. */ |
| 4909 | dma_buf_size < max_buf_size && buf_size > dma_buf_size; | 5004 | lpfc_vport_template.sg_tablesize = phba->cfg_sg_seg_cnt; |
| 4910 | dma_buf_size = dma_buf_size << 1) | 5005 | lpfc_template.sg_tablesize = phba->cfg_sg_seg_cnt; |
| 4911 | ; | 5006 | |
| 4912 | if (dma_buf_size == max_buf_size) | 5007 | if (phba->cfg_sg_dma_buf_size <= LPFC_MIN_SG_SLI4_BUF_SZ) |
| 4913 | phba->cfg_sg_seg_cnt = (dma_buf_size - | 5008 | phba->cfg_sg_dma_buf_size = LPFC_MIN_SG_SLI4_BUF_SZ; |
| 4914 | sizeof(struct fcp_cmnd) - sizeof(struct fcp_rsp) - | 5009 | else |
| 4915 | (2 * sizeof(struct sli4_sge))) / | 5010 | phba->cfg_sg_dma_buf_size = |
| 4916 | sizeof(struct sli4_sge); | 5011 | SLI4_PAGE_ALIGN(phba->cfg_sg_dma_buf_size); |
| 4917 | phba->cfg_sg_dma_buf_size = dma_buf_size; | 5012 | |
| 5013 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_FCP, | ||
| 5014 | "9087 sg_tablesize:%d dmabuf_size:%d total_sge:%d\n", | ||
| 5015 | phba->cfg_sg_seg_cnt, phba->cfg_sg_dma_buf_size, | ||
| 5016 | phba->cfg_total_seg_cnt); | ||
| 4918 | 5017 | ||
| 4919 | /* Initialize buffer queue management fields */ | 5018 | /* Initialize buffer queue management fields */ |
| 4920 | hbq_count = lpfc_sli_hbq_count(); | 5019 | hbq_count = lpfc_sli_hbq_count(); |
| @@ -5104,6 +5203,26 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 5104 | goto out_free_fcp_eq_hdl; | 5203 | goto out_free_fcp_eq_hdl; |
| 5105 | } | 5204 | } |
| 5106 | 5205 | ||
| 5206 | phba->sli4_hba.cpu_map = kzalloc((sizeof(struct lpfc_vector_map_info) * | ||
| 5207 | phba->sli4_hba.num_present_cpu), | ||
| 5208 | GFP_KERNEL); | ||
| 5209 | if (!phba->sli4_hba.cpu_map) { | ||
| 5210 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 5211 | "3327 Failed allocate memory for msi-x " | ||
| 5212 | "interrupt vector mapping\n"); | ||
| 5213 | rc = -ENOMEM; | ||
| 5214 | goto out_free_msix; | ||
| 5215 | } | ||
| 5216 | /* Initialize io channels for round robin */ | ||
| 5217 | cpup = phba->sli4_hba.cpu_map; | ||
| 5218 | rc = 0; | ||
| 5219 | for (i = 0; i < phba->sli4_hba.num_present_cpu; i++) { | ||
| 5220 | cpup->channel_id = rc; | ||
| 5221 | rc++; | ||
| 5222 | if (rc >= phba->cfg_fcp_io_channel) | ||
| 5223 | rc = 0; | ||
| 5224 | } | ||
| 5225 | |||
| 5107 | /* | 5226 | /* |
| 5108 | * Enable sr-iov virtual functions if supported and configured | 5227 | * Enable sr-iov virtual functions if supported and configured |
| 5109 | * through the module parameter. | 5228 | * through the module parameter. |
| @@ -5123,6 +5242,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
| 5123 | 5242 | ||
| 5124 | return 0; | 5243 | return 0; |
| 5125 | 5244 | ||
| 5245 | out_free_msix: | ||
| 5246 | kfree(phba->sli4_hba.msix_entries); | ||
| 5126 | out_free_fcp_eq_hdl: | 5247 | out_free_fcp_eq_hdl: |
| 5127 | kfree(phba->sli4_hba.fcp_eq_hdl); | 5248 | kfree(phba->sli4_hba.fcp_eq_hdl); |
| 5128 | out_free_fcf_rr_bmask: | 5249 | out_free_fcf_rr_bmask: |
| @@ -5152,6 +5273,11 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba) | |||
| 5152 | { | 5273 | { |
| 5153 | struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry; | 5274 | struct lpfc_fcf_conn_entry *conn_entry, *next_conn_entry; |
| 5154 | 5275 | ||
| 5276 | /* Free memory allocated for msi-x interrupt vector to CPU mapping */ | ||
| 5277 | kfree(phba->sli4_hba.cpu_map); | ||
| 5278 | phba->sli4_hba.num_present_cpu = 0; | ||
| 5279 | phba->sli4_hba.num_online_cpu = 0; | ||
| 5280 | |||
| 5155 | /* Free memory allocated for msi-x interrupt vector entries */ | 5281 | /* Free memory allocated for msi-x interrupt vector entries */ |
| 5156 | kfree(phba->sli4_hba.msix_entries); | 5282 | kfree(phba->sli4_hba.msix_entries); |
| 5157 | 5283 | ||
| @@ -5260,8 +5386,10 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba) | |||
| 5260 | init_waitqueue_head(&phba->work_waitq); | 5386 | init_waitqueue_head(&phba->work_waitq); |
| 5261 | 5387 | ||
| 5262 | /* Initialize the scsi buffer list used by driver for scsi IO */ | 5388 | /* Initialize the scsi buffer list used by driver for scsi IO */ |
| 5263 | spin_lock_init(&phba->scsi_buf_list_lock); | 5389 | spin_lock_init(&phba->scsi_buf_list_get_lock); |
| 5264 | INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list); | 5390 | INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_get); |
| 5391 | spin_lock_init(&phba->scsi_buf_list_put_lock); | ||
| 5392 | INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put); | ||
| 5265 | 5393 | ||
| 5266 | /* Initialize the fabric iocb list */ | 5394 | /* Initialize the fabric iocb list */ |
| 5267 | INIT_LIST_HEAD(&phba->fabric_iocb_list); | 5395 | INIT_LIST_HEAD(&phba->fabric_iocb_list); |
| @@ -6696,6 +6824,7 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba) | |||
| 6696 | int cfg_fcp_io_channel; | 6824 | int cfg_fcp_io_channel; |
| 6697 | uint32_t cpu; | 6825 | uint32_t cpu; |
| 6698 | uint32_t i = 0; | 6826 | uint32_t i = 0; |
| 6827 | uint32_t j = 0; | ||
| 6699 | 6828 | ||
| 6700 | 6829 | ||
| 6701 | /* | 6830 | /* |
| @@ -6706,15 +6835,21 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba) | |||
| 6706 | /* Sanity check on HBA EQ parameters */ | 6835 | /* Sanity check on HBA EQ parameters */ |
| 6707 | cfg_fcp_io_channel = phba->cfg_fcp_io_channel; | 6836 | cfg_fcp_io_channel = phba->cfg_fcp_io_channel; |
| 6708 | 6837 | ||
| 6709 | /* It doesn't make sense to have more io channels then CPUs */ | 6838 | /* It doesn't make sense to have more io channels then online CPUs */ |
| 6710 | for_each_online_cpu(cpu) { | 6839 | for_each_present_cpu(cpu) { |
| 6711 | i++; | 6840 | if (cpu_online(cpu)) |
| 6841 | i++; | ||
| 6842 | j++; | ||
| 6712 | } | 6843 | } |
| 6844 | phba->sli4_hba.num_online_cpu = i; | ||
| 6845 | phba->sli4_hba.num_present_cpu = j; | ||
| 6846 | |||
| 6713 | if (i < cfg_fcp_io_channel) { | 6847 | if (i < cfg_fcp_io_channel) { |
| 6714 | lpfc_printf_log(phba, | 6848 | lpfc_printf_log(phba, |
| 6715 | KERN_ERR, LOG_INIT, | 6849 | KERN_ERR, LOG_INIT, |
| 6716 | "3188 Reducing IO channels to match number of " | 6850 | "3188 Reducing IO channels to match number of " |
| 6717 | "CPUs: from %d to %d\n", cfg_fcp_io_channel, i); | 6851 | "online CPUs: from %d to %d\n", |
| 6852 | cfg_fcp_io_channel, i); | ||
| 6718 | cfg_fcp_io_channel = i; | 6853 | cfg_fcp_io_channel = i; |
| 6719 | } | 6854 | } |
| 6720 | 6855 | ||
| @@ -7743,8 +7878,13 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) | |||
| 7743 | 7878 | ||
| 7744 | out: | 7879 | out: |
| 7745 | /* Catch the not-ready port failure after a port reset. */ | 7880 | /* Catch the not-ready port failure after a port reset. */ |
| 7746 | if (num_resets >= MAX_IF_TYPE_2_RESETS) | 7881 | if (num_resets >= MAX_IF_TYPE_2_RESETS) { |
| 7882 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 7883 | "3317 HBA not functional: IP Reset Failed " | ||
| 7884 | "after (%d) retries, try: " | ||
| 7885 | "echo fw_reset > board_mode\n", num_resets); | ||
| 7747 | rc = -ENODEV; | 7886 | rc = -ENODEV; |
| 7887 | } | ||
| 7748 | 7888 | ||
| 7749 | return rc; | 7889 | return rc; |
| 7750 | } | 7890 | } |
| @@ -8209,6 +8349,269 @@ lpfc_sli_disable_intr(struct lpfc_hba *phba) | |||
| 8209 | } | 8349 | } |
| 8210 | 8350 | ||
| 8211 | /** | 8351 | /** |
| 8352 | * lpfc_find_next_cpu - Find next available CPU that matches the phys_id | ||
| 8353 | * @phba: pointer to lpfc hba data structure. | ||
| 8354 | * | ||
| 8355 | * Find next available CPU to use for IRQ to CPU affinity. | ||
| 8356 | */ | ||
| 8357 | static int | ||
| 8358 | lpfc_find_next_cpu(struct lpfc_hba *phba, uint32_t phys_id) | ||
| 8359 | { | ||
| 8360 | struct lpfc_vector_map_info *cpup; | ||
| 8361 | int cpu; | ||
| 8362 | |||
| 8363 | cpup = phba->sli4_hba.cpu_map; | ||
| 8364 | for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) { | ||
| 8365 | /* CPU must be online */ | ||
| 8366 | if (cpu_online(cpu)) { | ||
| 8367 | if ((cpup->irq == LPFC_VECTOR_MAP_EMPTY) && | ||
| 8368 | (lpfc_used_cpu[cpu] == LPFC_VECTOR_MAP_EMPTY) && | ||
| 8369 | (cpup->phys_id == phys_id)) { | ||
| 8370 | return cpu; | ||
| 8371 | } | ||
| 8372 | } | ||
| 8373 | cpup++; | ||
| 8374 | } | ||
| 8375 | |||
| 8376 | /* | ||
| 8377 | * If we get here, we have used ALL CPUs for the specific | ||
| 8378 | * phys_id. Now we need to clear out lpfc_used_cpu and start | ||
| 8379 | * reusing CPUs. | ||
| 8380 | */ | ||
| 8381 | |||
| 8382 | for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) { | ||
| 8383 | if (lpfc_used_cpu[cpu] == phys_id) | ||
| 8384 | lpfc_used_cpu[cpu] = LPFC_VECTOR_MAP_EMPTY; | ||
| 8385 | } | ||
| 8386 | |||
| 8387 | cpup = phba->sli4_hba.cpu_map; | ||
| 8388 | for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) { | ||
| 8389 | /* CPU must be online */ | ||
| 8390 | if (cpu_online(cpu)) { | ||
| 8391 | if ((cpup->irq == LPFC_VECTOR_MAP_EMPTY) && | ||
| 8392 | (cpup->phys_id == phys_id)) { | ||
| 8393 | return cpu; | ||
| 8394 | } | ||
| 8395 | } | ||
| 8396 | cpup++; | ||
| 8397 | } | ||
| 8398 | return LPFC_VECTOR_MAP_EMPTY; | ||
| 8399 | } | ||
| 8400 | |||
| 8401 | /** | ||
| 8402 | * lpfc_sli4_set_affinity - Set affinity for HBA IRQ vectors | ||
| 8403 | * @phba: pointer to lpfc hba data structure. | ||
| 8404 | * @vectors: number of HBA vectors | ||
| 8405 | * | ||
| 8406 | * Affinitize MSIX IRQ vectors to CPUs. Try to equally spread vector | ||
| 8407 | * affinization across multple physical CPUs (numa nodes). | ||
| 8408 | * In addition, this routine will assign an IO channel for each CPU | ||
| 8409 | * to use when issuing I/Os. | ||
| 8410 | */ | ||
| 8411 | static int | ||
| 8412 | lpfc_sli4_set_affinity(struct lpfc_hba *phba, int vectors) | ||
| 8413 | { | ||
| 8414 | int i, idx, saved_chann, used_chann, cpu, phys_id; | ||
| 8415 | int max_phys_id, num_io_channel, first_cpu; | ||
| 8416 | struct lpfc_vector_map_info *cpup; | ||
| 8417 | #ifdef CONFIG_X86 | ||
| 8418 | struct cpuinfo_x86 *cpuinfo; | ||
| 8419 | #endif | ||
| 8420 | struct cpumask *mask; | ||
| 8421 | uint8_t chann[LPFC_FCP_IO_CHAN_MAX+1]; | ||
| 8422 | |||
| 8423 | /* If there is no mapping, just return */ | ||
| 8424 | if (!phba->cfg_fcp_cpu_map) | ||
| 8425 | return 1; | ||
| 8426 | |||
| 8427 | /* Init cpu_map array */ | ||
| 8428 | memset(phba->sli4_hba.cpu_map, 0xff, | ||
| 8429 | (sizeof(struct lpfc_vector_map_info) * | ||
| 8430 | phba->sli4_hba.num_present_cpu)); | ||
| 8431 | |||
| 8432 | max_phys_id = 0; | ||
| 8433 | phys_id = 0; | ||
| 8434 | num_io_channel = 0; | ||
| 8435 | first_cpu = LPFC_VECTOR_MAP_EMPTY; | ||
| 8436 | |||
| 8437 | /* Update CPU map with physical id and core id of each CPU */ | ||
| 8438 | cpup = phba->sli4_hba.cpu_map; | ||
| 8439 | for (cpu = 0; cpu < phba->sli4_hba.num_present_cpu; cpu++) { | ||
| 8440 | #ifdef CONFIG_X86 | ||
| 8441 | cpuinfo = &cpu_data(cpu); | ||
| 8442 | cpup->phys_id = cpuinfo->phys_proc_id; | ||
| 8443 | cpup->core_id = cpuinfo->cpu_core_id; | ||
| 8444 | #else | ||
| 8445 | /* No distinction between CPUs for other platforms */ | ||
| 8446 | cpup->phys_id = 0; | ||
| 8447 | cpup->core_id = 0; | ||
| 8448 | #endif | ||
| 8449 | |||
| 8450 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
| 8451 | "3328 CPU physid %d coreid %d\n", | ||
| 8452 | cpup->phys_id, cpup->core_id); | ||
| 8453 | |||
| 8454 | if (cpup->phys_id > max_phys_id) | ||
| 8455 | max_phys_id = cpup->phys_id; | ||
| 8456 | cpup++; | ||
| 8457 | } | ||
| 8458 | |||
| 8459 | /* Now associate the HBA vectors with specific CPUs */ | ||
| 8460 | for (idx = 0; idx < vectors; idx++) { | ||
| 8461 | cpup = phba->sli4_hba.cpu_map; | ||
| 8462 | cpu = lpfc_find_next_cpu(phba, phys_id); | ||
| 8463 | if (cpu == LPFC_VECTOR_MAP_EMPTY) { | ||
| 8464 | |||
| 8465 | /* Try for all phys_id's */ | ||
| 8466 | for (i = 1; i < max_phys_id; i++) { | ||
| 8467 | phys_id++; | ||
| 8468 | if (phys_id > max_phys_id) | ||
| 8469 | phys_id = 0; | ||
| 8470 | cpu = lpfc_find_next_cpu(phba, phys_id); | ||
| 8471 | if (cpu == LPFC_VECTOR_MAP_EMPTY) | ||
| 8472 | continue; | ||
| 8473 | goto found; | ||
| 8474 | } | ||
| 8475 | |||
| 8476 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 8477 | "3329 Cannot set affinity:" | ||
| 8478 | "Error mapping vector %d (%d)\n", | ||
| 8479 | idx, vectors); | ||
| 8480 | return 0; | ||
| 8481 | } | ||
| 8482 | found: | ||
| 8483 | cpup += cpu; | ||
| 8484 | if (phba->cfg_fcp_cpu_map == LPFC_DRIVER_CPU_MAP) | ||
| 8485 | lpfc_used_cpu[cpu] = phys_id; | ||
| 8486 | |||
| 8487 | /* Associate vector with selected CPU */ | ||
| 8488 | cpup->irq = phba->sli4_hba.msix_entries[idx].vector; | ||
| 8489 | |||
| 8490 | /* Associate IO channel with selected CPU */ | ||
| 8491 | cpup->channel_id = idx; | ||
| 8492 | num_io_channel++; | ||
| 8493 | |||
| 8494 | if (first_cpu == LPFC_VECTOR_MAP_EMPTY) | ||
| 8495 | first_cpu = cpu; | ||
| 8496 | |||
| 8497 | /* Now affinitize to the selected CPU */ | ||
| 8498 | mask = &cpup->maskbits; | ||
| 8499 | cpumask_clear(mask); | ||
| 8500 | cpumask_set_cpu(cpu, mask); | ||
| 8501 | i = irq_set_affinity_hint(phba->sli4_hba.msix_entries[idx]. | ||
| 8502 | vector, mask); | ||
| 8503 | |||
| 8504 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
| 8505 | "3330 Set Affinity: CPU %d channel %d " | ||
| 8506 | "irq %d (%x)\n", | ||
| 8507 | cpu, cpup->channel_id, | ||
| 8508 | phba->sli4_hba.msix_entries[idx].vector, i); | ||
| 8509 | |||
| 8510 | /* Spread vector mapping across multple physical CPU nodes */ | ||
| 8511 | phys_id++; | ||
| 8512 | if (phys_id > max_phys_id) | ||
| 8513 | phys_id = 0; | ||
| 8514 | } | ||
| 8515 | |||
| 8516 | /* | ||
| 8517 | * Finally fill in the IO channel for any remaining CPUs. | ||
| 8518 | * At this point, all IO channels have been assigned to a specific | ||
| 8519 | * MSIx vector, mapped to a specific CPU. | ||
| 8520 | * Base the remaining IO channel assigned, to IO channels already | ||
| 8521 | * assigned to other CPUs on the same phys_id. | ||
| 8522 | */ | ||
| 8523 | for (i = 0; i <= max_phys_id; i++) { | ||
| 8524 | /* | ||
| 8525 | * If there are no io channels already mapped to | ||
| 8526 | * this phys_id, just round robin thru the io_channels. | ||
| 8527 | * Setup chann[] for round robin. | ||
| 8528 | */ | ||
| 8529 | for (idx = 0; idx < phba->cfg_fcp_io_channel; idx++) | ||
| 8530 | chann[idx] = idx; | ||
| 8531 | |||
| 8532 | saved_chann = 0; | ||
| 8533 | used_chann = 0; | ||
| 8534 | |||
| 8535 | /* | ||
| 8536 | * First build a list of IO channels already assigned | ||
| 8537 | * to this phys_id before reassigning the same IO | ||
| 8538 | * channels to the remaining CPUs. | ||
| 8539 | */ | ||
| 8540 | cpup = phba->sli4_hba.cpu_map; | ||
| 8541 | cpu = first_cpu; | ||
| 8542 | cpup += cpu; | ||
| 8543 | for (idx = 0; idx < phba->sli4_hba.num_present_cpu; | ||
| 8544 | idx++) { | ||
| 8545 | if (cpup->phys_id == i) { | ||
| 8546 | /* | ||
| 8547 | * Save any IO channels that are | ||
| 8548 | * already mapped to this phys_id. | ||
| 8549 | */ | ||
| 8550 | if (cpup->irq != LPFC_VECTOR_MAP_EMPTY) { | ||
| 8551 | chann[saved_chann] = | ||
| 8552 | cpup->channel_id; | ||
| 8553 | saved_chann++; | ||
| 8554 | goto out; | ||
| 8555 | } | ||
| 8556 | |||
| 8557 | /* See if we are using round-robin */ | ||
| 8558 | if (saved_chann == 0) | ||
| 8559 | saved_chann = | ||
| 8560 | phba->cfg_fcp_io_channel; | ||
| 8561 | |||
| 8562 | /* Associate next IO channel with CPU */ | ||
| 8563 | cpup->channel_id = chann[used_chann]; | ||
| 8564 | num_io_channel++; | ||
| 8565 | used_chann++; | ||
| 8566 | if (used_chann == saved_chann) | ||
| 8567 | used_chann = 0; | ||
| 8568 | |||
| 8569 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
| 8570 | "3331 Set IO_CHANN " | ||
| 8571 | "CPU %d channel %d\n", | ||
| 8572 | idx, cpup->channel_id); | ||
| 8573 | } | ||
| 8574 | out: | ||
| 8575 | cpu++; | ||
| 8576 | if (cpu >= phba->sli4_hba.num_present_cpu) { | ||
| 8577 | cpup = phba->sli4_hba.cpu_map; | ||
| 8578 | cpu = 0; | ||
| 8579 | } else { | ||
| 8580 | cpup++; | ||
| 8581 | } | ||
| 8582 | } | ||
| 8583 | } | ||
| 8584 | |||
| 8585 | if (phba->sli4_hba.num_online_cpu != phba->sli4_hba.num_present_cpu) { | ||
| 8586 | cpup = phba->sli4_hba.cpu_map; | ||
| 8587 | for (idx = 0; idx < phba->sli4_hba.num_present_cpu; idx++) { | ||
| 8588 | if (cpup->channel_id == LPFC_VECTOR_MAP_EMPTY) { | ||
| 8589 | cpup->channel_id = 0; | ||
| 8590 | num_io_channel++; | ||
| 8591 | |||
| 8592 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
| 8593 | "3332 Assign IO_CHANN " | ||
| 8594 | "CPU %d channel %d\n", | ||
| 8595 | idx, cpup->channel_id); | ||
| 8596 | } | ||
| 8597 | cpup++; | ||
| 8598 | } | ||
| 8599 | } | ||
| 8600 | |||
| 8601 | /* Sanity check */ | ||
| 8602 | if (num_io_channel != phba->sli4_hba.num_present_cpu) | ||
| 8603 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
| 8604 | "3333 Set affinity mismatch:" | ||
| 8605 | "%d chann != %d cpus: %d vactors\n", | ||
| 8606 | num_io_channel, phba->sli4_hba.num_present_cpu, | ||
| 8607 | vectors); | ||
| 8608 | |||
| 8609 | phba->cfg_fcp_io_sched = LPFC_FCP_SCHED_BY_CPU; | ||
| 8610 | return 1; | ||
| 8611 | } | ||
| 8612 | |||
| 8613 | |||
| 8614 | /** | ||
| 8212 | * lpfc_sli4_enable_msix - Enable MSI-X interrupt mode to SLI-4 device | 8615 | * lpfc_sli4_enable_msix - Enable MSI-X interrupt mode to SLI-4 device |
| 8213 | * @phba: pointer to lpfc hba data structure. | 8616 | * @phba: pointer to lpfc hba data structure. |
| 8214 | * | 8617 | * |
| @@ -8259,9 +8662,7 @@ enable_msix_vectors: | |||
| 8259 | phba->sli4_hba.msix_entries[index].vector, | 8662 | phba->sli4_hba.msix_entries[index].vector, |
| 8260 | phba->sli4_hba.msix_entries[index].entry); | 8663 | phba->sli4_hba.msix_entries[index].entry); |
| 8261 | 8664 | ||
| 8262 | /* | 8665 | /* Assign MSI-X vectors to interrupt handlers */ |
| 8263 | * Assign MSI-X vectors to interrupt handlers | ||
| 8264 | */ | ||
| 8265 | for (index = 0; index < vectors; index++) { | 8666 | for (index = 0; index < vectors; index++) { |
| 8266 | memset(&phba->sli4_hba.handler_name[index], 0, 16); | 8667 | memset(&phba->sli4_hba.handler_name[index], 0, 16); |
| 8267 | sprintf((char *)&phba->sli4_hba.handler_name[index], | 8668 | sprintf((char *)&phba->sli4_hba.handler_name[index], |
| @@ -8289,6 +8690,8 @@ enable_msix_vectors: | |||
| 8289 | phba->cfg_fcp_io_channel, vectors); | 8690 | phba->cfg_fcp_io_channel, vectors); |
| 8290 | phba->cfg_fcp_io_channel = vectors; | 8691 | phba->cfg_fcp_io_channel = vectors; |
| 8291 | } | 8692 | } |
| 8693 | |||
| 8694 | lpfc_sli4_set_affinity(phba, vectors); | ||
| 8292 | return rc; | 8695 | return rc; |
| 8293 | 8696 | ||
| 8294 | cfg_fail_out: | 8697 | cfg_fail_out: |
| @@ -9213,15 +9616,15 @@ lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba) | |||
| 9213 | /* Block all SCSI devices' I/Os on the host */ | 9616 | /* Block all SCSI devices' I/Os on the host */ |
| 9214 | lpfc_scsi_dev_block(phba); | 9617 | lpfc_scsi_dev_block(phba); |
| 9215 | 9618 | ||
| 9619 | /* Flush all driver's outstanding SCSI I/Os as we are to reset */ | ||
| 9620 | lpfc_sli_flush_fcp_rings(phba); | ||
| 9621 | |||
| 9216 | /* stop all timers */ | 9622 | /* stop all timers */ |
| 9217 | lpfc_stop_hba_timers(phba); | 9623 | lpfc_stop_hba_timers(phba); |
| 9218 | 9624 | ||
| 9219 | /* Disable interrupt and pci device */ | 9625 | /* Disable interrupt and pci device */ |
| 9220 | lpfc_sli_disable_intr(phba); | 9626 | lpfc_sli_disable_intr(phba); |
| 9221 | pci_disable_device(phba->pcidev); | 9627 | pci_disable_device(phba->pcidev); |
| 9222 | |||
| 9223 | /* Flush all driver's outstanding SCSI I/Os as we are to reset */ | ||
| 9224 | lpfc_sli_flush_fcp_rings(phba); | ||
| 9225 | } | 9628 | } |
| 9226 | 9629 | ||
| 9227 | /** | 9630 | /** |
| @@ -9966,6 +10369,9 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba) | |||
| 9966 | /* Block all SCSI devices' I/Os on the host */ | 10369 | /* Block all SCSI devices' I/Os on the host */ |
| 9967 | lpfc_scsi_dev_block(phba); | 10370 | lpfc_scsi_dev_block(phba); |
| 9968 | 10371 | ||
| 10372 | /* Flush all driver's outstanding SCSI I/Os as we are to reset */ | ||
| 10373 | lpfc_sli_flush_fcp_rings(phba); | ||
| 10374 | |||
| 9969 | /* stop all timers */ | 10375 | /* stop all timers */ |
| 9970 | lpfc_stop_hba_timers(phba); | 10376 | lpfc_stop_hba_timers(phba); |
| 9971 | 10377 | ||
| @@ -9973,9 +10379,6 @@ lpfc_sli4_prep_dev_for_reset(struct lpfc_hba *phba) | |||
| 9973 | lpfc_sli4_disable_intr(phba); | 10379 | lpfc_sli4_disable_intr(phba); |
| 9974 | lpfc_sli4_queue_destroy(phba); | 10380 | lpfc_sli4_queue_destroy(phba); |
| 9975 | pci_disable_device(phba->pcidev); | 10381 | pci_disable_device(phba->pcidev); |
| 9976 | |||
| 9977 | /* Flush all driver's outstanding SCSI I/Os as we are to reset */ | ||
| 9978 | lpfc_sli_flush_fcp_rings(phba); | ||
| 9979 | } | 10382 | } |
| 9980 | 10383 | ||
| 9981 | /** | 10384 | /** |
| @@ -10535,6 +10938,7 @@ static struct miscdevice lpfc_mgmt_dev = { | |||
| 10535 | static int __init | 10938 | static int __init |
| 10536 | lpfc_init(void) | 10939 | lpfc_init(void) |
| 10537 | { | 10940 | { |
| 10941 | int cpu; | ||
| 10538 | int error = 0; | 10942 | int error = 0; |
| 10539 | 10943 | ||
| 10540 | printk(LPFC_MODULE_DESC "\n"); | 10944 | printk(LPFC_MODULE_DESC "\n"); |
| @@ -10561,6 +10965,11 @@ lpfc_init(void) | |||
| 10561 | return -ENOMEM; | 10965 | return -ENOMEM; |
| 10562 | } | 10966 | } |
| 10563 | } | 10967 | } |
| 10968 | |||
| 10969 | /* Initialize in case vector mapping is needed */ | ||
| 10970 | for (cpu = 0; cpu < LPFC_MAX_CPU; cpu++) | ||
| 10971 | lpfc_used_cpu[cpu] = LPFC_VECTOR_MAP_EMPTY; | ||
| 10972 | |||
| 10564 | error = pci_register_driver(&lpfc_driver); | 10973 | error = pci_register_driver(&lpfc_driver); |
| 10565 | if (error) { | 10974 | if (error) { |
| 10566 | fc_release_transport(lpfc_transport_template); | 10975 | fc_release_transport(lpfc_transport_template); |
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index baf53e6c2bd1..2a4e5d21eab2 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */ | 37 | #define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */ |
| 38 | #define LOG_FIP 0x00020000 /* FIP events */ | 38 | #define LOG_FIP 0x00020000 /* FIP events */ |
| 39 | #define LOG_FCP_UNDER 0x00040000 /* FCP underruns errors */ | 39 | #define LOG_FCP_UNDER 0x00040000 /* FCP underruns errors */ |
| 40 | #define LOG_SCSI_CMD 0x00080000 /* ALL SCSI commands */ | ||
| 40 | #define LOG_ALL_MSG 0xffffffff /* LOG all messages */ | 41 | #define LOG_ALL_MSG 0xffffffff /* LOG all messages */ |
| 41 | 42 | ||
| 42 | #define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \ | 43 | #define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \ |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index a7a9fa468308..41363db7d426 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
| @@ -2149,18 +2149,21 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys) | |||
| 2149 | 2149 | ||
| 2150 | /* Only FC supports upd bit */ | 2150 | /* Only FC supports upd bit */ |
| 2151 | if ((phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) && | 2151 | if ((phba->sli4_hba.lnk_info.lnk_tp == LPFC_LNK_TYPE_FC) && |
| 2152 | (vport->fc_flag & FC_VFI_REGISTERED)) { | 2152 | (vport->fc_flag & FC_VFI_REGISTERED) && |
| 2153 | (!phba->fc_topology_changed)) { | ||
| 2153 | bf_set(lpfc_reg_vfi_vp, reg_vfi, 0); | 2154 | bf_set(lpfc_reg_vfi_vp, reg_vfi, 0); |
| 2154 | bf_set(lpfc_reg_vfi_upd, reg_vfi, 1); | 2155 | bf_set(lpfc_reg_vfi_upd, reg_vfi, 1); |
| 2155 | } | 2156 | } |
| 2156 | lpfc_printf_vlog(vport, KERN_INFO, LOG_MBOX, | 2157 | lpfc_printf_vlog(vport, KERN_INFO, LOG_MBOX, |
| 2157 | "3134 Register VFI, mydid:x%x, fcfi:%d, " | 2158 | "3134 Register VFI, mydid:x%x, fcfi:%d, " |
| 2158 | " vfi:%d, vpi:%d, fc_pname:%x%x\n", | 2159 | " vfi:%d, vpi:%d, fc_pname:%x%x fc_flag:x%x" |
| 2160 | " port_state:x%x topology chg:%d\n", | ||
| 2159 | vport->fc_myDID, | 2161 | vport->fc_myDID, |
| 2160 | phba->fcf.fcfi, | 2162 | phba->fcf.fcfi, |
| 2161 | phba->sli4_hba.vfi_ids[vport->vfi], | 2163 | phba->sli4_hba.vfi_ids[vport->vfi], |
| 2162 | phba->vpi_ids[vport->vpi], | 2164 | phba->vpi_ids[vport->vpi], |
| 2163 | reg_vfi->wwn[0], reg_vfi->wwn[1]); | 2165 | reg_vfi->wwn[0], reg_vfi->wwn[1], vport->fc_flag, |
| 2166 | vport->port_state, phba->fc_topology_changed); | ||
| 2164 | } | 2167 | } |
| 2165 | 2168 | ||
| 2166 | /** | 2169 | /** |
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index cd86069a0ba8..812d0cd7c86d 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c | |||
| @@ -64,18 +64,26 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align) | |||
| 64 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; | 64 | struct lpfc_dma_pool *pool = &phba->lpfc_mbuf_safety_pool; |
| 65 | int i; | 65 | int i; |
| 66 | 66 | ||
| 67 | if (phba->sli_rev == LPFC_SLI_REV4) | 67 | if (phba->sli_rev == LPFC_SLI_REV4) { |
| 68 | /* Calculate alignment */ | ||
| 69 | if (phba->cfg_sg_dma_buf_size < SLI4_PAGE_SIZE) | ||
| 70 | i = phba->cfg_sg_dma_buf_size; | ||
| 71 | else | ||
| 72 | i = SLI4_PAGE_SIZE; | ||
| 73 | |||
| 68 | phba->lpfc_scsi_dma_buf_pool = | 74 | phba->lpfc_scsi_dma_buf_pool = |
| 69 | pci_pool_create("lpfc_scsi_dma_buf_pool", | 75 | pci_pool_create("lpfc_scsi_dma_buf_pool", |
| 70 | phba->pcidev, | 76 | phba->pcidev, |
| 71 | phba->cfg_sg_dma_buf_size, | 77 | phba->cfg_sg_dma_buf_size, |
| 72 | phba->cfg_sg_dma_buf_size, | 78 | i, |
| 73 | 0); | 79 | 0); |
| 74 | else | 80 | } else { |
| 75 | phba->lpfc_scsi_dma_buf_pool = | 81 | phba->lpfc_scsi_dma_buf_pool = |
| 76 | pci_pool_create("lpfc_scsi_dma_buf_pool", | 82 | pci_pool_create("lpfc_scsi_dma_buf_pool", |
| 77 | phba->pcidev, phba->cfg_sg_dma_buf_size, | 83 | phba->pcidev, phba->cfg_sg_dma_buf_size, |
| 78 | align, 0); | 84 | align, 0); |
| 85 | } | ||
| 86 | |||
| 79 | if (!phba->lpfc_scsi_dma_buf_pool) | 87 | if (!phba->lpfc_scsi_dma_buf_pool) |
| 80 | goto fail; | 88 | goto fail; |
| 81 | 89 | ||
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 82f4d3542289..31e9b92f5a9b 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
| @@ -332,9 +332,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 332 | 332 | ||
| 333 | /* PLOGI chkparm OK */ | 333 | /* PLOGI chkparm OK */ |
| 334 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 334 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
| 335 | "0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n", | 335 | "0114 PLOGI chkparm OK Data: x%x x%x x%x " |
| 336 | "x%x x%x x%x\n", | ||
| 336 | ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag, | 337 | ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag, |
| 337 | ndlp->nlp_rpi); | 338 | ndlp->nlp_rpi, vport->port_state, |
| 339 | vport->fc_flag); | ||
| 338 | 340 | ||
| 339 | if (vport->cfg_fcp_class == 2 && sp->cls2.classValid) | 341 | if (vport->cfg_fcp_class == 2 && sp->cls2.classValid) |
| 340 | ndlp->nlp_fcp_info |= CLASS2; | 342 | ndlp->nlp_fcp_info |= CLASS2; |
| @@ -574,7 +576,7 @@ out: | |||
| 574 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); | 576 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
| 575 | 577 | ||
| 576 | /* 1 sec timeout */ | 578 | /* 1 sec timeout */ |
| 577 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 579 | mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000)); |
| 578 | 580 | ||
| 579 | spin_lock_irq(shost->host_lock); | 581 | spin_lock_irq(shost->host_lock); |
| 580 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 582 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
| @@ -631,7 +633,8 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 631 | * If there are other active VLinks present, | 633 | * If there are other active VLinks present, |
| 632 | * re-instantiate the Vlink using FDISC. | 634 | * re-instantiate the Vlink using FDISC. |
| 633 | */ | 635 | */ |
| 634 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 636 | mod_timer(&ndlp->nlp_delayfunc, |
| 637 | jiffies + msecs_to_jiffies(1000)); | ||
| 635 | spin_lock_irq(shost->host_lock); | 638 | spin_lock_irq(shost->host_lock); |
| 636 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 639 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
| 637 | spin_unlock_irq(shost->host_lock); | 640 | spin_unlock_irq(shost->host_lock); |
| @@ -648,7 +651,8 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 648 | !(ndlp->nlp_type & NLP_FCP_INITIATOR))) || | 651 | !(ndlp->nlp_type & NLP_FCP_INITIATOR))) || |
| 649 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { | 652 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { |
| 650 | /* Only try to re-login if this is NOT a Fabric Node */ | 653 | /* Only try to re-login if this is NOT a Fabric Node */ |
| 651 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 654 | mod_timer(&ndlp->nlp_delayfunc, |
| 655 | jiffies + msecs_to_jiffies(1000 * 1)); | ||
| 652 | spin_lock_irq(shost->host_lock); | 656 | spin_lock_irq(shost->host_lock); |
| 653 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 657 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
| 654 | spin_unlock_irq(shost->host_lock); | 658 | spin_unlock_irq(shost->host_lock); |
| @@ -969,7 +973,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 969 | } | 973 | } |
| 970 | 974 | ||
| 971 | /* Put ndlp in npr state set plogi timer for 1 sec */ | 975 | /* Put ndlp in npr state set plogi timer for 1 sec */ |
| 972 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 976 | mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000 * 1)); |
| 973 | spin_lock_irq(shost->host_lock); | 977 | spin_lock_irq(shost->host_lock); |
| 974 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 978 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
| 975 | spin_unlock_irq(shost->host_lock); | 979 | spin_unlock_irq(shost->host_lock); |
| @@ -1303,7 +1307,8 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport, | |||
| 1303 | if ((irsp->ulpStatus) || | 1307 | if ((irsp->ulpStatus) || |
| 1304 | (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) { | 1308 | (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) { |
| 1305 | /* 1 sec timeout */ | 1309 | /* 1 sec timeout */ |
| 1306 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); | 1310 | mod_timer(&ndlp->nlp_delayfunc, |
| 1311 | jiffies + msecs_to_jiffies(1000)); | ||
| 1307 | spin_lock_irq(shost->host_lock); | 1312 | spin_lock_irq(shost->host_lock); |
| 1308 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 1313 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
| 1309 | spin_unlock_irq(shost->host_lock); | 1314 | spin_unlock_irq(shost->host_lock); |
| @@ -1509,7 +1514,8 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport, | |||
| 1509 | } | 1514 | } |
| 1510 | 1515 | ||
| 1511 | /* Put ndlp in npr state set plogi timer for 1 sec */ | 1516 | /* Put ndlp in npr state set plogi timer for 1 sec */ |
| 1512 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 1517 | mod_timer(&ndlp->nlp_delayfunc, |
| 1518 | jiffies + msecs_to_jiffies(1000 * 1)); | ||
| 1513 | spin_lock_irq(shost->host_lock); | 1519 | spin_lock_irq(shost->host_lock); |
| 1514 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 1520 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
| 1515 | spin_unlock_irq(shost->host_lock); | 1521 | spin_unlock_irq(shost->host_lock); |
| @@ -2145,7 +2151,8 @@ lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
| 2145 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | 2151 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
| 2146 | 2152 | ||
| 2147 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) { | 2153 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) { |
| 2148 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 2154 | mod_timer(&ndlp->nlp_delayfunc, |
| 2155 | jiffies + msecs_to_jiffies(1000 * 1)); | ||
| 2149 | spin_lock_irq(shost->host_lock); | 2156 | spin_lock_irq(shost->host_lock); |
| 2150 | ndlp->nlp_flag |= NLP_DELAY_TMO; | 2157 | ndlp->nlp_flag |= NLP_DELAY_TMO; |
| 2151 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 2158 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 74b8710e1e90..8523b278ec9d 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
| @@ -24,6 +24,8 @@ | |||
| 24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
| 25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 26 | #include <asm/unaligned.h> | 26 | #include <asm/unaligned.h> |
| 27 | #include <linux/crc-t10dif.h> | ||
| 28 | #include <net/checksum.h> | ||
| 27 | 29 | ||
| 28 | #include <scsi/scsi.h> | 30 | #include <scsi/scsi.h> |
| 29 | #include <scsi/scsi_device.h> | 31 | #include <scsi/scsi_device.h> |
| @@ -48,7 +50,7 @@ | |||
| 48 | #define LPFC_RESET_WAIT 2 | 50 | #define LPFC_RESET_WAIT 2 |
| 49 | #define LPFC_ABORT_WAIT 2 | 51 | #define LPFC_ABORT_WAIT 2 |
| 50 | 52 | ||
| 51 | int _dump_buf_done; | 53 | int _dump_buf_done = 1; |
| 52 | 54 | ||
| 53 | static char *dif_op_str[] = { | 55 | static char *dif_op_str[] = { |
| 54 | "PROT_NORMAL", | 56 | "PROT_NORMAL", |
| @@ -66,6 +68,10 @@ struct scsi_dif_tuple { | |||
| 66 | __be32 ref_tag; /* Target LBA or indirect LBA */ | 68 | __be32 ref_tag; /* Target LBA or indirect LBA */ |
| 67 | }; | 69 | }; |
| 68 | 70 | ||
| 71 | #if !defined(SCSI_PROT_GUARD_CHECK) || !defined(SCSI_PROT_REF_CHECK) | ||
| 72 | #define scsi_prot_flagged(sc, flg) sc | ||
| 73 | #endif | ||
| 74 | |||
| 69 | static void | 75 | static void |
| 70 | lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); | 76 | lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); |
| 71 | static void | 77 | static void |
| @@ -534,7 +540,16 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc) | |||
| 534 | dma_addr_t pdma_phys_fcp_rsp; | 540 | dma_addr_t pdma_phys_fcp_rsp; |
| 535 | dma_addr_t pdma_phys_bpl; | 541 | dma_addr_t pdma_phys_bpl; |
| 536 | uint16_t iotag; | 542 | uint16_t iotag; |
| 537 | int bcnt; | 543 | int bcnt, bpl_size; |
| 544 | |||
| 545 | bpl_size = phba->cfg_sg_dma_buf_size - | ||
| 546 | (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); | ||
| 547 | |||
| 548 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | ||
| 549 | "9067 ALLOC %d scsi_bufs: %d (%d + %d + %d)\n", | ||
| 550 | num_to_alloc, phba->cfg_sg_dma_buf_size, | ||
| 551 | (int)sizeof(struct fcp_cmnd), | ||
| 552 | (int)sizeof(struct fcp_rsp), bpl_size); | ||
| 538 | 553 | ||
| 539 | for (bcnt = 0; bcnt < num_to_alloc; bcnt++) { | 554 | for (bcnt = 0; bcnt < num_to_alloc; bcnt++) { |
| 540 | psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); | 555 | psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); |
| @@ -759,7 +774,7 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba, | |||
| 759 | struct list_head *post_sblist, int sb_count) | 774 | struct list_head *post_sblist, int sb_count) |
| 760 | { | 775 | { |
| 761 | struct lpfc_scsi_buf *psb, *psb_next; | 776 | struct lpfc_scsi_buf *psb, *psb_next; |
| 762 | int status; | 777 | int status, sgl_size; |
| 763 | int post_cnt = 0, block_cnt = 0, num_posting = 0, num_posted = 0; | 778 | int post_cnt = 0, block_cnt = 0, num_posting = 0, num_posted = 0; |
| 764 | dma_addr_t pdma_phys_bpl1; | 779 | dma_addr_t pdma_phys_bpl1; |
| 765 | int last_xritag = NO_XRI; | 780 | int last_xritag = NO_XRI; |
| @@ -771,6 +786,9 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba, | |||
| 771 | if (sb_count <= 0) | 786 | if (sb_count <= 0) |
| 772 | return -EINVAL; | 787 | return -EINVAL; |
| 773 | 788 | ||
| 789 | sgl_size = phba->cfg_sg_dma_buf_size - | ||
| 790 | (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); | ||
| 791 | |||
| 774 | list_for_each_entry_safe(psb, psb_next, post_sblist, list) { | 792 | list_for_each_entry_safe(psb, psb_next, post_sblist, list) { |
| 775 | list_del_init(&psb->list); | 793 | list_del_init(&psb->list); |
| 776 | block_cnt++; | 794 | block_cnt++; |
| @@ -803,7 +821,7 @@ lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba, | |||
| 803 | post_cnt = block_cnt; | 821 | post_cnt = block_cnt; |
| 804 | } else if (block_cnt == 1) { | 822 | } else if (block_cnt == 1) { |
| 805 | /* last single sgl with non-contiguous xri */ | 823 | /* last single sgl with non-contiguous xri */ |
| 806 | if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE) | 824 | if (sgl_size > SGL_PAGE_SIZE) |
| 807 | pdma_phys_bpl1 = psb->dma_phys_bpl + | 825 | pdma_phys_bpl1 = psb->dma_phys_bpl + |
| 808 | SGL_PAGE_SIZE; | 826 | SGL_PAGE_SIZE; |
| 809 | else | 827 | else |
| @@ -885,9 +903,12 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba) | |||
| 885 | int num_posted, rc = 0; | 903 | int num_posted, rc = 0; |
| 886 | 904 | ||
| 887 | /* get all SCSI buffers need to repost to a local list */ | 905 | /* get all SCSI buffers need to repost to a local list */ |
| 888 | spin_lock_irq(&phba->scsi_buf_list_lock); | 906 | spin_lock_irq(&phba->scsi_buf_list_get_lock); |
| 889 | list_splice_init(&phba->lpfc_scsi_buf_list, &post_sblist); | 907 | spin_lock_irq(&phba->scsi_buf_list_put_lock); |
| 890 | spin_unlock_irq(&phba->scsi_buf_list_lock); | 908 | list_splice_init(&phba->lpfc_scsi_buf_list_get, &post_sblist); |
| 909 | list_splice(&phba->lpfc_scsi_buf_list_put, &post_sblist); | ||
| 910 | spin_unlock_irq(&phba->scsi_buf_list_put_lock); | ||
| 911 | spin_unlock_irq(&phba->scsi_buf_list_get_lock); | ||
| 891 | 912 | ||
| 892 | /* post the list of scsi buffer sgls to port if available */ | 913 | /* post the list of scsi buffer sgls to port if available */ |
| 893 | if (!list_empty(&post_sblist)) { | 914 | if (!list_empty(&post_sblist)) { |
| @@ -923,13 +944,22 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
| 923 | IOCB_t *iocb; | 944 | IOCB_t *iocb; |
| 924 | dma_addr_t pdma_phys_fcp_cmd; | 945 | dma_addr_t pdma_phys_fcp_cmd; |
| 925 | dma_addr_t pdma_phys_fcp_rsp; | 946 | dma_addr_t pdma_phys_fcp_rsp; |
| 926 | dma_addr_t pdma_phys_bpl, pdma_phys_bpl1; | 947 | dma_addr_t pdma_phys_bpl; |
| 927 | uint16_t iotag, lxri = 0; | 948 | uint16_t iotag, lxri = 0; |
| 928 | int bcnt, num_posted; | 949 | int bcnt, num_posted, sgl_size; |
| 929 | LIST_HEAD(prep_sblist); | 950 | LIST_HEAD(prep_sblist); |
| 930 | LIST_HEAD(post_sblist); | 951 | LIST_HEAD(post_sblist); |
| 931 | LIST_HEAD(scsi_sblist); | 952 | LIST_HEAD(scsi_sblist); |
| 932 | 953 | ||
| 954 | sgl_size = phba->cfg_sg_dma_buf_size - | ||
| 955 | (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); | ||
| 956 | |||
| 957 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | ||
| 958 | "9068 ALLOC %d scsi_bufs: %d (%d + %d + %d)\n", | ||
| 959 | num_to_alloc, phba->cfg_sg_dma_buf_size, sgl_size, | ||
| 960 | (int)sizeof(struct fcp_cmnd), | ||
| 961 | (int)sizeof(struct fcp_rsp)); | ||
| 962 | |||
| 933 | for (bcnt = 0; bcnt < num_to_alloc; bcnt++) { | 963 | for (bcnt = 0; bcnt < num_to_alloc; bcnt++) { |
| 934 | psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); | 964 | psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); |
| 935 | if (!psb) | 965 | if (!psb) |
| @@ -948,6 +978,15 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
| 948 | } | 978 | } |
| 949 | memset(psb->data, 0, phba->cfg_sg_dma_buf_size); | 979 | memset(psb->data, 0, phba->cfg_sg_dma_buf_size); |
| 950 | 980 | ||
| 981 | /* Page alignment is CRITICAL, double check to be sure */ | ||
| 982 | if (((unsigned long)(psb->data) & | ||
| 983 | (unsigned long)(SLI4_PAGE_SIZE - 1)) != 0) { | ||
| 984 | pci_pool_free(phba->lpfc_scsi_dma_buf_pool, | ||
| 985 | psb->data, psb->dma_handle); | ||
| 986 | kfree(psb); | ||
| 987 | break; | ||
| 988 | } | ||
| 989 | |||
| 951 | /* Allocate iotag for psb->cur_iocbq. */ | 990 | /* Allocate iotag for psb->cur_iocbq. */ |
| 952 | iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq); | 991 | iotag = lpfc_sli_next_iotag(phba, &psb->cur_iocbq); |
| 953 | if (iotag == 0) { | 992 | if (iotag == 0) { |
| @@ -968,17 +1007,14 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
| 968 | psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri]; | 1007 | psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri]; |
| 969 | psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP; | 1008 | psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP; |
| 970 | psb->fcp_bpl = psb->data; | 1009 | psb->fcp_bpl = psb->data; |
| 971 | psb->fcp_cmnd = (psb->data + phba->cfg_sg_dma_buf_size) | 1010 | psb->fcp_cmnd = (psb->data + sgl_size); |
| 972 | - (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); | ||
| 973 | psb->fcp_rsp = (struct fcp_rsp *)((uint8_t *)psb->fcp_cmnd + | 1011 | psb->fcp_rsp = (struct fcp_rsp *)((uint8_t *)psb->fcp_cmnd + |
| 974 | sizeof(struct fcp_cmnd)); | 1012 | sizeof(struct fcp_cmnd)); |
| 975 | 1013 | ||
| 976 | /* Initialize local short-hand pointers. */ | 1014 | /* Initialize local short-hand pointers. */ |
| 977 | sgl = (struct sli4_sge *)psb->fcp_bpl; | 1015 | sgl = (struct sli4_sge *)psb->fcp_bpl; |
| 978 | pdma_phys_bpl = psb->dma_handle; | 1016 | pdma_phys_bpl = psb->dma_handle; |
| 979 | pdma_phys_fcp_cmd = | 1017 | pdma_phys_fcp_cmd = (psb->dma_handle + sgl_size); |
| 980 | (psb->dma_handle + phba->cfg_sg_dma_buf_size) | ||
| 981 | - (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp)); | ||
| 982 | pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd); | 1018 | pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd); |
| 983 | 1019 | ||
| 984 | /* | 1020 | /* |
| @@ -1020,17 +1056,13 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) | |||
| 1020 | iocb->ulpLe = 1; | 1056 | iocb->ulpLe = 1; |
| 1021 | iocb->ulpClass = CLASS3; | 1057 | iocb->ulpClass = CLASS3; |
| 1022 | psb->cur_iocbq.context1 = psb; | 1058 | psb->cur_iocbq.context1 = psb; |
| 1023 | if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE) | ||
| 1024 | pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE; | ||
| 1025 | else | ||
| 1026 | pdma_phys_bpl1 = 0; | ||
| 1027 | psb->dma_phys_bpl = pdma_phys_bpl; | 1059 | psb->dma_phys_bpl = pdma_phys_bpl; |
| 1028 | 1060 | ||
| 1029 | /* add the scsi buffer to a post list */ | 1061 | /* add the scsi buffer to a post list */ |
| 1030 | list_add_tail(&psb->list, &post_sblist); | 1062 | list_add_tail(&psb->list, &post_sblist); |
| 1031 | spin_lock_irq(&phba->scsi_buf_list_lock); | 1063 | spin_lock_irq(&phba->scsi_buf_list_get_lock); |
| 1032 | phba->sli4_hba.scsi_xri_cnt++; | 1064 | phba->sli4_hba.scsi_xri_cnt++; |
| 1033 | spin_unlock_irq(&phba->scsi_buf_list_lock); | 1065 | spin_unlock_irq(&phba->scsi_buf_list_get_lock); |
| 1034 | } | 1066 | } |
| 1035 | lpfc_printf_log(phba, KERN_INFO, LOG_BG, | 1067 | lpfc_printf_log(phba, KERN_INFO, LOG_BG, |
| 1036 | "3021 Allocate %d out of %d requested new SCSI " | 1068 | "3021 Allocate %d out of %d requested new SCSI " |
| @@ -1079,17 +1111,23 @@ static struct lpfc_scsi_buf* | |||
| 1079 | lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | 1111 | lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) |
| 1080 | { | 1112 | { |
| 1081 | struct lpfc_scsi_buf * lpfc_cmd = NULL; | 1113 | struct lpfc_scsi_buf * lpfc_cmd = NULL; |
| 1082 | struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; | 1114 | struct list_head *scsi_buf_list_get = &phba->lpfc_scsi_buf_list_get; |
| 1083 | unsigned long iflag = 0; | 1115 | unsigned long gflag = 0; |
| 1084 | 1116 | unsigned long pflag = 0; | |
| 1085 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | 1117 | |
| 1086 | list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); | 1118 | spin_lock_irqsave(&phba->scsi_buf_list_get_lock, gflag); |
| 1087 | if (lpfc_cmd) { | 1119 | list_remove_head(scsi_buf_list_get, lpfc_cmd, struct lpfc_scsi_buf, |
| 1088 | lpfc_cmd->seg_cnt = 0; | 1120 | list); |
| 1089 | lpfc_cmd->nonsg_phys = 0; | 1121 | if (!lpfc_cmd) { |
| 1090 | lpfc_cmd->prot_seg_cnt = 0; | 1122 | spin_lock_irqsave(&phba->scsi_buf_list_put_lock, pflag); |
| 1123 | list_splice(&phba->lpfc_scsi_buf_list_put, | ||
| 1124 | &phba->lpfc_scsi_buf_list_get); | ||
| 1125 | INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put); | ||
| 1126 | list_remove_head(scsi_buf_list_get, lpfc_cmd, | ||
| 1127 | struct lpfc_scsi_buf, list); | ||
| 1128 | spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, pflag); | ||
| 1091 | } | 1129 | } |
| 1092 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | 1130 | spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, gflag); |
| 1093 | return lpfc_cmd; | 1131 | return lpfc_cmd; |
| 1094 | } | 1132 | } |
| 1095 | /** | 1133 | /** |
| @@ -1107,28 +1145,39 @@ static struct lpfc_scsi_buf* | |||
| 1107 | lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | 1145 | lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) |
| 1108 | { | 1146 | { |
| 1109 | struct lpfc_scsi_buf *lpfc_cmd ; | 1147 | struct lpfc_scsi_buf *lpfc_cmd ; |
| 1110 | unsigned long iflag = 0; | 1148 | unsigned long gflag = 0; |
| 1149 | unsigned long pflag = 0; | ||
| 1111 | int found = 0; | 1150 | int found = 0; |
| 1112 | 1151 | ||
| 1113 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | 1152 | spin_lock_irqsave(&phba->scsi_buf_list_get_lock, gflag); |
| 1114 | list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list, | 1153 | list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list_get, list) { |
| 1115 | list) { | ||
| 1116 | if (lpfc_test_rrq_active(phba, ndlp, | 1154 | if (lpfc_test_rrq_active(phba, ndlp, |
| 1117 | lpfc_cmd->cur_iocbq.sli4_lxritag)) | 1155 | lpfc_cmd->cur_iocbq.sli4_lxritag)) |
| 1118 | continue; | 1156 | continue; |
| 1119 | list_del(&lpfc_cmd->list); | 1157 | list_del(&lpfc_cmd->list); |
| 1120 | found = 1; | 1158 | found = 1; |
| 1121 | lpfc_cmd->seg_cnt = 0; | ||
| 1122 | lpfc_cmd->nonsg_phys = 0; | ||
| 1123 | lpfc_cmd->prot_seg_cnt = 0; | ||
| 1124 | break; | 1159 | break; |
| 1125 | } | 1160 | } |
| 1126 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, | 1161 | if (!found) { |
| 1127 | iflag); | 1162 | spin_lock_irqsave(&phba->scsi_buf_list_put_lock, pflag); |
| 1163 | list_splice(&phba->lpfc_scsi_buf_list_put, | ||
| 1164 | &phba->lpfc_scsi_buf_list_get); | ||
| 1165 | INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put); | ||
| 1166 | spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, pflag); | ||
| 1167 | list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list_get, | ||
| 1168 | list) { | ||
| 1169 | if (lpfc_test_rrq_active( | ||
| 1170 | phba, ndlp, lpfc_cmd->cur_iocbq.sli4_lxritag)) | ||
| 1171 | continue; | ||
| 1172 | list_del(&lpfc_cmd->list); | ||
| 1173 | found = 1; | ||
| 1174 | break; | ||
| 1175 | } | ||
| 1176 | } | ||
| 1177 | spin_unlock_irqrestore(&phba->scsi_buf_list_get_lock, gflag); | ||
| 1128 | if (!found) | 1178 | if (!found) |
| 1129 | return NULL; | 1179 | return NULL; |
| 1130 | else | 1180 | return lpfc_cmd; |
| 1131 | return lpfc_cmd; | ||
| 1132 | } | 1181 | } |
| 1133 | /** | 1182 | /** |
| 1134 | * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA | 1183 | * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA |
| @@ -1160,10 +1209,15 @@ lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb) | |||
| 1160 | { | 1209 | { |
| 1161 | unsigned long iflag = 0; | 1210 | unsigned long iflag = 0; |
| 1162 | 1211 | ||
| 1163 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | 1212 | psb->seg_cnt = 0; |
| 1213 | psb->nonsg_phys = 0; | ||
| 1214 | psb->prot_seg_cnt = 0; | ||
| 1215 | |||
| 1216 | spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag); | ||
| 1164 | psb->pCmd = NULL; | 1217 | psb->pCmd = NULL; |
| 1165 | list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list); | 1218 | psb->cur_iocbq.iocb_flag = LPFC_IO_FCP; |
| 1166 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | 1219 | list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put); |
| 1220 | spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag); | ||
| 1167 | } | 1221 | } |
| 1168 | 1222 | ||
| 1169 | /** | 1223 | /** |
| @@ -1181,6 +1235,10 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb) | |||
| 1181 | { | 1235 | { |
| 1182 | unsigned long iflag = 0; | 1236 | unsigned long iflag = 0; |
| 1183 | 1237 | ||
| 1238 | psb->seg_cnt = 0; | ||
| 1239 | psb->nonsg_phys = 0; | ||
| 1240 | psb->prot_seg_cnt = 0; | ||
| 1241 | |||
| 1184 | if (psb->exch_busy) { | 1242 | if (psb->exch_busy) { |
| 1185 | spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock, | 1243 | spin_lock_irqsave(&phba->sli4_hba.abts_scsi_buf_list_lock, |
| 1186 | iflag); | 1244 | iflag); |
| @@ -1190,11 +1248,11 @@ lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb) | |||
| 1190 | spin_unlock_irqrestore(&phba->sli4_hba.abts_scsi_buf_list_lock, | 1248 | spin_unlock_irqrestore(&phba->sli4_hba.abts_scsi_buf_list_lock, |
| 1191 | iflag); | 1249 | iflag); |
| 1192 | } else { | 1250 | } else { |
| 1193 | |||
| 1194 | spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag); | ||
| 1195 | psb->pCmd = NULL; | 1251 | psb->pCmd = NULL; |
| 1196 | list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list); | 1252 | psb->cur_iocbq.iocb_flag = LPFC_IO_FCP; |
| 1197 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | 1253 | spin_lock_irqsave(&phba->scsi_buf_list_put_lock, iflag); |
| 1254 | list_add_tail(&psb->list, &phba->lpfc_scsi_buf_list_put); | ||
| 1255 | spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, iflag); | ||
| 1198 | } | 1256 | } |
| 1199 | } | 1257 | } |
| 1200 | 1258 | ||
| @@ -1268,6 +1326,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
| 1268 | "dma_map_sg. Config %d, seg_cnt %d\n", | 1326 | "dma_map_sg. Config %d, seg_cnt %d\n", |
| 1269 | __func__, phba->cfg_sg_seg_cnt, | 1327 | __func__, phba->cfg_sg_seg_cnt, |
| 1270 | lpfc_cmd->seg_cnt); | 1328 | lpfc_cmd->seg_cnt); |
| 1329 | lpfc_cmd->seg_cnt = 0; | ||
| 1271 | scsi_dma_unmap(scsi_cmnd); | 1330 | scsi_dma_unmap(scsi_cmnd); |
| 1272 | return 1; | 1331 | return 1; |
| 1273 | } | 1332 | } |
| @@ -2013,9 +2072,21 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 2013 | bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR); | 2072 | bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR); |
| 2014 | bf_set(pde6_optx, pde6, txop); | 2073 | bf_set(pde6_optx, pde6, txop); |
| 2015 | bf_set(pde6_oprx, pde6, rxop); | 2074 | bf_set(pde6_oprx, pde6, rxop); |
| 2075 | |||
| 2076 | /* | ||
| 2077 | * We only need to check the data on READs, for WRITEs | ||
| 2078 | * protection data is automatically generated, not checked. | ||
| 2079 | */ | ||
| 2016 | if (datadir == DMA_FROM_DEVICE) { | 2080 | if (datadir == DMA_FROM_DEVICE) { |
| 2017 | bf_set(pde6_ce, pde6, checking); | 2081 | if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) |
| 2018 | bf_set(pde6_re, pde6, checking); | 2082 | bf_set(pde6_ce, pde6, checking); |
| 2083 | else | ||
| 2084 | bf_set(pde6_ce, pde6, 0); | ||
| 2085 | |||
| 2086 | if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) | ||
| 2087 | bf_set(pde6_re, pde6, checking); | ||
| 2088 | else | ||
| 2089 | bf_set(pde6_re, pde6, 0); | ||
| 2019 | } | 2090 | } |
| 2020 | bf_set(pde6_ai, pde6, 1); | 2091 | bf_set(pde6_ai, pde6, 1); |
| 2021 | bf_set(pde6_ae, pde6, 0); | 2092 | bf_set(pde6_ae, pde6, 0); |
| @@ -2145,6 +2216,10 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 2145 | 2216 | ||
| 2146 | split_offset = 0; | 2217 | split_offset = 0; |
| 2147 | do { | 2218 | do { |
| 2219 | /* Check to see if we ran out of space */ | ||
| 2220 | if (num_bde >= (phba->cfg_total_seg_cnt - 2)) | ||
| 2221 | return num_bde + 3; | ||
| 2222 | |||
| 2148 | /* setup PDE5 with what we have */ | 2223 | /* setup PDE5 with what we have */ |
| 2149 | pde5 = (struct lpfc_pde5 *) bpl; | 2224 | pde5 = (struct lpfc_pde5 *) bpl; |
| 2150 | memset(pde5, 0, sizeof(struct lpfc_pde5)); | 2225 | memset(pde5, 0, sizeof(struct lpfc_pde5)); |
| @@ -2164,8 +2239,17 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 2164 | bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR); | 2239 | bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR); |
| 2165 | bf_set(pde6_optx, pde6, txop); | 2240 | bf_set(pde6_optx, pde6, txop); |
| 2166 | bf_set(pde6_oprx, pde6, rxop); | 2241 | bf_set(pde6_oprx, pde6, rxop); |
| 2167 | bf_set(pde6_ce, pde6, checking); | 2242 | |
| 2168 | bf_set(pde6_re, pde6, checking); | 2243 | if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) |
| 2244 | bf_set(pde6_ce, pde6, checking); | ||
| 2245 | else | ||
| 2246 | bf_set(pde6_ce, pde6, 0); | ||
| 2247 | |||
| 2248 | if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) | ||
| 2249 | bf_set(pde6_re, pde6, checking); | ||
| 2250 | else | ||
| 2251 | bf_set(pde6_re, pde6, 0); | ||
| 2252 | |||
| 2169 | bf_set(pde6_ai, pde6, 1); | 2253 | bf_set(pde6_ai, pde6, 1); |
| 2170 | bf_set(pde6_ae, pde6, 0); | 2254 | bf_set(pde6_ae, pde6, 0); |
| 2171 | bf_set(pde6_apptagval, pde6, 0); | 2255 | bf_set(pde6_apptagval, pde6, 0); |
| @@ -2213,6 +2297,10 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 2213 | pgdone = 0; | 2297 | pgdone = 0; |
| 2214 | subtotal = 0; /* total bytes processed for current prot grp */ | 2298 | subtotal = 0; /* total bytes processed for current prot grp */ |
| 2215 | while (!pgdone) { | 2299 | while (!pgdone) { |
| 2300 | /* Check to see if we ran out of space */ | ||
| 2301 | if (num_bde >= phba->cfg_total_seg_cnt) | ||
| 2302 | return num_bde + 1; | ||
| 2303 | |||
| 2216 | if (!sgde) { | 2304 | if (!sgde) { |
| 2217 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 2305 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, |
| 2218 | "9065 BLKGRD:%s Invalid data segment\n", | 2306 | "9065 BLKGRD:%s Invalid data segment\n", |
| @@ -2324,7 +2412,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 2324 | struct sli4_sge_diseed *diseed = NULL; | 2412 | struct sli4_sge_diseed *diseed = NULL; |
| 2325 | dma_addr_t physaddr; | 2413 | dma_addr_t physaddr; |
| 2326 | int i = 0, num_sge = 0, status; | 2414 | int i = 0, num_sge = 0, status; |
| 2327 | int datadir = sc->sc_data_direction; | ||
| 2328 | uint32_t reftag; | 2415 | uint32_t reftag; |
| 2329 | unsigned blksize; | 2416 | unsigned blksize; |
| 2330 | uint8_t txop, rxop; | 2417 | uint8_t txop, rxop; |
| @@ -2362,13 +2449,26 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 2362 | diseed->ref_tag = cpu_to_le32(reftag); | 2449 | diseed->ref_tag = cpu_to_le32(reftag); |
| 2363 | diseed->ref_tag_tran = diseed->ref_tag; | 2450 | diseed->ref_tag_tran = diseed->ref_tag; |
| 2364 | 2451 | ||
| 2452 | /* | ||
| 2453 | * We only need to check the data on READs, for WRITEs | ||
| 2454 | * protection data is automatically generated, not checked. | ||
| 2455 | */ | ||
| 2456 | if (sc->sc_data_direction == DMA_FROM_DEVICE) { | ||
| 2457 | if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) | ||
| 2458 | bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); | ||
| 2459 | else | ||
| 2460 | bf_set(lpfc_sli4_sge_dif_ce, diseed, 0); | ||
| 2461 | |||
| 2462 | if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) | ||
| 2463 | bf_set(lpfc_sli4_sge_dif_re, diseed, checking); | ||
| 2464 | else | ||
| 2465 | bf_set(lpfc_sli4_sge_dif_re, diseed, 0); | ||
| 2466 | } | ||
| 2467 | |||
| 2365 | /* setup DISEED with the rest of the info */ | 2468 | /* setup DISEED with the rest of the info */ |
| 2366 | bf_set(lpfc_sli4_sge_dif_optx, diseed, txop); | 2469 | bf_set(lpfc_sli4_sge_dif_optx, diseed, txop); |
| 2367 | bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop); | 2470 | bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop); |
| 2368 | if (datadir == DMA_FROM_DEVICE) { | 2471 | |
| 2369 | bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); | ||
| 2370 | bf_set(lpfc_sli4_sge_dif_re, diseed, checking); | ||
| 2371 | } | ||
| 2372 | bf_set(lpfc_sli4_sge_dif_ai, diseed, 1); | 2472 | bf_set(lpfc_sli4_sge_dif_ai, diseed, 1); |
| 2373 | bf_set(lpfc_sli4_sge_dif_me, diseed, 0); | 2473 | bf_set(lpfc_sli4_sge_dif_me, diseed, 0); |
| 2374 | 2474 | ||
| @@ -2497,6 +2597,10 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 2497 | 2597 | ||
| 2498 | split_offset = 0; | 2598 | split_offset = 0; |
| 2499 | do { | 2599 | do { |
| 2600 | /* Check to see if we ran out of space */ | ||
| 2601 | if (num_sge >= (phba->cfg_total_seg_cnt - 2)) | ||
| 2602 | return num_sge + 3; | ||
| 2603 | |||
| 2500 | /* setup DISEED with what we have */ | 2604 | /* setup DISEED with what we have */ |
| 2501 | diseed = (struct sli4_sge_diseed *) sgl; | 2605 | diseed = (struct sli4_sge_diseed *) sgl; |
| 2502 | memset(diseed, 0, sizeof(struct sli4_sge_diseed)); | 2606 | memset(diseed, 0, sizeof(struct sli4_sge_diseed)); |
| @@ -2506,11 +2610,34 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 2506 | diseed->ref_tag = cpu_to_le32(reftag); | 2610 | diseed->ref_tag = cpu_to_le32(reftag); |
| 2507 | diseed->ref_tag_tran = diseed->ref_tag; | 2611 | diseed->ref_tag_tran = diseed->ref_tag; |
| 2508 | 2612 | ||
| 2613 | if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) { | ||
| 2614 | bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); | ||
| 2615 | |||
| 2616 | } else { | ||
| 2617 | bf_set(lpfc_sli4_sge_dif_ce, diseed, 0); | ||
| 2618 | /* | ||
| 2619 | * When in this mode, the hardware will replace | ||
| 2620 | * the guard tag from the host with a | ||
| 2621 | * newly generated good CRC for the wire. | ||
| 2622 | * Switch to raw mode here to avoid this | ||
| 2623 | * behavior. What the host sends gets put on the wire. | ||
| 2624 | */ | ||
| 2625 | if (txop == BG_OP_IN_CRC_OUT_CRC) { | ||
| 2626 | txop = BG_OP_RAW_MODE; | ||
| 2627 | rxop = BG_OP_RAW_MODE; | ||
| 2628 | } | ||
| 2629 | } | ||
| 2630 | |||
| 2631 | |||
| 2632 | if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) | ||
| 2633 | bf_set(lpfc_sli4_sge_dif_re, diseed, checking); | ||
| 2634 | else | ||
| 2635 | bf_set(lpfc_sli4_sge_dif_re, diseed, 0); | ||
| 2636 | |||
| 2509 | /* setup DISEED with the rest of the info */ | 2637 | /* setup DISEED with the rest of the info */ |
| 2510 | bf_set(lpfc_sli4_sge_dif_optx, diseed, txop); | 2638 | bf_set(lpfc_sli4_sge_dif_optx, diseed, txop); |
| 2511 | bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop); | 2639 | bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop); |
| 2512 | bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); | 2640 | |
| 2513 | bf_set(lpfc_sli4_sge_dif_re, diseed, checking); | ||
| 2514 | bf_set(lpfc_sli4_sge_dif_ai, diseed, 1); | 2641 | bf_set(lpfc_sli4_sge_dif_ai, diseed, 1); |
| 2515 | bf_set(lpfc_sli4_sge_dif_me, diseed, 0); | 2642 | bf_set(lpfc_sli4_sge_dif_me, diseed, 0); |
| 2516 | 2643 | ||
| @@ -2556,6 +2683,10 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
| 2556 | pgdone = 0; | 2683 | pgdone = 0; |
| 2557 | subtotal = 0; /* total bytes processed for current prot grp */ | 2684 | subtotal = 0; /* total bytes processed for current prot grp */ |
| 2558 | while (!pgdone) { | 2685 | while (!pgdone) { |
| 2686 | /* Check to see if we ran out of space */ | ||
| 2687 | if (num_sge >= phba->cfg_total_seg_cnt) | ||
| 2688 | return num_sge + 1; | ||
| 2689 | |||
| 2559 | if (!sgde) { | 2690 | if (!sgde) { |
| 2560 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 2691 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, |
| 2561 | "9086 BLKGRD:%s Invalid data segment\n", | 2692 | "9086 BLKGRD:%s Invalid data segment\n", |
| @@ -2670,6 +2801,47 @@ lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc) | |||
| 2670 | } | 2801 | } |
| 2671 | 2802 | ||
| 2672 | /** | 2803 | /** |
| 2804 | * lpfc_bg_scsi_adjust_dl - Adjust SCSI data length for BlockGuard | ||
| 2805 | * @phba: The Hba for which this call is being executed. | ||
| 2806 | * @lpfc_cmd: The scsi buffer which is going to be adjusted. | ||
| 2807 | * | ||
| 2808 | * Adjust the data length to account for how much data | ||
| 2809 | * is actually on the wire. | ||
| 2810 | * | ||
| 2811 | * returns the adjusted data length | ||
| 2812 | **/ | ||
| 2813 | static int | ||
| 2814 | lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba, | ||
| 2815 | struct lpfc_scsi_buf *lpfc_cmd) | ||
| 2816 | { | ||
| 2817 | struct scsi_cmnd *sc = lpfc_cmd->pCmd; | ||
| 2818 | int fcpdl; | ||
| 2819 | |||
| 2820 | fcpdl = scsi_bufflen(sc); | ||
| 2821 | |||
| 2822 | /* Check if there is protection data on the wire */ | ||
| 2823 | if (sc->sc_data_direction == DMA_FROM_DEVICE) { | ||
| 2824 | /* Read */ | ||
| 2825 | if (scsi_get_prot_op(sc) == SCSI_PROT_READ_INSERT) | ||
| 2826 | return fcpdl; | ||
| 2827 | |||
| 2828 | } else { | ||
| 2829 | /* Write */ | ||
| 2830 | if (scsi_get_prot_op(sc) == SCSI_PROT_WRITE_STRIP) | ||
| 2831 | return fcpdl; | ||
| 2832 | } | ||
| 2833 | |||
| 2834 | /* | ||
| 2835 | * If we are in DIF Type 1 mode every data block has a 8 byte | ||
| 2836 | * DIF (trailer) attached to it. Must ajust FCP data length. | ||
| 2837 | */ | ||
| 2838 | if (scsi_prot_flagged(sc, SCSI_PROT_TRANSFER_PI)) | ||
| 2839 | fcpdl += (fcpdl / lpfc_cmd_blksize(sc)) * 8; | ||
| 2840 | |||
| 2841 | return fcpdl; | ||
| 2842 | } | ||
| 2843 | |||
| 2844 | /** | ||
| 2673 | * lpfc_bg_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec | 2845 | * lpfc_bg_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec |
| 2674 | * @phba: The Hba for which this call is being executed. | 2846 | * @phba: The Hba for which this call is being executed. |
| 2675 | * @lpfc_cmd: The scsi buffer which is going to be prep'ed. | 2847 | * @lpfc_cmd: The scsi buffer which is going to be prep'ed. |
| @@ -2689,8 +2861,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, | |||
| 2689 | uint32_t num_bde = 0; | 2861 | uint32_t num_bde = 0; |
| 2690 | int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; | 2862 | int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; |
| 2691 | int prot_group_type = 0; | 2863 | int prot_group_type = 0; |
| 2692 | int diflen, fcpdl; | 2864 | int fcpdl; |
| 2693 | unsigned blksize; | ||
| 2694 | 2865 | ||
| 2695 | /* | 2866 | /* |
| 2696 | * Start the lpfc command prep by bumping the bpl beyond fcp_cmnd | 2867 | * Start the lpfc command prep by bumping the bpl beyond fcp_cmnd |
| @@ -2711,28 +2882,28 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, | |||
| 2711 | return 1; | 2882 | return 1; |
| 2712 | 2883 | ||
| 2713 | lpfc_cmd->seg_cnt = datasegcnt; | 2884 | lpfc_cmd->seg_cnt = datasegcnt; |
| 2714 | if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { | 2885 | |
| 2715 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 2886 | /* First check if data segment count from SCSI Layer is good */ |
| 2716 | "9067 BLKGRD: %s: Too many sg segments" | 2887 | if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) |
| 2717 | " from dma_map_sg. Config %d, seg_cnt" | 2888 | goto err; |
| 2718 | " %d\n", | ||
| 2719 | __func__, phba->cfg_sg_seg_cnt, | ||
| 2720 | lpfc_cmd->seg_cnt); | ||
| 2721 | scsi_dma_unmap(scsi_cmnd); | ||
| 2722 | return 1; | ||
| 2723 | } | ||
| 2724 | 2889 | ||
| 2725 | prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd); | 2890 | prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd); |
| 2726 | 2891 | ||
| 2727 | switch (prot_group_type) { | 2892 | switch (prot_group_type) { |
| 2728 | case LPFC_PG_TYPE_NO_DIF: | 2893 | case LPFC_PG_TYPE_NO_DIF: |
| 2894 | |||
| 2895 | /* Here we need to add a PDE5 and PDE6 to the count */ | ||
| 2896 | if ((lpfc_cmd->seg_cnt + 2) > phba->cfg_total_seg_cnt) | ||
| 2897 | goto err; | ||
| 2898 | |||
| 2729 | num_bde = lpfc_bg_setup_bpl(phba, scsi_cmnd, bpl, | 2899 | num_bde = lpfc_bg_setup_bpl(phba, scsi_cmnd, bpl, |
| 2730 | datasegcnt); | 2900 | datasegcnt); |
| 2731 | /* we should have 2 or more entries in buffer list */ | 2901 | /* we should have 2 or more entries in buffer list */ |
| 2732 | if (num_bde < 2) | 2902 | if (num_bde < 2) |
| 2733 | goto err; | 2903 | goto err; |
| 2734 | break; | 2904 | break; |
| 2735 | case LPFC_PG_TYPE_DIF_BUF:{ | 2905 | |
| 2906 | case LPFC_PG_TYPE_DIF_BUF: | ||
| 2736 | /* | 2907 | /* |
| 2737 | * This type indicates that protection buffers are | 2908 | * This type indicates that protection buffers are |
| 2738 | * passed to the driver, so that needs to be prepared | 2909 | * passed to the driver, so that needs to be prepared |
| @@ -2747,31 +2918,28 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, | |||
| 2747 | } | 2918 | } |
| 2748 | 2919 | ||
| 2749 | lpfc_cmd->prot_seg_cnt = protsegcnt; | 2920 | lpfc_cmd->prot_seg_cnt = protsegcnt; |
| 2750 | if (lpfc_cmd->prot_seg_cnt | 2921 | |
| 2751 | > phba->cfg_prot_sg_seg_cnt) { | 2922 | /* |
| 2752 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 2923 | * There is a minimun of 4 BPLs used for every |
| 2753 | "9068 BLKGRD: %s: Too many prot sg " | 2924 | * protection data segment. |
| 2754 | "segments from dma_map_sg. Config %d," | 2925 | */ |
| 2755 | "prot_seg_cnt %d\n", __func__, | 2926 | if ((lpfc_cmd->prot_seg_cnt * 4) > |
| 2756 | phba->cfg_prot_sg_seg_cnt, | 2927 | (phba->cfg_total_seg_cnt - 2)) |
| 2757 | lpfc_cmd->prot_seg_cnt); | 2928 | goto err; |
| 2758 | dma_unmap_sg(&phba->pcidev->dev, | ||
| 2759 | scsi_prot_sglist(scsi_cmnd), | ||
| 2760 | scsi_prot_sg_count(scsi_cmnd), | ||
| 2761 | datadir); | ||
| 2762 | scsi_dma_unmap(scsi_cmnd); | ||
| 2763 | return 1; | ||
| 2764 | } | ||
| 2765 | 2929 | ||
| 2766 | num_bde = lpfc_bg_setup_bpl_prot(phba, scsi_cmnd, bpl, | 2930 | num_bde = lpfc_bg_setup_bpl_prot(phba, scsi_cmnd, bpl, |
| 2767 | datasegcnt, protsegcnt); | 2931 | datasegcnt, protsegcnt); |
| 2768 | /* we should have 3 or more entries in buffer list */ | 2932 | /* we should have 3 or more entries in buffer list */ |
| 2769 | if (num_bde < 3) | 2933 | if ((num_bde < 3) || |
| 2934 | (num_bde > phba->cfg_total_seg_cnt)) | ||
| 2770 | goto err; | 2935 | goto err; |
| 2771 | break; | 2936 | break; |
| 2772 | } | 2937 | |
| 2773 | case LPFC_PG_TYPE_INVALID: | 2938 | case LPFC_PG_TYPE_INVALID: |
| 2774 | default: | 2939 | default: |
| 2940 | scsi_dma_unmap(scsi_cmnd); | ||
| 2941 | lpfc_cmd->seg_cnt = 0; | ||
| 2942 | |||
| 2775 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 2943 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
| 2776 | "9022 Unexpected protection group %i\n", | 2944 | "9022 Unexpected protection group %i\n", |
| 2777 | prot_group_type); | 2945 | prot_group_type); |
| @@ -2790,18 +2958,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, | |||
| 2790 | iocb_cmd->ulpBdeCount = 1; | 2958 | iocb_cmd->ulpBdeCount = 1; |
| 2791 | iocb_cmd->ulpLe = 1; | 2959 | iocb_cmd->ulpLe = 1; |
| 2792 | 2960 | ||
| 2793 | fcpdl = scsi_bufflen(scsi_cmnd); | 2961 | fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd); |
| 2794 | |||
| 2795 | if (scsi_get_prot_type(scsi_cmnd) == SCSI_PROT_DIF_TYPE1) { | ||
| 2796 | /* | ||
| 2797 | * We are in DIF Type 1 mode | ||
| 2798 | * Every data block has a 8 byte DIF (trailer) | ||
| 2799 | * attached to it. Must ajust FCP data length | ||
| 2800 | */ | ||
| 2801 | blksize = lpfc_cmd_blksize(scsi_cmnd); | ||
| 2802 | diflen = (fcpdl / blksize) * 8; | ||
| 2803 | fcpdl += diflen; | ||
| 2804 | } | ||
| 2805 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); | 2962 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); |
| 2806 | 2963 | ||
| 2807 | /* | 2964 | /* |
| @@ -2812,14 +2969,234 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, | |||
| 2812 | 2969 | ||
| 2813 | return 0; | 2970 | return 0; |
| 2814 | err: | 2971 | err: |
| 2972 | if (lpfc_cmd->seg_cnt) | ||
| 2973 | scsi_dma_unmap(scsi_cmnd); | ||
| 2974 | if (lpfc_cmd->prot_seg_cnt) | ||
| 2975 | dma_unmap_sg(&phba->pcidev->dev, scsi_prot_sglist(scsi_cmnd), | ||
| 2976 | scsi_prot_sg_count(scsi_cmnd), | ||
| 2977 | scsi_cmnd->sc_data_direction); | ||
| 2978 | |||
| 2815 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 2979 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
| 2816 | "9023 Could not setup all needed BDE's" | 2980 | "9023 Cannot setup S/G List for HBA" |
| 2817 | "prot_group_type=%d, num_bde=%d\n", | 2981 | "IO segs %d/%d BPL %d SCSI %d: %d %d\n", |
| 2982 | lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt, | ||
| 2983 | phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt, | ||
| 2818 | prot_group_type, num_bde); | 2984 | prot_group_type, num_bde); |
| 2985 | |||
| 2986 | lpfc_cmd->seg_cnt = 0; | ||
| 2987 | lpfc_cmd->prot_seg_cnt = 0; | ||
| 2819 | return 1; | 2988 | return 1; |
| 2820 | } | 2989 | } |
| 2821 | 2990 | ||
| 2822 | /* | 2991 | /* |
| 2992 | * This function calcuates the T10 DIF guard tag | ||
| 2993 | * on the specified data using a CRC algorithmn | ||
| 2994 | * using crc_t10dif. | ||
| 2995 | */ | ||
| 2996 | uint16_t | ||
| 2997 | lpfc_bg_crc(uint8_t *data, int count) | ||
| 2998 | { | ||
| 2999 | uint16_t crc = 0; | ||
| 3000 | uint16_t x; | ||
| 3001 | |||
| 3002 | crc = crc_t10dif(data, count); | ||
| 3003 | x = cpu_to_be16(crc); | ||
| 3004 | return x; | ||
| 3005 | } | ||
| 3006 | |||
| 3007 | /* | ||
| 3008 | * This function calcuates the T10 DIF guard tag | ||
| 3009 | * on the specified data using a CSUM algorithmn | ||
| 3010 | * using ip_compute_csum. | ||
| 3011 | */ | ||
| 3012 | uint16_t | ||
| 3013 | lpfc_bg_csum(uint8_t *data, int count) | ||
| 3014 | { | ||
| 3015 | uint16_t ret; | ||
| 3016 | |||
| 3017 | ret = ip_compute_csum(data, count); | ||
| 3018 | return ret; | ||
| 3019 | } | ||
| 3020 | |||
| 3021 | /* | ||
| 3022 | * This function examines the protection data to try to determine | ||
| 3023 | * what type of T10-DIF error occurred. | ||
| 3024 | */ | ||
| 3025 | void | ||
| 3026 | lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | ||
| 3027 | { | ||
| 3028 | struct scatterlist *sgpe; /* s/g prot entry */ | ||
| 3029 | struct scatterlist *sgde; /* s/g data entry */ | ||
| 3030 | struct scsi_cmnd *cmd = lpfc_cmd->pCmd; | ||
| 3031 | struct scsi_dif_tuple *src = NULL; | ||
| 3032 | uint8_t *data_src = NULL; | ||
| 3033 | uint16_t guard_tag, guard_type; | ||
| 3034 | uint16_t start_app_tag, app_tag; | ||
| 3035 | uint32_t start_ref_tag, ref_tag; | ||
| 3036 | int prot, protsegcnt; | ||
| 3037 | int err_type, len, data_len; | ||
| 3038 | int chk_ref, chk_app, chk_guard; | ||
| 3039 | uint16_t sum; | ||
| 3040 | unsigned blksize; | ||
| 3041 | |||
| 3042 | err_type = BGS_GUARD_ERR_MASK; | ||
| 3043 | sum = 0; | ||
| 3044 | guard_tag = 0; | ||
| 3045 | |||
| 3046 | /* First check to see if there is protection data to examine */ | ||
| 3047 | prot = scsi_get_prot_op(cmd); | ||
| 3048 | if ((prot == SCSI_PROT_READ_STRIP) || | ||
| 3049 | (prot == SCSI_PROT_WRITE_INSERT) || | ||
| 3050 | (prot == SCSI_PROT_NORMAL)) | ||
| 3051 | goto out; | ||
| 3052 | |||
| 3053 | /* Currently the driver just supports ref_tag and guard_tag checking */ | ||
| 3054 | chk_ref = 1; | ||
| 3055 | chk_app = 0; | ||
| 3056 | chk_guard = 0; | ||
| 3057 | |||
| 3058 | /* Setup a ptr to the protection data provided by the SCSI host */ | ||
| 3059 | sgpe = scsi_prot_sglist(cmd); | ||
| 3060 | protsegcnt = lpfc_cmd->prot_seg_cnt; | ||
| 3061 | |||
| 3062 | if (sgpe && protsegcnt) { | ||
| 3063 | |||
| 3064 | /* | ||
| 3065 | * We will only try to verify guard tag if the segment | ||
| 3066 | * data length is a multiple of the blksize. | ||
| 3067 | */ | ||
| 3068 | sgde = scsi_sglist(cmd); | ||
| 3069 | blksize = lpfc_cmd_blksize(cmd); | ||
| 3070 | data_src = (uint8_t *)sg_virt(sgde); | ||
| 3071 | data_len = sgde->length; | ||
| 3072 | if ((data_len & (blksize - 1)) == 0) | ||
| 3073 | chk_guard = 1; | ||
| 3074 | guard_type = scsi_host_get_guard(cmd->device->host); | ||
| 3075 | |||
| 3076 | start_ref_tag = (uint32_t)scsi_get_lba(cmd); /* Truncate LBA */ | ||
| 3077 | start_app_tag = src->app_tag; | ||
| 3078 | src = (struct scsi_dif_tuple *)sg_virt(sgpe); | ||
| 3079 | len = sgpe->length; | ||
| 3080 | while (src && protsegcnt) { | ||
| 3081 | while (len) { | ||
| 3082 | |||
| 3083 | /* | ||
| 3084 | * First check to see if a protection data | ||
| 3085 | * check is valid | ||
| 3086 | */ | ||
| 3087 | if ((src->ref_tag == 0xffffffff) || | ||
| 3088 | (src->app_tag == 0xffff)) { | ||
| 3089 | start_ref_tag++; | ||
| 3090 | goto skipit; | ||
| 3091 | } | ||
| 3092 | |||
| 3093 | /* App Tag checking */ | ||
| 3094 | app_tag = src->app_tag; | ||
| 3095 | if (chk_app && (app_tag != start_app_tag)) { | ||
| 3096 | err_type = BGS_APPTAG_ERR_MASK; | ||
| 3097 | goto out; | ||
| 3098 | } | ||
| 3099 | |||
| 3100 | /* Reference Tag checking */ | ||
| 3101 | ref_tag = be32_to_cpu(src->ref_tag); | ||
| 3102 | if (chk_ref && (ref_tag != start_ref_tag)) { | ||
| 3103 | err_type = BGS_REFTAG_ERR_MASK; | ||
| 3104 | goto out; | ||
| 3105 | } | ||
| 3106 | start_ref_tag++; | ||
| 3107 | |||
| 3108 | /* Guard Tag checking */ | ||
| 3109 | if (chk_guard) { | ||
| 3110 | guard_tag = src->guard_tag; | ||
| 3111 | if (guard_type == SHOST_DIX_GUARD_IP) | ||
| 3112 | sum = lpfc_bg_csum(data_src, | ||
| 3113 | blksize); | ||
| 3114 | else | ||
| 3115 | sum = lpfc_bg_crc(data_src, | ||
| 3116 | blksize); | ||
| 3117 | if ((guard_tag != sum)) { | ||
| 3118 | err_type = BGS_GUARD_ERR_MASK; | ||
| 3119 | goto out; | ||
| 3120 | } | ||
| 3121 | } | ||
| 3122 | skipit: | ||
| 3123 | len -= sizeof(struct scsi_dif_tuple); | ||
| 3124 | if (len < 0) | ||
| 3125 | len = 0; | ||
| 3126 | src++; | ||
| 3127 | |||
| 3128 | data_src += blksize; | ||
| 3129 | data_len -= blksize; | ||
| 3130 | |||
| 3131 | /* | ||
| 3132 | * Are we at the end of the Data segment? | ||
| 3133 | * The data segment is only used for Guard | ||
| 3134 | * tag checking. | ||
| 3135 | */ | ||
| 3136 | if (chk_guard && (data_len == 0)) { | ||
| 3137 | chk_guard = 0; | ||
| 3138 | sgde = sg_next(sgde); | ||
| 3139 | if (!sgde) | ||
| 3140 | goto out; | ||
| 3141 | |||
| 3142 | data_src = (uint8_t *)sg_virt(sgde); | ||
| 3143 | data_len = sgde->length; | ||
| 3144 | if ((data_len & (blksize - 1)) == 0) | ||
| 3145 | chk_guard = 1; | ||
| 3146 | } | ||
| 3147 | } | ||
| 3148 | |||
| 3149 | /* Goto the next Protection data segment */ | ||
| 3150 | sgpe = sg_next(sgpe); | ||
| 3151 | if (sgpe) { | ||
| 3152 | src = (struct scsi_dif_tuple *)sg_virt(sgpe); | ||
| 3153 | len = sgpe->length; | ||
| 3154 | } else { | ||
| 3155 | src = NULL; | ||
| 3156 | } | ||
| 3157 | protsegcnt--; | ||
| 3158 | } | ||
| 3159 | } | ||
| 3160 | out: | ||
| 3161 | if (err_type == BGS_GUARD_ERR_MASK) { | ||
| 3162 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
| 3163 | 0x10, 0x1); | ||
| 3164 | cmd->result = DRIVER_SENSE << 24 | ||
| 3165 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); | ||
| 3166 | phba->bg_guard_err_cnt++; | ||
| 3167 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, | ||
| 3168 | "9069 BLKGRD: LBA %lx grd_tag error %x != %x\n", | ||
| 3169 | (unsigned long)scsi_get_lba(cmd), | ||
| 3170 | sum, guard_tag); | ||
| 3171 | |||
| 3172 | } else if (err_type == BGS_REFTAG_ERR_MASK) { | ||
| 3173 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
| 3174 | 0x10, 0x3); | ||
| 3175 | cmd->result = DRIVER_SENSE << 24 | ||
| 3176 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); | ||
| 3177 | |||
| 3178 | phba->bg_reftag_err_cnt++; | ||
| 3179 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, | ||
| 3180 | "9066 BLKGRD: LBA %lx ref_tag error %x != %x\n", | ||
| 3181 | (unsigned long)scsi_get_lba(cmd), | ||
| 3182 | ref_tag, start_ref_tag); | ||
| 3183 | |||
| 3184 | } else if (err_type == BGS_APPTAG_ERR_MASK) { | ||
| 3185 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
| 3186 | 0x10, 0x2); | ||
| 3187 | cmd->result = DRIVER_SENSE << 24 | ||
| 3188 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); | ||
| 3189 | |||
| 3190 | phba->bg_apptag_err_cnt++; | ||
| 3191 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, | ||
| 3192 | "9041 BLKGRD: LBA %lx app_tag error %x != %x\n", | ||
| 3193 | (unsigned long)scsi_get_lba(cmd), | ||
| 3194 | app_tag, start_app_tag); | ||
| 3195 | } | ||
| 3196 | } | ||
| 3197 | |||
| 3198 | |||
| 3199 | /* | ||
| 2823 | * This function checks for BlockGuard errors detected by | 3200 | * This function checks for BlockGuard errors detected by |
| 2824 | * the HBA. In case of errors, the ASC/ASCQ fields in the | 3201 | * the HBA. In case of errors, the ASC/ASCQ fields in the |
| 2825 | * sense buffer will be set accordingly, paired with | 3202 | * sense buffer will be set accordingly, paired with |
| @@ -2842,12 +3219,6 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | |||
| 2842 | uint32_t bgstat = bgf->bgstat; | 3219 | uint32_t bgstat = bgf->bgstat; |
| 2843 | uint64_t failing_sector = 0; | 3220 | uint64_t failing_sector = 0; |
| 2844 | 3221 | ||
| 2845 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9069 BLKGRD: BG ERROR in cmd" | ||
| 2846 | " 0x%x lba 0x%llx blk cnt 0x%x " | ||
| 2847 | "bgstat=0x%x bghm=0x%x\n", | ||
| 2848 | cmd->cmnd[0], (unsigned long long)scsi_get_lba(cmd), | ||
| 2849 | blk_rq_sectors(cmd->request), bgstat, bghm); | ||
| 2850 | |||
| 2851 | spin_lock(&_dump_buf_lock); | 3222 | spin_lock(&_dump_buf_lock); |
| 2852 | if (!_dump_buf_done) { | 3223 | if (!_dump_buf_done) { |
| 2853 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9070 BLKGRD: Saving" | 3224 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9070 BLKGRD: Saving" |
| @@ -2870,18 +3241,24 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | |||
| 2870 | 3241 | ||
| 2871 | if (lpfc_bgs_get_invalid_prof(bgstat)) { | 3242 | if (lpfc_bgs_get_invalid_prof(bgstat)) { |
| 2872 | cmd->result = ScsiResult(DID_ERROR, 0); | 3243 | cmd->result = ScsiResult(DID_ERROR, 0); |
| 2873 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9072 BLKGRD: Invalid" | 3244 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, |
| 2874 | " BlockGuard profile. bgstat:0x%x\n", | 3245 | "9072 BLKGRD: Invalid BG Profile in cmd" |
| 2875 | bgstat); | 3246 | " 0x%x lba 0x%llx blk cnt 0x%x " |
| 3247 | "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], | ||
| 3248 | (unsigned long long)scsi_get_lba(cmd), | ||
| 3249 | blk_rq_sectors(cmd->request), bgstat, bghm); | ||
| 2876 | ret = (-1); | 3250 | ret = (-1); |
| 2877 | goto out; | 3251 | goto out; |
| 2878 | } | 3252 | } |
| 2879 | 3253 | ||
| 2880 | if (lpfc_bgs_get_uninit_dif_block(bgstat)) { | 3254 | if (lpfc_bgs_get_uninit_dif_block(bgstat)) { |
| 2881 | cmd->result = ScsiResult(DID_ERROR, 0); | 3255 | cmd->result = ScsiResult(DID_ERROR, 0); |
| 2882 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9073 BLKGRD: " | 3256 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, |
| 2883 | "Invalid BlockGuard DIF Block. bgstat:0x%x\n", | 3257 | "9073 BLKGRD: Invalid BG PDIF Block in cmd" |
| 2884 | bgstat); | 3258 | " 0x%x lba 0x%llx blk cnt 0x%x " |
| 3259 | "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], | ||
| 3260 | (unsigned long long)scsi_get_lba(cmd), | ||
| 3261 | blk_rq_sectors(cmd->request), bgstat, bghm); | ||
| 2885 | ret = (-1); | 3262 | ret = (-1); |
| 2886 | goto out; | 3263 | goto out; |
| 2887 | } | 3264 | } |
| @@ -2894,8 +3271,12 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | |||
| 2894 | cmd->result = DRIVER_SENSE << 24 | 3271 | cmd->result = DRIVER_SENSE << 24 |
| 2895 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); | 3272 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); |
| 2896 | phba->bg_guard_err_cnt++; | 3273 | phba->bg_guard_err_cnt++; |
| 2897 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 3274 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, |
| 2898 | "9055 BLKGRD: guard_tag error\n"); | 3275 | "9055 BLKGRD: Guard Tag error in cmd" |
| 3276 | " 0x%x lba 0x%llx blk cnt 0x%x " | ||
| 3277 | "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], | ||
| 3278 | (unsigned long long)scsi_get_lba(cmd), | ||
| 3279 | blk_rq_sectors(cmd->request), bgstat, bghm); | ||
| 2899 | } | 3280 | } |
| 2900 | 3281 | ||
| 2901 | if (lpfc_bgs_get_reftag_err(bgstat)) { | 3282 | if (lpfc_bgs_get_reftag_err(bgstat)) { |
| @@ -2907,8 +3288,12 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | |||
| 2907 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); | 3288 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); |
| 2908 | 3289 | ||
| 2909 | phba->bg_reftag_err_cnt++; | 3290 | phba->bg_reftag_err_cnt++; |
| 2910 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 3291 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, |
| 2911 | "9056 BLKGRD: ref_tag error\n"); | 3292 | "9056 BLKGRD: Ref Tag error in cmd" |
| 3293 | " 0x%x lba 0x%llx blk cnt 0x%x " | ||
| 3294 | "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], | ||
| 3295 | (unsigned long long)scsi_get_lba(cmd), | ||
| 3296 | blk_rq_sectors(cmd->request), bgstat, bghm); | ||
| 2912 | } | 3297 | } |
| 2913 | 3298 | ||
| 2914 | if (lpfc_bgs_get_apptag_err(bgstat)) { | 3299 | if (lpfc_bgs_get_apptag_err(bgstat)) { |
| @@ -2920,8 +3305,12 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | |||
| 2920 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); | 3305 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); |
| 2921 | 3306 | ||
| 2922 | phba->bg_apptag_err_cnt++; | 3307 | phba->bg_apptag_err_cnt++; |
| 2923 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 3308 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, |
| 2924 | "9061 BLKGRD: app_tag error\n"); | 3309 | "9061 BLKGRD: App Tag error in cmd" |
| 3310 | " 0x%x lba 0x%llx blk cnt 0x%x " | ||
| 3311 | "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], | ||
| 3312 | (unsigned long long)scsi_get_lba(cmd), | ||
| 3313 | blk_rq_sectors(cmd->request), bgstat, bghm); | ||
| 2925 | } | 3314 | } |
| 2926 | 3315 | ||
| 2927 | if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { | 3316 | if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { |
| @@ -2960,11 +3349,16 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | |||
| 2960 | 3349 | ||
| 2961 | if (!ret) { | 3350 | if (!ret) { |
| 2962 | /* No error was reported - problem in FW? */ | 3351 | /* No error was reported - problem in FW? */ |
| 2963 | cmd->result = ScsiResult(DID_ERROR, 0); | 3352 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, |
| 2964 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 3353 | "9057 BLKGRD: Unknown error in cmd" |
| 2965 | "9057 BLKGRD: Unknown error reported!\n"); | 3354 | " 0x%x lba 0x%llx blk cnt 0x%x " |
| 3355 | "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], | ||
| 3356 | (unsigned long long)scsi_get_lba(cmd), | ||
| 3357 | blk_rq_sectors(cmd->request), bgstat, bghm); | ||
| 3358 | |||
| 3359 | /* Calcuate what type of error it was */ | ||
| 3360 | lpfc_calc_bg_err(phba, lpfc_cmd); | ||
| 2966 | } | 3361 | } |
| 2967 | |||
| 2968 | out: | 3362 | out: |
| 2969 | return ret; | 3363 | return ret; |
| 2970 | } | 3364 | } |
| @@ -3028,6 +3422,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
| 3028 | "dma_map_sg. Config %d, seg_cnt %d\n", | 3422 | "dma_map_sg. Config %d, seg_cnt %d\n", |
| 3029 | __func__, phba->cfg_sg_seg_cnt, | 3423 | __func__, phba->cfg_sg_seg_cnt, |
| 3030 | lpfc_cmd->seg_cnt); | 3424 | lpfc_cmd->seg_cnt); |
| 3425 | lpfc_cmd->seg_cnt = 0; | ||
| 3031 | scsi_dma_unmap(scsi_cmnd); | 3426 | scsi_dma_unmap(scsi_cmnd); |
| 3032 | return 1; | 3427 | return 1; |
| 3033 | } | 3428 | } |
| @@ -3094,45 +3489,6 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
| 3094 | } | 3489 | } |
| 3095 | 3490 | ||
| 3096 | /** | 3491 | /** |
| 3097 | * lpfc_bg_scsi_adjust_dl - Adjust SCSI data length for BlockGuard | ||
| 3098 | * @phba: The Hba for which this call is being executed. | ||
| 3099 | * @lpfc_cmd: The scsi buffer which is going to be adjusted. | ||
| 3100 | * | ||
| 3101 | * Adjust the data length to account for how much data | ||
| 3102 | * is actually on the wire. | ||
| 3103 | * | ||
| 3104 | * returns the adjusted data length | ||
| 3105 | **/ | ||
| 3106 | static int | ||
| 3107 | lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba, | ||
| 3108 | struct lpfc_scsi_buf *lpfc_cmd) | ||
| 3109 | { | ||
| 3110 | struct scsi_cmnd *sc = lpfc_cmd->pCmd; | ||
| 3111 | int diflen, fcpdl; | ||
| 3112 | unsigned blksize; | ||
| 3113 | |||
| 3114 | fcpdl = scsi_bufflen(sc); | ||
| 3115 | |||
| 3116 | /* Check if there is protection data on the wire */ | ||
| 3117 | if (sc->sc_data_direction == DMA_FROM_DEVICE) { | ||
| 3118 | /* Read */ | ||
| 3119 | if (scsi_get_prot_op(sc) == SCSI_PROT_READ_INSERT) | ||
| 3120 | return fcpdl; | ||
| 3121 | |||
| 3122 | } else { | ||
| 3123 | /* Write */ | ||
| 3124 | if (scsi_get_prot_op(sc) == SCSI_PROT_WRITE_STRIP) | ||
| 3125 | return fcpdl; | ||
| 3126 | } | ||
| 3127 | |||
| 3128 | /* If protection data on the wire, adjust the count accordingly */ | ||
| 3129 | blksize = lpfc_cmd_blksize(sc); | ||
| 3130 | diflen = (fcpdl / blksize) * 8; | ||
| 3131 | fcpdl += diflen; | ||
| 3132 | return fcpdl; | ||
| 3133 | } | ||
| 3134 | |||
| 3135 | /** | ||
| 3136 | * lpfc_bg_scsi_prep_dma_buf_s4 - DMA mapping for scsi buffer to SLI4 IF spec | 3492 | * lpfc_bg_scsi_prep_dma_buf_s4 - DMA mapping for scsi buffer to SLI4 IF spec |
| 3137 | * @phba: The Hba for which this call is being executed. | 3493 | * @phba: The Hba for which this call is being executed. |
| 3138 | * @lpfc_cmd: The scsi buffer which is going to be mapped. | 3494 | * @lpfc_cmd: The scsi buffer which is going to be mapped. |
| @@ -3149,14 +3505,14 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, | |||
| 3149 | struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; | 3505 | struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; |
| 3150 | struct sli4_sge *sgl = (struct sli4_sge *)(lpfc_cmd->fcp_bpl); | 3506 | struct sli4_sge *sgl = (struct sli4_sge *)(lpfc_cmd->fcp_bpl); |
| 3151 | IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; | 3507 | IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; |
| 3152 | uint32_t num_bde = 0; | 3508 | uint32_t num_sge = 0; |
| 3153 | int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; | 3509 | int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; |
| 3154 | int prot_group_type = 0; | 3510 | int prot_group_type = 0; |
| 3155 | int fcpdl; | 3511 | int fcpdl; |
| 3156 | 3512 | ||
| 3157 | /* | 3513 | /* |
| 3158 | * Start the lpfc command prep by bumping the sgl beyond fcp_cmnd | 3514 | * Start the lpfc command prep by bumping the sgl beyond fcp_cmnd |
| 3159 | * fcp_rsp regions to the first data bde entry | 3515 | * fcp_rsp regions to the first data sge entry |
| 3160 | */ | 3516 | */ |
| 3161 | if (scsi_sg_count(scsi_cmnd)) { | 3517 | if (scsi_sg_count(scsi_cmnd)) { |
| 3162 | /* | 3518 | /* |
| @@ -3179,28 +3535,28 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, | |||
| 3179 | 3535 | ||
| 3180 | sgl += 1; | 3536 | sgl += 1; |
| 3181 | lpfc_cmd->seg_cnt = datasegcnt; | 3537 | lpfc_cmd->seg_cnt = datasegcnt; |
| 3182 | if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { | 3538 | |
| 3183 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 3539 | /* First check if data segment count from SCSI Layer is good */ |
| 3184 | "9087 BLKGRD: %s: Too many sg segments" | 3540 | if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) |
| 3185 | " from dma_map_sg. Config %d, seg_cnt" | 3541 | goto err; |
| 3186 | " %d\n", | ||
| 3187 | __func__, phba->cfg_sg_seg_cnt, | ||
| 3188 | lpfc_cmd->seg_cnt); | ||
| 3189 | scsi_dma_unmap(scsi_cmnd); | ||
| 3190 | return 1; | ||
| 3191 | } | ||
| 3192 | 3542 | ||
| 3193 | prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd); | 3543 | prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd); |
| 3194 | 3544 | ||
| 3195 | switch (prot_group_type) { | 3545 | switch (prot_group_type) { |
| 3196 | case LPFC_PG_TYPE_NO_DIF: | 3546 | case LPFC_PG_TYPE_NO_DIF: |
| 3197 | num_bde = lpfc_bg_setup_sgl(phba, scsi_cmnd, sgl, | 3547 | /* Here we need to add a DISEED to the count */ |
| 3548 | if ((lpfc_cmd->seg_cnt + 1) > phba->cfg_total_seg_cnt) | ||
| 3549 | goto err; | ||
| 3550 | |||
| 3551 | num_sge = lpfc_bg_setup_sgl(phba, scsi_cmnd, sgl, | ||
| 3198 | datasegcnt); | 3552 | datasegcnt); |
| 3553 | |||
| 3199 | /* we should have 2 or more entries in buffer list */ | 3554 | /* we should have 2 or more entries in buffer list */ |
| 3200 | if (num_bde < 2) | 3555 | if (num_sge < 2) |
| 3201 | goto err; | 3556 | goto err; |
| 3202 | break; | 3557 | break; |
| 3203 | case LPFC_PG_TYPE_DIF_BUF:{ | 3558 | |
| 3559 | case LPFC_PG_TYPE_DIF_BUF: | ||
| 3204 | /* | 3560 | /* |
| 3205 | * This type indicates that protection buffers are | 3561 | * This type indicates that protection buffers are |
| 3206 | * passed to the driver, so that needs to be prepared | 3562 | * passed to the driver, so that needs to be prepared |
| @@ -3215,31 +3571,28 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, | |||
| 3215 | } | 3571 | } |
| 3216 | 3572 | ||
| 3217 | lpfc_cmd->prot_seg_cnt = protsegcnt; | 3573 | lpfc_cmd->prot_seg_cnt = protsegcnt; |
| 3218 | if (lpfc_cmd->prot_seg_cnt | 3574 | /* |
| 3219 | > phba->cfg_prot_sg_seg_cnt) { | 3575 | * There is a minimun of 3 SGEs used for every |
| 3220 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 3576 | * protection data segment. |
| 3221 | "9088 BLKGRD: %s: Too many prot sg " | 3577 | */ |
| 3222 | "segments from dma_map_sg. Config %d," | 3578 | if ((lpfc_cmd->prot_seg_cnt * 3) > |
| 3223 | "prot_seg_cnt %d\n", __func__, | 3579 | (phba->cfg_total_seg_cnt - 2)) |
| 3224 | phba->cfg_prot_sg_seg_cnt, | 3580 | goto err; |
| 3225 | lpfc_cmd->prot_seg_cnt); | ||
| 3226 | dma_unmap_sg(&phba->pcidev->dev, | ||
| 3227 | scsi_prot_sglist(scsi_cmnd), | ||
| 3228 | scsi_prot_sg_count(scsi_cmnd), | ||
| 3229 | datadir); | ||
| 3230 | scsi_dma_unmap(scsi_cmnd); | ||
| 3231 | return 1; | ||
| 3232 | } | ||
| 3233 | 3581 | ||
| 3234 | num_bde = lpfc_bg_setup_sgl_prot(phba, scsi_cmnd, sgl, | 3582 | num_sge = lpfc_bg_setup_sgl_prot(phba, scsi_cmnd, sgl, |
| 3235 | datasegcnt, protsegcnt); | 3583 | datasegcnt, protsegcnt); |
| 3584 | |||
| 3236 | /* we should have 3 or more entries in buffer list */ | 3585 | /* we should have 3 or more entries in buffer list */ |
| 3237 | if (num_bde < 3) | 3586 | if ((num_sge < 3) || |
| 3587 | (num_sge > phba->cfg_total_seg_cnt)) | ||
| 3238 | goto err; | 3588 | goto err; |
| 3239 | break; | 3589 | break; |
| 3240 | } | 3590 | |
| 3241 | case LPFC_PG_TYPE_INVALID: | 3591 | case LPFC_PG_TYPE_INVALID: |
| 3242 | default: | 3592 | default: |
| 3593 | scsi_dma_unmap(scsi_cmnd); | ||
| 3594 | lpfc_cmd->seg_cnt = 0; | ||
| 3595 | |||
| 3243 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 3596 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
| 3244 | "9083 Unexpected protection group %i\n", | 3597 | "9083 Unexpected protection group %i\n", |
| 3245 | prot_group_type); | 3598 | prot_group_type); |
| @@ -3263,7 +3616,6 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, | |||
| 3263 | } | 3616 | } |
| 3264 | 3617 | ||
| 3265 | fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd); | 3618 | fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd); |
| 3266 | |||
| 3267 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); | 3619 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); |
| 3268 | 3620 | ||
| 3269 | /* | 3621 | /* |
| @@ -3274,10 +3626,22 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, | |||
| 3274 | 3626 | ||
| 3275 | return 0; | 3627 | return 0; |
| 3276 | err: | 3628 | err: |
| 3629 | if (lpfc_cmd->seg_cnt) | ||
| 3630 | scsi_dma_unmap(scsi_cmnd); | ||
| 3631 | if (lpfc_cmd->prot_seg_cnt) | ||
| 3632 | dma_unmap_sg(&phba->pcidev->dev, scsi_prot_sglist(scsi_cmnd), | ||
| 3633 | scsi_prot_sg_count(scsi_cmnd), | ||
| 3634 | scsi_cmnd->sc_data_direction); | ||
| 3635 | |||
| 3277 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 3636 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, |
| 3278 | "9084 Could not setup all needed BDE's" | 3637 | "9084 Cannot setup S/G List for HBA" |
| 3279 | "prot_group_type=%d, num_bde=%d\n", | 3638 | "IO segs %d/%d SGL %d SCSI %d: %d %d\n", |
| 3280 | prot_group_type, num_bde); | 3639 | lpfc_cmd->seg_cnt, lpfc_cmd->prot_seg_cnt, |
| 3640 | phba->cfg_total_seg_cnt, phba->cfg_sg_seg_cnt, | ||
| 3641 | prot_group_type, num_sge); | ||
| 3642 | |||
| 3643 | lpfc_cmd->seg_cnt = 0; | ||
| 3644 | lpfc_cmd->prot_seg_cnt = 0; | ||
| 3281 | return 1; | 3645 | return 1; |
| 3282 | } | 3646 | } |
| 3283 | 3647 | ||
| @@ -4357,7 +4721,8 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) | |||
| 4357 | 4721 | ||
| 4358 | if (scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) { | 4722 | if (scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) { |
| 4359 | if (vport->phba->cfg_enable_bg) { | 4723 | if (vport->phba->cfg_enable_bg) { |
| 4360 | lpfc_printf_vlog(vport, KERN_INFO, LOG_BG, | 4724 | lpfc_printf_vlog(vport, |
| 4725 | KERN_INFO, LOG_SCSI_CMD, | ||
| 4361 | "9033 BLKGRD: rcvd %s cmd:x%x " | 4726 | "9033 BLKGRD: rcvd %s cmd:x%x " |
| 4362 | "sector x%llx cnt %u pt %x\n", | 4727 | "sector x%llx cnt %u pt %x\n", |
| 4363 | dif_op_str[scsi_get_prot_op(cmnd)], | 4728 | dif_op_str[scsi_get_prot_op(cmnd)], |
| @@ -4369,7 +4734,8 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) | |||
| 4369 | err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd); | 4734 | err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd); |
| 4370 | } else { | 4735 | } else { |
| 4371 | if (vport->phba->cfg_enable_bg) { | 4736 | if (vport->phba->cfg_enable_bg) { |
| 4372 | lpfc_printf_vlog(vport, KERN_INFO, LOG_BG, | 4737 | lpfc_printf_vlog(vport, |
| 4738 | KERN_INFO, LOG_SCSI_CMD, | ||
| 4373 | "9038 BLKGRD: rcvd PROT_NORMAL cmd: " | 4739 | "9038 BLKGRD: rcvd PROT_NORMAL cmd: " |
| 4374 | "x%x sector x%llx cnt %u pt %x\n", | 4740 | "x%x sector x%llx cnt %u pt %x\n", |
| 4375 | cmnd->cmnd[0], | 4741 | cmnd->cmnd[0], |
| @@ -4542,7 +4908,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) | |||
| 4542 | /* Wait for abort to complete */ | 4908 | /* Wait for abort to complete */ |
| 4543 | wait_event_timeout(waitq, | 4909 | wait_event_timeout(waitq, |
| 4544 | (lpfc_cmd->pCmd != cmnd), | 4910 | (lpfc_cmd->pCmd != cmnd), |
| 4545 | (2*vport->cfg_devloss_tmo*HZ)); | 4911 | msecs_to_jiffies(2*vport->cfg_devloss_tmo*1000)); |
| 4546 | lpfc_cmd->waitq = NULL; | 4912 | lpfc_cmd->waitq = NULL; |
| 4547 | 4913 | ||
| 4548 | if (lpfc_cmd->pCmd == cmnd) { | 4914 | if (lpfc_cmd->pCmd == cmnd) { |
| @@ -5012,16 +5378,24 @@ lpfc_host_reset_handler(struct scsi_cmnd *cmnd) | |||
| 5012 | struct lpfc_hba *phba = vport->phba; | 5378 | struct lpfc_hba *phba = vport->phba; |
| 5013 | int rc, ret = SUCCESS; | 5379 | int rc, ret = SUCCESS; |
| 5014 | 5380 | ||
| 5381 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, | ||
| 5382 | "3172 SCSI layer issued Host Reset Data:\n"); | ||
| 5383 | |||
| 5015 | lpfc_offline_prep(phba, LPFC_MBX_WAIT); | 5384 | lpfc_offline_prep(phba, LPFC_MBX_WAIT); |
| 5016 | lpfc_offline(phba); | 5385 | lpfc_offline(phba); |
| 5017 | rc = lpfc_sli_brdrestart(phba); | 5386 | rc = lpfc_sli_brdrestart(phba); |
| 5018 | if (rc) | 5387 | if (rc) |
| 5019 | ret = FAILED; | 5388 | ret = FAILED; |
| 5020 | lpfc_online(phba); | 5389 | rc = lpfc_online(phba); |
| 5390 | if (rc) | ||
| 5391 | ret = FAILED; | ||
| 5021 | lpfc_unblock_mgmt_io(phba); | 5392 | lpfc_unblock_mgmt_io(phba); |
| 5022 | 5393 | ||
| 5023 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | 5394 | if (ret == FAILED) { |
| 5024 | "3172 SCSI layer issued Host Reset Data: x%x\n", ret); | 5395 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, |
| 5396 | "3323 Failed host reset, bring it offline\n"); | ||
| 5397 | lpfc_sli4_offline_eratt(phba); | ||
| 5398 | } | ||
| 5025 | return ret; | 5399 | return ret; |
| 5026 | } | 5400 | } |
| 5027 | 5401 | ||
| @@ -5088,11 +5462,11 @@ lpfc_slave_alloc(struct scsi_device *sdev) | |||
| 5088 | } | 5462 | } |
| 5089 | num_allocated = lpfc_new_scsi_buf(vport, num_to_alloc); | 5463 | num_allocated = lpfc_new_scsi_buf(vport, num_to_alloc); |
| 5090 | if (num_to_alloc != num_allocated) { | 5464 | if (num_to_alloc != num_allocated) { |
| 5091 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, | 5465 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, |
| 5092 | "0708 Allocation request of %d " | 5466 | "0708 Allocation request of %d " |
| 5093 | "command buffers did not succeed. " | 5467 | "command buffers did not succeed. " |
| 5094 | "Allocated %d buffers.\n", | 5468 | "Allocated %d buffers.\n", |
| 5095 | num_to_alloc, num_allocated); | 5469 | num_to_alloc, num_allocated); |
| 5096 | } | 5470 | } |
| 5097 | if (num_allocated > 0) | 5471 | if (num_allocated > 0) |
| 5098 | phba->total_scsi_bufs += num_allocated; | 5472 | phba->total_scsi_bufs += num_allocated; |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 35dd17eb0f27..572579f87de4 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
| @@ -667,7 +667,7 @@ lpfc_handle_rrq_active(struct lpfc_hba *phba) | |||
| 667 | 667 | ||
| 668 | spin_lock_irqsave(&phba->hbalock, iflags); | 668 | spin_lock_irqsave(&phba->hbalock, iflags); |
| 669 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; | 669 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; |
| 670 | next_time = jiffies + HZ * (phba->fc_ratov + 1); | 670 | next_time = jiffies + msecs_to_jiffies(1000 * (phba->fc_ratov + 1)); |
| 671 | list_for_each_entry_safe(rrq, nextrrq, | 671 | list_for_each_entry_safe(rrq, nextrrq, |
| 672 | &phba->active_rrq_list, list) { | 672 | &phba->active_rrq_list, list) { |
| 673 | if (time_after(jiffies, rrq->rrq_stop_time)) | 673 | if (time_after(jiffies, rrq->rrq_stop_time)) |
| @@ -782,7 +782,7 @@ lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba) | |||
| 782 | return; | 782 | return; |
| 783 | spin_lock_irqsave(&phba->hbalock, iflags); | 783 | spin_lock_irqsave(&phba->hbalock, iflags); |
| 784 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; | 784 | phba->hba_flag &= ~HBA_RRQ_ACTIVE; |
| 785 | next_time = jiffies + HZ * (phba->fc_ratov * 2); | 785 | next_time = jiffies + msecs_to_jiffies(1000 * (phba->fc_ratov * 2)); |
| 786 | list_splice_init(&phba->active_rrq_list, &rrq_list); | 786 | list_splice_init(&phba->active_rrq_list, &rrq_list); |
| 787 | spin_unlock_irqrestore(&phba->hbalock, iflags); | 787 | spin_unlock_irqrestore(&phba->hbalock, iflags); |
| 788 | 788 | ||
| @@ -878,7 +878,8 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
| 878 | else | 878 | else |
| 879 | rrq->send_rrq = 0; | 879 | rrq->send_rrq = 0; |
| 880 | rrq->xritag = xritag; | 880 | rrq->xritag = xritag; |
| 881 | rrq->rrq_stop_time = jiffies + HZ * (phba->fc_ratov + 1); | 881 | rrq->rrq_stop_time = jiffies + |
| 882 | msecs_to_jiffies(1000 * (phba->fc_ratov + 1)); | ||
| 882 | rrq->ndlp = ndlp; | 883 | rrq->ndlp = ndlp; |
| 883 | rrq->nlp_DID = ndlp->nlp_DID; | 884 | rrq->nlp_DID = ndlp->nlp_DID; |
| 884 | rrq->vport = ndlp->vport; | 885 | rrq->vport = ndlp->vport; |
| @@ -926,8 +927,7 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) | |||
| 926 | } else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) && | 927 | } else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) && |
| 927 | !(piocbq->iocb_flag & LPFC_IO_LIBDFC)) | 928 | !(piocbq->iocb_flag & LPFC_IO_LIBDFC)) |
| 928 | ndlp = piocbq->context_un.ndlp; | 929 | ndlp = piocbq->context_un.ndlp; |
| 929 | else if ((piocbq->iocb.ulpCommand == CMD_ELS_REQUEST64_CR) && | 930 | else if (piocbq->iocb_flag & LPFC_IO_LIBDFC) |
| 930 | (piocbq->iocb_flag & LPFC_IO_LIBDFC)) | ||
| 931 | ndlp = piocbq->context_un.ndlp; | 931 | ndlp = piocbq->context_un.ndlp; |
| 932 | else | 932 | else |
| 933 | ndlp = piocbq->context1; | 933 | ndlp = piocbq->context1; |
| @@ -1339,7 +1339,8 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
| 1339 | BUG(); | 1339 | BUG(); |
| 1340 | else | 1340 | else |
| 1341 | mod_timer(&piocb->vport->els_tmofunc, | 1341 | mod_timer(&piocb->vport->els_tmofunc, |
| 1342 | jiffies + HZ * (phba->fc_ratov << 1)); | 1342 | jiffies + |
| 1343 | msecs_to_jiffies(1000 * (phba->fc_ratov << 1))); | ||
| 1343 | } | 1344 | } |
| 1344 | 1345 | ||
| 1345 | 1346 | ||
| @@ -2340,7 +2341,8 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) | |||
| 2340 | /* Mailbox cmd <cmd> Cmpl <cmpl> */ | 2341 | /* Mailbox cmd <cmd> Cmpl <cmpl> */ |
| 2341 | lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, | 2342 | lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, |
| 2342 | "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl x%p " | 2343 | "(%d):0307 Mailbox cmd x%x (x%x/x%x) Cmpl x%p " |
| 2343 | "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x\n", | 2344 | "Data: x%x x%x x%x x%x x%x x%x x%x x%x x%x " |
| 2345 | "x%x x%x x%x\n", | ||
| 2344 | pmb->vport ? pmb->vport->vpi : 0, | 2346 | pmb->vport ? pmb->vport->vpi : 0, |
| 2345 | pmbox->mbxCommand, | 2347 | pmbox->mbxCommand, |
| 2346 | lpfc_sli_config_mbox_subsys_get(phba, pmb), | 2348 | lpfc_sli_config_mbox_subsys_get(phba, pmb), |
| @@ -2354,7 +2356,10 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) | |||
| 2354 | pmbox->un.varWords[4], | 2356 | pmbox->un.varWords[4], |
| 2355 | pmbox->un.varWords[5], | 2357 | pmbox->un.varWords[5], |
| 2356 | pmbox->un.varWords[6], | 2358 | pmbox->un.varWords[6], |
| 2357 | pmbox->un.varWords[7]); | 2359 | pmbox->un.varWords[7], |
| 2360 | pmbox->un.varWords[8], | ||
| 2361 | pmbox->un.varWords[9], | ||
| 2362 | pmbox->un.varWords[10]); | ||
| 2358 | 2363 | ||
| 2359 | if (pmb->mbox_cmpl) | 2364 | if (pmb->mbox_cmpl) |
| 2360 | pmb->mbox_cmpl(phba,pmb); | 2365 | pmb->mbox_cmpl(phba,pmb); |
| @@ -2908,8 +2913,9 @@ void lpfc_poll_eratt(unsigned long ptr) | |||
| 2908 | lpfc_worker_wake_up(phba); | 2913 | lpfc_worker_wake_up(phba); |
| 2909 | else | 2914 | else |
| 2910 | /* Restart the timer for next eratt poll */ | 2915 | /* Restart the timer for next eratt poll */ |
| 2911 | mod_timer(&phba->eratt_poll, jiffies + | 2916 | mod_timer(&phba->eratt_poll, |
| 2912 | HZ * LPFC_ERATT_POLL_INTERVAL); | 2917 | jiffies + |
| 2918 | msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL)); | ||
| 2913 | return; | 2919 | return; |
| 2914 | } | 2920 | } |
| 2915 | 2921 | ||
| @@ -5511,6 +5517,7 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type) | |||
| 5511 | list_del_init(&rsrc_blk->list); | 5517 | list_del_init(&rsrc_blk->list); |
| 5512 | kfree(rsrc_blk); | 5518 | kfree(rsrc_blk); |
| 5513 | } | 5519 | } |
| 5520 | phba->sli4_hba.max_cfg_param.vpi_used = 0; | ||
| 5514 | break; | 5521 | break; |
| 5515 | case LPFC_RSC_TYPE_FCOE_XRI: | 5522 | case LPFC_RSC_TYPE_FCOE_XRI: |
| 5516 | kfree(phba->sli4_hba.xri_bmask); | 5523 | kfree(phba->sli4_hba.xri_bmask); |
| @@ -5811,6 +5818,7 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba) | |||
| 5811 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI); | 5818 | lpfc_sli4_dealloc_extent(phba, LPFC_RSC_TYPE_FCOE_VFI); |
| 5812 | } else { | 5819 | } else { |
| 5813 | kfree(phba->vpi_bmask); | 5820 | kfree(phba->vpi_bmask); |
| 5821 | phba->sli4_hba.max_cfg_param.vpi_used = 0; | ||
| 5814 | kfree(phba->vpi_ids); | 5822 | kfree(phba->vpi_ids); |
| 5815 | bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); | 5823 | bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0); |
| 5816 | kfree(phba->sli4_hba.xri_bmask); | 5824 | kfree(phba->sli4_hba.xri_bmask); |
| @@ -5992,7 +6000,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba) | |||
| 5992 | struct lpfc_sglq *sglq_entry = NULL; | 6000 | struct lpfc_sglq *sglq_entry = NULL; |
| 5993 | struct lpfc_sglq *sglq_entry_next = NULL; | 6001 | struct lpfc_sglq *sglq_entry_next = NULL; |
| 5994 | struct lpfc_sglq *sglq_entry_first = NULL; | 6002 | struct lpfc_sglq *sglq_entry_first = NULL; |
| 5995 | int status, post_cnt = 0, num_posted = 0, block_cnt = 0; | 6003 | int status, total_cnt, post_cnt = 0, num_posted = 0, block_cnt = 0; |
| 5996 | int last_xritag = NO_XRI; | 6004 | int last_xritag = NO_XRI; |
| 5997 | LIST_HEAD(prep_sgl_list); | 6005 | LIST_HEAD(prep_sgl_list); |
| 5998 | LIST_HEAD(blck_sgl_list); | 6006 | LIST_HEAD(blck_sgl_list); |
| @@ -6004,6 +6012,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba) | |||
| 6004 | list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &allc_sgl_list); | 6012 | list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &allc_sgl_list); |
| 6005 | spin_unlock_irq(&phba->hbalock); | 6013 | spin_unlock_irq(&phba->hbalock); |
| 6006 | 6014 | ||
| 6015 | total_cnt = phba->sli4_hba.els_xri_cnt; | ||
| 6007 | list_for_each_entry_safe(sglq_entry, sglq_entry_next, | 6016 | list_for_each_entry_safe(sglq_entry, sglq_entry_next, |
| 6008 | &allc_sgl_list, list) { | 6017 | &allc_sgl_list, list) { |
| 6009 | list_del_init(&sglq_entry->list); | 6018 | list_del_init(&sglq_entry->list); |
| @@ -6055,9 +6064,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba) | |||
| 6055 | sglq_entry->sli4_xritag); | 6064 | sglq_entry->sli4_xritag); |
| 6056 | list_add_tail(&sglq_entry->list, | 6065 | list_add_tail(&sglq_entry->list, |
| 6057 | &free_sgl_list); | 6066 | &free_sgl_list); |
| 6058 | spin_lock_irq(&phba->hbalock); | 6067 | total_cnt--; |
| 6059 | phba->sli4_hba.els_xri_cnt--; | ||
| 6060 | spin_unlock_irq(&phba->hbalock); | ||
| 6061 | } | 6068 | } |
| 6062 | } | 6069 | } |
| 6063 | } | 6070 | } |
| @@ -6085,9 +6092,7 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba) | |||
| 6085 | (sglq_entry_first->sli4_xritag + | 6092 | (sglq_entry_first->sli4_xritag + |
| 6086 | post_cnt - 1)); | 6093 | post_cnt - 1)); |
| 6087 | list_splice_init(&blck_sgl_list, &free_sgl_list); | 6094 | list_splice_init(&blck_sgl_list, &free_sgl_list); |
| 6088 | spin_lock_irq(&phba->hbalock); | 6095 | total_cnt -= post_cnt; |
| 6089 | phba->sli4_hba.els_xri_cnt -= post_cnt; | ||
| 6090 | spin_unlock_irq(&phba->hbalock); | ||
| 6091 | } | 6096 | } |
| 6092 | 6097 | ||
| 6093 | /* don't reset xirtag due to hole in xri block */ | 6098 | /* don't reset xirtag due to hole in xri block */ |
| @@ -6097,6 +6102,8 @@ lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba) | |||
| 6097 | /* reset els sgl post count for next round of posting */ | 6102 | /* reset els sgl post count for next round of posting */ |
| 6098 | post_cnt = 0; | 6103 | post_cnt = 0; |
| 6099 | } | 6104 | } |
| 6105 | /* update the number of XRIs posted for ELS */ | ||
| 6106 | phba->sli4_hba.els_xri_cnt = total_cnt; | ||
| 6100 | 6107 | ||
| 6101 | /* free the els sgls failed to post */ | 6108 | /* free the els sgls failed to post */ |
| 6102 | lpfc_free_sgl_list(phba, &free_sgl_list); | 6109 | lpfc_free_sgl_list(phba, &free_sgl_list); |
| @@ -6446,16 +6453,17 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) | |||
| 6446 | 6453 | ||
| 6447 | /* Start the ELS watchdog timer */ | 6454 | /* Start the ELS watchdog timer */ |
| 6448 | mod_timer(&vport->els_tmofunc, | 6455 | mod_timer(&vport->els_tmofunc, |
| 6449 | jiffies + HZ * (phba->fc_ratov * 2)); | 6456 | jiffies + msecs_to_jiffies(1000 * (phba->fc_ratov * 2))); |
| 6450 | 6457 | ||
| 6451 | /* Start heart beat timer */ | 6458 | /* Start heart beat timer */ |
| 6452 | mod_timer(&phba->hb_tmofunc, | 6459 | mod_timer(&phba->hb_tmofunc, |
| 6453 | jiffies + HZ * LPFC_HB_MBOX_INTERVAL); | 6460 | jiffies + msecs_to_jiffies(1000 * LPFC_HB_MBOX_INTERVAL)); |
| 6454 | phba->hb_outstanding = 0; | 6461 | phba->hb_outstanding = 0; |
| 6455 | phba->last_completion_time = jiffies; | 6462 | phba->last_completion_time = jiffies; |
| 6456 | 6463 | ||
| 6457 | /* Start error attention (ERATT) polling timer */ | 6464 | /* Start error attention (ERATT) polling timer */ |
| 6458 | mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL); | 6465 | mod_timer(&phba->eratt_poll, |
| 6466 | jiffies + msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL)); | ||
| 6459 | 6467 | ||
| 6460 | /* Enable PCIe device Advanced Error Reporting (AER) if configured */ | 6468 | /* Enable PCIe device Advanced Error Reporting (AER) if configured */ |
| 6461 | if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) { | 6469 | if (phba->cfg_aer_support == 1 && !(phba->hba_flag & HBA_AER_ENABLED)) { |
| @@ -6822,8 +6830,9 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, | |||
| 6822 | goto out_not_finished; | 6830 | goto out_not_finished; |
| 6823 | } | 6831 | } |
| 6824 | /* timeout active mbox command */ | 6832 | /* timeout active mbox command */ |
| 6825 | mod_timer(&psli->mbox_tmo, (jiffies + | 6833 | timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba, pmbox) * |
| 6826 | (HZ * lpfc_mbox_tmo_val(phba, pmbox)))); | 6834 | 1000); |
| 6835 | mod_timer(&psli->mbox_tmo, jiffies + timeout); | ||
| 6827 | } | 6836 | } |
| 6828 | 6837 | ||
| 6829 | /* Mailbox cmd <cmd> issue */ | 6838 | /* Mailbox cmd <cmd> issue */ |
| @@ -7496,7 +7505,7 @@ lpfc_sli4_post_async_mbox(struct lpfc_hba *phba) | |||
| 7496 | 7505 | ||
| 7497 | /* Start timer for the mbox_tmo and log some mailbox post messages */ | 7506 | /* Start timer for the mbox_tmo and log some mailbox post messages */ |
| 7498 | mod_timer(&psli->mbox_tmo, (jiffies + | 7507 | mod_timer(&psli->mbox_tmo, (jiffies + |
| 7499 | (HZ * lpfc_mbox_tmo_val(phba, mboxq)))); | 7508 | msecs_to_jiffies(1000 * lpfc_mbox_tmo_val(phba, mboxq)))); |
| 7500 | 7509 | ||
| 7501 | lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, | 7510 | lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_SLI, |
| 7502 | "(%d):0355 Mailbox cmd x%x (x%x/x%x) issue Data: " | 7511 | "(%d):0355 Mailbox cmd x%x (x%x/x%x) issue Data: " |
| @@ -7914,15 +7923,21 @@ lpfc_sli4_bpl2sgl(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, | |||
| 7914 | static inline uint32_t | 7923 | static inline uint32_t |
| 7915 | lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba) | 7924 | lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba) |
| 7916 | { | 7925 | { |
| 7917 | int i; | 7926 | struct lpfc_vector_map_info *cpup; |
| 7918 | 7927 | int chann, cpu; | |
| 7919 | if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU) | ||
| 7920 | i = smp_processor_id(); | ||
| 7921 | else | ||
| 7922 | i = atomic_add_return(1, &phba->fcp_qidx); | ||
| 7923 | 7928 | ||
| 7924 | i = (i % phba->cfg_fcp_io_channel); | 7929 | if (phba->cfg_fcp_io_sched == LPFC_FCP_SCHED_BY_CPU) { |
| 7925 | return i; | 7930 | cpu = smp_processor_id(); |
| 7931 | if (cpu < phba->sli4_hba.num_present_cpu) { | ||
| 7932 | cpup = phba->sli4_hba.cpu_map; | ||
| 7933 | cpup += cpu; | ||
| 7934 | return cpup->channel_id; | ||
| 7935 | } | ||
| 7936 | chann = cpu; | ||
| 7937 | } | ||
| 7938 | chann = atomic_add_return(1, &phba->fcp_qidx); | ||
| 7939 | chann = (chann % phba->cfg_fcp_io_channel); | ||
| 7940 | return chann; | ||
| 7926 | } | 7941 | } |
| 7927 | 7942 | ||
| 7928 | /** | 7943 | /** |
| @@ -8444,10 +8459,14 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, | |||
| 8444 | 8459 | ||
| 8445 | if ((piocb->iocb_flag & LPFC_IO_FCP) || | 8460 | if ((piocb->iocb_flag & LPFC_IO_FCP) || |
| 8446 | (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) { | 8461 | (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) { |
| 8462 | if (unlikely(!phba->sli4_hba.fcp_wq)) | ||
| 8463 | return IOCB_ERROR; | ||
| 8447 | if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx], | 8464 | if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx], |
| 8448 | &wqe)) | 8465 | &wqe)) |
| 8449 | return IOCB_ERROR; | 8466 | return IOCB_ERROR; |
| 8450 | } else { | 8467 | } else { |
| 8468 | if (unlikely(!phba->sli4_hba.els_wq)) | ||
| 8469 | return IOCB_ERROR; | ||
| 8451 | if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) | 8470 | if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe)) |
| 8452 | return IOCB_ERROR; | 8471 | return IOCB_ERROR; |
| 8453 | } | 8472 | } |
| @@ -10003,7 +10022,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, | |||
| 10003 | retval = lpfc_sli_issue_iocb(phba, ring_number, piocb, | 10022 | retval = lpfc_sli_issue_iocb(phba, ring_number, piocb, |
| 10004 | SLI_IOCB_RET_IOCB); | 10023 | SLI_IOCB_RET_IOCB); |
| 10005 | if (retval == IOCB_SUCCESS) { | 10024 | if (retval == IOCB_SUCCESS) { |
| 10006 | timeout_req = timeout * HZ; | 10025 | timeout_req = msecs_to_jiffies(timeout * 1000); |
| 10007 | timeleft = wait_event_timeout(done_q, | 10026 | timeleft = wait_event_timeout(done_q, |
| 10008 | lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE), | 10027 | lpfc_chk_iocb_flg(phba, piocb, LPFC_IO_WAKE), |
| 10009 | timeout_req); | 10028 | timeout_req); |
| @@ -10108,7 +10127,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, | |||
| 10108 | if (retval == MBX_BUSY || retval == MBX_SUCCESS) { | 10127 | if (retval == MBX_BUSY || retval == MBX_SUCCESS) { |
| 10109 | wait_event_interruptible_timeout(done_q, | 10128 | wait_event_interruptible_timeout(done_q, |
| 10110 | pmboxq->mbox_flag & LPFC_MBX_WAKE, | 10129 | pmboxq->mbox_flag & LPFC_MBX_WAKE, |
| 10111 | timeout * HZ); | 10130 | msecs_to_jiffies(timeout * 1000)); |
| 10112 | 10131 | ||
| 10113 | spin_lock_irqsave(&phba->hbalock, flag); | 10132 | spin_lock_irqsave(&phba->hbalock, flag); |
| 10114 | pmboxq->context1 = NULL; | 10133 | pmboxq->context1 = NULL; |
| @@ -12899,8 +12918,9 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq, | |||
| 12899 | } | 12918 | } |
| 12900 | wq->db_regaddr = bar_memmap_p + db_offset; | 12919 | wq->db_regaddr = bar_memmap_p + db_offset; |
| 12901 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 12920 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 12902 | "3264 WQ[%d]: barset:x%x, offset:x%x\n", | 12921 | "3264 WQ[%d]: barset:x%x, offset:x%x, " |
| 12903 | wq->queue_id, pci_barset, db_offset); | 12922 | "format:x%x\n", wq->queue_id, pci_barset, |
| 12923 | db_offset, wq->db_format); | ||
| 12904 | } else { | 12924 | } else { |
| 12905 | wq->db_format = LPFC_DB_LIST_FORMAT; | 12925 | wq->db_format = LPFC_DB_LIST_FORMAT; |
| 12906 | wq->db_regaddr = phba->sli4_hba.WQDBregaddr; | 12926 | wq->db_regaddr = phba->sli4_hba.WQDBregaddr; |
| @@ -13120,8 +13140,9 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, | |||
| 13120 | } | 13140 | } |
| 13121 | hrq->db_regaddr = bar_memmap_p + db_offset; | 13141 | hrq->db_regaddr = bar_memmap_p + db_offset; |
| 13122 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 13142 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
| 13123 | "3266 RQ[qid:%d]: barset:x%x, offset:x%x\n", | 13143 | "3266 RQ[qid:%d]: barset:x%x, offset:x%x, " |
| 13124 | hrq->queue_id, pci_barset, db_offset); | 13144 | "format:x%x\n", hrq->queue_id, pci_barset, |
| 13145 | db_offset, hrq->db_format); | ||
| 13125 | } else { | 13146 | } else { |
| 13126 | hrq->db_format = LPFC_DB_RING_FORMAT; | 13147 | hrq->db_format = LPFC_DB_RING_FORMAT; |
| 13127 | hrq->db_regaddr = phba->sli4_hba.RQDBregaddr; | 13148 | hrq->db_regaddr = phba->sli4_hba.RQDBregaddr; |
| @@ -13971,13 +13992,14 @@ lpfc_fc_frame_check(struct lpfc_hba *phba, struct fc_frame_header *fc_hdr) | |||
| 13971 | } | 13992 | } |
| 13972 | 13993 | ||
| 13973 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 13994 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
| 13974 | "2538 Received frame rctl:%s type:%s " | 13995 | "2538 Received frame rctl:%s (x%x), type:%s (x%x), " |
| 13975 | "Frame Data:%08x %08x %08x %08x %08x %08x\n", | 13996 | "frame Data:%08x %08x %08x %08x %08x %08x %08x\n", |
| 13976 | rctl_names[fc_hdr->fh_r_ctl], | 13997 | rctl_names[fc_hdr->fh_r_ctl], fc_hdr->fh_r_ctl, |
| 13977 | type_names[fc_hdr->fh_type], | 13998 | type_names[fc_hdr->fh_type], fc_hdr->fh_type, |
| 13978 | be32_to_cpu(header[0]), be32_to_cpu(header[1]), | 13999 | be32_to_cpu(header[0]), be32_to_cpu(header[1]), |
| 13979 | be32_to_cpu(header[2]), be32_to_cpu(header[3]), | 14000 | be32_to_cpu(header[2]), be32_to_cpu(header[3]), |
| 13980 | be32_to_cpu(header[4]), be32_to_cpu(header[5])); | 14001 | be32_to_cpu(header[4]), be32_to_cpu(header[5]), |
| 14002 | be32_to_cpu(header[6])); | ||
| 13981 | return 0; | 14003 | return 0; |
| 13982 | drop: | 14004 | drop: |
| 13983 | lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, | 14005 | lpfc_printf_log(phba, KERN_WARNING, LOG_ELS, |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index be02b59ea279..67af460184ba 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
| @@ -346,11 +346,6 @@ struct lpfc_bmbx { | |||
| 346 | #define SLI4_CT_VFI 2 | 346 | #define SLI4_CT_VFI 2 |
| 347 | #define SLI4_CT_FCFI 3 | 347 | #define SLI4_CT_FCFI 3 |
| 348 | 348 | ||
| 349 | #define LPFC_SLI4_FL1_MAX_SEGMENT_SIZE 0x10000 | ||
| 350 | #define LPFC_SLI4_FL1_MAX_BUF_SIZE 0X2000 | ||
| 351 | #define LPFC_SLI4_MIN_BUF_SIZE 0x400 | ||
| 352 | #define LPFC_SLI4_MAX_BUF_SIZE 0x20000 | ||
| 353 | |||
| 354 | /* | 349 | /* |
| 355 | * SLI4 specific data structures | 350 | * SLI4 specific data structures |
| 356 | */ | 351 | */ |
| @@ -440,6 +435,17 @@ struct lpfc_sli4_lnk_info { | |||
| 440 | 435 | ||
| 441 | #define LPFC_SLI4_HANDLER_NAME_SZ 16 | 436 | #define LPFC_SLI4_HANDLER_NAME_SZ 16 |
| 442 | 437 | ||
| 438 | /* Used for IRQ vector to CPU mapping */ | ||
| 439 | struct lpfc_vector_map_info { | ||
| 440 | uint16_t phys_id; | ||
| 441 | uint16_t core_id; | ||
| 442 | uint16_t irq; | ||
| 443 | uint16_t channel_id; | ||
| 444 | struct cpumask maskbits; | ||
| 445 | }; | ||
| 446 | #define LPFC_VECTOR_MAP_EMPTY 0xffff | ||
| 447 | #define LPFC_MAX_CPU 256 | ||
| 448 | |||
| 443 | /* SLI4 HBA data structure entries */ | 449 | /* SLI4 HBA data structure entries */ |
| 444 | struct lpfc_sli4_hba { | 450 | struct lpfc_sli4_hba { |
| 445 | void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for | 451 | void __iomem *conf_regs_memmap_p; /* Kernel memory mapped address for |
| @@ -573,6 +579,11 @@ struct lpfc_sli4_hba { | |||
| 573 | struct lpfc_iov iov; | 579 | struct lpfc_iov iov; |
| 574 | spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ | 580 | spinlock_t abts_scsi_buf_list_lock; /* list of aborted SCSI IOs */ |
| 575 | spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */ | 581 | spinlock_t abts_sgl_list_lock; /* list of aborted els IOs */ |
| 582 | |||
| 583 | /* CPU to vector mapping information */ | ||
| 584 | struct lpfc_vector_map_info *cpu_map; | ||
| 585 | uint16_t num_online_cpu; | ||
| 586 | uint16_t num_present_cpu; | ||
| 576 | }; | 587 | }; |
| 577 | 588 | ||
| 578 | enum lpfc_sge_type { | 589 | enum lpfc_sge_type { |
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 664cd04f7cd8..a38dc3b16969 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | * included with this package. * | 18 | * included with this package. * |
| 19 | *******************************************************************/ | 19 | *******************************************************************/ |
| 20 | 20 | ||
| 21 | #define LPFC_DRIVER_VERSION "8.3.38" | 21 | #define LPFC_DRIVER_VERSION "8.3.39" |
| 22 | #define LPFC_DRIVER_NAME "lpfc" | 22 | #define LPFC_DRIVER_NAME "lpfc" |
| 23 | 23 | ||
| 24 | /* Used for SLI 2/3 */ | 24 | /* Used for SLI 2/3 */ |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index 0fe188e66000..e28e431564b0 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
| @@ -80,7 +80,7 @@ inline void lpfc_vport_set_state(struct lpfc_vport *vport, | |||
| 80 | } | 80 | } |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static int | 83 | int |
| 84 | lpfc_alloc_vpi(struct lpfc_hba *phba) | 84 | lpfc_alloc_vpi(struct lpfc_hba *phba) |
| 85 | { | 85 | { |
| 86 | unsigned long vpi; | 86 | unsigned long vpi; |
| @@ -568,6 +568,7 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
| 568 | struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; | 568 | struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data; |
| 569 | struct lpfc_hba *phba = vport->phba; | 569 | struct lpfc_hba *phba = vport->phba; |
| 570 | long timeout; | 570 | long timeout; |
| 571 | bool ns_ndlp_referenced = false; | ||
| 571 | 572 | ||
| 572 | if (vport->port_type == LPFC_PHYSICAL_PORT) { | 573 | if (vport->port_type == LPFC_PHYSICAL_PORT) { |
| 573 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, | 574 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, |
| @@ -628,6 +629,18 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
| 628 | 629 | ||
| 629 | lpfc_debugfs_terminate(vport); | 630 | lpfc_debugfs_terminate(vport); |
| 630 | 631 | ||
| 632 | /* | ||
| 633 | * The call to fc_remove_host might release the NameServer ndlp. Since | ||
| 634 | * we might need to use the ndlp to send the DA_ID CT command, | ||
| 635 | * increment the reference for the NameServer ndlp to prevent it from | ||
| 636 | * being released. | ||
| 637 | */ | ||
| 638 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | ||
| 639 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { | ||
| 640 | lpfc_nlp_get(ndlp); | ||
| 641 | ns_ndlp_referenced = true; | ||
| 642 | } | ||
| 643 | |||
| 631 | /* Remove FC host and then SCSI host with the vport */ | 644 | /* Remove FC host and then SCSI host with the vport */ |
| 632 | fc_remove_host(lpfc_shost_from_vport(vport)); | 645 | fc_remove_host(lpfc_shost_from_vport(vport)); |
| 633 | scsi_remove_host(lpfc_shost_from_vport(vport)); | 646 | scsi_remove_host(lpfc_shost_from_vport(vport)); |
| @@ -734,6 +747,16 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
| 734 | lpfc_discovery_wait(vport); | 747 | lpfc_discovery_wait(vport); |
| 735 | 748 | ||
| 736 | skip_logo: | 749 | skip_logo: |
| 750 | |||
| 751 | /* | ||
| 752 | * If the NameServer ndlp has been incremented to allow the DA_ID CT | ||
| 753 | * command to be sent, decrement the ndlp now. | ||
| 754 | */ | ||
| 755 | if (ns_ndlp_referenced) { | ||
| 756 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | ||
| 757 | lpfc_nlp_put(ndlp); | ||
| 758 | } | ||
| 759 | |||
| 737 | lpfc_cleanup(vport); | 760 | lpfc_cleanup(vport); |
| 738 | lpfc_sli_host_down(vport); | 761 | lpfc_sli_host_down(vport); |
| 739 | 762 | ||
diff --git a/drivers/scsi/lpfc/lpfc_vport.h b/drivers/scsi/lpfc/lpfc_vport.h index 90828340acea..6b2c94eb8134 100644 --- a/drivers/scsi/lpfc/lpfc_vport.h +++ b/drivers/scsi/lpfc/lpfc_vport.h | |||
| @@ -90,6 +90,7 @@ int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *); | |||
| 90 | int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint); | 90 | int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint); |
| 91 | struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *); | 91 | struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *); |
| 92 | void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **); | 92 | void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **); |
| 93 | int lpfc_alloc_vpi(struct lpfc_hba *phba); | ||
| 93 | 94 | ||
| 94 | /* | 95 | /* |
| 95 | * queuecommand VPORT-specific return codes. Specified in the host byte code. | 96 | * queuecommand VPORT-specific return codes. Specified in the host byte code. |
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 7c90d57b867e..3a9ddae86f1f 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c | |||
| @@ -4931,11 +4931,12 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) | |||
| 4931 | printk(KERN_ERR "megaraid_sas: timed out while" | 4931 | printk(KERN_ERR "megaraid_sas: timed out while" |
| 4932 | "waiting for HBA to recover\n"); | 4932 | "waiting for HBA to recover\n"); |
| 4933 | error = -ENODEV; | 4933 | error = -ENODEV; |
| 4934 | goto out_kfree_ioc; | 4934 | goto out_up; |
| 4935 | } | 4935 | } |
| 4936 | spin_unlock_irqrestore(&instance->hba_lock, flags); | 4936 | spin_unlock_irqrestore(&instance->hba_lock, flags); |
| 4937 | 4937 | ||
| 4938 | error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc); | 4938 | error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc); |
| 4939 | out_up: | ||
| 4939 | up(&instance->ioctl_sem); | 4940 | up(&instance->ioctl_sem); |
| 4940 | 4941 | ||
| 4941 | out_kfree_ioc: | 4942 | out_kfree_ioc: |
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 74550922ad55..7b7381d7671f 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c | |||
| @@ -254,7 +254,7 @@ static int mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost) | |||
| 254 | } | 254 | } |
| 255 | for (i = 0; i < MVS_MAX_DEVICES; i++) { | 255 | for (i = 0; i < MVS_MAX_DEVICES; i++) { |
| 256 | mvi->devices[i].taskfileset = MVS_ID_NOT_MAPPED; | 256 | mvi->devices[i].taskfileset = MVS_ID_NOT_MAPPED; |
| 257 | mvi->devices[i].dev_type = NO_DEVICE; | 257 | mvi->devices[i].dev_type = SAS_PHY_UNUSED; |
| 258 | mvi->devices[i].device_id = i; | 258 | mvi->devices[i].device_id = i; |
| 259 | mvi->devices[i].dev_status = MVS_DEV_NORMAL; | 259 | mvi->devices[i].dev_status = MVS_DEV_NORMAL; |
| 260 | init_timer(&mvi->devices[i].timer); | 260 | init_timer(&mvi->devices[i].timer); |
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 532110f4562a..c9e244984e30 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c | |||
| @@ -706,7 +706,7 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi, | |||
| 706 | return 0; | 706 | return 0; |
| 707 | } | 707 | } |
| 708 | 708 | ||
| 709 | #define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == NO_DEVICE))) | 709 | #define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == SAS_PHY_UNUSED))) |
| 710 | static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf, | 710 | static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf, |
| 711 | struct mvs_tmf_task *tmf, int *pass) | 711 | struct mvs_tmf_task *tmf, int *pass) |
| 712 | { | 712 | { |
| @@ -726,7 +726,7 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf | |||
| 726 | * libsas will use dev->port, should | 726 | * libsas will use dev->port, should |
| 727 | * not call task_done for sata | 727 | * not call task_done for sata |
| 728 | */ | 728 | */ |
| 729 | if (dev->dev_type != SATA_DEV) | 729 | if (dev->dev_type != SAS_SATA_DEV) |
| 730 | task->task_done(task); | 730 | task->task_done(task); |
| 731 | return rc; | 731 | return rc; |
| 732 | } | 732 | } |
| @@ -1159,10 +1159,10 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st) | |||
| 1159 | phy->identify.device_type = | 1159 | phy->identify.device_type = |
| 1160 | phy->att_dev_info & PORT_DEV_TYPE_MASK; | 1160 | phy->att_dev_info & PORT_DEV_TYPE_MASK; |
| 1161 | 1161 | ||
| 1162 | if (phy->identify.device_type == SAS_END_DEV) | 1162 | if (phy->identify.device_type == SAS_END_DEVICE) |
| 1163 | phy->identify.target_port_protocols = | 1163 | phy->identify.target_port_protocols = |
| 1164 | SAS_PROTOCOL_SSP; | 1164 | SAS_PROTOCOL_SSP; |
| 1165 | else if (phy->identify.device_type != NO_DEVICE) | 1165 | else if (phy->identify.device_type != SAS_PHY_UNUSED) |
| 1166 | phy->identify.target_port_protocols = | 1166 | phy->identify.target_port_protocols = |
| 1167 | SAS_PROTOCOL_SMP; | 1167 | SAS_PROTOCOL_SMP; |
| 1168 | if (oob_done) | 1168 | if (oob_done) |
| @@ -1260,7 +1260,7 @@ struct mvs_device *mvs_alloc_dev(struct mvs_info *mvi) | |||
| 1260 | { | 1260 | { |
| 1261 | u32 dev; | 1261 | u32 dev; |
| 1262 | for (dev = 0; dev < MVS_MAX_DEVICES; dev++) { | 1262 | for (dev = 0; dev < MVS_MAX_DEVICES; dev++) { |
| 1263 | if (mvi->devices[dev].dev_type == NO_DEVICE) { | 1263 | if (mvi->devices[dev].dev_type == SAS_PHY_UNUSED) { |
| 1264 | mvi->devices[dev].device_id = dev; | 1264 | mvi->devices[dev].device_id = dev; |
| 1265 | return &mvi->devices[dev]; | 1265 | return &mvi->devices[dev]; |
| 1266 | } | 1266 | } |
| @@ -1278,7 +1278,7 @@ void mvs_free_dev(struct mvs_device *mvi_dev) | |||
| 1278 | u32 id = mvi_dev->device_id; | 1278 | u32 id = mvi_dev->device_id; |
| 1279 | memset(mvi_dev, 0, sizeof(*mvi_dev)); | 1279 | memset(mvi_dev, 0, sizeof(*mvi_dev)); |
| 1280 | mvi_dev->device_id = id; | 1280 | mvi_dev->device_id = id; |
| 1281 | mvi_dev->dev_type = NO_DEVICE; | 1281 | mvi_dev->dev_type = SAS_PHY_UNUSED; |
| 1282 | mvi_dev->dev_status = MVS_DEV_NORMAL; | 1282 | mvi_dev->dev_status = MVS_DEV_NORMAL; |
| 1283 | mvi_dev->taskfileset = MVS_ID_NOT_MAPPED; | 1283 | mvi_dev->taskfileset = MVS_ID_NOT_MAPPED; |
| 1284 | } | 1284 | } |
| @@ -1480,7 +1480,7 @@ static int mvs_debug_I_T_nexus_reset(struct domain_device *dev) | |||
| 1480 | { | 1480 | { |
| 1481 | int rc; | 1481 | int rc; |
| 1482 | struct sas_phy *phy = sas_get_local_phy(dev); | 1482 | struct sas_phy *phy = sas_get_local_phy(dev); |
| 1483 | int reset_type = (dev->dev_type == SATA_DEV || | 1483 | int reset_type = (dev->dev_type == SAS_SATA_DEV || |
| 1484 | (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; | 1484 | (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; |
| 1485 | rc = sas_phy_reset(phy, reset_type); | 1485 | rc = sas_phy_reset(phy, reset_type); |
| 1486 | sas_put_local_phy(phy); | 1486 | sas_put_local_phy(phy); |
| @@ -1629,7 +1629,7 @@ int mvs_abort_task(struct sas_task *task) | |||
| 1629 | 1629 | ||
| 1630 | } else if (task->task_proto & SAS_PROTOCOL_SATA || | 1630 | } else if (task->task_proto & SAS_PROTOCOL_SATA || |
| 1631 | task->task_proto & SAS_PROTOCOL_STP) { | 1631 | task->task_proto & SAS_PROTOCOL_STP) { |
| 1632 | if (SATA_DEV == dev->dev_type) { | 1632 | if (SAS_SATA_DEV == dev->dev_type) { |
| 1633 | struct mvs_slot_info *slot = task->lldd_task; | 1633 | struct mvs_slot_info *slot = task->lldd_task; |
| 1634 | u32 slot_idx = (u32)(slot - mvi->slot_info); | 1634 | u32 slot_idx = (u32)(slot - mvi->slot_info); |
| 1635 | mv_dprintk("mvs_abort_task() mvi=%p task=%p " | 1635 | mv_dprintk("mvs_abort_task() mvi=%p task=%p " |
diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index 9f3cc13a5ce7..60e2fb7f2dca 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h | |||
| @@ -67,7 +67,7 @@ extern const struct mvs_dispatch mvs_94xx_dispatch; | |||
| 67 | extern struct kmem_cache *mvs_task_list_cache; | 67 | extern struct kmem_cache *mvs_task_list_cache; |
| 68 | 68 | ||
| 69 | #define DEV_IS_EXPANDER(type) \ | 69 | #define DEV_IS_EXPANDER(type) \ |
| 70 | ((type == EDGE_DEV) || (type == FANOUT_DEV)) | 70 | ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) |
| 71 | 71 | ||
| 72 | #define bit(n) ((u64)1 << n) | 72 | #define bit(n) ((u64)1 << n) |
| 73 | 73 | ||
| @@ -241,7 +241,7 @@ struct mvs_phy { | |||
| 241 | 241 | ||
| 242 | struct mvs_device { | 242 | struct mvs_device { |
| 243 | struct list_head dev_entry; | 243 | struct list_head dev_entry; |
| 244 | enum sas_dev_type dev_type; | 244 | enum sas_device_type dev_type; |
| 245 | struct mvs_info *mvi_info; | 245 | struct mvs_info *mvi_info; |
| 246 | struct domain_device *sas_device; | 246 | struct domain_device *sas_device; |
| 247 | struct timer_list timer; | 247 | struct timer_list timer; |
diff --git a/drivers/scsi/pm8001/Makefile b/drivers/scsi/pm8001/Makefile index 52f04296171c..ce4cd87c7c66 100644 --- a/drivers/scsi/pm8001/Makefile +++ b/drivers/scsi/pm8001/Makefile | |||
| @@ -4,9 +4,10 @@ | |||
| 4 | # Copyright (C) 2008-2009 USI Co., Ltd. | 4 | # Copyright (C) 2008-2009 USI Co., Ltd. |
| 5 | 5 | ||
| 6 | 6 | ||
| 7 | obj-$(CONFIG_SCSI_PM8001) += pm8001.o | 7 | obj-$(CONFIG_SCSI_PM8001) += pm80xx.o |
| 8 | pm8001-y += pm8001_init.o \ | 8 | pm80xx-y += pm8001_init.o \ |
| 9 | pm8001_sas.o \ | 9 | pm8001_sas.o \ |
| 10 | pm8001_ctl.o \ | 10 | pm8001_ctl.o \ |
| 11 | pm8001_hwi.o | 11 | pm8001_hwi.o \ |
| 12 | pm80xx_hwi.o | ||
| 12 | 13 | ||
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index 45bc197bc22f..d99f41c2ca13 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver | 2 | * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2008-2009 USI Co., Ltd. | 4 | * Copyright (c) 2008-2009 USI Co., Ltd. |
| 5 | * All rights reserved. | 5 | * All rights reserved. |
| @@ -58,8 +58,13 @@ static ssize_t pm8001_ctl_mpi_interface_rev_show(struct device *cdev, | |||
| 58 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | 58 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); |
| 59 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | 59 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; |
| 60 | 60 | ||
| 61 | return snprintf(buf, PAGE_SIZE, "%d\n", | 61 | if (pm8001_ha->chip_id == chip_8001) { |
| 62 | pm8001_ha->main_cfg_tbl.interface_rev); | 62 | return snprintf(buf, PAGE_SIZE, "%d\n", |
| 63 | pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev); | ||
| 64 | } else { | ||
| 65 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
| 66 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev); | ||
| 67 | } | ||
| 63 | } | 68 | } |
| 64 | static | 69 | static |
| 65 | DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL); | 70 | DEVICE_ATTR(interface_rev, S_IRUGO, pm8001_ctl_mpi_interface_rev_show, NULL); |
| @@ -78,11 +83,19 @@ static ssize_t pm8001_ctl_fw_version_show(struct device *cdev, | |||
| 78 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | 83 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); |
| 79 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | 84 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; |
| 80 | 85 | ||
| 81 | return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", | 86 | if (pm8001_ha->chip_id == chip_8001) { |
| 82 | (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 24), | 87 | return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", |
| 83 | (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 16), | 88 | (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 24), |
| 84 | (u8)(pm8001_ha->main_cfg_tbl.firmware_rev >> 8), | 89 | (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 16), |
| 85 | (u8)(pm8001_ha->main_cfg_tbl.firmware_rev)); | 90 | (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev >> 8), |
| 91 | (u8)(pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev)); | ||
| 92 | } else { | ||
| 93 | return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", | ||
| 94 | (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 24), | ||
| 95 | (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 16), | ||
| 96 | (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev >> 8), | ||
| 97 | (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev)); | ||
| 98 | } | ||
| 86 | } | 99 | } |
| 87 | static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL); | 100 | static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL); |
| 88 | /** | 101 | /** |
| @@ -99,8 +112,13 @@ static ssize_t pm8001_ctl_max_out_io_show(struct device *cdev, | |||
| 99 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | 112 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); |
| 100 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | 113 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; |
| 101 | 114 | ||
| 102 | return snprintf(buf, PAGE_SIZE, "%d\n", | 115 | if (pm8001_ha->chip_id == chip_8001) { |
| 103 | pm8001_ha->main_cfg_tbl.max_out_io); | 116 | return snprintf(buf, PAGE_SIZE, "%d\n", |
| 117 | pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io); | ||
| 118 | } else { | ||
| 119 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
| 120 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io); | ||
| 121 | } | ||
| 104 | } | 122 | } |
| 105 | static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL); | 123 | static DEVICE_ATTR(max_out_io, S_IRUGO, pm8001_ctl_max_out_io_show, NULL); |
| 106 | /** | 124 | /** |
| @@ -117,8 +135,15 @@ static ssize_t pm8001_ctl_max_devices_show(struct device *cdev, | |||
| 117 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | 135 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); |
| 118 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | 136 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; |
| 119 | 137 | ||
| 120 | return snprintf(buf, PAGE_SIZE, "%04d\n", | 138 | if (pm8001_ha->chip_id == chip_8001) { |
| 121 | (u16)(pm8001_ha->main_cfg_tbl.max_sgl >> 16)); | 139 | return snprintf(buf, PAGE_SIZE, "%04d\n", |
| 140 | (u16)(pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl >> 16) | ||
| 141 | ); | ||
| 142 | } else { | ||
| 143 | return snprintf(buf, PAGE_SIZE, "%04d\n", | ||
| 144 | (u16)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl >> 16) | ||
| 145 | ); | ||
| 146 | } | ||
| 122 | } | 147 | } |
| 123 | static DEVICE_ATTR(max_devices, S_IRUGO, pm8001_ctl_max_devices_show, NULL); | 148 | static DEVICE_ATTR(max_devices, S_IRUGO, pm8001_ctl_max_devices_show, NULL); |
| 124 | /** | 149 | /** |
| @@ -136,8 +161,15 @@ static ssize_t pm8001_ctl_max_sg_list_show(struct device *cdev, | |||
| 136 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | 161 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); |
| 137 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | 162 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; |
| 138 | 163 | ||
| 139 | return snprintf(buf, PAGE_SIZE, "%04d\n", | 164 | if (pm8001_ha->chip_id == chip_8001) { |
| 140 | pm8001_ha->main_cfg_tbl.max_sgl & 0x0000FFFF); | 165 | return snprintf(buf, PAGE_SIZE, "%04d\n", |
| 166 | pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl & 0x0000FFFF | ||
| 167 | ); | ||
| 168 | } else { | ||
| 169 | return snprintf(buf, PAGE_SIZE, "%04d\n", | ||
| 170 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl & 0x0000FFFF | ||
| 171 | ); | ||
| 172 | } | ||
| 141 | } | 173 | } |
| 142 | static DEVICE_ATTR(max_sg_list, S_IRUGO, pm8001_ctl_max_sg_list_show, NULL); | 174 | static DEVICE_ATTR(max_sg_list, S_IRUGO, pm8001_ctl_max_sg_list_show, NULL); |
| 143 | 175 | ||
| @@ -173,7 +205,14 @@ static ssize_t pm8001_ctl_sas_spec_support_show(struct device *cdev, | |||
| 173 | struct Scsi_Host *shost = class_to_shost(cdev); | 205 | struct Scsi_Host *shost = class_to_shost(cdev); |
| 174 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | 206 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); |
| 175 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; | 207 | struct pm8001_hba_info *pm8001_ha = sha->lldd_ha; |
| 176 | mode = (pm8001_ha->main_cfg_tbl.ctrl_cap_flag & 0xfe000000)>>25; | 208 | /* fe000000 means supports SAS2.1 */ |
| 209 | if (pm8001_ha->chip_id == chip_8001) | ||
| 210 | mode = (pm8001_ha->main_cfg_tbl.pm8001_tbl.ctrl_cap_flag & | ||
| 211 | 0xfe000000)>>25; | ||
| 212 | else | ||
| 213 | /* fe000000 means supports SAS2.1 */ | ||
| 214 | mode = (pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag & | ||
| 215 | 0xfe000000)>>25; | ||
| 177 | return show_sas_spec_support_status(mode, buf); | 216 | return show_sas_spec_support_status(mode, buf); |
| 178 | } | 217 | } |
| 179 | static DEVICE_ATTR(sas_spec_support, S_IRUGO, | 218 | static DEVICE_ATTR(sas_spec_support, S_IRUGO, |
| @@ -361,10 +400,11 @@ static int pm8001_set_nvmd(struct pm8001_hba_info *pm8001_ha) | |||
| 361 | goto out; | 400 | goto out; |
| 362 | } | 401 | } |
| 363 | payload = (struct pm8001_ioctl_payload *)ioctlbuffer; | 402 | payload = (struct pm8001_ioctl_payload *)ioctlbuffer; |
| 364 | memcpy((u8 *)payload->func_specific, (u8 *)pm8001_ha->fw_image->data, | 403 | memcpy((u8 *)&payload->func_specific, (u8 *)pm8001_ha->fw_image->data, |
| 365 | pm8001_ha->fw_image->size); | 404 | pm8001_ha->fw_image->size); |
| 366 | payload->length = pm8001_ha->fw_image->size; | 405 | payload->length = pm8001_ha->fw_image->size; |
| 367 | payload->id = 0; | 406 | payload->id = 0; |
| 407 | payload->minor_function = 0x1; | ||
| 368 | pm8001_ha->nvmd_completion = &completion; | 408 | pm8001_ha->nvmd_completion = &completion; |
| 369 | ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); | 409 | ret = PM8001_CHIP_DISP->set_nvmd_req(pm8001_ha, payload); |
| 370 | wait_for_completion(&completion); | 410 | wait_for_completion(&completion); |
| @@ -411,7 +451,7 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) | |||
| 411 | payload->length = 1024*16; | 451 | payload->length = 1024*16; |
| 412 | payload->id = 0; | 452 | payload->id = 0; |
| 413 | fwControl = | 453 | fwControl = |
| 414 | (struct fw_control_info *)payload->func_specific; | 454 | (struct fw_control_info *)&payload->func_specific; |
| 415 | fwControl->len = IOCTL_BUF_SIZE; /* IN */ | 455 | fwControl->len = IOCTL_BUF_SIZE; /* IN */ |
| 416 | fwControl->size = partitionSize + HEADER_LEN;/* IN */ | 456 | fwControl->size = partitionSize + HEADER_LEN;/* IN */ |
| 417 | fwControl->retcode = 0;/* OUT */ | 457 | fwControl->retcode = 0;/* OUT */ |
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index c3d20c8d4abe..479c5a7a863a 100644 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver | 2 | * PMC-Sierra 8001/8081/8088/8089 SAS/SATA based host adapters driver |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2008-2009 USI Co., Ltd. | 4 | * Copyright (c) 2008-2009 USI Co., Ltd. |
| 5 | * All rights reserved. | 5 | * All rights reserved. |
| @@ -43,9 +43,12 @@ | |||
| 43 | 43 | ||
| 44 | enum chip_flavors { | 44 | enum chip_flavors { |
| 45 | chip_8001, | 45 | chip_8001, |
| 46 | chip_8008, | ||
| 47 | chip_8009, | ||
| 48 | chip_8018, | ||
| 49 | chip_8019 | ||
| 46 | }; | 50 | }; |
| 47 | #define USI_MAX_MEMCNT 9 | 51 | |
| 48 | #define PM8001_MAX_DMA_SG SG_ALL | ||
| 49 | enum phy_speed { | 52 | enum phy_speed { |
| 50 | PHY_SPEED_15 = 0x01, | 53 | PHY_SPEED_15 = 0x01, |
| 51 | PHY_SPEED_30 = 0x02, | 54 | PHY_SPEED_30 = 0x02, |
| @@ -69,23 +72,34 @@ enum port_type { | |||
| 69 | #define PM8001_MPI_QUEUE 1024 /* maximum mpi queue entries */ | 72 | #define PM8001_MPI_QUEUE 1024 /* maximum mpi queue entries */ |
| 70 | #define PM8001_MAX_INB_NUM 1 | 73 | #define PM8001_MAX_INB_NUM 1 |
| 71 | #define PM8001_MAX_OUTB_NUM 1 | 74 | #define PM8001_MAX_OUTB_NUM 1 |
| 75 | #define PM8001_MAX_SPCV_INB_NUM 1 | ||
| 76 | #define PM8001_MAX_SPCV_OUTB_NUM 4 | ||
| 72 | #define PM8001_CAN_QUEUE 508 /* SCSI Queue depth */ | 77 | #define PM8001_CAN_QUEUE 508 /* SCSI Queue depth */ |
| 73 | 78 | ||
| 79 | /* Inbound/Outbound queue size */ | ||
| 80 | #define IOMB_SIZE_SPC 64 | ||
| 81 | #define IOMB_SIZE_SPCV 128 | ||
| 82 | |||
| 74 | /* unchangeable hardware details */ | 83 | /* unchangeable hardware details */ |
| 75 | #define PM8001_MAX_PHYS 8 /* max. possible phys */ | 84 | #define PM8001_MAX_PHYS 16 /* max. possible phys */ |
| 76 | #define PM8001_MAX_PORTS 8 /* max. possible ports */ | 85 | #define PM8001_MAX_PORTS 16 /* max. possible ports */ |
| 77 | #define PM8001_MAX_DEVICES 1024 /* max supported device */ | 86 | #define PM8001_MAX_DEVICES 2048 /* max supported device */ |
| 87 | #define PM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */ | ||
| 78 | 88 | ||
| 89 | #define USI_MAX_MEMCNT_BASE 5 | ||
| 90 | #define IB (USI_MAX_MEMCNT_BASE + 1) | ||
| 91 | #define CI (IB + PM8001_MAX_SPCV_INB_NUM) | ||
| 92 | #define OB (CI + PM8001_MAX_SPCV_INB_NUM) | ||
| 93 | #define PI (OB + PM8001_MAX_SPCV_OUTB_NUM) | ||
| 94 | #define USI_MAX_MEMCNT (PI + PM8001_MAX_SPCV_OUTB_NUM) | ||
| 95 | #define PM8001_MAX_DMA_SG SG_ALL | ||
| 79 | enum memory_region_num { | 96 | enum memory_region_num { |
| 80 | AAP1 = 0x0, /* application acceleration processor */ | 97 | AAP1 = 0x0, /* application acceleration processor */ |
| 81 | IOP, /* IO processor */ | 98 | IOP, /* IO processor */ |
| 82 | CI, /* consumer index */ | ||
| 83 | PI, /* producer index */ | ||
| 84 | IB, /* inbound queue */ | ||
| 85 | OB, /* outbound queue */ | ||
| 86 | NVMD, /* NVM device */ | 99 | NVMD, /* NVM device */ |
| 87 | DEV_MEM, /* memory for devices */ | 100 | DEV_MEM, /* memory for devices */ |
| 88 | CCB_MEM, /* memory for command control block */ | 101 | CCB_MEM, /* memory for command control block */ |
| 102 | FW_FLASH /* memory for fw flash update */ | ||
| 89 | }; | 103 | }; |
| 90 | #define PM8001_EVENT_LOG_SIZE (128 * 1024) | 104 | #define PM8001_EVENT_LOG_SIZE (128 * 1024) |
| 91 | 105 | ||
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index b8dd05074abb..69dd49c05f1e 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
| @@ -50,32 +50,39 @@ | |||
| 50 | static void read_main_config_table(struct pm8001_hba_info *pm8001_ha) | 50 | static void read_main_config_table(struct pm8001_hba_info *pm8001_ha) |
| 51 | { | 51 | { |
| 52 | void __iomem *address = pm8001_ha->main_cfg_tbl_addr; | 52 | void __iomem *address = pm8001_ha->main_cfg_tbl_addr; |
| 53 | pm8001_ha->main_cfg_tbl.signature = pm8001_mr32(address, 0x00); | 53 | pm8001_ha->main_cfg_tbl.pm8001_tbl.signature = |
| 54 | pm8001_ha->main_cfg_tbl.interface_rev = pm8001_mr32(address, 0x04); | 54 | pm8001_mr32(address, 0x00); |
| 55 | pm8001_ha->main_cfg_tbl.firmware_rev = pm8001_mr32(address, 0x08); | 55 | pm8001_ha->main_cfg_tbl.pm8001_tbl.interface_rev = |
| 56 | pm8001_ha->main_cfg_tbl.max_out_io = pm8001_mr32(address, 0x0C); | 56 | pm8001_mr32(address, 0x04); |
| 57 | pm8001_ha->main_cfg_tbl.max_sgl = pm8001_mr32(address, 0x10); | 57 | pm8001_ha->main_cfg_tbl.pm8001_tbl.firmware_rev = |
| 58 | pm8001_ha->main_cfg_tbl.ctrl_cap_flag = pm8001_mr32(address, 0x14); | 58 | pm8001_mr32(address, 0x08); |
| 59 | pm8001_ha->main_cfg_tbl.gst_offset = pm8001_mr32(address, 0x18); | 59 | pm8001_ha->main_cfg_tbl.pm8001_tbl.max_out_io = |
| 60 | pm8001_ha->main_cfg_tbl.inbound_queue_offset = | 60 | pm8001_mr32(address, 0x0C); |
| 61 | pm8001_ha->main_cfg_tbl.pm8001_tbl.max_sgl = | ||
| 62 | pm8001_mr32(address, 0x10); | ||
| 63 | pm8001_ha->main_cfg_tbl.pm8001_tbl.ctrl_cap_flag = | ||
| 64 | pm8001_mr32(address, 0x14); | ||
| 65 | pm8001_ha->main_cfg_tbl.pm8001_tbl.gst_offset = | ||
| 66 | pm8001_mr32(address, 0x18); | ||
| 67 | pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_queue_offset = | ||
| 61 | pm8001_mr32(address, MAIN_IBQ_OFFSET); | 68 | pm8001_mr32(address, MAIN_IBQ_OFFSET); |
| 62 | pm8001_ha->main_cfg_tbl.outbound_queue_offset = | 69 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_queue_offset = |
| 63 | pm8001_mr32(address, MAIN_OBQ_OFFSET); | 70 | pm8001_mr32(address, MAIN_OBQ_OFFSET); |
| 64 | pm8001_ha->main_cfg_tbl.hda_mode_flag = | 71 | pm8001_ha->main_cfg_tbl.pm8001_tbl.hda_mode_flag = |
| 65 | pm8001_mr32(address, MAIN_HDA_FLAGS_OFFSET); | 72 | pm8001_mr32(address, MAIN_HDA_FLAGS_OFFSET); |
| 66 | 73 | ||
| 67 | /* read analog Setting offset from the configuration table */ | 74 | /* read analog Setting offset from the configuration table */ |
| 68 | pm8001_ha->main_cfg_tbl.anolog_setup_table_offset = | 75 | pm8001_ha->main_cfg_tbl.pm8001_tbl.anolog_setup_table_offset = |
| 69 | pm8001_mr32(address, MAIN_ANALOG_SETUP_OFFSET); | 76 | pm8001_mr32(address, MAIN_ANALOG_SETUP_OFFSET); |
| 70 | 77 | ||
| 71 | /* read Error Dump Offset and Length */ | 78 | /* read Error Dump Offset and Length */ |
| 72 | pm8001_ha->main_cfg_tbl.fatal_err_dump_offset0 = | 79 | pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_offset0 = |
| 73 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_OFFSET); | 80 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_OFFSET); |
| 74 | pm8001_ha->main_cfg_tbl.fatal_err_dump_length0 = | 81 | pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_length0 = |
| 75 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_LENGTH); | 82 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_LENGTH); |
| 76 | pm8001_ha->main_cfg_tbl.fatal_err_dump_offset1 = | 83 | pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_offset1 = |
| 77 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_OFFSET); | 84 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_OFFSET); |
| 78 | pm8001_ha->main_cfg_tbl.fatal_err_dump_length1 = | 85 | pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_dump_length1 = |
| 79 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_LENGTH); | 86 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_LENGTH); |
| 80 | } | 87 | } |
| 81 | 88 | ||
| @@ -86,31 +93,56 @@ static void read_main_config_table(struct pm8001_hba_info *pm8001_ha) | |||
| 86 | static void read_general_status_table(struct pm8001_hba_info *pm8001_ha) | 93 | static void read_general_status_table(struct pm8001_hba_info *pm8001_ha) |
| 87 | { | 94 | { |
| 88 | void __iomem *address = pm8001_ha->general_stat_tbl_addr; | 95 | void __iomem *address = pm8001_ha->general_stat_tbl_addr; |
| 89 | pm8001_ha->gs_tbl.gst_len_mpistate = pm8001_mr32(address, 0x00); | 96 | pm8001_ha->gs_tbl.pm8001_tbl.gst_len_mpistate = |
| 90 | pm8001_ha->gs_tbl.iq_freeze_state0 = pm8001_mr32(address, 0x04); | 97 | pm8001_mr32(address, 0x00); |
| 91 | pm8001_ha->gs_tbl.iq_freeze_state1 = pm8001_mr32(address, 0x08); | 98 | pm8001_ha->gs_tbl.pm8001_tbl.iq_freeze_state0 = |
| 92 | pm8001_ha->gs_tbl.msgu_tcnt = pm8001_mr32(address, 0x0C); | 99 | pm8001_mr32(address, 0x04); |
| 93 | pm8001_ha->gs_tbl.iop_tcnt = pm8001_mr32(address, 0x10); | 100 | pm8001_ha->gs_tbl.pm8001_tbl.iq_freeze_state1 = |
| 94 | pm8001_ha->gs_tbl.reserved = pm8001_mr32(address, 0x14); | 101 | pm8001_mr32(address, 0x08); |
| 95 | pm8001_ha->gs_tbl.phy_state[0] = pm8001_mr32(address, 0x18); | 102 | pm8001_ha->gs_tbl.pm8001_tbl.msgu_tcnt = |
| 96 | pm8001_ha->gs_tbl.phy_state[1] = pm8001_mr32(address, 0x1C); | 103 | pm8001_mr32(address, 0x0C); |
| 97 | pm8001_ha->gs_tbl.phy_state[2] = pm8001_mr32(address, 0x20); | 104 | pm8001_ha->gs_tbl.pm8001_tbl.iop_tcnt = |
| 98 | pm8001_ha->gs_tbl.phy_state[3] = pm8001_mr32(address, 0x24); | 105 | pm8001_mr32(address, 0x10); |
| 99 | pm8001_ha->gs_tbl.phy_state[4] = pm8001_mr32(address, 0x28); | 106 | pm8001_ha->gs_tbl.pm8001_tbl.rsvd = |
| 100 | pm8001_ha->gs_tbl.phy_state[5] = pm8001_mr32(address, 0x2C); | 107 | pm8001_mr32(address, 0x14); |
| 101 | pm8001_ha->gs_tbl.phy_state[6] = pm8001_mr32(address, 0x30); | 108 | pm8001_ha->gs_tbl.pm8001_tbl.phy_state[0] = |
| 102 | pm8001_ha->gs_tbl.phy_state[7] = pm8001_mr32(address, 0x34); | 109 | pm8001_mr32(address, 0x18); |
| 103 | pm8001_ha->gs_tbl.reserved1 = pm8001_mr32(address, 0x38); | 110 | pm8001_ha->gs_tbl.pm8001_tbl.phy_state[1] = |
| 104 | pm8001_ha->gs_tbl.reserved2 = pm8001_mr32(address, 0x3C); | 111 | pm8001_mr32(address, 0x1C); |
| 105 | pm8001_ha->gs_tbl.reserved3 = pm8001_mr32(address, 0x40); | 112 | pm8001_ha->gs_tbl.pm8001_tbl.phy_state[2] = |
| 106 | pm8001_ha->gs_tbl.recover_err_info[0] = pm8001_mr32(address, 0x44); | 113 | pm8001_mr32(address, 0x20); |
| 107 | pm8001_ha->gs_tbl.recover_err_info[1] = pm8001_mr32(address, 0x48); | 114 | pm8001_ha->gs_tbl.pm8001_tbl.phy_state[3] = |
| 108 | pm8001_ha->gs_tbl.recover_err_info[2] = pm8001_mr32(address, 0x4C); | 115 | pm8001_mr32(address, 0x24); |
| 109 | pm8001_ha->gs_tbl.recover_err_info[3] = pm8001_mr32(address, 0x50); | 116 | pm8001_ha->gs_tbl.pm8001_tbl.phy_state[4] = |
| 110 | pm8001_ha->gs_tbl.recover_err_info[4] = pm8001_mr32(address, 0x54); | 117 | pm8001_mr32(address, 0x28); |
| 111 | pm8001_ha->gs_tbl.recover_err_info[5] = pm8001_mr32(address, 0x58); | 118 | pm8001_ha->gs_tbl.pm8001_tbl.phy_state[5] = |
| 112 | pm8001_ha->gs_tbl.recover_err_info[6] = pm8001_mr32(address, 0x5C); | 119 | pm8001_mr32(address, 0x2C); |
| 113 | pm8001_ha->gs_tbl.recover_err_info[7] = pm8001_mr32(address, 0x60); | 120 | pm8001_ha->gs_tbl.pm8001_tbl.phy_state[6] = |
| 121 | pm8001_mr32(address, 0x30); | ||
| 122 | pm8001_ha->gs_tbl.pm8001_tbl.phy_state[7] = | ||
| 123 | pm8001_mr32(address, 0x34); | ||
| 124 | pm8001_ha->gs_tbl.pm8001_tbl.gpio_input_val = | ||
| 125 | pm8001_mr32(address, 0x38); | ||
| 126 | pm8001_ha->gs_tbl.pm8001_tbl.rsvd1[0] = | ||
| 127 | pm8001_mr32(address, 0x3C); | ||
| 128 | pm8001_ha->gs_tbl.pm8001_tbl.rsvd1[1] = | ||
| 129 | pm8001_mr32(address, 0x40); | ||
| 130 | pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[0] = | ||
| 131 | pm8001_mr32(address, 0x44); | ||
| 132 | pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[1] = | ||
| 133 | pm8001_mr32(address, 0x48); | ||
| 134 | pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[2] = | ||
| 135 | pm8001_mr32(address, 0x4C); | ||
| 136 | pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[3] = | ||
| 137 | pm8001_mr32(address, 0x50); | ||
| 138 | pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[4] = | ||
| 139 | pm8001_mr32(address, 0x54); | ||
| 140 | pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[5] = | ||
| 141 | pm8001_mr32(address, 0x58); | ||
| 142 | pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[6] = | ||
| 143 | pm8001_mr32(address, 0x5C); | ||
| 144 | pm8001_ha->gs_tbl.pm8001_tbl.recover_err_info[7] = | ||
| 145 | pm8001_mr32(address, 0x60); | ||
| 114 | } | 146 | } |
| 115 | 147 | ||
| 116 | /** | 148 | /** |
| @@ -119,10 +151,9 @@ static void read_general_status_table(struct pm8001_hba_info *pm8001_ha) | |||
| 119 | */ | 151 | */ |
| 120 | static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha) | 152 | static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha) |
| 121 | { | 153 | { |
| 122 | int inbQ_num = 1; | ||
| 123 | int i; | 154 | int i; |
| 124 | void __iomem *address = pm8001_ha->inbnd_q_tbl_addr; | 155 | void __iomem *address = pm8001_ha->inbnd_q_tbl_addr; |
| 125 | for (i = 0; i < inbQ_num; i++) { | 156 | for (i = 0; i < PM8001_MAX_INB_NUM; i++) { |
| 126 | u32 offset = i * 0x20; | 157 | u32 offset = i * 0x20; |
| 127 | pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = | 158 | pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = |
| 128 | get_pci_bar_index(pm8001_mr32(address, (offset + 0x14))); | 159 | get_pci_bar_index(pm8001_mr32(address, (offset + 0x14))); |
| @@ -137,10 +168,9 @@ static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha) | |||
| 137 | */ | 168 | */ |
| 138 | static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha) | 169 | static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha) |
| 139 | { | 170 | { |
| 140 | int outbQ_num = 1; | ||
| 141 | int i; | 171 | int i; |
| 142 | void __iomem *address = pm8001_ha->outbnd_q_tbl_addr; | 172 | void __iomem *address = pm8001_ha->outbnd_q_tbl_addr; |
| 143 | for (i = 0; i < outbQ_num; i++) { | 173 | for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) { |
| 144 | u32 offset = i * 0x24; | 174 | u32 offset = i * 0x24; |
| 145 | pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = | 175 | pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = |
| 146 | get_pci_bar_index(pm8001_mr32(address, (offset + 0x14))); | 176 | get_pci_bar_index(pm8001_mr32(address, (offset + 0x14))); |
| @@ -155,54 +185,57 @@ static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha) | |||
| 155 | */ | 185 | */ |
| 156 | static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) | 186 | static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) |
| 157 | { | 187 | { |
| 158 | int qn = 1; | ||
| 159 | int i; | 188 | int i; |
| 160 | u32 offsetib, offsetob; | 189 | u32 offsetib, offsetob; |
| 161 | void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr; | 190 | void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr; |
| 162 | void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr; | 191 | void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr; |
| 163 | 192 | ||
| 164 | pm8001_ha->main_cfg_tbl.inbound_q_nppd_hppd = 0; | 193 | pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_q_nppd_hppd = 0; |
| 165 | pm8001_ha->main_cfg_tbl.outbound_hw_event_pid0_3 = 0; | 194 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid0_3 = 0; |
| 166 | pm8001_ha->main_cfg_tbl.outbound_hw_event_pid4_7 = 0; | 195 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid4_7 = 0; |
| 167 | pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid0_3 = 0; | 196 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid0_3 = 0; |
| 168 | pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid4_7 = 0; | 197 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid4_7 = 0; |
| 169 | pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid0_3 = 0; | 198 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ITNexus_event_pid0_3 = |
| 170 | pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid4_7 = 0; | 199 | 0; |
| 171 | pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid0_3 = 0; | 200 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ITNexus_event_pid4_7 = |
| 172 | pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid4_7 = 0; | 201 | 0; |
| 173 | pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid0_3 = 0; | 202 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ssp_event_pid0_3 = 0; |
| 174 | pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid4_7 = 0; | 203 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_ssp_event_pid4_7 = 0; |
| 175 | 204 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_smp_event_pid0_3 = 0; | |
| 176 | pm8001_ha->main_cfg_tbl.upper_event_log_addr = | 205 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_tgt_smp_event_pid4_7 = 0; |
| 206 | |||
| 207 | pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_event_log_addr = | ||
| 177 | pm8001_ha->memoryMap.region[AAP1].phys_addr_hi; | 208 | pm8001_ha->memoryMap.region[AAP1].phys_addr_hi; |
| 178 | pm8001_ha->main_cfg_tbl.lower_event_log_addr = | 209 | pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_event_log_addr = |
| 179 | pm8001_ha->memoryMap.region[AAP1].phys_addr_lo; | 210 | pm8001_ha->memoryMap.region[AAP1].phys_addr_lo; |
| 180 | pm8001_ha->main_cfg_tbl.event_log_size = PM8001_EVENT_LOG_SIZE; | 211 | pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_size = |
| 181 | pm8001_ha->main_cfg_tbl.event_log_option = 0x01; | 212 | PM8001_EVENT_LOG_SIZE; |
| 182 | pm8001_ha->main_cfg_tbl.upper_iop_event_log_addr = | 213 | pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_option = 0x01; |
| 214 | pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_iop_event_log_addr = | ||
| 183 | pm8001_ha->memoryMap.region[IOP].phys_addr_hi; | 215 | pm8001_ha->memoryMap.region[IOP].phys_addr_hi; |
| 184 | pm8001_ha->main_cfg_tbl.lower_iop_event_log_addr = | 216 | pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_iop_event_log_addr = |
| 185 | pm8001_ha->memoryMap.region[IOP].phys_addr_lo; | 217 | pm8001_ha->memoryMap.region[IOP].phys_addr_lo; |
| 186 | pm8001_ha->main_cfg_tbl.iop_event_log_size = PM8001_EVENT_LOG_SIZE; | 218 | pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_size = |
| 187 | pm8001_ha->main_cfg_tbl.iop_event_log_option = 0x01; | 219 | PM8001_EVENT_LOG_SIZE; |
| 188 | pm8001_ha->main_cfg_tbl.fatal_err_interrupt = 0x01; | 220 | pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option = 0x01; |
| 189 | for (i = 0; i < qn; i++) { | 221 | pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt = 0x01; |
| 222 | for (i = 0; i < PM8001_MAX_INB_NUM; i++) { | ||
| 190 | pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = | 223 | pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = |
| 191 | PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30); | 224 | PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30); |
| 192 | pm8001_ha->inbnd_q_tbl[i].upper_base_addr = | 225 | pm8001_ha->inbnd_q_tbl[i].upper_base_addr = |
| 193 | pm8001_ha->memoryMap.region[IB].phys_addr_hi; | 226 | pm8001_ha->memoryMap.region[IB + i].phys_addr_hi; |
| 194 | pm8001_ha->inbnd_q_tbl[i].lower_base_addr = | 227 | pm8001_ha->inbnd_q_tbl[i].lower_base_addr = |
| 195 | pm8001_ha->memoryMap.region[IB].phys_addr_lo; | 228 | pm8001_ha->memoryMap.region[IB + i].phys_addr_lo; |
| 196 | pm8001_ha->inbnd_q_tbl[i].base_virt = | 229 | pm8001_ha->inbnd_q_tbl[i].base_virt = |
| 197 | (u8 *)pm8001_ha->memoryMap.region[IB].virt_ptr; | 230 | (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr; |
| 198 | pm8001_ha->inbnd_q_tbl[i].total_length = | 231 | pm8001_ha->inbnd_q_tbl[i].total_length = |
| 199 | pm8001_ha->memoryMap.region[IB].total_len; | 232 | pm8001_ha->memoryMap.region[IB + i].total_len; |
| 200 | pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr = | 233 | pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr = |
| 201 | pm8001_ha->memoryMap.region[CI].phys_addr_hi; | 234 | pm8001_ha->memoryMap.region[CI + i].phys_addr_hi; |
| 202 | pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr = | 235 | pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr = |
| 203 | pm8001_ha->memoryMap.region[CI].phys_addr_lo; | 236 | pm8001_ha->memoryMap.region[CI + i].phys_addr_lo; |
| 204 | pm8001_ha->inbnd_q_tbl[i].ci_virt = | 237 | pm8001_ha->inbnd_q_tbl[i].ci_virt = |
| 205 | pm8001_ha->memoryMap.region[CI].virt_ptr; | 238 | pm8001_ha->memoryMap.region[CI + i].virt_ptr; |
| 206 | offsetib = i * 0x20; | 239 | offsetib = i * 0x20; |
| 207 | pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = | 240 | pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = |
| 208 | get_pci_bar_index(pm8001_mr32(addressib, | 241 | get_pci_bar_index(pm8001_mr32(addressib, |
| @@ -212,25 +245,25 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) | |||
| 212 | pm8001_ha->inbnd_q_tbl[i].producer_idx = 0; | 245 | pm8001_ha->inbnd_q_tbl[i].producer_idx = 0; |
| 213 | pm8001_ha->inbnd_q_tbl[i].consumer_index = 0; | 246 | pm8001_ha->inbnd_q_tbl[i].consumer_index = 0; |
| 214 | } | 247 | } |
| 215 | for (i = 0; i < qn; i++) { | 248 | for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) { |
| 216 | pm8001_ha->outbnd_q_tbl[i].element_size_cnt = | 249 | pm8001_ha->outbnd_q_tbl[i].element_size_cnt = |
| 217 | PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30); | 250 | PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30); |
| 218 | pm8001_ha->outbnd_q_tbl[i].upper_base_addr = | 251 | pm8001_ha->outbnd_q_tbl[i].upper_base_addr = |
| 219 | pm8001_ha->memoryMap.region[OB].phys_addr_hi; | 252 | pm8001_ha->memoryMap.region[OB + i].phys_addr_hi; |
| 220 | pm8001_ha->outbnd_q_tbl[i].lower_base_addr = | 253 | pm8001_ha->outbnd_q_tbl[i].lower_base_addr = |
| 221 | pm8001_ha->memoryMap.region[OB].phys_addr_lo; | 254 | pm8001_ha->memoryMap.region[OB + i].phys_addr_lo; |
| 222 | pm8001_ha->outbnd_q_tbl[i].base_virt = | 255 | pm8001_ha->outbnd_q_tbl[i].base_virt = |
| 223 | (u8 *)pm8001_ha->memoryMap.region[OB].virt_ptr; | 256 | (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr; |
| 224 | pm8001_ha->outbnd_q_tbl[i].total_length = | 257 | pm8001_ha->outbnd_q_tbl[i].total_length = |
| 225 | pm8001_ha->memoryMap.region[OB].total_len; | 258 | pm8001_ha->memoryMap.region[OB + i].total_len; |
| 226 | pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr = | 259 | pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr = |
| 227 | pm8001_ha->memoryMap.region[PI].phys_addr_hi; | 260 | pm8001_ha->memoryMap.region[PI + i].phys_addr_hi; |
| 228 | pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr = | 261 | pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr = |
| 229 | pm8001_ha->memoryMap.region[PI].phys_addr_lo; | 262 | pm8001_ha->memoryMap.region[PI + i].phys_addr_lo; |
| 230 | pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = | 263 | pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = |
| 231 | 0 | (10 << 16) | (0 << 24); | 264 | 0 | (10 << 16) | (i << 24); |
| 232 | pm8001_ha->outbnd_q_tbl[i].pi_virt = | 265 | pm8001_ha->outbnd_q_tbl[i].pi_virt = |
| 233 | pm8001_ha->memoryMap.region[PI].virt_ptr; | 266 | pm8001_ha->memoryMap.region[PI + i].virt_ptr; |
| 234 | offsetob = i * 0x24; | 267 | offsetob = i * 0x24; |
| 235 | pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = | 268 | pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = |
| 236 | get_pci_bar_index(pm8001_mr32(addressob, | 269 | get_pci_bar_index(pm8001_mr32(addressob, |
| @@ -250,42 +283,51 @@ static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) | |||
| 250 | { | 283 | { |
| 251 | void __iomem *address = pm8001_ha->main_cfg_tbl_addr; | 284 | void __iomem *address = pm8001_ha->main_cfg_tbl_addr; |
| 252 | pm8001_mw32(address, 0x24, | 285 | pm8001_mw32(address, 0x24, |
| 253 | pm8001_ha->main_cfg_tbl.inbound_q_nppd_hppd); | 286 | pm8001_ha->main_cfg_tbl.pm8001_tbl.inbound_q_nppd_hppd); |
| 254 | pm8001_mw32(address, 0x28, | 287 | pm8001_mw32(address, 0x28, |
| 255 | pm8001_ha->main_cfg_tbl.outbound_hw_event_pid0_3); | 288 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid0_3); |
| 256 | pm8001_mw32(address, 0x2C, | 289 | pm8001_mw32(address, 0x2C, |
| 257 | pm8001_ha->main_cfg_tbl.outbound_hw_event_pid4_7); | 290 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_hw_event_pid4_7); |
| 258 | pm8001_mw32(address, 0x30, | 291 | pm8001_mw32(address, 0x30, |
| 259 | pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid0_3); | 292 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid0_3); |
| 260 | pm8001_mw32(address, 0x34, | 293 | pm8001_mw32(address, 0x34, |
| 261 | pm8001_ha->main_cfg_tbl.outbound_ncq_event_pid4_7); | 294 | pm8001_ha->main_cfg_tbl.pm8001_tbl.outbound_ncq_event_pid4_7); |
| 262 | pm8001_mw32(address, 0x38, | 295 | pm8001_mw32(address, 0x38, |
| 263 | pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid0_3); | 296 | pm8001_ha->main_cfg_tbl.pm8001_tbl. |
| 297 | outbound_tgt_ITNexus_event_pid0_3); | ||
| 264 | pm8001_mw32(address, 0x3C, | 298 | pm8001_mw32(address, 0x3C, |
| 265 | pm8001_ha->main_cfg_tbl.outbound_tgt_ITNexus_event_pid4_7); | 299 | pm8001_ha->main_cfg_tbl.pm8001_tbl. |
| 300 | outbound_tgt_ITNexus_event_pid4_7); | ||
| 266 | pm8001_mw32(address, 0x40, | 301 | pm8001_mw32(address, 0x40, |
| 267 | pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid0_3); | 302 | pm8001_ha->main_cfg_tbl.pm8001_tbl. |
| 303 | outbound_tgt_ssp_event_pid0_3); | ||
| 268 | pm8001_mw32(address, 0x44, | 304 | pm8001_mw32(address, 0x44, |
| 269 | pm8001_ha->main_cfg_tbl.outbound_tgt_ssp_event_pid4_7); | 305 | pm8001_ha->main_cfg_tbl.pm8001_tbl. |
| 306 | outbound_tgt_ssp_event_pid4_7); | ||
| 270 | pm8001_mw32(address, 0x48, | 307 | pm8001_mw32(address, 0x48, |
| 271 | pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid0_3); | 308 | pm8001_ha->main_cfg_tbl.pm8001_tbl. |
| 309 | outbound_tgt_smp_event_pid0_3); | ||
| 272 | pm8001_mw32(address, 0x4C, | 310 | pm8001_mw32(address, 0x4C, |
| 273 | pm8001_ha->main_cfg_tbl.outbound_tgt_smp_event_pid4_7); | 311 | pm8001_ha->main_cfg_tbl.pm8001_tbl. |
| 312 | outbound_tgt_smp_event_pid4_7); | ||
| 274 | pm8001_mw32(address, 0x50, | 313 | pm8001_mw32(address, 0x50, |
| 275 | pm8001_ha->main_cfg_tbl.upper_event_log_addr); | 314 | pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_event_log_addr); |
| 276 | pm8001_mw32(address, 0x54, | 315 | pm8001_mw32(address, 0x54, |
| 277 | pm8001_ha->main_cfg_tbl.lower_event_log_addr); | 316 | pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_event_log_addr); |
| 278 | pm8001_mw32(address, 0x58, pm8001_ha->main_cfg_tbl.event_log_size); | 317 | pm8001_mw32(address, 0x58, |
| 279 | pm8001_mw32(address, 0x5C, pm8001_ha->main_cfg_tbl.event_log_option); | 318 | pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_size); |
| 319 | pm8001_mw32(address, 0x5C, | ||
| 320 | pm8001_ha->main_cfg_tbl.pm8001_tbl.event_log_option); | ||
| 280 | pm8001_mw32(address, 0x60, | 321 | pm8001_mw32(address, 0x60, |
| 281 | pm8001_ha->main_cfg_tbl.upper_iop_event_log_addr); | 322 | pm8001_ha->main_cfg_tbl.pm8001_tbl.upper_iop_event_log_addr); |
| 282 | pm8001_mw32(address, 0x64, | 323 | pm8001_mw32(address, 0x64, |
| 283 | pm8001_ha->main_cfg_tbl.lower_iop_event_log_addr); | 324 | pm8001_ha->main_cfg_tbl.pm8001_tbl.lower_iop_event_log_addr); |
| 284 | pm8001_mw32(address, 0x68, pm8001_ha->main_cfg_tbl.iop_event_log_size); | 325 | pm8001_mw32(address, 0x68, |
| 326 | pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_size); | ||
| 285 | pm8001_mw32(address, 0x6C, | 327 | pm8001_mw32(address, 0x6C, |
| 286 | pm8001_ha->main_cfg_tbl.iop_event_log_option); | 328 | pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option); |
| 287 | pm8001_mw32(address, 0x70, | 329 | pm8001_mw32(address, 0x70, |
| 288 | pm8001_ha->main_cfg_tbl.fatal_err_interrupt); | 330 | pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt); |
| 289 | } | 331 | } |
| 290 | 332 | ||
| 291 | /** | 333 | /** |
| @@ -597,6 +639,19 @@ static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) | |||
| 597 | */ | 639 | */ |
| 598 | static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha) | 640 | static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha) |
| 599 | { | 641 | { |
| 642 | u8 i = 0; | ||
| 643 | u16 deviceid; | ||
| 644 | pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); | ||
| 645 | /* 8081 controllers need BAR shift to access MPI space | ||
| 646 | * as this is shared with BIOS data */ | ||
| 647 | if (deviceid == 0x8081) { | ||
| 648 | if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) { | ||
| 649 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 650 | pm8001_printk("Shift Bar4 to 0x%x failed\n", | ||
| 651 | GSM_SM_BASE)); | ||
| 652 | return -1; | ||
| 653 | } | ||
| 654 | } | ||
| 600 | /* check the firmware status */ | 655 | /* check the firmware status */ |
| 601 | if (-1 == check_fw_ready(pm8001_ha)) { | 656 | if (-1 == check_fw_ready(pm8001_ha)) { |
| 602 | PM8001_FAIL_DBG(pm8001_ha, | 657 | PM8001_FAIL_DBG(pm8001_ha, |
| @@ -613,11 +668,16 @@ static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha) | |||
| 613 | read_outbnd_queue_table(pm8001_ha); | 668 | read_outbnd_queue_table(pm8001_ha); |
| 614 | /* update main config table ,inbound table and outbound table */ | 669 | /* update main config table ,inbound table and outbound table */ |
| 615 | update_main_config_table(pm8001_ha); | 670 | update_main_config_table(pm8001_ha); |
| 616 | update_inbnd_queue_table(pm8001_ha, 0); | 671 | for (i = 0; i < PM8001_MAX_INB_NUM; i++) |
| 617 | update_outbnd_queue_table(pm8001_ha, 0); | 672 | update_inbnd_queue_table(pm8001_ha, i); |
| 618 | mpi_set_phys_g3_with_ssc(pm8001_ha, 0); | 673 | for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) |
| 619 | /* 7->130ms, 34->500ms, 119->1.5s */ | 674 | update_outbnd_queue_table(pm8001_ha, i); |
| 620 | mpi_set_open_retry_interval_reg(pm8001_ha, 119); | 675 | /* 8081 controller donot require these operations */ |
| 676 | if (deviceid != 0x8081) { | ||
| 677 | mpi_set_phys_g3_with_ssc(pm8001_ha, 0); | ||
| 678 | /* 7->130ms, 34->500ms, 119->1.5s */ | ||
| 679 | mpi_set_open_retry_interval_reg(pm8001_ha, 119); | ||
| 680 | } | ||
| 621 | /* notify firmware update finished and check initialization status */ | 681 | /* notify firmware update finished and check initialization status */ |
| 622 | if (0 == mpi_init_check(pm8001_ha)) { | 682 | if (0 == mpi_init_check(pm8001_ha)) { |
| 623 | PM8001_INIT_DBG(pm8001_ha, | 683 | PM8001_INIT_DBG(pm8001_ha, |
| @@ -639,6 +699,16 @@ static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) | |||
| 639 | u32 max_wait_count; | 699 | u32 max_wait_count; |
| 640 | u32 value; | 700 | u32 value; |
| 641 | u32 gst_len_mpistate; | 701 | u32 gst_len_mpistate; |
| 702 | u16 deviceid; | ||
| 703 | pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); | ||
| 704 | if (deviceid == 0x8081) { | ||
| 705 | if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_SM_BASE)) { | ||
| 706 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 707 | pm8001_printk("Shift Bar4 to 0x%x failed\n", | ||
| 708 | GSM_SM_BASE)); | ||
| 709 | return -1; | ||
| 710 | } | ||
| 711 | } | ||
| 642 | init_pci_device_addresses(pm8001_ha); | 712 | init_pci_device_addresses(pm8001_ha); |
| 643 | /* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the | 713 | /* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the |
| 644 | table is stop */ | 714 | table is stop */ |
| @@ -740,14 +810,14 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info *pm8001_ha) | |||
| 740 | * pm8001_chip_soft_rst - soft reset the PM8001 chip, so that the clear all | 810 | * pm8001_chip_soft_rst - soft reset the PM8001 chip, so that the clear all |
| 741 | * the FW register status to the originated status. | 811 | * the FW register status to the originated status. |
| 742 | * @pm8001_ha: our hba card information | 812 | * @pm8001_ha: our hba card information |
| 743 | * @signature: signature in host scratch pad0 register. | ||
| 744 | */ | 813 | */ |
| 745 | static int | 814 | static int |
| 746 | pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | 815 | pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) |
| 747 | { | 816 | { |
| 748 | u32 regVal, toggleVal; | 817 | u32 regVal, toggleVal; |
| 749 | u32 max_wait_count; | 818 | u32 max_wait_count; |
| 750 | u32 regVal1, regVal2, regVal3; | 819 | u32 regVal1, regVal2, regVal3; |
| 820 | u32 signature = 0x252acbcd; /* for host scratch pad0 */ | ||
| 751 | unsigned long flags; | 821 | unsigned long flags; |
| 752 | 822 | ||
| 753 | /* step1: Check FW is ready for soft reset */ | 823 | /* step1: Check FW is ready for soft reset */ |
| @@ -1113,7 +1183,7 @@ static void pm8001_hw_chip_rst(struct pm8001_hba_info *pm8001_ha) | |||
| 1113 | * pm8001_chip_iounmap - which maped when initialized. | 1183 | * pm8001_chip_iounmap - which maped when initialized. |
| 1114 | * @pm8001_ha: our hba card information | 1184 | * @pm8001_ha: our hba card information |
| 1115 | */ | 1185 | */ |
| 1116 | static void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha) | 1186 | void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha) |
| 1117 | { | 1187 | { |
| 1118 | s8 bar, logical = 0; | 1188 | s8 bar, logical = 0; |
| 1119 | for (bar = 0; bar < 6; bar++) { | 1189 | for (bar = 0; bar < 6; bar++) { |
| @@ -1192,7 +1262,7 @@ pm8001_chip_msix_interrupt_disable(struct pm8001_hba_info *pm8001_ha, | |||
| 1192 | * @pm8001_ha: our hba card information | 1262 | * @pm8001_ha: our hba card information |
| 1193 | */ | 1263 | */ |
| 1194 | static void | 1264 | static void |
| 1195 | pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha) | 1265 | pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec) |
| 1196 | { | 1266 | { |
| 1197 | #ifdef PM8001_USE_MSIX | 1267 | #ifdef PM8001_USE_MSIX |
| 1198 | pm8001_chip_msix_interrupt_enable(pm8001_ha, 0); | 1268 | pm8001_chip_msix_interrupt_enable(pm8001_ha, 0); |
| @@ -1207,7 +1277,7 @@ pm8001_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha) | |||
| 1207 | * @pm8001_ha: our hba card information | 1277 | * @pm8001_ha: our hba card information |
| 1208 | */ | 1278 | */ |
| 1209 | static void | 1279 | static void |
| 1210 | pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha) | 1280 | pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec) |
| 1211 | { | 1281 | { |
| 1212 | #ifdef PM8001_USE_MSIX | 1282 | #ifdef PM8001_USE_MSIX |
| 1213 | pm8001_chip_msix_interrupt_disable(pm8001_ha, 0); | 1283 | pm8001_chip_msix_interrupt_disable(pm8001_ha, 0); |
| @@ -1218,12 +1288,13 @@ pm8001_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha) | |||
| 1218 | } | 1288 | } |
| 1219 | 1289 | ||
| 1220 | /** | 1290 | /** |
| 1221 | * mpi_msg_free_get- get the free message buffer for transfer inbound queue. | 1291 | * pm8001_mpi_msg_free_get - get the free message buffer for transfer |
| 1292 | * inbound queue. | ||
| 1222 | * @circularQ: the inbound queue we want to transfer to HBA. | 1293 | * @circularQ: the inbound queue we want to transfer to HBA. |
| 1223 | * @messageSize: the message size of this transfer, normally it is 64 bytes | 1294 | * @messageSize: the message size of this transfer, normally it is 64 bytes |
| 1224 | * @messagePtr: the pointer to message. | 1295 | * @messagePtr: the pointer to message. |
| 1225 | */ | 1296 | */ |
| 1226 | static int mpi_msg_free_get(struct inbound_queue_table *circularQ, | 1297 | int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ, |
| 1227 | u16 messageSize, void **messagePtr) | 1298 | u16 messageSize, void **messagePtr) |
| 1228 | { | 1299 | { |
| 1229 | u32 offset, consumer_index; | 1300 | u32 offset, consumer_index; |
| @@ -1231,7 +1302,7 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ, | |||
| 1231 | u8 bcCount = 1; /* only support single buffer */ | 1302 | u8 bcCount = 1; /* only support single buffer */ |
| 1232 | 1303 | ||
| 1233 | /* Checks is the requested message size can be allocated in this queue*/ | 1304 | /* Checks is the requested message size can be allocated in this queue*/ |
| 1234 | if (messageSize > 64) { | 1305 | if (messageSize > IOMB_SIZE_SPCV) { |
| 1235 | *messagePtr = NULL; | 1306 | *messagePtr = NULL; |
| 1236 | return -1; | 1307 | return -1; |
| 1237 | } | 1308 | } |
| @@ -1245,7 +1316,7 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ, | |||
| 1245 | return -1; | 1316 | return -1; |
| 1246 | } | 1317 | } |
| 1247 | /* get memory IOMB buffer address */ | 1318 | /* get memory IOMB buffer address */ |
| 1248 | offset = circularQ->producer_idx * 64; | 1319 | offset = circularQ->producer_idx * messageSize; |
| 1249 | /* increment to next bcCount element */ | 1320 | /* increment to next bcCount element */ |
| 1250 | circularQ->producer_idx = (circularQ->producer_idx + bcCount) | 1321 | circularQ->producer_idx = (circularQ->producer_idx + bcCount) |
| 1251 | % PM8001_MPI_QUEUE; | 1322 | % PM8001_MPI_QUEUE; |
| @@ -1257,29 +1328,30 @@ static int mpi_msg_free_get(struct inbound_queue_table *circularQ, | |||
| 1257 | } | 1328 | } |
| 1258 | 1329 | ||
| 1259 | /** | 1330 | /** |
| 1260 | * mpi_build_cmd- build the message queue for transfer, update the PI to FW | 1331 | * pm8001_mpi_build_cmd- build the message queue for transfer, update the PI to |
| 1261 | * to tell the fw to get this message from IOMB. | 1332 | * FW to tell the fw to get this message from IOMB. |
| 1262 | * @pm8001_ha: our hba card information | 1333 | * @pm8001_ha: our hba card information |
| 1263 | * @circularQ: the inbound queue we want to transfer to HBA. | 1334 | * @circularQ: the inbound queue we want to transfer to HBA. |
| 1264 | * @opCode: the operation code represents commands which LLDD and fw recognized. | 1335 | * @opCode: the operation code represents commands which LLDD and fw recognized. |
| 1265 | * @payload: the command payload of each operation command. | 1336 | * @payload: the command payload of each operation command. |
| 1266 | */ | 1337 | */ |
| 1267 | static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, | 1338 | int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, |
| 1268 | struct inbound_queue_table *circularQ, | 1339 | struct inbound_queue_table *circularQ, |
| 1269 | u32 opCode, void *payload) | 1340 | u32 opCode, void *payload, u32 responseQueue) |
| 1270 | { | 1341 | { |
| 1271 | u32 Header = 0, hpriority = 0, bc = 1, category = 0x02; | 1342 | u32 Header = 0, hpriority = 0, bc = 1, category = 0x02; |
| 1272 | u32 responseQueue = 0; | ||
| 1273 | void *pMessage; | 1343 | void *pMessage; |
| 1274 | 1344 | ||
| 1275 | if (mpi_msg_free_get(circularQ, 64, &pMessage) < 0) { | 1345 | if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size, |
| 1346 | &pMessage) < 0) { | ||
| 1276 | PM8001_IO_DBG(pm8001_ha, | 1347 | PM8001_IO_DBG(pm8001_ha, |
| 1277 | pm8001_printk("No free mpi buffer\n")); | 1348 | pm8001_printk("No free mpi buffer\n")); |
| 1278 | return -1; | 1349 | return -1; |
| 1279 | } | 1350 | } |
| 1280 | BUG_ON(!payload); | 1351 | BUG_ON(!payload); |
| 1281 | /*Copy to the payload*/ | 1352 | /*Copy to the payload*/ |
| 1282 | memcpy(pMessage, payload, (64 - sizeof(struct mpi_msg_hdr))); | 1353 | memcpy(pMessage, payload, (pm8001_ha->iomb_size - |
| 1354 | sizeof(struct mpi_msg_hdr))); | ||
| 1283 | 1355 | ||
| 1284 | /*Build the header*/ | 1356 | /*Build the header*/ |
| 1285 | Header = ((1 << 31) | (hpriority << 30) | ((bc & 0x1f) << 24) | 1357 | Header = ((1 << 31) | (hpriority << 30) | ((bc & 0x1f) << 24) |
| @@ -1291,12 +1363,13 @@ static int mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, | |||
| 1291 | pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar, | 1363 | pm8001_cw32(pm8001_ha, circularQ->pi_pci_bar, |
| 1292 | circularQ->pi_offset, circularQ->producer_idx); | 1364 | circularQ->pi_offset, circularQ->producer_idx); |
| 1293 | PM8001_IO_DBG(pm8001_ha, | 1365 | PM8001_IO_DBG(pm8001_ha, |
| 1294 | pm8001_printk("after PI= %d CI= %d\n", circularQ->producer_idx, | 1366 | pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n", |
| 1295 | circularQ->consumer_index)); | 1367 | responseQueue, opCode, circularQ->producer_idx, |
| 1368 | circularQ->consumer_index)); | ||
| 1296 | return 0; | 1369 | return 0; |
| 1297 | } | 1370 | } |
| 1298 | 1371 | ||
| 1299 | static u32 mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, | 1372 | u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, |
| 1300 | struct outbound_queue_table *circularQ, u8 bc) | 1373 | struct outbound_queue_table *circularQ, u8 bc) |
| 1301 | { | 1374 | { |
| 1302 | u32 producer_index; | 1375 | u32 producer_index; |
| @@ -1305,7 +1378,7 @@ static u32 mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, | |||
| 1305 | 1378 | ||
| 1306 | msgHeader = (struct mpi_msg_hdr *)(pMsg - sizeof(struct mpi_msg_hdr)); | 1379 | msgHeader = (struct mpi_msg_hdr *)(pMsg - sizeof(struct mpi_msg_hdr)); |
| 1307 | pOutBoundMsgHeader = (struct mpi_msg_hdr *)(circularQ->base_virt + | 1380 | pOutBoundMsgHeader = (struct mpi_msg_hdr *)(circularQ->base_virt + |
| 1308 | circularQ->consumer_idx * 64); | 1381 | circularQ->consumer_idx * pm8001_ha->iomb_size); |
| 1309 | if (pOutBoundMsgHeader != msgHeader) { | 1382 | if (pOutBoundMsgHeader != msgHeader) { |
| 1310 | PM8001_FAIL_DBG(pm8001_ha, | 1383 | PM8001_FAIL_DBG(pm8001_ha, |
| 1311 | pm8001_printk("consumer_idx = %d msgHeader = %p\n", | 1384 | pm8001_printk("consumer_idx = %d msgHeader = %p\n", |
| @@ -1336,13 +1409,14 @@ static u32 mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, | |||
| 1336 | } | 1409 | } |
| 1337 | 1410 | ||
| 1338 | /** | 1411 | /** |
| 1339 | * mpi_msg_consume- get the MPI message from outbound queue message table. | 1412 | * pm8001_mpi_msg_consume- get the MPI message from outbound queue |
| 1413 | * message table. | ||
| 1340 | * @pm8001_ha: our hba card information | 1414 | * @pm8001_ha: our hba card information |
| 1341 | * @circularQ: the outbound queue table. | 1415 | * @circularQ: the outbound queue table. |
| 1342 | * @messagePtr1: the message contents of this outbound message. | 1416 | * @messagePtr1: the message contents of this outbound message. |
| 1343 | * @pBC: the message size. | 1417 | * @pBC: the message size. |
| 1344 | */ | 1418 | */ |
| 1345 | static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, | 1419 | u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, |
| 1346 | struct outbound_queue_table *circularQ, | 1420 | struct outbound_queue_table *circularQ, |
| 1347 | void **messagePtr1, u8 *pBC) | 1421 | void **messagePtr1, u8 *pBC) |
| 1348 | { | 1422 | { |
| @@ -1356,7 +1430,7 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, | |||
| 1356 | /*Get the pointer to the circular queue buffer element*/ | 1430 | /*Get the pointer to the circular queue buffer element*/ |
| 1357 | msgHeader = (struct mpi_msg_hdr *) | 1431 | msgHeader = (struct mpi_msg_hdr *) |
| 1358 | (circularQ->base_virt + | 1432 | (circularQ->base_virt + |
| 1359 | circularQ->consumer_idx * 64); | 1433 | circularQ->consumer_idx * pm8001_ha->iomb_size); |
| 1360 | /* read header */ | 1434 | /* read header */ |
| 1361 | header_tmp = pm8001_read_32(msgHeader); | 1435 | header_tmp = pm8001_read_32(msgHeader); |
| 1362 | msgHeader_tmp = cpu_to_le32(header_tmp); | 1436 | msgHeader_tmp = cpu_to_le32(header_tmp); |
| @@ -1416,7 +1490,7 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, | |||
| 1416 | return MPI_IO_STATUS_BUSY; | 1490 | return MPI_IO_STATUS_BUSY; |
| 1417 | } | 1491 | } |
| 1418 | 1492 | ||
| 1419 | static void pm8001_work_fn(struct work_struct *work) | 1493 | void pm8001_work_fn(struct work_struct *work) |
| 1420 | { | 1494 | { |
| 1421 | struct pm8001_work *pw = container_of(work, struct pm8001_work, work); | 1495 | struct pm8001_work *pw = container_of(work, struct pm8001_work, work); |
| 1422 | struct pm8001_device *pm8001_dev; | 1496 | struct pm8001_device *pm8001_dev; |
| @@ -1431,7 +1505,7 @@ static void pm8001_work_fn(struct work_struct *work) | |||
| 1431 | pm8001_dev = pw->data; /* Most stash device structure */ | 1505 | pm8001_dev = pw->data; /* Most stash device structure */ |
| 1432 | if ((pm8001_dev == NULL) | 1506 | if ((pm8001_dev == NULL) |
| 1433 | || ((pw->handler != IO_XFER_ERROR_BREAK) | 1507 | || ((pw->handler != IO_XFER_ERROR_BREAK) |
| 1434 | && (pm8001_dev->dev_type == NO_DEVICE))) { | 1508 | && (pm8001_dev->dev_type == SAS_PHY_UNUSED))) { |
| 1435 | kfree(pw); | 1509 | kfree(pw); |
| 1436 | return; | 1510 | return; |
| 1437 | } | 1511 | } |
| @@ -1596,7 +1670,7 @@ static void pm8001_work_fn(struct work_struct *work) | |||
| 1596 | } break; | 1670 | } break; |
| 1597 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | 1671 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: |
| 1598 | dev = pm8001_dev->sas_device; | 1672 | dev = pm8001_dev->sas_device; |
| 1599 | pm8001_I_T_nexus_reset(dev); | 1673 | pm8001_I_T_nexus_event_handler(dev); |
| 1600 | break; | 1674 | break; |
| 1601 | case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: | 1675 | case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: |
| 1602 | dev = pm8001_dev->sas_device; | 1676 | dev = pm8001_dev->sas_device; |
| @@ -1614,7 +1688,7 @@ static void pm8001_work_fn(struct work_struct *work) | |||
| 1614 | kfree(pw); | 1688 | kfree(pw); |
| 1615 | } | 1689 | } |
| 1616 | 1690 | ||
| 1617 | static int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data, | 1691 | int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data, |
| 1618 | int handler) | 1692 | int handler) |
| 1619 | { | 1693 | { |
| 1620 | struct pm8001_work *pw; | 1694 | struct pm8001_work *pw; |
| @@ -1633,6 +1707,123 @@ static int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data, | |||
| 1633 | return ret; | 1707 | return ret; |
| 1634 | } | 1708 | } |
| 1635 | 1709 | ||
| 1710 | static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha, | ||
| 1711 | struct pm8001_device *pm8001_ha_dev) | ||
| 1712 | { | ||
| 1713 | int res; | ||
| 1714 | u32 ccb_tag; | ||
| 1715 | struct pm8001_ccb_info *ccb; | ||
| 1716 | struct sas_task *task = NULL; | ||
| 1717 | struct task_abort_req task_abort; | ||
| 1718 | struct inbound_queue_table *circularQ; | ||
| 1719 | u32 opc = OPC_INB_SATA_ABORT; | ||
| 1720 | int ret; | ||
| 1721 | |||
| 1722 | if (!pm8001_ha_dev) { | ||
| 1723 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n")); | ||
| 1724 | return; | ||
| 1725 | } | ||
| 1726 | |||
| 1727 | task = sas_alloc_slow_task(GFP_ATOMIC); | ||
| 1728 | |||
| 1729 | if (!task) { | ||
| 1730 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot " | ||
| 1731 | "allocate task\n")); | ||
| 1732 | return; | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | task->task_done = pm8001_task_done; | ||
| 1736 | |||
| 1737 | res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); | ||
| 1738 | if (res) | ||
| 1739 | return; | ||
| 1740 | |||
| 1741 | ccb = &pm8001_ha->ccb_info[ccb_tag]; | ||
| 1742 | ccb->device = pm8001_ha_dev; | ||
| 1743 | ccb->ccb_tag = ccb_tag; | ||
| 1744 | ccb->task = task; | ||
| 1745 | |||
| 1746 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 1747 | |||
| 1748 | memset(&task_abort, 0, sizeof(task_abort)); | ||
| 1749 | task_abort.abort_all = cpu_to_le32(1); | ||
| 1750 | task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id); | ||
| 1751 | task_abort.tag = cpu_to_le32(ccb_tag); | ||
| 1752 | |||
| 1753 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); | ||
| 1754 | |||
| 1755 | } | ||
| 1756 | |||
| 1757 | static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, | ||
| 1758 | struct pm8001_device *pm8001_ha_dev) | ||
| 1759 | { | ||
| 1760 | struct sata_start_req sata_cmd; | ||
| 1761 | int res; | ||
| 1762 | u32 ccb_tag; | ||
| 1763 | struct pm8001_ccb_info *ccb; | ||
| 1764 | struct sas_task *task = NULL; | ||
| 1765 | struct host_to_dev_fis fis; | ||
| 1766 | struct domain_device *dev; | ||
| 1767 | struct inbound_queue_table *circularQ; | ||
| 1768 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | ||
| 1769 | |||
| 1770 | task = sas_alloc_slow_task(GFP_ATOMIC); | ||
| 1771 | |||
| 1772 | if (!task) { | ||
| 1773 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1774 | pm8001_printk("cannot allocate task !!!\n")); | ||
| 1775 | return; | ||
| 1776 | } | ||
| 1777 | task->task_done = pm8001_task_done; | ||
| 1778 | |||
| 1779 | res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); | ||
| 1780 | if (res) { | ||
| 1781 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1782 | pm8001_printk("cannot allocate tag !!!\n")); | ||
| 1783 | return; | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | /* allocate domain device by ourselves as libsas | ||
| 1787 | * is not going to provide any | ||
| 1788 | */ | ||
| 1789 | dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC); | ||
| 1790 | if (!dev) { | ||
| 1791 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1792 | pm8001_printk("Domain device cannot be allocated\n")); | ||
| 1793 | sas_free_task(task); | ||
| 1794 | return; | ||
| 1795 | } else { | ||
| 1796 | task->dev = dev; | ||
| 1797 | task->dev->lldd_dev = pm8001_ha_dev; | ||
| 1798 | } | ||
| 1799 | |||
| 1800 | ccb = &pm8001_ha->ccb_info[ccb_tag]; | ||
| 1801 | ccb->device = pm8001_ha_dev; | ||
| 1802 | ccb->ccb_tag = ccb_tag; | ||
| 1803 | ccb->task = task; | ||
| 1804 | pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG; | ||
| 1805 | pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG; | ||
| 1806 | |||
| 1807 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | ||
| 1808 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 1809 | |||
| 1810 | /* construct read log FIS */ | ||
| 1811 | memset(&fis, 0, sizeof(struct host_to_dev_fis)); | ||
| 1812 | fis.fis_type = 0x27; | ||
| 1813 | fis.flags = 0x80; | ||
| 1814 | fis.command = ATA_CMD_READ_LOG_EXT; | ||
| 1815 | fis.lbal = 0x10; | ||
| 1816 | fis.sector_count = 0x1; | ||
| 1817 | |||
| 1818 | sata_cmd.tag = cpu_to_le32(ccb_tag); | ||
| 1819 | sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); | ||
| 1820 | sata_cmd.ncqtag_atap_dir_m |= ((0x1 << 7) | (0x5 << 9)); | ||
| 1821 | memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); | ||
| 1822 | |||
| 1823 | res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); | ||
| 1824 | |||
| 1825 | } | ||
| 1826 | |||
| 1636 | /** | 1827 | /** |
| 1637 | * mpi_ssp_completion- process the event that FW response to the SSP request. | 1828 | * mpi_ssp_completion- process the event that FW response to the SSP request. |
| 1638 | * @pm8001_ha: our hba card information | 1829 | * @pm8001_ha: our hba card information |
| @@ -1867,7 +2058,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
| 1867 | break; | 2058 | break; |
| 1868 | } | 2059 | } |
| 1869 | PM8001_IO_DBG(pm8001_ha, | 2060 | PM8001_IO_DBG(pm8001_ha, |
| 1870 | pm8001_printk("scsi_status = %x \n ", | 2061 | pm8001_printk("scsi_status = %x\n ", |
| 1871 | psspPayload->ssp_resp_iu.status)); | 2062 | psspPayload->ssp_resp_iu.status)); |
| 1872 | spin_lock_irqsave(&t->task_state_lock, flags); | 2063 | spin_lock_irqsave(&t->task_state_lock, flags); |
| 1873 | t->task_state_flags &= ~SAS_TASK_STATE_PENDING; | 2064 | t->task_state_flags &= ~SAS_TASK_STATE_PENDING; |
| @@ -2096,16 +2287,44 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 2096 | status = le32_to_cpu(psataPayload->status); | 2287 | status = le32_to_cpu(psataPayload->status); |
| 2097 | tag = le32_to_cpu(psataPayload->tag); | 2288 | tag = le32_to_cpu(psataPayload->tag); |
| 2098 | 2289 | ||
| 2290 | if (!tag) { | ||
| 2291 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2292 | pm8001_printk("tag null\n")); | ||
| 2293 | return; | ||
| 2294 | } | ||
| 2099 | ccb = &pm8001_ha->ccb_info[tag]; | 2295 | ccb = &pm8001_ha->ccb_info[tag]; |
| 2100 | param = le32_to_cpu(psataPayload->param); | 2296 | param = le32_to_cpu(psataPayload->param); |
| 2101 | t = ccb->task; | 2297 | if (ccb) { |
| 2298 | t = ccb->task; | ||
| 2299 | pm8001_dev = ccb->device; | ||
| 2300 | } else { | ||
| 2301 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2302 | pm8001_printk("ccb null\n")); | ||
| 2303 | return; | ||
| 2304 | } | ||
| 2305 | |||
| 2306 | if (t) { | ||
| 2307 | if (t->dev && (t->dev->lldd_dev)) | ||
| 2308 | pm8001_dev = t->dev->lldd_dev; | ||
| 2309 | } else { | ||
| 2310 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2311 | pm8001_printk("task null\n")); | ||
| 2312 | return; | ||
| 2313 | } | ||
| 2314 | |||
| 2315 | if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG)) | ||
| 2316 | && unlikely(!t || !t->lldd_task || !t->dev)) { | ||
| 2317 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2318 | pm8001_printk("task or dev null\n")); | ||
| 2319 | return; | ||
| 2320 | } | ||
| 2321 | |||
| 2102 | ts = &t->task_status; | 2322 | ts = &t->task_status; |
| 2103 | pm8001_dev = ccb->device; | 2323 | if (!ts) { |
| 2104 | if (status) | ||
| 2105 | PM8001_FAIL_DBG(pm8001_ha, | 2324 | PM8001_FAIL_DBG(pm8001_ha, |
| 2106 | pm8001_printk("sata IO status 0x%x\n", status)); | 2325 | pm8001_printk("ts null\n")); |
| 2107 | if (unlikely(!t || !t->lldd_task || !t->dev)) | ||
| 2108 | return; | 2326 | return; |
| 2327 | } | ||
| 2109 | 2328 | ||
| 2110 | switch (status) { | 2329 | switch (status) { |
| 2111 | case IO_SUCCESS: | 2330 | case IO_SUCCESS: |
| @@ -2113,6 +2332,19 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 2113 | if (param == 0) { | 2332 | if (param == 0) { |
| 2114 | ts->resp = SAS_TASK_COMPLETE; | 2333 | ts->resp = SAS_TASK_COMPLETE; |
| 2115 | ts->stat = SAM_STAT_GOOD; | 2334 | ts->stat = SAM_STAT_GOOD; |
| 2335 | /* check if response is for SEND READ LOG */ | ||
| 2336 | if (pm8001_dev && | ||
| 2337 | (pm8001_dev->id & NCQ_READ_LOG_FLAG)) { | ||
| 2338 | /* set new bit for abort_all */ | ||
| 2339 | pm8001_dev->id |= NCQ_ABORT_ALL_FLAG; | ||
| 2340 | /* clear bit for read log */ | ||
| 2341 | pm8001_dev->id = pm8001_dev->id & 0x7FFFFFFF; | ||
| 2342 | pm8001_send_abort_all(pm8001_ha, pm8001_dev); | ||
| 2343 | /* Free the tag */ | ||
| 2344 | pm8001_tag_free(pm8001_ha, tag); | ||
| 2345 | sas_free_task(t); | ||
| 2346 | return; | ||
| 2347 | } | ||
| 2116 | } else { | 2348 | } else { |
| 2117 | u8 len; | 2349 | u8 len; |
| 2118 | ts->resp = SAS_TASK_COMPLETE; | 2350 | ts->resp = SAS_TASK_COMPLETE; |
| @@ -2424,6 +2656,29 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
| 2424 | unsigned long flags; | 2656 | unsigned long flags; |
| 2425 | 2657 | ||
| 2426 | ccb = &pm8001_ha->ccb_info[tag]; | 2658 | ccb = &pm8001_ha->ccb_info[tag]; |
| 2659 | |||
| 2660 | if (ccb) { | ||
| 2661 | t = ccb->task; | ||
| 2662 | pm8001_dev = ccb->device; | ||
| 2663 | } else { | ||
| 2664 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2665 | pm8001_printk("No CCB !!!. returning\n")); | ||
| 2666 | } | ||
| 2667 | if (event) | ||
| 2668 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2669 | pm8001_printk("SATA EVENT 0x%x\n", event)); | ||
| 2670 | |||
| 2671 | /* Check if this is NCQ error */ | ||
| 2672 | if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) { | ||
| 2673 | /* find device using device id */ | ||
| 2674 | pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id); | ||
| 2675 | /* send read log extension */ | ||
| 2676 | if (pm8001_dev) | ||
| 2677 | pm8001_send_read_log(pm8001_ha, pm8001_dev); | ||
| 2678 | return; | ||
| 2679 | } | ||
| 2680 | |||
| 2681 | ccb = &pm8001_ha->ccb_info[tag]; | ||
| 2427 | t = ccb->task; | 2682 | t = ccb->task; |
| 2428 | pm8001_dev = ccb->device; | 2683 | pm8001_dev = ccb->device; |
| 2429 | if (event) | 2684 | if (event) |
| @@ -2432,9 +2687,9 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
| 2432 | if (unlikely(!t || !t->lldd_task || !t->dev)) | 2687 | if (unlikely(!t || !t->lldd_task || !t->dev)) |
| 2433 | return; | 2688 | return; |
| 2434 | ts = &t->task_status; | 2689 | ts = &t->task_status; |
| 2435 | PM8001_IO_DBG(pm8001_ha, | 2690 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( |
| 2436 | pm8001_printk("port_id = %x,device_id = %x\n", | 2691 | "port_id:0x%x, device_id:0x%x, tag:0x%x, event:0x%x\n", |
| 2437 | port_id, dev_id)); | 2692 | port_id, dev_id, tag, event)); |
| 2438 | switch (event) { | 2693 | switch (event) { |
| 2439 | case IO_OVERFLOW: | 2694 | case IO_OVERFLOW: |
| 2440 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); | 2695 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); |
| @@ -2822,8 +3077,8 @@ mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 2822 | } | 3077 | } |
| 2823 | } | 3078 | } |
| 2824 | 3079 | ||
| 2825 | static void | 3080 | void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, |
| 2826 | mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | 3081 | void *piomb) |
| 2827 | { | 3082 | { |
| 2828 | struct set_dev_state_resp *pPayload = | 3083 | struct set_dev_state_resp *pPayload = |
| 2829 | (struct set_dev_state_resp *)(piomb + 4); | 3084 | (struct set_dev_state_resp *)(piomb + 4); |
| @@ -2843,8 +3098,7 @@ mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 2843 | pm8001_ccb_free(pm8001_ha, tag); | 3098 | pm8001_ccb_free(pm8001_ha, tag); |
| 2844 | } | 3099 | } |
| 2845 | 3100 | ||
| 2846 | static void | 3101 | void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) |
| 2847 | mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 2848 | { | 3102 | { |
| 2849 | struct get_nvm_data_resp *pPayload = | 3103 | struct get_nvm_data_resp *pPayload = |
| 2850 | (struct get_nvm_data_resp *)(piomb + 4); | 3104 | (struct get_nvm_data_resp *)(piomb + 4); |
| @@ -2863,8 +3117,8 @@ mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 2863 | pm8001_ccb_free(pm8001_ha, tag); | 3117 | pm8001_ccb_free(pm8001_ha, tag); |
| 2864 | } | 3118 | } |
| 2865 | 3119 | ||
| 2866 | static void | 3120 | void |
| 2867 | mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | 3121 | pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) |
| 2868 | { | 3122 | { |
| 2869 | struct fw_control_ex *fw_control_context; | 3123 | struct fw_control_ex *fw_control_context; |
| 2870 | struct get_nvm_data_resp *pPayload = | 3124 | struct get_nvm_data_resp *pPayload = |
| @@ -2925,7 +3179,7 @@ mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 2925 | pm8001_ccb_free(pm8001_ha, tag); | 3179 | pm8001_ccb_free(pm8001_ha, tag); |
| 2926 | } | 3180 | } |
| 2927 | 3181 | ||
| 2928 | static int mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb) | 3182 | int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb) |
| 2929 | { | 3183 | { |
| 2930 | struct local_phy_ctl_resp *pPayload = | 3184 | struct local_phy_ctl_resp *pPayload = |
| 2931 | (struct local_phy_ctl_resp *)(piomb + 4); | 3185 | (struct local_phy_ctl_resp *)(piomb + 4); |
| @@ -2954,7 +3208,7 @@ static int mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 2954 | * while receive a broadcast(change) primitive just tell the sas | 3208 | * while receive a broadcast(change) primitive just tell the sas |
| 2955 | * layer to discover the changed domain rather than the whole domain. | 3209 | * layer to discover the changed domain rather than the whole domain. |
| 2956 | */ | 3210 | */ |
| 2957 | static void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i) | 3211 | void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i) |
| 2958 | { | 3212 | { |
| 2959 | struct pm8001_phy *phy = &pm8001_ha->phy[i]; | 3213 | struct pm8001_phy *phy = &pm8001_ha->phy[i]; |
| 2960 | struct asd_sas_phy *sas_phy = &phy->sas_phy; | 3214 | struct asd_sas_phy *sas_phy = &phy->sas_phy; |
| @@ -2988,7 +3242,7 @@ static void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i) | |||
| 2988 | } | 3242 | } |
| 2989 | 3243 | ||
| 2990 | /* Get the link rate speed */ | 3244 | /* Get the link rate speed */ |
| 2991 | static void get_lrate_mode(struct pm8001_phy *phy, u8 link_rate) | 3245 | void pm8001_get_lrate_mode(struct pm8001_phy *phy, u8 link_rate) |
| 2992 | { | 3246 | { |
| 2993 | struct sas_phy *sas_phy = phy->sas_phy.phy; | 3247 | struct sas_phy *sas_phy = phy->sas_phy.phy; |
| 2994 | 3248 | ||
| @@ -3025,7 +3279,7 @@ static void get_lrate_mode(struct pm8001_phy *phy, u8 link_rate) | |||
| 3025 | * LOCKING: the frame_rcvd_lock needs to be held since this parses the frame | 3279 | * LOCKING: the frame_rcvd_lock needs to be held since this parses the frame |
| 3026 | * buffer. | 3280 | * buffer. |
| 3027 | */ | 3281 | */ |
| 3028 | static void pm8001_get_attached_sas_addr(struct pm8001_phy *phy, | 3282 | void pm8001_get_attached_sas_addr(struct pm8001_phy *phy, |
| 3029 | u8 *sas_addr) | 3283 | u8 *sas_addr) |
| 3030 | { | 3284 | { |
| 3031 | if (phy->sas_phy.frame_rcvd[0] == 0x34 | 3285 | if (phy->sas_phy.frame_rcvd[0] == 0x34 |
| @@ -3067,7 +3321,7 @@ static void pm8001_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha, | |||
| 3067 | ((phyId & 0x0F) << 4) | (port_id & 0x0F)); | 3321 | ((phyId & 0x0F) << 4) | (port_id & 0x0F)); |
| 3068 | payload.param0 = cpu_to_le32(param0); | 3322 | payload.param0 = cpu_to_le32(param0); |
| 3069 | payload.param1 = cpu_to_le32(param1); | 3323 | payload.param1 = cpu_to_le32(param1); |
| 3070 | mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); | 3324 | pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); |
| 3071 | } | 3325 | } |
| 3072 | 3326 | ||
| 3073 | static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, | 3327 | static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, |
| @@ -3112,19 +3366,19 @@ hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3112 | pm8001_chip_phy_ctl_req(pm8001_ha, phy_id, | 3366 | pm8001_chip_phy_ctl_req(pm8001_ha, phy_id, |
| 3113 | PHY_NOTIFY_ENABLE_SPINUP); | 3367 | PHY_NOTIFY_ENABLE_SPINUP); |
| 3114 | port->port_attached = 1; | 3368 | port->port_attached = 1; |
| 3115 | get_lrate_mode(phy, link_rate); | 3369 | pm8001_get_lrate_mode(phy, link_rate); |
| 3116 | break; | 3370 | break; |
| 3117 | case SAS_EDGE_EXPANDER_DEVICE: | 3371 | case SAS_EDGE_EXPANDER_DEVICE: |
| 3118 | PM8001_MSG_DBG(pm8001_ha, | 3372 | PM8001_MSG_DBG(pm8001_ha, |
| 3119 | pm8001_printk("expander device.\n")); | 3373 | pm8001_printk("expander device.\n")); |
| 3120 | port->port_attached = 1; | 3374 | port->port_attached = 1; |
| 3121 | get_lrate_mode(phy, link_rate); | 3375 | pm8001_get_lrate_mode(phy, link_rate); |
| 3122 | break; | 3376 | break; |
| 3123 | case SAS_FANOUT_EXPANDER_DEVICE: | 3377 | case SAS_FANOUT_EXPANDER_DEVICE: |
| 3124 | PM8001_MSG_DBG(pm8001_ha, | 3378 | PM8001_MSG_DBG(pm8001_ha, |
| 3125 | pm8001_printk("fanout expander device.\n")); | 3379 | pm8001_printk("fanout expander device.\n")); |
| 3126 | port->port_attached = 1; | 3380 | port->port_attached = 1; |
| 3127 | get_lrate_mode(phy, link_rate); | 3381 | pm8001_get_lrate_mode(phy, link_rate); |
| 3128 | break; | 3382 | break; |
| 3129 | default: | 3383 | default: |
| 3130 | PM8001_MSG_DBG(pm8001_ha, | 3384 | PM8001_MSG_DBG(pm8001_ha, |
| @@ -3179,7 +3433,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3179 | " phy id = %d\n", port_id, phy_id)); | 3433 | " phy id = %d\n", port_id, phy_id)); |
| 3180 | port->port_state = portstate; | 3434 | port->port_state = portstate; |
| 3181 | port->port_attached = 1; | 3435 | port->port_attached = 1; |
| 3182 | get_lrate_mode(phy, link_rate); | 3436 | pm8001_get_lrate_mode(phy, link_rate); |
| 3183 | phy->phy_type |= PORT_TYPE_SATA; | 3437 | phy->phy_type |= PORT_TYPE_SATA; |
| 3184 | phy->phy_attached = 1; | 3438 | phy->phy_attached = 1; |
| 3185 | phy->sas_phy.oob_mode = SATA_OOB_MODE; | 3439 | phy->sas_phy.oob_mode = SATA_OOB_MODE; |
| @@ -3189,7 +3443,7 @@ hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3189 | sizeof(struct dev_to_host_fis)); | 3443 | sizeof(struct dev_to_host_fis)); |
| 3190 | phy->frame_rcvd_size = sizeof(struct dev_to_host_fis); | 3444 | phy->frame_rcvd_size = sizeof(struct dev_to_host_fis); |
| 3191 | phy->identify.target_port_protocols = SAS_PROTOCOL_SATA; | 3445 | phy->identify.target_port_protocols = SAS_PROTOCOL_SATA; |
| 3192 | phy->identify.device_type = SATA_DEV; | 3446 | phy->identify.device_type = SAS_SATA_DEV; |
| 3193 | pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr); | 3447 | pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr); |
| 3194 | spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); | 3448 | spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); |
| 3195 | pm8001_bytes_dmaed(pm8001_ha, phy_id); | 3449 | pm8001_bytes_dmaed(pm8001_ha, phy_id); |
| @@ -3260,7 +3514,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3260 | } | 3514 | } |
| 3261 | 3515 | ||
| 3262 | /** | 3516 | /** |
| 3263 | * mpi_reg_resp -process register device ID response. | 3517 | * pm8001_mpi_reg_resp -process register device ID response. |
| 3264 | * @pm8001_ha: our hba card information | 3518 | * @pm8001_ha: our hba card information |
| 3265 | * @piomb: IO message buffer | 3519 | * @piomb: IO message buffer |
| 3266 | * | 3520 | * |
| @@ -3269,7 +3523,7 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3269 | * has assigned, from now,inter-communication with FW is no longer using the | 3523 | * has assigned, from now,inter-communication with FW is no longer using the |
| 3270 | * SAS address, use device ID which FW assigned. | 3524 | * SAS address, use device ID which FW assigned. |
| 3271 | */ | 3525 | */ |
| 3272 | static int mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | 3526 | int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) |
| 3273 | { | 3527 | { |
| 3274 | u32 status; | 3528 | u32 status; |
| 3275 | u32 device_id; | 3529 | u32 device_id; |
| @@ -3331,7 +3585,7 @@ static int mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3331 | return 0; | 3585 | return 0; |
| 3332 | } | 3586 | } |
| 3333 | 3587 | ||
| 3334 | static int mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | 3588 | int pm8001_mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) |
| 3335 | { | 3589 | { |
| 3336 | u32 status; | 3590 | u32 status; |
| 3337 | u32 device_id; | 3591 | u32 device_id; |
| @@ -3347,8 +3601,13 @@ static int mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3347 | return 0; | 3601 | return 0; |
| 3348 | } | 3602 | } |
| 3349 | 3603 | ||
| 3350 | static int | 3604 | /** |
| 3351 | mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | 3605 | * fw_flash_update_resp - Response from FW for flash update command. |
| 3606 | * @pm8001_ha: our hba card information | ||
| 3607 | * @piomb: IO message buffer | ||
| 3608 | */ | ||
| 3609 | int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 3610 | void *piomb) | ||
| 3352 | { | 3611 | { |
| 3353 | u32 status; | 3612 | u32 status; |
| 3354 | struct fw_control_ex fw_control_context; | 3613 | struct fw_control_ex fw_control_context; |
| @@ -3403,10 +3662,6 @@ mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3403 | break; | 3662 | break; |
| 3404 | } | 3663 | } |
| 3405 | ccb->fw_control_context->fw_control->retcode = status; | 3664 | ccb->fw_control_context->fw_control->retcode = status; |
| 3406 | pci_free_consistent(pm8001_ha->pdev, | ||
| 3407 | fw_control_context.len, | ||
| 3408 | fw_control_context.virtAddr, | ||
| 3409 | fw_control_context.phys_addr); | ||
| 3410 | complete(pm8001_ha->nvmd_completion); | 3665 | complete(pm8001_ha->nvmd_completion); |
| 3411 | ccb->task = NULL; | 3666 | ccb->task = NULL; |
| 3412 | ccb->ccb_tag = 0xFFFFFFFF; | 3667 | ccb->ccb_tag = 0xFFFFFFFF; |
| @@ -3414,8 +3669,7 @@ mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3414 | return 0; | 3669 | return 0; |
| 3415 | } | 3670 | } |
| 3416 | 3671 | ||
| 3417 | static int | 3672 | int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb) |
| 3418 | mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | ||
| 3419 | { | 3673 | { |
| 3420 | u32 status; | 3674 | u32 status; |
| 3421 | int i; | 3675 | int i; |
| @@ -3431,8 +3685,7 @@ mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | |||
| 3431 | return 0; | 3685 | return 0; |
| 3432 | } | 3686 | } |
| 3433 | 3687 | ||
| 3434 | static int | 3688 | int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) |
| 3435 | mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 3436 | { | 3689 | { |
| 3437 | struct sas_task *t; | 3690 | struct sas_task *t; |
| 3438 | struct pm8001_ccb_info *ccb; | 3691 | struct pm8001_ccb_info *ccb; |
| @@ -3440,19 +3693,29 @@ mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3440 | u32 status ; | 3693 | u32 status ; |
| 3441 | u32 tag, scp; | 3694 | u32 tag, scp; |
| 3442 | struct task_status_struct *ts; | 3695 | struct task_status_struct *ts; |
| 3696 | struct pm8001_device *pm8001_dev; | ||
| 3443 | 3697 | ||
| 3444 | struct task_abort_resp *pPayload = | 3698 | struct task_abort_resp *pPayload = |
| 3445 | (struct task_abort_resp *)(piomb + 4); | 3699 | (struct task_abort_resp *)(piomb + 4); |
| 3446 | 3700 | ||
| 3447 | status = le32_to_cpu(pPayload->status); | 3701 | status = le32_to_cpu(pPayload->status); |
| 3448 | tag = le32_to_cpu(pPayload->tag); | 3702 | tag = le32_to_cpu(pPayload->tag); |
| 3703 | if (!tag) { | ||
| 3704 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 3705 | pm8001_printk(" TAG NULL. RETURNING !!!")); | ||
| 3706 | return -1; | ||
| 3707 | } | ||
| 3708 | |||
| 3449 | scp = le32_to_cpu(pPayload->scp); | 3709 | scp = le32_to_cpu(pPayload->scp); |
| 3450 | ccb = &pm8001_ha->ccb_info[tag]; | 3710 | ccb = &pm8001_ha->ccb_info[tag]; |
| 3451 | t = ccb->task; | 3711 | t = ccb->task; |
| 3452 | PM8001_IO_DBG(pm8001_ha, | 3712 | pm8001_dev = ccb->device; /* retrieve device */ |
| 3453 | pm8001_printk(" status = 0x%x\n", status)); | 3713 | |
| 3454 | if (t == NULL) | 3714 | if (!t) { |
| 3715 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 3716 | pm8001_printk(" TASK NULL. RETURNING !!!")); | ||
| 3455 | return -1; | 3717 | return -1; |
| 3718 | } | ||
| 3456 | ts = &t->task_status; | 3719 | ts = &t->task_status; |
| 3457 | if (status != 0) | 3720 | if (status != 0) |
| 3458 | PM8001_FAIL_DBG(pm8001_ha, | 3721 | PM8001_FAIL_DBG(pm8001_ha, |
| @@ -3476,7 +3739,15 @@ mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3476 | spin_unlock_irqrestore(&t->task_state_lock, flags); | 3739 | spin_unlock_irqrestore(&t->task_state_lock, flags); |
| 3477 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | 3740 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); |
| 3478 | mb(); | 3741 | mb(); |
| 3479 | t->task_done(t); | 3742 | |
| 3743 | if ((pm8001_dev->id & NCQ_ABORT_ALL_FLAG) && t) { | ||
| 3744 | pm8001_tag_free(pm8001_ha, tag); | ||
| 3745 | sas_free_task(t); | ||
| 3746 | /* clear the flag */ | ||
| 3747 | pm8001_dev->id &= 0xBFFFFFFF; | ||
| 3748 | } else | ||
| 3749 | t->task_done(t); | ||
| 3750 | |||
| 3480 | return 0; | 3751 | return 0; |
| 3481 | } | 3752 | } |
| 3482 | 3753 | ||
| @@ -3727,17 +3998,17 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3727 | case OPC_OUB_LOCAL_PHY_CNTRL: | 3998 | case OPC_OUB_LOCAL_PHY_CNTRL: |
| 3728 | PM8001_MSG_DBG(pm8001_ha, | 3999 | PM8001_MSG_DBG(pm8001_ha, |
| 3729 | pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n")); | 4000 | pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n")); |
| 3730 | mpi_local_phy_ctl(pm8001_ha, piomb); | 4001 | pm8001_mpi_local_phy_ctl(pm8001_ha, piomb); |
| 3731 | break; | 4002 | break; |
| 3732 | case OPC_OUB_DEV_REGIST: | 4003 | case OPC_OUB_DEV_REGIST: |
| 3733 | PM8001_MSG_DBG(pm8001_ha, | 4004 | PM8001_MSG_DBG(pm8001_ha, |
| 3734 | pm8001_printk("OPC_OUB_DEV_REGIST\n")); | 4005 | pm8001_printk("OPC_OUB_DEV_REGIST\n")); |
| 3735 | mpi_reg_resp(pm8001_ha, piomb); | 4006 | pm8001_mpi_reg_resp(pm8001_ha, piomb); |
| 3736 | break; | 4007 | break; |
| 3737 | case OPC_OUB_DEREG_DEV: | 4008 | case OPC_OUB_DEREG_DEV: |
| 3738 | PM8001_MSG_DBG(pm8001_ha, | 4009 | PM8001_MSG_DBG(pm8001_ha, |
| 3739 | pm8001_printk("unregister the device\n")); | 4010 | pm8001_printk("unregister the device\n")); |
| 3740 | mpi_dereg_resp(pm8001_ha, piomb); | 4011 | pm8001_mpi_dereg_resp(pm8001_ha, piomb); |
| 3741 | break; | 4012 | break; |
| 3742 | case OPC_OUB_GET_DEV_HANDLE: | 4013 | case OPC_OUB_GET_DEV_HANDLE: |
| 3743 | PM8001_MSG_DBG(pm8001_ha, | 4014 | PM8001_MSG_DBG(pm8001_ha, |
| @@ -3775,7 +4046,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3775 | case OPC_OUB_FW_FLASH_UPDATE: | 4046 | case OPC_OUB_FW_FLASH_UPDATE: |
| 3776 | PM8001_MSG_DBG(pm8001_ha, | 4047 | PM8001_MSG_DBG(pm8001_ha, |
| 3777 | pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n")); | 4048 | pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n")); |
| 3778 | mpi_fw_flash_update_resp(pm8001_ha, piomb); | 4049 | pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb); |
| 3779 | break; | 4050 | break; |
| 3780 | case OPC_OUB_GPIO_RESPONSE: | 4051 | case OPC_OUB_GPIO_RESPONSE: |
| 3781 | PM8001_MSG_DBG(pm8001_ha, | 4052 | PM8001_MSG_DBG(pm8001_ha, |
| @@ -3788,17 +4059,17 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3788 | case OPC_OUB_GENERAL_EVENT: | 4059 | case OPC_OUB_GENERAL_EVENT: |
| 3789 | PM8001_MSG_DBG(pm8001_ha, | 4060 | PM8001_MSG_DBG(pm8001_ha, |
| 3790 | pm8001_printk("OPC_OUB_GENERAL_EVENT\n")); | 4061 | pm8001_printk("OPC_OUB_GENERAL_EVENT\n")); |
| 3791 | mpi_general_event(pm8001_ha, piomb); | 4062 | pm8001_mpi_general_event(pm8001_ha, piomb); |
| 3792 | break; | 4063 | break; |
| 3793 | case OPC_OUB_SSP_ABORT_RSP: | 4064 | case OPC_OUB_SSP_ABORT_RSP: |
| 3794 | PM8001_MSG_DBG(pm8001_ha, | 4065 | PM8001_MSG_DBG(pm8001_ha, |
| 3795 | pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n")); | 4066 | pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n")); |
| 3796 | mpi_task_abort_resp(pm8001_ha, piomb); | 4067 | pm8001_mpi_task_abort_resp(pm8001_ha, piomb); |
| 3797 | break; | 4068 | break; |
| 3798 | case OPC_OUB_SATA_ABORT_RSP: | 4069 | case OPC_OUB_SATA_ABORT_RSP: |
| 3799 | PM8001_MSG_DBG(pm8001_ha, | 4070 | PM8001_MSG_DBG(pm8001_ha, |
| 3800 | pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n")); | 4071 | pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n")); |
| 3801 | mpi_task_abort_resp(pm8001_ha, piomb); | 4072 | pm8001_mpi_task_abort_resp(pm8001_ha, piomb); |
| 3802 | break; | 4073 | break; |
| 3803 | case OPC_OUB_SAS_DIAG_MODE_START_END: | 4074 | case OPC_OUB_SAS_DIAG_MODE_START_END: |
| 3804 | PM8001_MSG_DBG(pm8001_ha, | 4075 | PM8001_MSG_DBG(pm8001_ha, |
| @@ -3823,17 +4094,17 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3823 | case OPC_OUB_SMP_ABORT_RSP: | 4094 | case OPC_OUB_SMP_ABORT_RSP: |
| 3824 | PM8001_MSG_DBG(pm8001_ha, | 4095 | PM8001_MSG_DBG(pm8001_ha, |
| 3825 | pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n")); | 4096 | pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n")); |
| 3826 | mpi_task_abort_resp(pm8001_ha, piomb); | 4097 | pm8001_mpi_task_abort_resp(pm8001_ha, piomb); |
| 3827 | break; | 4098 | break; |
| 3828 | case OPC_OUB_GET_NVMD_DATA: | 4099 | case OPC_OUB_GET_NVMD_DATA: |
| 3829 | PM8001_MSG_DBG(pm8001_ha, | 4100 | PM8001_MSG_DBG(pm8001_ha, |
| 3830 | pm8001_printk("OPC_OUB_GET_NVMD_DATA\n")); | 4101 | pm8001_printk("OPC_OUB_GET_NVMD_DATA\n")); |
| 3831 | mpi_get_nvmd_resp(pm8001_ha, piomb); | 4102 | pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb); |
| 3832 | break; | 4103 | break; |
| 3833 | case OPC_OUB_SET_NVMD_DATA: | 4104 | case OPC_OUB_SET_NVMD_DATA: |
| 3834 | PM8001_MSG_DBG(pm8001_ha, | 4105 | PM8001_MSG_DBG(pm8001_ha, |
| 3835 | pm8001_printk("OPC_OUB_SET_NVMD_DATA\n")); | 4106 | pm8001_printk("OPC_OUB_SET_NVMD_DATA\n")); |
| 3836 | mpi_set_nvmd_resp(pm8001_ha, piomb); | 4107 | pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb); |
| 3837 | break; | 4108 | break; |
| 3838 | case OPC_OUB_DEVICE_HANDLE_REMOVAL: | 4109 | case OPC_OUB_DEVICE_HANDLE_REMOVAL: |
| 3839 | PM8001_MSG_DBG(pm8001_ha, | 4110 | PM8001_MSG_DBG(pm8001_ha, |
| @@ -3842,7 +4113,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3842 | case OPC_OUB_SET_DEVICE_STATE: | 4113 | case OPC_OUB_SET_DEVICE_STATE: |
| 3843 | PM8001_MSG_DBG(pm8001_ha, | 4114 | PM8001_MSG_DBG(pm8001_ha, |
| 3844 | pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n")); | 4115 | pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n")); |
| 3845 | mpi_set_dev_state_resp(pm8001_ha, piomb); | 4116 | pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb); |
| 3846 | break; | 4117 | break; |
| 3847 | case OPC_OUB_GET_DEVICE_STATE: | 4118 | case OPC_OUB_GET_DEVICE_STATE: |
| 3848 | PM8001_MSG_DBG(pm8001_ha, | 4119 | PM8001_MSG_DBG(pm8001_ha, |
| @@ -3864,7 +4135,7 @@ static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 3864 | } | 4135 | } |
| 3865 | } | 4136 | } |
| 3866 | 4137 | ||
| 3867 | static int process_oq(struct pm8001_hba_info *pm8001_ha) | 4138 | static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) |
| 3868 | { | 4139 | { |
| 3869 | struct outbound_queue_table *circularQ; | 4140 | struct outbound_queue_table *circularQ; |
| 3870 | void *pMsg1 = NULL; | 4141 | void *pMsg1 = NULL; |
| @@ -3873,14 +4144,15 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha) | |||
| 3873 | unsigned long flags; | 4144 | unsigned long flags; |
| 3874 | 4145 | ||
| 3875 | spin_lock_irqsave(&pm8001_ha->lock, flags); | 4146 | spin_lock_irqsave(&pm8001_ha->lock, flags); |
| 3876 | circularQ = &pm8001_ha->outbnd_q_tbl[0]; | 4147 | circularQ = &pm8001_ha->outbnd_q_tbl[vec]; |
| 3877 | do { | 4148 | do { |
| 3878 | ret = mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc); | 4149 | ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc); |
| 3879 | if (MPI_IO_STATUS_SUCCESS == ret) { | 4150 | if (MPI_IO_STATUS_SUCCESS == ret) { |
| 3880 | /* process the outbound message */ | 4151 | /* process the outbound message */ |
| 3881 | process_one_iomb(pm8001_ha, (void *)(pMsg1 - 4)); | 4152 | process_one_iomb(pm8001_ha, (void *)(pMsg1 - 4)); |
| 3882 | /* free the message from the outbound circular buffer */ | 4153 | /* free the message from the outbound circular buffer */ |
| 3883 | mpi_msg_free_set(pm8001_ha, pMsg1, circularQ, bc); | 4154 | pm8001_mpi_msg_free_set(pm8001_ha, pMsg1, |
| 4155 | circularQ, bc); | ||
| 3884 | } | 4156 | } |
| 3885 | if (MPI_IO_STATUS_BUSY == ret) { | 4157 | if (MPI_IO_STATUS_BUSY == ret) { |
| 3886 | /* Update the producer index from SPC */ | 4158 | /* Update the producer index from SPC */ |
| @@ -3903,7 +4175,7 @@ static const u8 data_dir_flags[] = { | |||
| 3903 | [PCI_DMA_FROMDEVICE] = DATA_DIR_IN,/* INBOUND */ | 4175 | [PCI_DMA_FROMDEVICE] = DATA_DIR_IN,/* INBOUND */ |
| 3904 | [PCI_DMA_NONE] = DATA_DIR_NONE,/* NO TRANSFER */ | 4176 | [PCI_DMA_NONE] = DATA_DIR_NONE,/* NO TRANSFER */ |
| 3905 | }; | 4177 | }; |
| 3906 | static void | 4178 | void |
| 3907 | pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd) | 4179 | pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd) |
| 3908 | { | 4180 | { |
| 3909 | int i; | 4181 | int i; |
| @@ -3978,7 +4250,7 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha, | |||
| 3978 | smp_cmd.long_smp_req.long_resp_size = | 4250 | smp_cmd.long_smp_req.long_resp_size = |
| 3979 | cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4); | 4251 | cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4); |
| 3980 | build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd); | 4252 | build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd); |
| 3981 | mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd); | 4253 | pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0); |
| 3982 | return 0; | 4254 | return 0; |
| 3983 | 4255 | ||
| 3984 | err_out_2: | 4256 | err_out_2: |
| @@ -4042,7 +4314,7 @@ static int pm8001_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4042 | ssp_cmd.len = cpu_to_le32(task->total_xfer_len); | 4314 | ssp_cmd.len = cpu_to_le32(task->total_xfer_len); |
| 4043 | ssp_cmd.esgl = 0; | 4315 | ssp_cmd.esgl = 0; |
| 4044 | } | 4316 | } |
| 4045 | ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd); | 4317 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, 0); |
| 4046 | return ret; | 4318 | return ret; |
| 4047 | } | 4319 | } |
| 4048 | 4320 | ||
| @@ -4060,6 +4332,7 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4060 | u32 ATAP = 0x0; | 4332 | u32 ATAP = 0x0; |
| 4061 | u32 dir; | 4333 | u32 dir; |
| 4062 | struct inbound_queue_table *circularQ; | 4334 | struct inbound_queue_table *circularQ; |
| 4335 | unsigned long flags; | ||
| 4063 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | 4336 | u32 opc = OPC_INB_SATA_HOST_OPSTART; |
| 4064 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | 4337 | memset(&sata_cmd, 0, sizeof(sata_cmd)); |
| 4065 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4338 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
| @@ -4080,8 +4353,10 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4080 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n")); | 4353 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n")); |
| 4081 | } | 4354 | } |
| 4082 | } | 4355 | } |
| 4083 | if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) | 4356 | if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) { |
| 4357 | task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3); | ||
| 4084 | ncg_tag = hdr_tag; | 4358 | ncg_tag = hdr_tag; |
| 4359 | } | ||
| 4085 | dir = data_dir_flags[task->data_dir] << 8; | 4360 | dir = data_dir_flags[task->data_dir] << 8; |
| 4086 | sata_cmd.tag = cpu_to_le32(tag); | 4361 | sata_cmd.tag = cpu_to_le32(tag); |
| 4087 | sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); | 4362 | sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); |
| @@ -4112,7 +4387,55 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4112 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); | 4387 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); |
| 4113 | sata_cmd.esgl = 0; | 4388 | sata_cmd.esgl = 0; |
| 4114 | } | 4389 | } |
| 4115 | ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd); | 4390 | |
| 4391 | /* Check for read log for failed drive and return */ | ||
| 4392 | if (sata_cmd.sata_fis.command == 0x2f) { | ||
| 4393 | if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) || | ||
| 4394 | (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) || | ||
| 4395 | (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) { | ||
| 4396 | struct task_status_struct *ts; | ||
| 4397 | |||
| 4398 | pm8001_ha_dev->id &= 0xDFFFFFFF; | ||
| 4399 | ts = &task->task_status; | ||
| 4400 | |||
| 4401 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
| 4402 | ts->resp = SAS_TASK_COMPLETE; | ||
| 4403 | ts->stat = SAM_STAT_GOOD; | ||
| 4404 | task->task_state_flags &= ~SAS_TASK_STATE_PENDING; | ||
| 4405 | task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | ||
| 4406 | task->task_state_flags |= SAS_TASK_STATE_DONE; | ||
| 4407 | if (unlikely((task->task_state_flags & | ||
| 4408 | SAS_TASK_STATE_ABORTED))) { | ||
| 4409 | spin_unlock_irqrestore(&task->task_state_lock, | ||
| 4410 | flags); | ||
| 4411 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 4412 | pm8001_printk("task 0x%p resp 0x%x " | ||
| 4413 | " stat 0x%x but aborted by upper layer " | ||
| 4414 | "\n", task, ts->resp, ts->stat)); | ||
| 4415 | pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); | ||
| 4416 | } else if (task->uldd_task) { | ||
| 4417 | spin_unlock_irqrestore(&task->task_state_lock, | ||
| 4418 | flags); | ||
| 4419 | pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); | ||
| 4420 | mb();/* ditto */ | ||
| 4421 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 4422 | task->task_done(task); | ||
| 4423 | spin_lock_irq(&pm8001_ha->lock); | ||
| 4424 | return 0; | ||
| 4425 | } else if (!task->uldd_task) { | ||
| 4426 | spin_unlock_irqrestore(&task->task_state_lock, | ||
| 4427 | flags); | ||
| 4428 | pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); | ||
| 4429 | mb();/*ditto*/ | ||
| 4430 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 4431 | task->task_done(task); | ||
| 4432 | spin_lock_irq(&pm8001_ha->lock); | ||
| 4433 | return 0; | ||
| 4434 | } | ||
| 4435 | } | ||
| 4436 | } | ||
| 4437 | |||
| 4438 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); | ||
| 4116 | return ret; | 4439 | return ret; |
| 4117 | } | 4440 | } |
| 4118 | 4441 | ||
| @@ -4142,12 +4465,12 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) | |||
| 4142 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | | 4465 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | |
| 4143 | LINKMODE_AUTO | LINKRATE_15 | | 4466 | LINKMODE_AUTO | LINKRATE_15 | |
| 4144 | LINKRATE_30 | LINKRATE_60 | phy_id); | 4467 | LINKRATE_30 | LINKRATE_60 | phy_id); |
| 4145 | payload.sas_identify.dev_type = SAS_END_DEV; | 4468 | payload.sas_identify.dev_type = SAS_END_DEVICE; |
| 4146 | payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL; | 4469 | payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL; |
| 4147 | memcpy(payload.sas_identify.sas_addr, | 4470 | memcpy(payload.sas_identify.sas_addr, |
| 4148 | pm8001_ha->sas_addr, SAS_ADDR_SIZE); | 4471 | pm8001_ha->sas_addr, SAS_ADDR_SIZE); |
| 4149 | payload.sas_identify.phy_id = phy_id; | 4472 | payload.sas_identify.phy_id = phy_id; |
| 4150 | ret = mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload); | 4473 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0); |
| 4151 | return ret; | 4474 | return ret; |
| 4152 | } | 4475 | } |
| 4153 | 4476 | ||
| @@ -4157,7 +4480,7 @@ pm8001_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) | |||
| 4157 | * @num: the inbound queue number | 4480 | * @num: the inbound queue number |
| 4158 | * @phy_id: the phy id which we wanted to start up. | 4481 | * @phy_id: the phy id which we wanted to start up. |
| 4159 | */ | 4482 | */ |
| 4160 | static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, | 4483 | int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, |
| 4161 | u8 phy_id) | 4484 | u8 phy_id) |
| 4162 | { | 4485 | { |
| 4163 | struct phy_stop_req payload; | 4486 | struct phy_stop_req payload; |
| @@ -4169,12 +4492,12 @@ static int pm8001_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4169 | memset(&payload, 0, sizeof(payload)); | 4492 | memset(&payload, 0, sizeof(payload)); |
| 4170 | payload.tag = cpu_to_le32(tag); | 4493 | payload.tag = cpu_to_le32(tag); |
| 4171 | payload.phy_id = cpu_to_le32(phy_id); | 4494 | payload.phy_id = cpu_to_le32(phy_id); |
| 4172 | ret = mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload); | 4495 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0); |
| 4173 | return ret; | 4496 | return ret; |
| 4174 | } | 4497 | } |
| 4175 | 4498 | ||
| 4176 | /** | 4499 | /** |
| 4177 | * see comments on mpi_reg_resp. | 4500 | * see comments on pm8001_mpi_reg_resp. |
| 4178 | */ | 4501 | */ |
| 4179 | static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, | 4502 | static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, |
| 4180 | struct pm8001_device *pm8001_dev, u32 flag) | 4503 | struct pm8001_device *pm8001_dev, u32 flag) |
| @@ -4204,11 +4527,11 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4204 | if (flag == 1) | 4527 | if (flag == 1) |
| 4205 | stp_sspsmp_sata = 0x02; /*direct attached sata */ | 4528 | stp_sspsmp_sata = 0x02; /*direct attached sata */ |
| 4206 | else { | 4529 | else { |
| 4207 | if (pm8001_dev->dev_type == SATA_DEV) | 4530 | if (pm8001_dev->dev_type == SAS_SATA_DEV) |
| 4208 | stp_sspsmp_sata = 0x00; /* stp*/ | 4531 | stp_sspsmp_sata = 0x00; /* stp*/ |
| 4209 | else if (pm8001_dev->dev_type == SAS_END_DEV || | 4532 | else if (pm8001_dev->dev_type == SAS_END_DEVICE || |
| 4210 | pm8001_dev->dev_type == EDGE_DEV || | 4533 | pm8001_dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || |
| 4211 | pm8001_dev->dev_type == FANOUT_DEV) | 4534 | pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) |
| 4212 | stp_sspsmp_sata = 0x01; /*ssp or smp*/ | 4535 | stp_sspsmp_sata = 0x01; /*ssp or smp*/ |
| 4213 | } | 4536 | } |
| 4214 | if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) | 4537 | if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) |
| @@ -4228,14 +4551,14 @@ static int pm8001_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4228 | cpu_to_le32(ITNT | (firstBurstSize * 0x10000)); | 4551 | cpu_to_le32(ITNT | (firstBurstSize * 0x10000)); |
| 4229 | memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr, | 4552 | memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr, |
| 4230 | SAS_ADDR_SIZE); | 4553 | SAS_ADDR_SIZE); |
| 4231 | rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); | 4554 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); |
| 4232 | return rc; | 4555 | return rc; |
| 4233 | } | 4556 | } |
| 4234 | 4557 | ||
| 4235 | /** | 4558 | /** |
| 4236 | * see comments on mpi_reg_resp. | 4559 | * see comments on pm8001_mpi_reg_resp. |
| 4237 | */ | 4560 | */ |
| 4238 | static int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, | 4561 | int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, |
| 4239 | u32 device_id) | 4562 | u32 device_id) |
| 4240 | { | 4563 | { |
| 4241 | struct dereg_dev_req payload; | 4564 | struct dereg_dev_req payload; |
| @@ -4249,7 +4572,7 @@ static int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4249 | payload.device_id = cpu_to_le32(device_id); | 4572 | payload.device_id = cpu_to_le32(device_id); |
| 4250 | PM8001_MSG_DBG(pm8001_ha, | 4573 | PM8001_MSG_DBG(pm8001_ha, |
| 4251 | pm8001_printk("unregister device device_id = %d\n", device_id)); | 4574 | pm8001_printk("unregister device device_id = %d\n", device_id)); |
| 4252 | ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); | 4575 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); |
| 4253 | return ret; | 4576 | return ret; |
| 4254 | } | 4577 | } |
| 4255 | 4578 | ||
| @@ -4272,7 +4595,7 @@ static int pm8001_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4272 | payload.tag = cpu_to_le32(1); | 4595 | payload.tag = cpu_to_le32(1); |
| 4273 | payload.phyop_phyid = | 4596 | payload.phyop_phyid = |
| 4274 | cpu_to_le32(((phy_op & 0xff) << 8) | (phyId & 0x0F)); | 4597 | cpu_to_le32(((phy_op & 0xff) << 8) | (phyId & 0x0F)); |
| 4275 | ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); | 4598 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); |
| 4276 | return ret; | 4599 | return ret; |
| 4277 | } | 4600 | } |
| 4278 | 4601 | ||
| @@ -4296,11 +4619,11 @@ static u32 pm8001_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha) | |||
| 4296 | * @stat: stat. | 4619 | * @stat: stat. |
| 4297 | */ | 4620 | */ |
| 4298 | static irqreturn_t | 4621 | static irqreturn_t |
| 4299 | pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha) | 4622 | pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) |
| 4300 | { | 4623 | { |
| 4301 | pm8001_chip_interrupt_disable(pm8001_ha); | 4624 | pm8001_chip_interrupt_disable(pm8001_ha, vec); |
| 4302 | process_oq(pm8001_ha); | 4625 | process_oq(pm8001_ha, vec); |
| 4303 | pm8001_chip_interrupt_enable(pm8001_ha); | 4626 | pm8001_chip_interrupt_enable(pm8001_ha, vec); |
| 4304 | return IRQ_HANDLED; | 4627 | return IRQ_HANDLED; |
| 4305 | } | 4628 | } |
| 4306 | 4629 | ||
| @@ -4322,7 +4645,7 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc, | |||
| 4322 | task_abort.device_id = cpu_to_le32(dev_id); | 4645 | task_abort.device_id = cpu_to_le32(dev_id); |
| 4323 | task_abort.tag = cpu_to_le32(cmd_tag); | 4646 | task_abort.tag = cpu_to_le32(cmd_tag); |
| 4324 | } | 4647 | } |
| 4325 | ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort); | 4648 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); |
| 4326 | return ret; | 4649 | return ret; |
| 4327 | } | 4650 | } |
| 4328 | 4651 | ||
| @@ -4331,16 +4654,17 @@ static int send_task_abort(struct pm8001_hba_info *pm8001_ha, u32 opc, | |||
| 4331 | * @task: the task we wanted to aborted. | 4654 | * @task: the task we wanted to aborted. |
| 4332 | * @flag: the abort flag. | 4655 | * @flag: the abort flag. |
| 4333 | */ | 4656 | */ |
| 4334 | static int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, | 4657 | int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, |
| 4335 | struct pm8001_device *pm8001_dev, u8 flag, u32 task_tag, u32 cmd_tag) | 4658 | struct pm8001_device *pm8001_dev, u8 flag, u32 task_tag, u32 cmd_tag) |
| 4336 | { | 4659 | { |
| 4337 | u32 opc, device_id; | 4660 | u32 opc, device_id; |
| 4338 | int rc = TMF_RESP_FUNC_FAILED; | 4661 | int rc = TMF_RESP_FUNC_FAILED; |
| 4339 | PM8001_EH_DBG(pm8001_ha, pm8001_printk("cmd_tag = %x, abort task tag" | 4662 | PM8001_EH_DBG(pm8001_ha, |
| 4340 | " = %x", cmd_tag, task_tag)); | 4663 | pm8001_printk("cmd_tag = %x, abort task tag = 0x%x", |
| 4341 | if (pm8001_dev->dev_type == SAS_END_DEV) | 4664 | cmd_tag, task_tag)); |
| 4665 | if (pm8001_dev->dev_type == SAS_END_DEVICE) | ||
| 4342 | opc = OPC_INB_SSP_ABORT; | 4666 | opc = OPC_INB_SSP_ABORT; |
| 4343 | else if (pm8001_dev->dev_type == SATA_DEV) | 4667 | else if (pm8001_dev->dev_type == SAS_SATA_DEV) |
| 4344 | opc = OPC_INB_SATA_ABORT; | 4668 | opc = OPC_INB_SATA_ABORT; |
| 4345 | else | 4669 | else |
| 4346 | opc = OPC_INB_SMP_ABORT;/* SMP */ | 4670 | opc = OPC_INB_SMP_ABORT;/* SMP */ |
| @@ -4358,7 +4682,7 @@ static int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, | |||
| 4358 | * @ccb: the ccb information. | 4682 | * @ccb: the ccb information. |
| 4359 | * @tmf: task management function. | 4683 | * @tmf: task management function. |
| 4360 | */ | 4684 | */ |
| 4361 | static int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, | 4685 | int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, |
| 4362 | struct pm8001_ccb_info *ccb, struct pm8001_tmf_task *tmf) | 4686 | struct pm8001_ccb_info *ccb, struct pm8001_tmf_task *tmf) |
| 4363 | { | 4687 | { |
| 4364 | struct sas_task *task = ccb->task; | 4688 | struct sas_task *task = ccb->task; |
| @@ -4376,11 +4700,11 @@ static int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4376 | memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8); | 4700 | memcpy(sspTMCmd.lun, task->ssp_task.LUN, 8); |
| 4377 | sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag); | 4701 | sspTMCmd.tag = cpu_to_le32(ccb->ccb_tag); |
| 4378 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4702 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
| 4379 | ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd); | 4703 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sspTMCmd, 0); |
| 4380 | return ret; | 4704 | return ret; |
| 4381 | } | 4705 | } |
| 4382 | 4706 | ||
| 4383 | static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, | 4707 | int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, |
| 4384 | void *payload) | 4708 | void *payload) |
| 4385 | { | 4709 | { |
| 4386 | u32 opc = OPC_INB_GET_NVMD_DATA; | 4710 | u32 opc = OPC_INB_GET_NVMD_DATA; |
| @@ -4397,7 +4721,7 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4397 | fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL); | 4721 | fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL); |
| 4398 | if (!fw_control_context) | 4722 | if (!fw_control_context) |
| 4399 | return -ENOMEM; | 4723 | return -ENOMEM; |
| 4400 | fw_control_context->usrAddr = (u8 *)&ioctl_payload->func_specific[0]; | 4724 | fw_control_context->usrAddr = (u8 *)ioctl_payload->func_specific; |
| 4401 | fw_control_context->len = ioctl_payload->length; | 4725 | fw_control_context->len = ioctl_payload->length; |
| 4402 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4726 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
| 4403 | memset(&nvmd_req, 0, sizeof(nvmd_req)); | 4727 | memset(&nvmd_req, 0, sizeof(nvmd_req)); |
| @@ -4456,11 +4780,11 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4456 | default: | 4780 | default: |
| 4457 | break; | 4781 | break; |
| 4458 | } | 4782 | } |
| 4459 | rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req); | 4783 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0); |
| 4460 | return rc; | 4784 | return rc; |
| 4461 | } | 4785 | } |
| 4462 | 4786 | ||
| 4463 | static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, | 4787 | int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, |
| 4464 | void *payload) | 4788 | void *payload) |
| 4465 | { | 4789 | { |
| 4466 | u32 opc = OPC_INB_SET_NVMD_DATA; | 4790 | u32 opc = OPC_INB_SET_NVMD_DATA; |
| @@ -4479,7 +4803,7 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4479 | return -ENOMEM; | 4803 | return -ENOMEM; |
| 4480 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | 4804 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; |
| 4481 | memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr, | 4805 | memcpy(pm8001_ha->memoryMap.region[NVMD].virt_ptr, |
| 4482 | ioctl_payload->func_specific, | 4806 | &ioctl_payload->func_specific, |
| 4483 | ioctl_payload->length); | 4807 | ioctl_payload->length); |
| 4484 | memset(&nvmd_req, 0, sizeof(nvmd_req)); | 4808 | memset(&nvmd_req, 0, sizeof(nvmd_req)); |
| 4485 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4809 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
| @@ -4536,7 +4860,7 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4536 | default: | 4860 | default: |
| 4537 | break; | 4861 | break; |
| 4538 | } | 4862 | } |
| 4539 | rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req); | 4863 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0); |
| 4540 | return rc; | 4864 | return rc; |
| 4541 | } | 4865 | } |
| 4542 | 4866 | ||
| @@ -4545,7 +4869,7 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4545 | * @pm8001_ha: our hba card information. | 4869 | * @pm8001_ha: our hba card information. |
| 4546 | * @fw_flash_updata_info: firmware flash update param | 4870 | * @fw_flash_updata_info: firmware flash update param |
| 4547 | */ | 4871 | */ |
| 4548 | static int | 4872 | int |
| 4549 | pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha, | 4873 | pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha, |
| 4550 | void *fw_flash_updata_info, u32 tag) | 4874 | void *fw_flash_updata_info, u32 tag) |
| 4551 | { | 4875 | { |
| @@ -4567,11 +4891,11 @@ pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha, | |||
| 4567 | cpu_to_le32(lower_32_bits(le64_to_cpu(info->sgl.addr))); | 4891 | cpu_to_le32(lower_32_bits(le64_to_cpu(info->sgl.addr))); |
| 4568 | payload.sgl_addr_hi = | 4892 | payload.sgl_addr_hi = |
| 4569 | cpu_to_le32(upper_32_bits(le64_to_cpu(info->sgl.addr))); | 4893 | cpu_to_le32(upper_32_bits(le64_to_cpu(info->sgl.addr))); |
| 4570 | ret = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); | 4894 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); |
| 4571 | return ret; | 4895 | return ret; |
| 4572 | } | 4896 | } |
| 4573 | 4897 | ||
| 4574 | static int | 4898 | int |
| 4575 | pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | 4899 | pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, |
| 4576 | void *payload) | 4900 | void *payload) |
| 4577 | { | 4901 | { |
| @@ -4581,29 +4905,14 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4581 | int rc; | 4905 | int rc; |
| 4582 | u32 tag; | 4906 | u32 tag; |
| 4583 | struct pm8001_ccb_info *ccb; | 4907 | struct pm8001_ccb_info *ccb; |
| 4584 | void *buffer = NULL; | 4908 | void *buffer = pm8001_ha->memoryMap.region[FW_FLASH].virt_ptr; |
| 4585 | dma_addr_t phys_addr; | 4909 | dma_addr_t phys_addr = pm8001_ha->memoryMap.region[FW_FLASH].phys_addr; |
| 4586 | u32 phys_addr_hi; | ||
| 4587 | u32 phys_addr_lo; | ||
| 4588 | struct pm8001_ioctl_payload *ioctl_payload = payload; | 4910 | struct pm8001_ioctl_payload *ioctl_payload = payload; |
| 4589 | 4911 | ||
| 4590 | fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL); | 4912 | fw_control_context = kzalloc(sizeof(struct fw_control_ex), GFP_KERNEL); |
| 4591 | if (!fw_control_context) | 4913 | if (!fw_control_context) |
| 4592 | return -ENOMEM; | 4914 | return -ENOMEM; |
| 4593 | fw_control = (struct fw_control_info *)&ioctl_payload->func_specific[0]; | 4915 | fw_control = (struct fw_control_info *)&ioctl_payload->func_specific; |
| 4594 | if (fw_control->len != 0) { | ||
| 4595 | if (pm8001_mem_alloc(pm8001_ha->pdev, | ||
| 4596 | (void **)&buffer, | ||
| 4597 | &phys_addr, | ||
| 4598 | &phys_addr_hi, | ||
| 4599 | &phys_addr_lo, | ||
| 4600 | fw_control->len, 0) != 0) { | ||
| 4601 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 4602 | pm8001_printk("Mem alloc failure\n")); | ||
| 4603 | kfree(fw_control_context); | ||
| 4604 | return -ENOMEM; | ||
| 4605 | } | ||
| 4606 | } | ||
| 4607 | memcpy(buffer, fw_control->buffer, fw_control->len); | 4916 | memcpy(buffer, fw_control->buffer, fw_control->len); |
| 4608 | flash_update_info.sgl.addr = cpu_to_le64(phys_addr); | 4917 | flash_update_info.sgl.addr = cpu_to_le64(phys_addr); |
| 4609 | flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len); | 4918 | flash_update_info.sgl.im_len.len = cpu_to_le32(fw_control->len); |
| @@ -4613,6 +4922,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4613 | flash_update_info.total_image_len = fw_control->size; | 4922 | flash_update_info.total_image_len = fw_control->size; |
| 4614 | fw_control_context->fw_control = fw_control; | 4923 | fw_control_context->fw_control = fw_control; |
| 4615 | fw_control_context->virtAddr = buffer; | 4924 | fw_control_context->virtAddr = buffer; |
| 4925 | fw_control_context->phys_addr = phys_addr; | ||
| 4616 | fw_control_context->len = fw_control->len; | 4926 | fw_control_context->len = fw_control->len; |
| 4617 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | 4927 | rc = pm8001_tag_alloc(pm8001_ha, &tag); |
| 4618 | if (rc) { | 4928 | if (rc) { |
| @@ -4627,7 +4937,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4627 | return rc; | 4937 | return rc; |
| 4628 | } | 4938 | } |
| 4629 | 4939 | ||
| 4630 | static int | 4940 | int |
| 4631 | pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, | 4941 | pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, |
| 4632 | struct pm8001_device *pm8001_dev, u32 state) | 4942 | struct pm8001_device *pm8001_dev, u32 state) |
| 4633 | { | 4943 | { |
| @@ -4648,7 +4958,7 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, | |||
| 4648 | payload.tag = cpu_to_le32(tag); | 4958 | payload.tag = cpu_to_le32(tag); |
| 4649 | payload.device_id = cpu_to_le32(pm8001_dev->device_id); | 4959 | payload.device_id = cpu_to_le32(pm8001_dev->device_id); |
| 4650 | payload.nds = cpu_to_le32(state); | 4960 | payload.nds = cpu_to_le32(state); |
| 4651 | rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); | 4961 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); |
| 4652 | return rc; | 4962 | return rc; |
| 4653 | 4963 | ||
| 4654 | } | 4964 | } |
| @@ -4673,7 +4983,7 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha) | |||
| 4673 | payload.SSAHOLT = cpu_to_le32(0xd << 25); | 4983 | payload.SSAHOLT = cpu_to_le32(0xd << 25); |
| 4674 | payload.sata_hol_tmo = cpu_to_le32(80); | 4984 | payload.sata_hol_tmo = cpu_to_le32(80); |
| 4675 | payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff); | 4985 | payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff); |
| 4676 | rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); | 4986 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); |
| 4677 | return rc; | 4987 | return rc; |
| 4678 | 4988 | ||
| 4679 | } | 4989 | } |
| @@ -4706,4 +5016,3 @@ const struct pm8001_dispatch pm8001_8001_dispatch = { | |||
| 4706 | .set_dev_state_req = pm8001_chip_set_dev_state_req, | 5016 | .set_dev_state_req = pm8001_chip_set_dev_state_req, |
| 4707 | .sas_re_init_req = pm8001_chip_sas_re_initialization, | 5017 | .sas_re_init_req = pm8001_chip_sas_re_initialization, |
| 4708 | }; | 5018 | }; |
| 4709 | |||
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h index d437309cb1e1..d7c1e2034226 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.h +++ b/drivers/scsi/pm8001/pm8001_hwi.h | |||
| @@ -131,6 +131,8 @@ | |||
| 131 | #define LINKRATE_30 (0x02 << 8) | 131 | #define LINKRATE_30 (0x02 << 8) |
| 132 | #define LINKRATE_60 (0x04 << 8) | 132 | #define LINKRATE_60 (0x04 << 8) |
| 133 | 133 | ||
| 134 | /* for new SPC controllers MEMBASE III is shared between BIOS and DATA */ | ||
| 135 | #define GSM_SM_BASE 0x4F0000 | ||
| 134 | struct mpi_msg_hdr{ | 136 | struct mpi_msg_hdr{ |
| 135 | __le32 header; /* Bits [11:0] - Message operation code */ | 137 | __le32 header; /* Bits [11:0] - Message operation code */ |
| 136 | /* Bits [15:12] - Message Category */ | 138 | /* Bits [15:12] - Message Category */ |
| @@ -298,7 +300,7 @@ struct local_phy_ctl_resp { | |||
| 298 | 300 | ||
| 299 | 301 | ||
| 300 | #define OP_BITS 0x0000FF00 | 302 | #define OP_BITS 0x0000FF00 |
| 301 | #define ID_BITS 0x0000000F | 303 | #define ID_BITS 0x000000FF |
| 302 | 304 | ||
| 303 | /* | 305 | /* |
| 304 | * brief the data structure of PORT Control Command | 306 | * brief the data structure of PORT Control Command |
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 3d5e522e00fc..e4b9bc7f5410 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver | 2 | * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2008-2009 USI Co., Ltd. | 4 | * Copyright (c) 2008-2009 USI Co., Ltd. |
| 5 | * All rights reserved. | 5 | * All rights reserved. |
| @@ -44,8 +44,16 @@ | |||
| 44 | 44 | ||
| 45 | static struct scsi_transport_template *pm8001_stt; | 45 | static struct scsi_transport_template *pm8001_stt; |
| 46 | 46 | ||
| 47 | /** | ||
| 48 | * chip info structure to identify chip key functionality as | ||
| 49 | * encryption available/not, no of ports, hw specific function ref | ||
| 50 | */ | ||
| 47 | static const struct pm8001_chip_info pm8001_chips[] = { | 51 | static const struct pm8001_chip_info pm8001_chips[] = { |
| 48 | [chip_8001] = { 8, &pm8001_8001_dispatch,}, | 52 | [chip_8001] = {0, 8, &pm8001_8001_dispatch,}, |
| 53 | [chip_8008] = {0, 8, &pm8001_80xx_dispatch,}, | ||
| 54 | [chip_8009] = {1, 8, &pm8001_80xx_dispatch,}, | ||
| 55 | [chip_8018] = {0, 16, &pm8001_80xx_dispatch,}, | ||
| 56 | [chip_8019] = {1, 16, &pm8001_80xx_dispatch,}, | ||
| 49 | }; | 57 | }; |
| 50 | static int pm8001_id; | 58 | static int pm8001_id; |
| 51 | 59 | ||
| @@ -155,37 +163,75 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha) | |||
| 155 | } | 163 | } |
| 156 | 164 | ||
| 157 | #ifdef PM8001_USE_TASKLET | 165 | #ifdef PM8001_USE_TASKLET |
| 166 | |||
| 167 | /** | ||
| 168 | * tasklet for 64 msi-x interrupt handler | ||
| 169 | * @opaque: the passed general host adapter struct | ||
| 170 | * Note: pm8001_tasklet is common for pm8001 & pm80xx | ||
| 171 | */ | ||
| 158 | static void pm8001_tasklet(unsigned long opaque) | 172 | static void pm8001_tasklet(unsigned long opaque) |
| 159 | { | 173 | { |
| 160 | struct pm8001_hba_info *pm8001_ha; | 174 | struct pm8001_hba_info *pm8001_ha; |
| 175 | u32 vec; | ||
| 161 | pm8001_ha = (struct pm8001_hba_info *)opaque; | 176 | pm8001_ha = (struct pm8001_hba_info *)opaque; |
| 162 | if (unlikely(!pm8001_ha)) | 177 | if (unlikely(!pm8001_ha)) |
| 163 | BUG_ON(1); | 178 | BUG_ON(1); |
| 164 | PM8001_CHIP_DISP->isr(pm8001_ha); | 179 | vec = pm8001_ha->int_vector; |
| 180 | PM8001_CHIP_DISP->isr(pm8001_ha, vec); | ||
| 181 | } | ||
| 182 | #endif | ||
| 183 | |||
| 184 | static struct pm8001_hba_info *outq_to_hba(u8 *outq) | ||
| 185 | { | ||
| 186 | return container_of((outq - *outq), struct pm8001_hba_info, outq[0]); | ||
| 165 | } | 187 | } |
| 188 | |||
| 189 | /** | ||
| 190 | * pm8001_interrupt_handler_msix - main MSIX interrupt handler. | ||
| 191 | * It obtains the vector number and calls the equivalent bottom | ||
| 192 | * half or services directly. | ||
| 193 | * @opaque: the passed outbound queue/vector. Host structure is | ||
| 194 | * retrieved from the same. | ||
| 195 | */ | ||
| 196 | static irqreturn_t pm8001_interrupt_handler_msix(int irq, void *opaque) | ||
| 197 | { | ||
| 198 | struct pm8001_hba_info *pm8001_ha = outq_to_hba(opaque); | ||
| 199 | u8 outq = *(u8 *)opaque; | ||
| 200 | irqreturn_t ret = IRQ_HANDLED; | ||
| 201 | if (unlikely(!pm8001_ha)) | ||
| 202 | return IRQ_NONE; | ||
| 203 | if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha)) | ||
| 204 | return IRQ_NONE; | ||
| 205 | pm8001_ha->int_vector = outq; | ||
| 206 | #ifdef PM8001_USE_TASKLET | ||
| 207 | tasklet_schedule(&pm8001_ha->tasklet); | ||
| 208 | #else | ||
| 209 | ret = PM8001_CHIP_DISP->isr(pm8001_ha, outq); | ||
| 166 | #endif | 210 | #endif |
| 211 | return ret; | ||
| 212 | } | ||
| 167 | 213 | ||
| 214 | /** | ||
| 215 | * pm8001_interrupt_handler_intx - main INTx interrupt handler. | ||
| 216 | * @dev_id: sas_ha structure. The HBA is retrieved from sas_has structure. | ||
| 217 | */ | ||
| 168 | 218 | ||
| 169 | /** | 219 | static irqreturn_t pm8001_interrupt_handler_intx(int irq, void *dev_id) |
| 170 | * pm8001_interrupt - when HBA originate a interrupt,we should invoke this | ||
| 171 | * dispatcher to handle each case. | ||
| 172 | * @irq: irq number. | ||
| 173 | * @opaque: the passed general host adapter struct | ||
| 174 | */ | ||
| 175 | static irqreturn_t pm8001_interrupt(int irq, void *opaque) | ||
| 176 | { | 220 | { |
| 177 | struct pm8001_hba_info *pm8001_ha; | 221 | struct pm8001_hba_info *pm8001_ha; |
| 178 | irqreturn_t ret = IRQ_HANDLED; | 222 | irqreturn_t ret = IRQ_HANDLED; |
| 179 | struct sas_ha_struct *sha = opaque; | 223 | struct sas_ha_struct *sha = dev_id; |
| 180 | pm8001_ha = sha->lldd_ha; | 224 | pm8001_ha = sha->lldd_ha; |
| 181 | if (unlikely(!pm8001_ha)) | 225 | if (unlikely(!pm8001_ha)) |
| 182 | return IRQ_NONE; | 226 | return IRQ_NONE; |
| 183 | if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha)) | 227 | if (!PM8001_CHIP_DISP->is_our_interupt(pm8001_ha)) |
| 184 | return IRQ_NONE; | 228 | return IRQ_NONE; |
| 229 | |||
| 230 | pm8001_ha->int_vector = 0; | ||
| 185 | #ifdef PM8001_USE_TASKLET | 231 | #ifdef PM8001_USE_TASKLET |
| 186 | tasklet_schedule(&pm8001_ha->tasklet); | 232 | tasklet_schedule(&pm8001_ha->tasklet); |
| 187 | #else | 233 | #else |
| 188 | ret = PM8001_CHIP_DISP->isr(pm8001_ha); | 234 | ret = PM8001_CHIP_DISP->isr(pm8001_ha, 0); |
| 189 | #endif | 235 | #endif |
| 190 | return ret; | 236 | return ret; |
| 191 | } | 237 | } |
| @@ -195,10 +241,14 @@ static irqreturn_t pm8001_interrupt(int irq, void *opaque) | |||
| 195 | * @pm8001_ha:our hba structure. | 241 | * @pm8001_ha:our hba structure. |
| 196 | * | 242 | * |
| 197 | */ | 243 | */ |
| 198 | static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha) | 244 | static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, |
| 245 | const struct pci_device_id *ent) | ||
| 199 | { | 246 | { |
| 200 | int i; | 247 | int i; |
| 201 | spin_lock_init(&pm8001_ha->lock); | 248 | spin_lock_init(&pm8001_ha->lock); |
| 249 | PM8001_INIT_DBG(pm8001_ha, | ||
| 250 | pm8001_printk("pm8001_alloc: PHY:%x\n", | ||
| 251 | pm8001_ha->chip->n_phy)); | ||
| 202 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { | 252 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { |
| 203 | pm8001_phy_init(pm8001_ha, i); | 253 | pm8001_phy_init(pm8001_ha, i); |
| 204 | pm8001_ha->port[i].wide_port_phymap = 0; | 254 | pm8001_ha->port[i].wide_port_phymap = 0; |
| @@ -222,30 +272,57 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha) | |||
| 222 | pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE; | 272 | pm8001_ha->memoryMap.region[IOP].total_len = PM8001_EVENT_LOG_SIZE; |
| 223 | pm8001_ha->memoryMap.region[IOP].alignment = 32; | 273 | pm8001_ha->memoryMap.region[IOP].alignment = 32; |
| 224 | 274 | ||
| 225 | /* MPI Memory region 3 for consumer Index of inbound queues */ | 275 | for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { |
| 226 | pm8001_ha->memoryMap.region[CI].num_elements = 1; | 276 | /* MPI Memory region 3 for consumer Index of inbound queues */ |
| 227 | pm8001_ha->memoryMap.region[CI].element_size = 4; | 277 | pm8001_ha->memoryMap.region[CI+i].num_elements = 1; |
| 228 | pm8001_ha->memoryMap.region[CI].total_len = 4; | 278 | pm8001_ha->memoryMap.region[CI+i].element_size = 4; |
| 229 | pm8001_ha->memoryMap.region[CI].alignment = 4; | 279 | pm8001_ha->memoryMap.region[CI+i].total_len = 4; |
| 230 | 280 | pm8001_ha->memoryMap.region[CI+i].alignment = 4; | |
| 231 | /* MPI Memory region 4 for producer Index of outbound queues */ | 281 | |
| 232 | pm8001_ha->memoryMap.region[PI].num_elements = 1; | 282 | if ((ent->driver_data) != chip_8001) { |
| 233 | pm8001_ha->memoryMap.region[PI].element_size = 4; | 283 | /* MPI Memory region 5 inbound queues */ |
| 234 | pm8001_ha->memoryMap.region[PI].total_len = 4; | 284 | pm8001_ha->memoryMap.region[IB+i].num_elements = |
| 235 | pm8001_ha->memoryMap.region[PI].alignment = 4; | 285 | PM8001_MPI_QUEUE; |
| 236 | 286 | pm8001_ha->memoryMap.region[IB+i].element_size = 128; | |
| 237 | /* MPI Memory region 5 inbound queues */ | 287 | pm8001_ha->memoryMap.region[IB+i].total_len = |
| 238 | pm8001_ha->memoryMap.region[IB].num_elements = PM8001_MPI_QUEUE; | 288 | PM8001_MPI_QUEUE * 128; |
| 239 | pm8001_ha->memoryMap.region[IB].element_size = 64; | 289 | pm8001_ha->memoryMap.region[IB+i].alignment = 128; |
| 240 | pm8001_ha->memoryMap.region[IB].total_len = PM8001_MPI_QUEUE * 64; | 290 | } else { |
| 241 | pm8001_ha->memoryMap.region[IB].alignment = 64; | 291 | pm8001_ha->memoryMap.region[IB+i].num_elements = |
| 242 | 292 | PM8001_MPI_QUEUE; | |
| 243 | /* MPI Memory region 6 outbound queues */ | 293 | pm8001_ha->memoryMap.region[IB+i].element_size = 64; |
| 244 | pm8001_ha->memoryMap.region[OB].num_elements = PM8001_MPI_QUEUE; | 294 | pm8001_ha->memoryMap.region[IB+i].total_len = |
| 245 | pm8001_ha->memoryMap.region[OB].element_size = 64; | 295 | PM8001_MPI_QUEUE * 64; |
| 246 | pm8001_ha->memoryMap.region[OB].total_len = PM8001_MPI_QUEUE * 64; | 296 | pm8001_ha->memoryMap.region[IB+i].alignment = 64; |
| 247 | pm8001_ha->memoryMap.region[OB].alignment = 64; | 297 | } |
| 298 | } | ||
| 299 | |||
| 300 | for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) { | ||
| 301 | /* MPI Memory region 4 for producer Index of outbound queues */ | ||
| 302 | pm8001_ha->memoryMap.region[PI+i].num_elements = 1; | ||
| 303 | pm8001_ha->memoryMap.region[PI+i].element_size = 4; | ||
| 304 | pm8001_ha->memoryMap.region[PI+i].total_len = 4; | ||
| 305 | pm8001_ha->memoryMap.region[PI+i].alignment = 4; | ||
| 306 | |||
| 307 | if (ent->driver_data != chip_8001) { | ||
| 308 | /* MPI Memory region 6 Outbound queues */ | ||
| 309 | pm8001_ha->memoryMap.region[OB+i].num_elements = | ||
| 310 | PM8001_MPI_QUEUE; | ||
| 311 | pm8001_ha->memoryMap.region[OB+i].element_size = 128; | ||
| 312 | pm8001_ha->memoryMap.region[OB+i].total_len = | ||
| 313 | PM8001_MPI_QUEUE * 128; | ||
| 314 | pm8001_ha->memoryMap.region[OB+i].alignment = 128; | ||
| 315 | } else { | ||
| 316 | /* MPI Memory region 6 Outbound queues */ | ||
| 317 | pm8001_ha->memoryMap.region[OB+i].num_elements = | ||
| 318 | PM8001_MPI_QUEUE; | ||
| 319 | pm8001_ha->memoryMap.region[OB+i].element_size = 64; | ||
| 320 | pm8001_ha->memoryMap.region[OB+i].total_len = | ||
| 321 | PM8001_MPI_QUEUE * 64; | ||
| 322 | pm8001_ha->memoryMap.region[OB+i].alignment = 64; | ||
| 323 | } | ||
| 248 | 324 | ||
| 325 | } | ||
| 249 | /* Memory region write DMA*/ | 326 | /* Memory region write DMA*/ |
| 250 | pm8001_ha->memoryMap.region[NVMD].num_elements = 1; | 327 | pm8001_ha->memoryMap.region[NVMD].num_elements = 1; |
| 251 | pm8001_ha->memoryMap.region[NVMD].element_size = 4096; | 328 | pm8001_ha->memoryMap.region[NVMD].element_size = 4096; |
| @@ -264,6 +341,9 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha) | |||
| 264 | pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB * | 341 | pm8001_ha->memoryMap.region[CCB_MEM].total_len = PM8001_MAX_CCB * |
| 265 | sizeof(struct pm8001_ccb_info); | 342 | sizeof(struct pm8001_ccb_info); |
| 266 | 343 | ||
| 344 | /* Memory region for fw flash */ | ||
| 345 | pm8001_ha->memoryMap.region[FW_FLASH].total_len = 4096; | ||
| 346 | |||
| 267 | for (i = 0; i < USI_MAX_MEMCNT; i++) { | 347 | for (i = 0; i < USI_MAX_MEMCNT; i++) { |
| 268 | if (pm8001_mem_alloc(pm8001_ha->pdev, | 348 | if (pm8001_mem_alloc(pm8001_ha->pdev, |
| 269 | &pm8001_ha->memoryMap.region[i].virt_ptr, | 349 | &pm8001_ha->memoryMap.region[i].virt_ptr, |
| @@ -281,7 +361,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha) | |||
| 281 | 361 | ||
| 282 | pm8001_ha->devices = pm8001_ha->memoryMap.region[DEV_MEM].virt_ptr; | 362 | pm8001_ha->devices = pm8001_ha->memoryMap.region[DEV_MEM].virt_ptr; |
| 283 | for (i = 0; i < PM8001_MAX_DEVICES; i++) { | 363 | for (i = 0; i < PM8001_MAX_DEVICES; i++) { |
| 284 | pm8001_ha->devices[i].dev_type = NO_DEVICE; | 364 | pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED; |
| 285 | pm8001_ha->devices[i].id = i; | 365 | pm8001_ha->devices[i].id = i; |
| 286 | pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES; | 366 | pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES; |
| 287 | pm8001_ha->devices[i].running_req = 0; | 367 | pm8001_ha->devices[i].running_req = 0; |
| @@ -339,10 +419,12 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha) | |||
| 339 | ioremap(pm8001_ha->io_mem[logicalBar].membase, | 419 | ioremap(pm8001_ha->io_mem[logicalBar].membase, |
| 340 | pm8001_ha->io_mem[logicalBar].memsize); | 420 | pm8001_ha->io_mem[logicalBar].memsize); |
| 341 | PM8001_INIT_DBG(pm8001_ha, | 421 | PM8001_INIT_DBG(pm8001_ha, |
| 342 | pm8001_printk("PCI: bar %d, logicalBar %d " | 422 | pm8001_printk("PCI: bar %d, logicalBar %d ", |
| 343 | "virt_addr=%lx,len=%d\n", bar, logicalBar, | 423 | bar, logicalBar)); |
| 344 | (unsigned long) | 424 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk( |
| 345 | pm8001_ha->io_mem[logicalBar].memvirtaddr, | 425 | "base addr %llx virt_addr=%llx len=%d\n", |
| 426 | (u64)pm8001_ha->io_mem[logicalBar].membase, | ||
| 427 | (u64)pm8001_ha->io_mem[logicalBar].memvirtaddr, | ||
| 346 | pm8001_ha->io_mem[logicalBar].memsize)); | 428 | pm8001_ha->io_mem[logicalBar].memsize)); |
| 347 | } else { | 429 | } else { |
| 348 | pm8001_ha->io_mem[logicalBar].membase = 0; | 430 | pm8001_ha->io_mem[logicalBar].membase = 0; |
| @@ -361,8 +443,9 @@ static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha) | |||
| 361 | * @shost: scsi host struct which has been initialized before. | 443 | * @shost: scsi host struct which has been initialized before. |
| 362 | */ | 444 | */ |
| 363 | static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, | 445 | static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, |
| 364 | u32 chip_id, | 446 | const struct pci_device_id *ent, |
| 365 | struct Scsi_Host *shost) | 447 | struct Scsi_Host *shost) |
| 448 | |||
| 366 | { | 449 | { |
| 367 | struct pm8001_hba_info *pm8001_ha; | 450 | struct pm8001_hba_info *pm8001_ha; |
| 368 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | 451 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); |
| @@ -374,7 +457,7 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, | |||
| 374 | 457 | ||
| 375 | pm8001_ha->pdev = pdev; | 458 | pm8001_ha->pdev = pdev; |
| 376 | pm8001_ha->dev = &pdev->dev; | 459 | pm8001_ha->dev = &pdev->dev; |
| 377 | pm8001_ha->chip_id = chip_id; | 460 | pm8001_ha->chip_id = ent->driver_data; |
| 378 | pm8001_ha->chip = &pm8001_chips[pm8001_ha->chip_id]; | 461 | pm8001_ha->chip = &pm8001_chips[pm8001_ha->chip_id]; |
| 379 | pm8001_ha->irq = pdev->irq; | 462 | pm8001_ha->irq = pdev->irq; |
| 380 | pm8001_ha->sas = sha; | 463 | pm8001_ha->sas = sha; |
| @@ -382,12 +465,22 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, | |||
| 382 | pm8001_ha->id = pm8001_id++; | 465 | pm8001_ha->id = pm8001_id++; |
| 383 | pm8001_ha->logging_level = 0x01; | 466 | pm8001_ha->logging_level = 0x01; |
| 384 | sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id); | 467 | sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id); |
| 468 | /* IOMB size is 128 for 8088/89 controllers */ | ||
| 469 | if (pm8001_ha->chip_id != chip_8001) | ||
| 470 | pm8001_ha->iomb_size = IOMB_SIZE_SPCV; | ||
| 471 | else | ||
| 472 | pm8001_ha->iomb_size = IOMB_SIZE_SPC; | ||
| 473 | |||
| 385 | #ifdef PM8001_USE_TASKLET | 474 | #ifdef PM8001_USE_TASKLET |
| 475 | /** | ||
| 476 | * default tasklet for non msi-x interrupt handler/first msi-x | ||
| 477 | * interrupt handler | ||
| 478 | **/ | ||
| 386 | tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet, | 479 | tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet, |
| 387 | (unsigned long)pm8001_ha); | 480 | (unsigned long)pm8001_ha); |
| 388 | #endif | 481 | #endif |
| 389 | pm8001_ioremap(pm8001_ha); | 482 | pm8001_ioremap(pm8001_ha); |
| 390 | if (!pm8001_alloc(pm8001_ha)) | 483 | if (!pm8001_alloc(pm8001_ha, ent)) |
| 391 | return pm8001_ha; | 484 | return pm8001_ha; |
| 392 | pm8001_free(pm8001_ha); | 485 | pm8001_free(pm8001_ha); |
| 393 | return NULL; | 486 | return NULL; |
| @@ -512,21 +605,50 @@ static void pm8001_post_sas_ha_init(struct Scsi_Host *shost, | |||
| 512 | */ | 605 | */ |
| 513 | static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) | 606 | static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) |
| 514 | { | 607 | { |
| 515 | u8 i; | 608 | u8 i, j; |
| 516 | #ifdef PM8001_READ_VPD | 609 | #ifdef PM8001_READ_VPD |
| 610 | /* For new SPC controllers WWN is stored in flash vpd | ||
| 611 | * For SPC/SPCve controllers WWN is stored in EEPROM | ||
| 612 | * For Older SPC WWN is stored in NVMD | ||
| 613 | */ | ||
| 517 | DECLARE_COMPLETION_ONSTACK(completion); | 614 | DECLARE_COMPLETION_ONSTACK(completion); |
| 518 | struct pm8001_ioctl_payload payload; | 615 | struct pm8001_ioctl_payload payload; |
| 616 | u16 deviceid; | ||
| 617 | pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); | ||
| 519 | pm8001_ha->nvmd_completion = &completion; | 618 | pm8001_ha->nvmd_completion = &completion; |
| 520 | payload.minor_function = 0; | 619 | |
| 521 | payload.length = 128; | 620 | if (pm8001_ha->chip_id == chip_8001) { |
| 522 | payload.func_specific = kzalloc(128, GFP_KERNEL); | 621 | if (deviceid == 0x8081) { |
| 622 | payload.minor_function = 4; | ||
| 623 | payload.length = 4096; | ||
| 624 | } else { | ||
| 625 | payload.minor_function = 0; | ||
| 626 | payload.length = 128; | ||
| 627 | } | ||
| 628 | } else { | ||
| 629 | payload.minor_function = 1; | ||
| 630 | payload.length = 4096; | ||
| 631 | } | ||
| 632 | payload.offset = 0; | ||
| 633 | payload.func_specific = kzalloc(payload.length, GFP_KERNEL); | ||
| 523 | PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); | 634 | PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); |
| 524 | wait_for_completion(&completion); | 635 | wait_for_completion(&completion); |
| 636 | |||
| 637 | for (i = 0, j = 0; i <= 7; i++, j++) { | ||
| 638 | if (pm8001_ha->chip_id == chip_8001) { | ||
| 639 | if (deviceid == 0x8081) | ||
| 640 | pm8001_ha->sas_addr[j] = | ||
| 641 | payload.func_specific[0x704 + i]; | ||
| 642 | } else | ||
| 643 | pm8001_ha->sas_addr[j] = | ||
| 644 | payload.func_specific[0x804 + i]; | ||
| 645 | } | ||
| 646 | |||
| 525 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { | 647 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { |
| 526 | memcpy(&pm8001_ha->phy[i].dev_sas_addr, pm8001_ha->sas_addr, | 648 | memcpy(&pm8001_ha->phy[i].dev_sas_addr, |
| 527 | SAS_ADDR_SIZE); | 649 | pm8001_ha->sas_addr, SAS_ADDR_SIZE); |
| 528 | PM8001_INIT_DBG(pm8001_ha, | 650 | PM8001_INIT_DBG(pm8001_ha, |
| 529 | pm8001_printk("phy %d sas_addr = %016llx \n", i, | 651 | pm8001_printk("phy %d sas_addr = %016llx\n", i, |
| 530 | pm8001_ha->phy[i].dev_sas_addr)); | 652 | pm8001_ha->phy[i].dev_sas_addr)); |
| 531 | } | 653 | } |
| 532 | #else | 654 | #else |
| @@ -547,31 +669,50 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) | |||
| 547 | * @chip_info: our ha struct. | 669 | * @chip_info: our ha struct. |
| 548 | * @irq_handler: irq_handler | 670 | * @irq_handler: irq_handler |
| 549 | */ | 671 | */ |
| 550 | static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha, | 672 | static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) |
| 551 | irq_handler_t irq_handler) | ||
| 552 | { | 673 | { |
| 553 | u32 i = 0, j = 0; | 674 | u32 i = 0, j = 0; |
| 554 | u32 number_of_intr = 1; | 675 | u32 number_of_intr; |
| 555 | int flag = 0; | 676 | int flag = 0; |
| 556 | u32 max_entry; | 677 | u32 max_entry; |
| 557 | int rc; | 678 | int rc; |
| 679 | static char intr_drvname[PM8001_MAX_MSIX_VEC][sizeof(DRV_NAME)+3]; | ||
| 680 | |||
| 681 | /* SPCv controllers supports 64 msi-x */ | ||
| 682 | if (pm8001_ha->chip_id == chip_8001) { | ||
| 683 | number_of_intr = 1; | ||
| 684 | flag |= IRQF_DISABLED; | ||
| 685 | } else { | ||
| 686 | number_of_intr = PM8001_MAX_MSIX_VEC; | ||
| 687 | flag &= ~IRQF_SHARED; | ||
| 688 | flag |= IRQF_DISABLED; | ||
| 689 | } | ||
| 690 | |||
| 558 | max_entry = sizeof(pm8001_ha->msix_entries) / | 691 | max_entry = sizeof(pm8001_ha->msix_entries) / |
| 559 | sizeof(pm8001_ha->msix_entries[0]); | 692 | sizeof(pm8001_ha->msix_entries[0]); |
| 560 | flag |= IRQF_DISABLED; | ||
| 561 | for (i = 0; i < max_entry ; i++) | 693 | for (i = 0; i < max_entry ; i++) |
| 562 | pm8001_ha->msix_entries[i].entry = i; | 694 | pm8001_ha->msix_entries[i].entry = i; |
| 563 | rc = pci_enable_msix(pm8001_ha->pdev, pm8001_ha->msix_entries, | 695 | rc = pci_enable_msix(pm8001_ha->pdev, pm8001_ha->msix_entries, |
| 564 | number_of_intr); | 696 | number_of_intr); |
| 565 | pm8001_ha->number_of_intr = number_of_intr; | 697 | pm8001_ha->number_of_intr = number_of_intr; |
| 566 | if (!rc) { | 698 | if (!rc) { |
| 699 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk( | ||
| 700 | "pci_enable_msix request ret:%d no of intr %d\n", | ||
| 701 | rc, pm8001_ha->number_of_intr)); | ||
| 702 | |||
| 703 | for (i = 0; i < number_of_intr; i++) | ||
| 704 | pm8001_ha->outq[i] = i; | ||
| 705 | |||
| 567 | for (i = 0; i < number_of_intr; i++) { | 706 | for (i = 0; i < number_of_intr; i++) { |
| 707 | snprintf(intr_drvname[i], sizeof(intr_drvname[0]), | ||
| 708 | DRV_NAME"%d", i); | ||
| 568 | if (request_irq(pm8001_ha->msix_entries[i].vector, | 709 | if (request_irq(pm8001_ha->msix_entries[i].vector, |
| 569 | irq_handler, flag, DRV_NAME, | 710 | pm8001_interrupt_handler_msix, flag, |
| 570 | SHOST_TO_SAS_HA(pm8001_ha->shost))) { | 711 | intr_drvname[i], &pm8001_ha->outq[i])) { |
| 571 | for (j = 0; j < i; j++) | 712 | for (j = 0; j < i; j++) |
| 572 | free_irq( | 713 | free_irq( |
| 573 | pm8001_ha->msix_entries[j].vector, | 714 | pm8001_ha->msix_entries[j].vector, |
| 574 | SHOST_TO_SAS_HA(pm8001_ha->shost)); | 715 | &pm8001_ha->outq[j]); |
| 575 | pci_disable_msix(pm8001_ha->pdev); | 716 | pci_disable_msix(pm8001_ha->pdev); |
| 576 | break; | 717 | break; |
| 577 | } | 718 | } |
| @@ -588,22 +729,24 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha, | |||
| 588 | static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) | 729 | static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) |
| 589 | { | 730 | { |
| 590 | struct pci_dev *pdev; | 731 | struct pci_dev *pdev; |
| 591 | irq_handler_t irq_handler = pm8001_interrupt; | ||
| 592 | int rc; | 732 | int rc; |
| 593 | 733 | ||
| 594 | pdev = pm8001_ha->pdev; | 734 | pdev = pm8001_ha->pdev; |
| 595 | 735 | ||
| 596 | #ifdef PM8001_USE_MSIX | 736 | #ifdef PM8001_USE_MSIX |
| 597 | if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) | 737 | if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) |
| 598 | return pm8001_setup_msix(pm8001_ha, irq_handler); | 738 | return pm8001_setup_msix(pm8001_ha); |
| 599 | else | 739 | else { |
| 740 | PM8001_INIT_DBG(pm8001_ha, | ||
| 741 | pm8001_printk("MSIX not supported!!!\n")); | ||
| 600 | goto intx; | 742 | goto intx; |
| 743 | } | ||
| 601 | #endif | 744 | #endif |
| 602 | 745 | ||
| 603 | intx: | 746 | intx: |
| 604 | /* initialize the INT-X interrupt */ | 747 | /* initialize the INT-X interrupt */ |
| 605 | rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED, DRV_NAME, | 748 | rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED, |
| 606 | SHOST_TO_SAS_HA(pm8001_ha->shost)); | 749 | DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost)); |
| 607 | return rc; | 750 | return rc; |
| 608 | } | 751 | } |
| 609 | 752 | ||
| @@ -621,12 +764,13 @@ static int pm8001_pci_probe(struct pci_dev *pdev, | |||
| 621 | { | 764 | { |
| 622 | unsigned int rc; | 765 | unsigned int rc; |
| 623 | u32 pci_reg; | 766 | u32 pci_reg; |
| 767 | u8 i = 0; | ||
| 624 | struct pm8001_hba_info *pm8001_ha; | 768 | struct pm8001_hba_info *pm8001_ha; |
| 625 | struct Scsi_Host *shost = NULL; | 769 | struct Scsi_Host *shost = NULL; |
| 626 | const struct pm8001_chip_info *chip; | 770 | const struct pm8001_chip_info *chip; |
| 627 | 771 | ||
| 628 | dev_printk(KERN_INFO, &pdev->dev, | 772 | dev_printk(KERN_INFO, &pdev->dev, |
| 629 | "pm8001: driver version %s\n", DRV_VERSION); | 773 | "pm80xx: driver version %s\n", DRV_VERSION); |
| 630 | rc = pci_enable_device(pdev); | 774 | rc = pci_enable_device(pdev); |
| 631 | if (rc) | 775 | if (rc) |
| 632 | goto err_out_enable; | 776 | goto err_out_enable; |
| @@ -665,25 +809,39 @@ static int pm8001_pci_probe(struct pci_dev *pdev, | |||
| 665 | goto err_out_free; | 809 | goto err_out_free; |
| 666 | } | 810 | } |
| 667 | pci_set_drvdata(pdev, SHOST_TO_SAS_HA(shost)); | 811 | pci_set_drvdata(pdev, SHOST_TO_SAS_HA(shost)); |
| 668 | pm8001_ha = pm8001_pci_alloc(pdev, chip_8001, shost); | 812 | /* ent->driver variable is used to differentiate between controllers */ |
| 813 | pm8001_ha = pm8001_pci_alloc(pdev, ent, shost); | ||
| 669 | if (!pm8001_ha) { | 814 | if (!pm8001_ha) { |
| 670 | rc = -ENOMEM; | 815 | rc = -ENOMEM; |
| 671 | goto err_out_free; | 816 | goto err_out_free; |
| 672 | } | 817 | } |
| 673 | list_add_tail(&pm8001_ha->list, &hba_list); | 818 | list_add_tail(&pm8001_ha->list, &hba_list); |
| 674 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); | 819 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); |
| 675 | rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); | 820 | rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); |
| 676 | if (rc) | 821 | if (rc) { |
| 822 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( | ||
| 823 | "chip_init failed [ret: %d]\n", rc)); | ||
| 677 | goto err_out_ha_free; | 824 | goto err_out_ha_free; |
| 825 | } | ||
| 678 | 826 | ||
| 679 | rc = scsi_add_host(shost, &pdev->dev); | 827 | rc = scsi_add_host(shost, &pdev->dev); |
| 680 | if (rc) | 828 | if (rc) |
| 681 | goto err_out_ha_free; | 829 | goto err_out_ha_free; |
| 682 | rc = pm8001_request_irq(pm8001_ha); | 830 | rc = pm8001_request_irq(pm8001_ha); |
| 683 | if (rc) | 831 | if (rc) { |
| 832 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( | ||
| 833 | "pm8001_request_irq failed [ret: %d]\n", rc)); | ||
| 684 | goto err_out_shost; | 834 | goto err_out_shost; |
| 835 | } | ||
| 836 | |||
| 837 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0); | ||
| 838 | if (pm8001_ha->chip_id != chip_8001) { | ||
| 839 | for (i = 1; i < pm8001_ha->number_of_intr; i++) | ||
| 840 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); | ||
| 841 | /* setup thermal configuration. */ | ||
| 842 | pm80xx_set_thermal_config(pm8001_ha); | ||
| 843 | } | ||
| 685 | 844 | ||
| 686 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha); | ||
| 687 | pm8001_init_sas_add(pm8001_ha); | 845 | pm8001_init_sas_add(pm8001_ha); |
| 688 | pm8001_post_sas_ha_init(shost, chip); | 846 | pm8001_post_sas_ha_init(shost, chip); |
| 689 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); | 847 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); |
| @@ -719,14 +877,15 @@ static void pm8001_pci_remove(struct pci_dev *pdev) | |||
| 719 | sas_remove_host(pm8001_ha->shost); | 877 | sas_remove_host(pm8001_ha->shost); |
| 720 | list_del(&pm8001_ha->list); | 878 | list_del(&pm8001_ha->list); |
| 721 | scsi_remove_host(pm8001_ha->shost); | 879 | scsi_remove_host(pm8001_ha->shost); |
| 722 | PM8001_CHIP_DISP->interrupt_disable(pm8001_ha); | 880 | PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); |
| 723 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); | 881 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); |
| 724 | 882 | ||
| 725 | #ifdef PM8001_USE_MSIX | 883 | #ifdef PM8001_USE_MSIX |
| 726 | for (i = 0; i < pm8001_ha->number_of_intr; i++) | 884 | for (i = 0; i < pm8001_ha->number_of_intr; i++) |
| 727 | synchronize_irq(pm8001_ha->msix_entries[i].vector); | 885 | synchronize_irq(pm8001_ha->msix_entries[i].vector); |
| 728 | for (i = 0; i < pm8001_ha->number_of_intr; i++) | 886 | for (i = 0; i < pm8001_ha->number_of_intr; i++) |
| 729 | free_irq(pm8001_ha->msix_entries[i].vector, sha); | 887 | free_irq(pm8001_ha->msix_entries[i].vector, |
| 888 | &pm8001_ha->outq[i]); | ||
| 730 | pci_disable_msix(pdev); | 889 | pci_disable_msix(pdev); |
| 731 | #else | 890 | #else |
| 732 | free_irq(pm8001_ha->irq, sha); | 891 | free_irq(pm8001_ha->irq, sha); |
| @@ -763,13 +922,14 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 763 | printk(KERN_ERR " PCI PM not supported\n"); | 922 | printk(KERN_ERR " PCI PM not supported\n"); |
| 764 | return -ENODEV; | 923 | return -ENODEV; |
| 765 | } | 924 | } |
| 766 | PM8001_CHIP_DISP->interrupt_disable(pm8001_ha); | 925 | PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); |
| 767 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); | 926 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); |
| 768 | #ifdef PM8001_USE_MSIX | 927 | #ifdef PM8001_USE_MSIX |
| 769 | for (i = 0; i < pm8001_ha->number_of_intr; i++) | 928 | for (i = 0; i < pm8001_ha->number_of_intr; i++) |
| 770 | synchronize_irq(pm8001_ha->msix_entries[i].vector); | 929 | synchronize_irq(pm8001_ha->msix_entries[i].vector); |
| 771 | for (i = 0; i < pm8001_ha->number_of_intr; i++) | 930 | for (i = 0; i < pm8001_ha->number_of_intr; i++) |
| 772 | free_irq(pm8001_ha->msix_entries[i].vector, sha); | 931 | free_irq(pm8001_ha->msix_entries[i].vector, |
| 932 | &pm8001_ha->outq[i]); | ||
| 773 | pci_disable_msix(pdev); | 933 | pci_disable_msix(pdev); |
| 774 | #else | 934 | #else |
| 775 | free_irq(pm8001_ha->irq, sha); | 935 | free_irq(pm8001_ha->irq, sha); |
| @@ -798,6 +958,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev) | |||
| 798 | struct sas_ha_struct *sha = pci_get_drvdata(pdev); | 958 | struct sas_ha_struct *sha = pci_get_drvdata(pdev); |
| 799 | struct pm8001_hba_info *pm8001_ha; | 959 | struct pm8001_hba_info *pm8001_ha; |
| 800 | int rc; | 960 | int rc; |
| 961 | u8 i = 0; | ||
| 801 | u32 device_state; | 962 | u32 device_state; |
| 802 | pm8001_ha = sha->lldd_ha; | 963 | pm8001_ha = sha->lldd_ha; |
| 803 | device_state = pdev->current_state; | 964 | device_state = pdev->current_state; |
| @@ -820,19 +981,33 @@ static int pm8001_pci_resume(struct pci_dev *pdev) | |||
| 820 | if (rc) | 981 | if (rc) |
| 821 | goto err_out_disable; | 982 | goto err_out_disable; |
| 822 | 983 | ||
| 823 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha, 0x252acbcd); | 984 | /* chip soft rst only for spc */ |
| 985 | if (pm8001_ha->chip_id == chip_8001) { | ||
| 986 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); | ||
| 987 | PM8001_INIT_DBG(pm8001_ha, | ||
| 988 | pm8001_printk("chip soft reset successful\n")); | ||
| 989 | } | ||
| 824 | rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); | 990 | rc = PM8001_CHIP_DISP->chip_init(pm8001_ha); |
| 825 | if (rc) | 991 | if (rc) |
| 826 | goto err_out_disable; | 992 | goto err_out_disable; |
| 827 | PM8001_CHIP_DISP->interrupt_disable(pm8001_ha); | 993 | |
| 994 | /* disable all the interrupt bits */ | ||
| 995 | PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); | ||
| 996 | |||
| 828 | rc = pm8001_request_irq(pm8001_ha); | 997 | rc = pm8001_request_irq(pm8001_ha); |
| 829 | if (rc) | 998 | if (rc) |
| 830 | goto err_out_disable; | 999 | goto err_out_disable; |
| 831 | #ifdef PM8001_USE_TASKLET | 1000 | #ifdef PM8001_USE_TASKLET |
| 1001 | /* default tasklet for non msi-x interrupt handler/first msi-x | ||
| 1002 | * interrupt handler */ | ||
| 832 | tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet, | 1003 | tasklet_init(&pm8001_ha->tasklet, pm8001_tasklet, |
| 833 | (unsigned long)pm8001_ha); | 1004 | (unsigned long)pm8001_ha); |
| 834 | #endif | 1005 | #endif |
| 835 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha); | 1006 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, 0); |
| 1007 | if (pm8001_ha->chip_id != chip_8001) { | ||
| 1008 | for (i = 1; i < pm8001_ha->number_of_intr; i++) | ||
| 1009 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); | ||
| 1010 | } | ||
| 836 | scsi_unblock_requests(pm8001_ha->shost); | 1011 | scsi_unblock_requests(pm8001_ha->shost); |
| 837 | return 0; | 1012 | return 0; |
| 838 | 1013 | ||
| @@ -843,14 +1018,45 @@ err_out_enable: | |||
| 843 | return rc; | 1018 | return rc; |
| 844 | } | 1019 | } |
| 845 | 1020 | ||
| 1021 | /* update of pci device, vendor id and driver data with | ||
| 1022 | * unique value for each of the controller | ||
| 1023 | */ | ||
| 846 | static struct pci_device_id pm8001_pci_table[] = { | 1024 | static struct pci_device_id pm8001_pci_table[] = { |
| 847 | { | 1025 | { PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 }, |
| 848 | PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 | ||
| 849 | }, | ||
| 850 | { | 1026 | { |
| 851 | PCI_DEVICE(0x117c, 0x0042), | 1027 | PCI_DEVICE(0x117c, 0x0042), |
| 852 | .driver_data = chip_8001 | 1028 | .driver_data = chip_8001 |
| 853 | }, | 1029 | }, |
| 1030 | /* Support for SPC/SPCv/SPCve controllers */ | ||
| 1031 | { PCI_VDEVICE(ADAPTEC2, 0x8001), chip_8001 }, | ||
| 1032 | { PCI_VDEVICE(PMC_Sierra, 0x8008), chip_8008 }, | ||
| 1033 | { PCI_VDEVICE(ADAPTEC2, 0x8008), chip_8008 }, | ||
| 1034 | { PCI_VDEVICE(PMC_Sierra, 0x8018), chip_8018 }, | ||
| 1035 | { PCI_VDEVICE(ADAPTEC2, 0x8018), chip_8018 }, | ||
| 1036 | { PCI_VDEVICE(PMC_Sierra, 0x8009), chip_8009 }, | ||
| 1037 | { PCI_VDEVICE(ADAPTEC2, 0x8009), chip_8009 }, | ||
| 1038 | { PCI_VDEVICE(PMC_Sierra, 0x8019), chip_8019 }, | ||
| 1039 | { PCI_VDEVICE(ADAPTEC2, 0x8019), chip_8019 }, | ||
| 1040 | { PCI_VENDOR_ID_ADAPTEC2, 0x8081, | ||
| 1041 | PCI_VENDOR_ID_ADAPTEC2, 0x0400, 0, 0, chip_8001 }, | ||
| 1042 | { PCI_VENDOR_ID_ADAPTEC2, 0x8081, | ||
| 1043 | PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8001 }, | ||
| 1044 | { PCI_VENDOR_ID_ADAPTEC2, 0x8088, | ||
| 1045 | PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8008 }, | ||
| 1046 | { PCI_VENDOR_ID_ADAPTEC2, 0x8088, | ||
| 1047 | PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8008 }, | ||
| 1048 | { PCI_VENDOR_ID_ADAPTEC2, 0x8089, | ||
| 1049 | PCI_VENDOR_ID_ADAPTEC2, 0x0008, 0, 0, chip_8009 }, | ||
| 1050 | { PCI_VENDOR_ID_ADAPTEC2, 0x8089, | ||
| 1051 | PCI_VENDOR_ID_ADAPTEC2, 0x0800, 0, 0, chip_8009 }, | ||
| 1052 | { PCI_VENDOR_ID_ADAPTEC2, 0x8088, | ||
| 1053 | PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8018 }, | ||
| 1054 | { PCI_VENDOR_ID_ADAPTEC2, 0x8088, | ||
| 1055 | PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8018 }, | ||
| 1056 | { PCI_VENDOR_ID_ADAPTEC2, 0x8089, | ||
| 1057 | PCI_VENDOR_ID_ADAPTEC2, 0x0016, 0, 0, chip_8019 }, | ||
| 1058 | { PCI_VENDOR_ID_ADAPTEC2, 0x8089, | ||
| 1059 | PCI_VENDOR_ID_ADAPTEC2, 0x1600, 0, 0, chip_8019 }, | ||
| 854 | {} /* terminate list */ | 1060 | {} /* terminate list */ |
| 855 | }; | 1061 | }; |
| 856 | 1062 | ||
| @@ -870,7 +1076,7 @@ static int __init pm8001_init(void) | |||
| 870 | { | 1076 | { |
| 871 | int rc = -ENOMEM; | 1077 | int rc = -ENOMEM; |
| 872 | 1078 | ||
| 873 | pm8001_wq = alloc_workqueue("pm8001", 0, 0); | 1079 | pm8001_wq = alloc_workqueue("pm80xx", 0, 0); |
| 874 | if (!pm8001_wq) | 1080 | if (!pm8001_wq) |
| 875 | goto err; | 1081 | goto err; |
| 876 | 1082 | ||
| @@ -902,7 +1108,8 @@ module_init(pm8001_init); | |||
| 902 | module_exit(pm8001_exit); | 1108 | module_exit(pm8001_exit); |
| 903 | 1109 | ||
| 904 | MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>"); | 1110 | MODULE_AUTHOR("Jack Wang <jack_wang@usish.com>"); |
| 905 | MODULE_DESCRIPTION("PMC-Sierra PM8001 SAS/SATA controller driver"); | 1111 | MODULE_DESCRIPTION( |
| 1112 | "PMC-Sierra PM8001/8081/8088/8089 SAS/SATA controller driver"); | ||
| 906 | MODULE_VERSION(DRV_VERSION); | 1113 | MODULE_VERSION(DRV_VERSION); |
| 907 | MODULE_LICENSE("GPL"); | 1114 | MODULE_LICENSE("GPL"); |
| 908 | MODULE_DEVICE_TABLE(pci, pm8001_pci_table); | 1115 | MODULE_DEVICE_TABLE(pci, pm8001_pci_table); |
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index b961112395d5..a85d73de7c80 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver | 2 | * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2008-2009 USI Co., Ltd. | 4 | * Copyright (c) 2008-2009 USI Co., Ltd. |
| 5 | * All rights reserved. | 5 | * All rights reserved. |
| @@ -68,7 +68,7 @@ static void pm8001_tag_clear(struct pm8001_hba_info *pm8001_ha, u32 tag) | |||
| 68 | clear_bit(tag, bitmap); | 68 | clear_bit(tag, bitmap); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag) | 71 | void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag) |
| 72 | { | 72 | { |
| 73 | pm8001_tag_clear(pm8001_ha, tag); | 73 | pm8001_tag_clear(pm8001_ha, tag); |
| 74 | } | 74 | } |
| @@ -212,10 +212,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, | |||
| 212 | break; | 212 | break; |
| 213 | case PHY_FUNC_GET_EVENTS: | 213 | case PHY_FUNC_GET_EVENTS: |
| 214 | spin_lock_irqsave(&pm8001_ha->lock, flags); | 214 | spin_lock_irqsave(&pm8001_ha->lock, flags); |
| 215 | if (-1 == pm8001_bar4_shift(pm8001_ha, | 215 | if (pm8001_ha->chip_id == chip_8001) { |
| 216 | if (-1 == pm8001_bar4_shift(pm8001_ha, | ||
| 216 | (phy_id < 4) ? 0x30000 : 0x40000)) { | 217 | (phy_id < 4) ? 0x30000 : 0x40000)) { |
| 217 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | 218 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); |
| 218 | return -EINVAL; | 219 | return -EINVAL; |
| 220 | } | ||
| 219 | } | 221 | } |
| 220 | { | 222 | { |
| 221 | struct sas_phy *phy = sas_phy->phy; | 223 | struct sas_phy *phy = sas_phy->phy; |
| @@ -228,7 +230,8 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, | |||
| 228 | phy->loss_of_dword_sync_count = qp[3]; | 230 | phy->loss_of_dword_sync_count = qp[3]; |
| 229 | phy->phy_reset_problem_count = qp[4]; | 231 | phy->phy_reset_problem_count = qp[4]; |
| 230 | } | 232 | } |
| 231 | pm8001_bar4_shift(pm8001_ha, 0); | 233 | if (pm8001_ha->chip_id == chip_8001) |
| 234 | pm8001_bar4_shift(pm8001_ha, 0); | ||
| 232 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | 235 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); |
| 233 | return 0; | 236 | return 0; |
| 234 | default: | 237 | default: |
| @@ -249,7 +252,9 @@ void pm8001_scan_start(struct Scsi_Host *shost) | |||
| 249 | struct pm8001_hba_info *pm8001_ha; | 252 | struct pm8001_hba_info *pm8001_ha; |
| 250 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | 253 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); |
| 251 | pm8001_ha = sha->lldd_ha; | 254 | pm8001_ha = sha->lldd_ha; |
| 252 | PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha); | 255 | /* SAS_RE_INITIALIZATION not available in SPCv/ve */ |
| 256 | if (pm8001_ha->chip_id == chip_8001) | ||
| 257 | PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha); | ||
| 253 | for (i = 0; i < pm8001_ha->chip->n_phy; ++i) | 258 | for (i = 0; i < pm8001_ha->chip->n_phy; ++i) |
| 254 | PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i); | 259 | PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i); |
| 255 | } | 260 | } |
| @@ -352,7 +357,7 @@ static int sas_find_local_port_id(struct domain_device *dev) | |||
| 352 | * @tmf: the task management IU | 357 | * @tmf: the task management IU |
| 353 | */ | 358 | */ |
| 354 | #define DEV_IS_GONE(pm8001_dev) \ | 359 | #define DEV_IS_GONE(pm8001_dev) \ |
| 355 | ((!pm8001_dev || (pm8001_dev->dev_type == NO_DEVICE))) | 360 | ((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED))) |
| 356 | static int pm8001_task_exec(struct sas_task *task, const int num, | 361 | static int pm8001_task_exec(struct sas_task *task, const int num, |
| 357 | gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf) | 362 | gfp_t gfp_flags, int is_tmf, struct pm8001_tmf_task *tmf) |
| 358 | { | 363 | { |
| @@ -370,7 +375,7 @@ static int pm8001_task_exec(struct sas_task *task, const int num, | |||
| 370 | struct task_status_struct *tsm = &t->task_status; | 375 | struct task_status_struct *tsm = &t->task_status; |
| 371 | tsm->resp = SAS_TASK_UNDELIVERED; | 376 | tsm->resp = SAS_TASK_UNDELIVERED; |
| 372 | tsm->stat = SAS_PHY_DOWN; | 377 | tsm->stat = SAS_PHY_DOWN; |
| 373 | if (dev->dev_type != SATA_DEV) | 378 | if (dev->dev_type != SAS_SATA_DEV) |
| 374 | t->task_done(t); | 379 | t->task_done(t); |
| 375 | return 0; | 380 | return 0; |
| 376 | } | 381 | } |
| @@ -548,7 +553,7 @@ struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha) | |||
| 548 | { | 553 | { |
| 549 | u32 dev; | 554 | u32 dev; |
| 550 | for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) { | 555 | for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) { |
| 551 | if (pm8001_ha->devices[dev].dev_type == NO_DEVICE) { | 556 | if (pm8001_ha->devices[dev].dev_type == SAS_PHY_UNUSED) { |
| 552 | pm8001_ha->devices[dev].id = dev; | 557 | pm8001_ha->devices[dev].id = dev; |
| 553 | return &pm8001_ha->devices[dev]; | 558 | return &pm8001_ha->devices[dev]; |
| 554 | } | 559 | } |
| @@ -560,13 +565,31 @@ struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha) | |||
| 560 | } | 565 | } |
| 561 | return NULL; | 566 | return NULL; |
| 562 | } | 567 | } |
| 568 | /** | ||
| 569 | * pm8001_find_dev - find a matching pm8001_device | ||
| 570 | * @pm8001_ha: our hba card information | ||
| 571 | */ | ||
| 572 | struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, | ||
| 573 | u32 device_id) | ||
| 574 | { | ||
| 575 | u32 dev; | ||
| 576 | for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) { | ||
| 577 | if (pm8001_ha->devices[dev].device_id == device_id) | ||
| 578 | return &pm8001_ha->devices[dev]; | ||
| 579 | } | ||
| 580 | if (dev == PM8001_MAX_DEVICES) { | ||
| 581 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("NO MATCHING " | ||
| 582 | "DEVICE FOUND !!!\n")); | ||
| 583 | } | ||
| 584 | return NULL; | ||
| 585 | } | ||
| 563 | 586 | ||
| 564 | static void pm8001_free_dev(struct pm8001_device *pm8001_dev) | 587 | static void pm8001_free_dev(struct pm8001_device *pm8001_dev) |
| 565 | { | 588 | { |
| 566 | u32 id = pm8001_dev->id; | 589 | u32 id = pm8001_dev->id; |
| 567 | memset(pm8001_dev, 0, sizeof(*pm8001_dev)); | 590 | memset(pm8001_dev, 0, sizeof(*pm8001_dev)); |
| 568 | pm8001_dev->id = id; | 591 | pm8001_dev->id = id; |
| 569 | pm8001_dev->dev_type = NO_DEVICE; | 592 | pm8001_dev->dev_type = SAS_PHY_UNUSED; |
| 570 | pm8001_dev->device_id = PM8001_MAX_DEVICES; | 593 | pm8001_dev->device_id = PM8001_MAX_DEVICES; |
| 571 | pm8001_dev->sas_device = NULL; | 594 | pm8001_dev->sas_device = NULL; |
| 572 | } | 595 | } |
| @@ -624,7 +647,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev) | |||
| 624 | res = -1; | 647 | res = -1; |
| 625 | } | 648 | } |
| 626 | } else { | 649 | } else { |
| 627 | if (dev->dev_type == SATA_DEV) { | 650 | if (dev->dev_type == SAS_SATA_DEV) { |
| 628 | pm8001_device->attached_phy = | 651 | pm8001_device->attached_phy = |
| 629 | dev->rphy->identify.phy_identifier; | 652 | dev->rphy->identify.phy_identifier; |
| 630 | flag = 1; /* directly sata*/ | 653 | flag = 1; /* directly sata*/ |
| @@ -634,7 +657,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev) | |||
| 634 | PM8001_CHIP_DISP->reg_dev_req(pm8001_ha, pm8001_device, flag); | 657 | PM8001_CHIP_DISP->reg_dev_req(pm8001_ha, pm8001_device, flag); |
| 635 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | 658 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); |
| 636 | wait_for_completion(&completion); | 659 | wait_for_completion(&completion); |
| 637 | if (dev->dev_type == SAS_END_DEV) | 660 | if (dev->dev_type == SAS_END_DEVICE) |
| 638 | msleep(50); | 661 | msleep(50); |
| 639 | pm8001_ha->flags = PM8001F_RUN_TIME; | 662 | pm8001_ha->flags = PM8001F_RUN_TIME; |
| 640 | return 0; | 663 | return 0; |
| @@ -648,7 +671,7 @@ int pm8001_dev_found(struct domain_device *dev) | |||
| 648 | return pm8001_dev_found_notify(dev); | 671 | return pm8001_dev_found_notify(dev); |
| 649 | } | 672 | } |
| 650 | 673 | ||
| 651 | static void pm8001_task_done(struct sas_task *task) | 674 | void pm8001_task_done(struct sas_task *task) |
| 652 | { | 675 | { |
| 653 | if (!del_timer(&task->slow_task->timer)) | 676 | if (!del_timer(&task->slow_task->timer)) |
| 654 | return; | 677 | return; |
| @@ -904,7 +927,7 @@ void pm8001_open_reject_retry( | |||
| 904 | struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[i]; | 927 | struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[i]; |
| 905 | 928 | ||
| 906 | pm8001_dev = ccb->device; | 929 | pm8001_dev = ccb->device; |
| 907 | if (!pm8001_dev || (pm8001_dev->dev_type == NO_DEVICE)) | 930 | if (!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)) |
| 908 | continue; | 931 | continue; |
| 909 | if (!device_to_close) { | 932 | if (!device_to_close) { |
| 910 | uintptr_t d = (uintptr_t)pm8001_dev | 933 | uintptr_t d = (uintptr_t)pm8001_dev |
| @@ -995,6 +1018,72 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev) | |||
| 995 | return rc; | 1018 | return rc; |
| 996 | } | 1019 | } |
| 997 | 1020 | ||
| 1021 | /* | ||
| 1022 | * This function handle the IT_NEXUS_XXX event or completion | ||
| 1023 | * status code for SSP/SATA/SMP I/O request. | ||
| 1024 | */ | ||
| 1025 | int pm8001_I_T_nexus_event_handler(struct domain_device *dev) | ||
| 1026 | { | ||
| 1027 | int rc = TMF_RESP_FUNC_FAILED; | ||
| 1028 | struct pm8001_device *pm8001_dev; | ||
| 1029 | struct pm8001_hba_info *pm8001_ha; | ||
| 1030 | struct sas_phy *phy; | ||
| 1031 | u32 device_id = 0; | ||
| 1032 | |||
| 1033 | if (!dev || !dev->lldd_dev) | ||
| 1034 | return -1; | ||
| 1035 | |||
| 1036 | pm8001_dev = dev->lldd_dev; | ||
| 1037 | device_id = pm8001_dev->device_id; | ||
| 1038 | pm8001_ha = pm8001_find_ha_by_dev(dev); | ||
| 1039 | |||
| 1040 | PM8001_EH_DBG(pm8001_ha, | ||
| 1041 | pm8001_printk("I_T_Nexus handler invoked !!")); | ||
| 1042 | |||
| 1043 | phy = sas_get_local_phy(dev); | ||
| 1044 | |||
| 1045 | if (dev_is_sata(dev)) { | ||
| 1046 | DECLARE_COMPLETION_ONSTACK(completion_setstate); | ||
| 1047 | if (scsi_is_sas_phy_local(phy)) { | ||
| 1048 | rc = 0; | ||
| 1049 | goto out; | ||
| 1050 | } | ||
| 1051 | /* send internal ssp/sata/smp abort command to FW */ | ||
| 1052 | rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , | ||
| 1053 | dev, 1, 0); | ||
| 1054 | msleep(100); | ||
| 1055 | |||
| 1056 | /* deregister the target device */ | ||
| 1057 | pm8001_dev_gone_notify(dev); | ||
| 1058 | msleep(200); | ||
| 1059 | |||
| 1060 | /*send phy reset to hard reset target */ | ||
| 1061 | rc = sas_phy_reset(phy, 1); | ||
| 1062 | msleep(2000); | ||
| 1063 | pm8001_dev->setds_completion = &completion_setstate; | ||
| 1064 | |||
| 1065 | wait_for_completion(&completion_setstate); | ||
| 1066 | } else { | ||
| 1067 | /* send internal ssp/sata/smp abort command to FW */ | ||
| 1068 | rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev , | ||
| 1069 | dev, 1, 0); | ||
| 1070 | msleep(100); | ||
| 1071 | |||
| 1072 | /* deregister the target device */ | ||
| 1073 | pm8001_dev_gone_notify(dev); | ||
| 1074 | msleep(200); | ||
| 1075 | |||
| 1076 | /*send phy reset to hard reset target */ | ||
| 1077 | rc = sas_phy_reset(phy, 1); | ||
| 1078 | msleep(2000); | ||
| 1079 | } | ||
| 1080 | PM8001_EH_DBG(pm8001_ha, pm8001_printk(" for device[%x]:rc=%d\n", | ||
| 1081 | pm8001_dev->device_id, rc)); | ||
| 1082 | out: | ||
| 1083 | sas_put_local_phy(phy); | ||
| 1084 | |||
| 1085 | return rc; | ||
| 1086 | } | ||
| 998 | /* mandatory SAM-3, the task reset the specified LUN*/ | 1087 | /* mandatory SAM-3, the task reset the specified LUN*/ |
| 999 | int pm8001_lu_reset(struct domain_device *dev, u8 *lun) | 1088 | int pm8001_lu_reset(struct domain_device *dev, u8 *lun) |
| 1000 | { | 1089 | { |
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 11008205aeb3..570819464d90 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * PMC-Sierra SPC 8001 SAS/SATA based host adapters driver | 2 | * PMC-Sierra PM8001/8081/8088/8089 SAS/SATA based host adapters driver |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2008-2009 USI Co., Ltd. | 4 | * Copyright (c) 2008-2009 USI Co., Ltd. |
| 5 | * All rights reserved. | 5 | * All rights reserved. |
| @@ -57,8 +57,8 @@ | |||
| 57 | #include <linux/atomic.h> | 57 | #include <linux/atomic.h> |
| 58 | #include "pm8001_defs.h" | 58 | #include "pm8001_defs.h" |
| 59 | 59 | ||
| 60 | #define DRV_NAME "pm8001" | 60 | #define DRV_NAME "pm80xx" |
| 61 | #define DRV_VERSION "0.1.36" | 61 | #define DRV_VERSION "0.1.37" |
| 62 | #define PM8001_FAIL_LOGGING 0x01 /* Error message logging */ | 62 | #define PM8001_FAIL_LOGGING 0x01 /* Error message logging */ |
| 63 | #define PM8001_INIT_LOGGING 0x02 /* driver init logging */ | 63 | #define PM8001_INIT_LOGGING 0x02 /* driver init logging */ |
| 64 | #define PM8001_DISC_LOGGING 0x04 /* discovery layer logging */ | 64 | #define PM8001_DISC_LOGGING 0x04 /* discovery layer logging */ |
| @@ -66,8 +66,8 @@ | |||
| 66 | #define PM8001_EH_LOGGING 0x10 /* libsas EH function logging*/ | 66 | #define PM8001_EH_LOGGING 0x10 /* libsas EH function logging*/ |
| 67 | #define PM8001_IOCTL_LOGGING 0x20 /* IOCTL message logging */ | 67 | #define PM8001_IOCTL_LOGGING 0x20 /* IOCTL message logging */ |
| 68 | #define PM8001_MSG_LOGGING 0x40 /* misc message logging */ | 68 | #define PM8001_MSG_LOGGING 0x40 /* misc message logging */ |
| 69 | #define pm8001_printk(format, arg...) printk(KERN_INFO "%s %d:" format,\ | 69 | #define pm8001_printk(format, arg...) printk(KERN_INFO "pm80xx %s %d:" \ |
| 70 | __func__, __LINE__, ## arg) | 70 | format, __func__, __LINE__, ## arg) |
| 71 | #define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD) \ | 71 | #define PM8001_CHECK_LOGGING(HBA, LEVEL, CMD) \ |
| 72 | do { \ | 72 | do { \ |
| 73 | if (unlikely(HBA->logging_level & LEVEL)) \ | 73 | if (unlikely(HBA->logging_level & LEVEL)) \ |
| @@ -103,11 +103,12 @@ do { \ | |||
| 103 | #define PM8001_READ_VPD | 103 | #define PM8001_READ_VPD |
| 104 | 104 | ||
| 105 | 105 | ||
| 106 | #define DEV_IS_EXPANDER(type) ((type == EDGE_DEV) || (type == FANOUT_DEV)) | 106 | #define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) |
| 107 | 107 | ||
| 108 | #define PM8001_NAME_LENGTH 32/* generic length of strings */ | 108 | #define PM8001_NAME_LENGTH 32/* generic length of strings */ |
| 109 | extern struct list_head hba_list; | 109 | extern struct list_head hba_list; |
| 110 | extern const struct pm8001_dispatch pm8001_8001_dispatch; | 110 | extern const struct pm8001_dispatch pm8001_8001_dispatch; |
| 111 | extern const struct pm8001_dispatch pm8001_80xx_dispatch; | ||
| 111 | 112 | ||
| 112 | struct pm8001_hba_info; | 113 | struct pm8001_hba_info; |
| 113 | struct pm8001_ccb_info; | 114 | struct pm8001_ccb_info; |
| @@ -131,15 +132,15 @@ struct pm8001_ioctl_payload { | |||
| 131 | struct pm8001_dispatch { | 132 | struct pm8001_dispatch { |
| 132 | char *name; | 133 | char *name; |
| 133 | int (*chip_init)(struct pm8001_hba_info *pm8001_ha); | 134 | int (*chip_init)(struct pm8001_hba_info *pm8001_ha); |
| 134 | int (*chip_soft_rst)(struct pm8001_hba_info *pm8001_ha, u32 signature); | 135 | int (*chip_soft_rst)(struct pm8001_hba_info *pm8001_ha); |
| 135 | void (*chip_rst)(struct pm8001_hba_info *pm8001_ha); | 136 | void (*chip_rst)(struct pm8001_hba_info *pm8001_ha); |
| 136 | int (*chip_ioremap)(struct pm8001_hba_info *pm8001_ha); | 137 | int (*chip_ioremap)(struct pm8001_hba_info *pm8001_ha); |
| 137 | void (*chip_iounmap)(struct pm8001_hba_info *pm8001_ha); | 138 | void (*chip_iounmap)(struct pm8001_hba_info *pm8001_ha); |
| 138 | irqreturn_t (*isr)(struct pm8001_hba_info *pm8001_ha); | 139 | irqreturn_t (*isr)(struct pm8001_hba_info *pm8001_ha, u8 vec); |
| 139 | u32 (*is_our_interupt)(struct pm8001_hba_info *pm8001_ha); | 140 | u32 (*is_our_interupt)(struct pm8001_hba_info *pm8001_ha); |
| 140 | int (*isr_process_oq)(struct pm8001_hba_info *pm8001_ha); | 141 | int (*isr_process_oq)(struct pm8001_hba_info *pm8001_ha, u8 vec); |
| 141 | void (*interrupt_enable)(struct pm8001_hba_info *pm8001_ha); | 142 | void (*interrupt_enable)(struct pm8001_hba_info *pm8001_ha, u8 vec); |
| 142 | void (*interrupt_disable)(struct pm8001_hba_info *pm8001_ha); | 143 | void (*interrupt_disable)(struct pm8001_hba_info *pm8001_ha, u8 vec); |
| 143 | void (*make_prd)(struct scatterlist *scatter, int nr, void *prd); | 144 | void (*make_prd)(struct scatterlist *scatter, int nr, void *prd); |
| 144 | int (*smp_req)(struct pm8001_hba_info *pm8001_ha, | 145 | int (*smp_req)(struct pm8001_hba_info *pm8001_ha, |
| 145 | struct pm8001_ccb_info *ccb); | 146 | struct pm8001_ccb_info *ccb); |
| @@ -173,6 +174,7 @@ struct pm8001_dispatch { | |||
| 173 | }; | 174 | }; |
| 174 | 175 | ||
| 175 | struct pm8001_chip_info { | 176 | struct pm8001_chip_info { |
| 177 | u32 encrypt; | ||
| 176 | u32 n_phy; | 178 | u32 n_phy; |
| 177 | const struct pm8001_dispatch *dispatch; | 179 | const struct pm8001_dispatch *dispatch; |
| 178 | }; | 180 | }; |
| @@ -204,7 +206,7 @@ struct pm8001_phy { | |||
| 204 | }; | 206 | }; |
| 205 | 207 | ||
| 206 | struct pm8001_device { | 208 | struct pm8001_device { |
| 207 | enum sas_dev_type dev_type; | 209 | enum sas_device_type dev_type; |
| 208 | struct domain_device *sas_device; | 210 | struct domain_device *sas_device; |
| 209 | u32 attached_phy; | 211 | u32 attached_phy; |
| 210 | u32 id; | 212 | u32 id; |
| @@ -256,7 +258,20 @@ struct mpi_mem_req { | |||
| 256 | struct mpi_mem region[USI_MAX_MEMCNT]; | 258 | struct mpi_mem region[USI_MAX_MEMCNT]; |
| 257 | }; | 259 | }; |
| 258 | 260 | ||
| 259 | struct main_cfg_table { | 261 | struct encrypt { |
| 262 | u32 cipher_mode; | ||
| 263 | u32 sec_mode; | ||
| 264 | u32 status; | ||
| 265 | u32 flag; | ||
| 266 | }; | ||
| 267 | |||
| 268 | struct sas_phy_attribute_table { | ||
| 269 | u32 phystart1_16[16]; | ||
| 270 | u32 outbound_hw_event_pid1_16[16]; | ||
| 271 | }; | ||
| 272 | |||
| 273 | union main_cfg_table { | ||
| 274 | struct { | ||
| 260 | u32 signature; | 275 | u32 signature; |
| 261 | u32 interface_rev; | 276 | u32 interface_rev; |
| 262 | u32 firmware_rev; | 277 | u32 firmware_rev; |
| @@ -292,19 +307,69 @@ struct main_cfg_table { | |||
| 292 | u32 fatal_err_dump_length1; | 307 | u32 fatal_err_dump_length1; |
| 293 | u32 hda_mode_flag; | 308 | u32 hda_mode_flag; |
| 294 | u32 anolog_setup_table_offset; | 309 | u32 anolog_setup_table_offset; |
| 310 | u32 rsvd[4]; | ||
| 311 | } pm8001_tbl; | ||
| 312 | |||
| 313 | struct { | ||
| 314 | u32 signature; | ||
| 315 | u32 interface_rev; | ||
| 316 | u32 firmware_rev; | ||
| 317 | u32 max_out_io; | ||
| 318 | u32 max_sgl; | ||
| 319 | u32 ctrl_cap_flag; | ||
| 320 | u32 gst_offset; | ||
| 321 | u32 inbound_queue_offset; | ||
| 322 | u32 outbound_queue_offset; | ||
| 323 | u32 inbound_q_nppd_hppd; | ||
| 324 | u32 rsvd[8]; | ||
| 325 | u32 crc_core_dump; | ||
| 326 | u32 rsvd1; | ||
| 327 | u32 upper_event_log_addr; | ||
| 328 | u32 lower_event_log_addr; | ||
| 329 | u32 event_log_size; | ||
| 330 | u32 event_log_severity; | ||
| 331 | u32 upper_pcs_event_log_addr; | ||
| 332 | u32 lower_pcs_event_log_addr; | ||
| 333 | u32 pcs_event_log_size; | ||
| 334 | u32 pcs_event_log_severity; | ||
| 335 | u32 fatal_err_interrupt; | ||
| 336 | u32 fatal_err_dump_offset0; | ||
| 337 | u32 fatal_err_dump_length0; | ||
| 338 | u32 fatal_err_dump_offset1; | ||
| 339 | u32 fatal_err_dump_length1; | ||
| 340 | u32 gpio_led_mapping; | ||
| 341 | u32 analog_setup_table_offset; | ||
| 342 | u32 int_vec_table_offset; | ||
| 343 | u32 phy_attr_table_offset; | ||
| 344 | u32 port_recovery_timer; | ||
| 345 | u32 interrupt_reassertion_delay; | ||
| 346 | } pm80xx_tbl; | ||
| 295 | }; | 347 | }; |
| 296 | struct general_status_table { | 348 | |
| 349 | union general_status_table { | ||
| 350 | struct { | ||
| 297 | u32 gst_len_mpistate; | 351 | u32 gst_len_mpistate; |
| 298 | u32 iq_freeze_state0; | 352 | u32 iq_freeze_state0; |
| 299 | u32 iq_freeze_state1; | 353 | u32 iq_freeze_state1; |
| 300 | u32 msgu_tcnt; | 354 | u32 msgu_tcnt; |
| 301 | u32 iop_tcnt; | 355 | u32 iop_tcnt; |
| 302 | u32 reserved; | 356 | u32 rsvd; |
| 303 | u32 phy_state[8]; | 357 | u32 phy_state[8]; |
| 304 | u32 reserved1; | 358 | u32 gpio_input_val; |
| 305 | u32 reserved2; | 359 | u32 rsvd1[2]; |
| 306 | u32 reserved3; | 360 | u32 recover_err_info[8]; |
| 361 | } pm8001_tbl; | ||
| 362 | struct { | ||
| 363 | u32 gst_len_mpistate; | ||
| 364 | u32 iq_freeze_state0; | ||
| 365 | u32 iq_freeze_state1; | ||
| 366 | u32 msgu_tcnt; | ||
| 367 | u32 iop_tcnt; | ||
| 368 | u32 rsvd[9]; | ||
| 369 | u32 gpio_input_val; | ||
| 370 | u32 rsvd1[2]; | ||
| 307 | u32 recover_err_info[8]; | 371 | u32 recover_err_info[8]; |
| 372 | } pm80xx_tbl; | ||
| 308 | }; | 373 | }; |
| 309 | struct inbound_queue_table { | 374 | struct inbound_queue_table { |
| 310 | u32 element_pri_size_cnt; | 375 | u32 element_pri_size_cnt; |
| @@ -351,15 +416,21 @@ struct pm8001_hba_info { | |||
| 351 | struct device *dev; | 416 | struct device *dev; |
| 352 | struct pm8001_hba_memspace io_mem[6]; | 417 | struct pm8001_hba_memspace io_mem[6]; |
| 353 | struct mpi_mem_req memoryMap; | 418 | struct mpi_mem_req memoryMap; |
| 419 | struct encrypt encrypt_info; /* support encryption */ | ||
| 354 | void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/ | 420 | void __iomem *msg_unit_tbl_addr;/*Message Unit Table Addr*/ |
| 355 | void __iomem *main_cfg_tbl_addr;/*Main Config Table Addr*/ | 421 | void __iomem *main_cfg_tbl_addr;/*Main Config Table Addr*/ |
| 356 | void __iomem *general_stat_tbl_addr;/*General Status Table Addr*/ | 422 | void __iomem *general_stat_tbl_addr;/*General Status Table Addr*/ |
| 357 | void __iomem *inbnd_q_tbl_addr;/*Inbound Queue Config Table Addr*/ | 423 | void __iomem *inbnd_q_tbl_addr;/*Inbound Queue Config Table Addr*/ |
| 358 | void __iomem *outbnd_q_tbl_addr;/*Outbound Queue Config Table Addr*/ | 424 | void __iomem *outbnd_q_tbl_addr;/*Outbound Queue Config Table Addr*/ |
| 359 | struct main_cfg_table main_cfg_tbl; | 425 | void __iomem *pspa_q_tbl_addr; |
| 360 | struct general_status_table gs_tbl; | 426 | /*MPI SAS PHY attributes Queue Config Table Addr*/ |
| 361 | struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_INB_NUM]; | 427 | void __iomem *ivt_tbl_addr; /*MPI IVT Table Addr */ |
| 362 | struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_OUTB_NUM]; | 428 | union main_cfg_table main_cfg_tbl; |
| 429 | union general_status_table gs_tbl; | ||
| 430 | struct inbound_queue_table inbnd_q_tbl[PM8001_MAX_SPCV_INB_NUM]; | ||
| 431 | struct outbound_queue_table outbnd_q_tbl[PM8001_MAX_SPCV_OUTB_NUM]; | ||
| 432 | struct sas_phy_attribute_table phy_attr_table; | ||
| 433 | /* MPI SAS PHY attributes */ | ||
| 363 | u8 sas_addr[SAS_ADDR_SIZE]; | 434 | u8 sas_addr[SAS_ADDR_SIZE]; |
| 364 | struct sas_ha_struct *sas;/* SCSI/SAS glue */ | 435 | struct sas_ha_struct *sas;/* SCSI/SAS glue */ |
| 365 | struct Scsi_Host *shost; | 436 | struct Scsi_Host *shost; |
| @@ -372,10 +443,12 @@ struct pm8001_hba_info { | |||
| 372 | struct pm8001_port port[PM8001_MAX_PHYS]; | 443 | struct pm8001_port port[PM8001_MAX_PHYS]; |
| 373 | u32 id; | 444 | u32 id; |
| 374 | u32 irq; | 445 | u32 irq; |
| 446 | u32 iomb_size; /* SPC and SPCV IOMB size */ | ||
| 375 | struct pm8001_device *devices; | 447 | struct pm8001_device *devices; |
| 376 | struct pm8001_ccb_info *ccb_info; | 448 | struct pm8001_ccb_info *ccb_info; |
| 377 | #ifdef PM8001_USE_MSIX | 449 | #ifdef PM8001_USE_MSIX |
| 378 | struct msix_entry msix_entries[16];/*for msi-x interrupt*/ | 450 | struct msix_entry msix_entries[PM8001_MAX_MSIX_VEC]; |
| 451 | /*for msi-x interrupt*/ | ||
| 379 | int number_of_intr;/*will be used in remove()*/ | 452 | int number_of_intr;/*will be used in remove()*/ |
| 380 | #endif | 453 | #endif |
| 381 | #ifdef PM8001_USE_TASKLET | 454 | #ifdef PM8001_USE_TASKLET |
| @@ -383,7 +456,10 @@ struct pm8001_hba_info { | |||
| 383 | #endif | 456 | #endif |
| 384 | u32 logging_level; | 457 | u32 logging_level; |
| 385 | u32 fw_status; | 458 | u32 fw_status; |
| 459 | u32 smp_exp_mode; | ||
| 460 | u32 int_vector; | ||
| 386 | const struct firmware *fw_image; | 461 | const struct firmware *fw_image; |
| 462 | u8 outq[PM8001_MAX_MSIX_VEC]; | ||
| 387 | }; | 463 | }; |
| 388 | 464 | ||
| 389 | struct pm8001_work { | 465 | struct pm8001_work { |
| @@ -419,6 +495,9 @@ struct pm8001_fw_image_header { | |||
| 419 | #define FLASH_UPDATE_DNLD_NOT_SUPPORTED 0x10 | 495 | #define FLASH_UPDATE_DNLD_NOT_SUPPORTED 0x10 |
| 420 | #define FLASH_UPDATE_DISABLED 0x11 | 496 | #define FLASH_UPDATE_DISABLED 0x11 |
| 421 | 497 | ||
| 498 | #define NCQ_READ_LOG_FLAG 0x80000000 | ||
| 499 | #define NCQ_ABORT_ALL_FLAG 0x40000000 | ||
| 500 | #define NCQ_2ND_RLE_FLAG 0x20000000 | ||
| 422 | /** | 501 | /** |
| 423 | * brief param structure for firmware flash update. | 502 | * brief param structure for firmware flash update. |
| 424 | */ | 503 | */ |
| @@ -484,6 +563,7 @@ int pm8001_dev_found(struct domain_device *dev); | |||
| 484 | void pm8001_dev_gone(struct domain_device *dev); | 563 | void pm8001_dev_gone(struct domain_device *dev); |
| 485 | int pm8001_lu_reset(struct domain_device *dev, u8 *lun); | 564 | int pm8001_lu_reset(struct domain_device *dev, u8 *lun); |
| 486 | int pm8001_I_T_nexus_reset(struct domain_device *dev); | 565 | int pm8001_I_T_nexus_reset(struct domain_device *dev); |
| 566 | int pm8001_I_T_nexus_event_handler(struct domain_device *dev); | ||
| 487 | int pm8001_query_task(struct sas_task *task); | 567 | int pm8001_query_task(struct sas_task *task); |
| 488 | void pm8001_open_reject_retry( | 568 | void pm8001_open_reject_retry( |
| 489 | struct pm8001_hba_info *pm8001_ha, | 569 | struct pm8001_hba_info *pm8001_ha, |
| @@ -493,6 +573,61 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr, | |||
| 493 | dma_addr_t *pphys_addr, u32 *pphys_addr_hi, u32 *pphys_addr_lo, | 573 | dma_addr_t *pphys_addr, u32 *pphys_addr_hi, u32 *pphys_addr_lo, |
| 494 | u32 mem_size, u32 align); | 574 | u32 mem_size, u32 align); |
| 495 | 575 | ||
| 576 | void pm8001_chip_iounmap(struct pm8001_hba_info *pm8001_ha); | ||
| 577 | int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, | ||
| 578 | struct inbound_queue_table *circularQ, | ||
| 579 | u32 opCode, void *payload, u32 responseQueue); | ||
| 580 | int pm8001_mpi_msg_free_get(struct inbound_queue_table *circularQ, | ||
| 581 | u16 messageSize, void **messagePtr); | ||
| 582 | u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, | ||
| 583 | struct outbound_queue_table *circularQ, u8 bc); | ||
| 584 | u32 pm8001_mpi_msg_consume(struct pm8001_hba_info *pm8001_ha, | ||
| 585 | struct outbound_queue_table *circularQ, | ||
| 586 | void **messagePtr1, u8 *pBC); | ||
| 587 | int pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, | ||
| 588 | struct pm8001_device *pm8001_dev, u32 state); | ||
| 589 | int pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, | ||
| 590 | void *payload); | ||
| 591 | int pm8001_chip_fw_flash_update_build(struct pm8001_hba_info *pm8001_ha, | ||
| 592 | void *fw_flash_updata_info, u32 tag); | ||
| 593 | int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, void *payload); | ||
| 594 | int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, void *payload); | ||
| 595 | int pm8001_chip_ssp_tm_req(struct pm8001_hba_info *pm8001_ha, | ||
| 596 | struct pm8001_ccb_info *ccb, | ||
| 597 | struct pm8001_tmf_task *tmf); | ||
| 598 | int pm8001_chip_abort_task(struct pm8001_hba_info *pm8001_ha, | ||
| 599 | struct pm8001_device *pm8001_dev, | ||
| 600 | u8 flag, u32 task_tag, u32 cmd_tag); | ||
| 601 | int pm8001_chip_dereg_dev_req(struct pm8001_hba_info *pm8001_ha, u32 device_id); | ||
| 602 | void pm8001_chip_make_sg(struct scatterlist *scatter, int nr, void *prd); | ||
| 603 | void pm8001_work_fn(struct work_struct *work); | ||
| 604 | int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, | ||
| 605 | void *data, int handler); | ||
| 606 | void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 607 | void *piomb); | ||
| 608 | void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 609 | void *piomb); | ||
| 610 | void pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 611 | void *piomb); | ||
| 612 | int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, | ||
| 613 | void *piomb); | ||
| 614 | void pm8001_get_lrate_mode(struct pm8001_phy *phy, u8 link_rate); | ||
| 615 | void pm8001_get_attached_sas_addr(struct pm8001_phy *phy, u8 *sas_addr); | ||
| 616 | void pm8001_bytes_dmaed(struct pm8001_hba_info *pm8001_ha, int i); | ||
| 617 | int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb); | ||
| 618 | int pm8001_mpi_dereg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb); | ||
| 619 | int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 620 | void *piomb); | ||
| 621 | int pm8001_mpi_general_event(struct pm8001_hba_info *pm8001_ha , void *piomb); | ||
| 622 | int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb); | ||
| 623 | struct sas_task *pm8001_alloc_task(void); | ||
| 624 | void pm8001_task_done(struct sas_task *task); | ||
| 625 | void pm8001_free_task(struct sas_task *task); | ||
| 626 | void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag); | ||
| 627 | struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha, | ||
| 628 | u32 device_id); | ||
| 629 | int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); | ||
| 630 | |||
| 496 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | 631 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); |
| 497 | 632 | ||
| 498 | /* ctl shared API */ | 633 | /* ctl shared API */ |
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c new file mode 100644 index 000000000000..302514d8157b --- /dev/null +++ b/drivers/scsi/pm8001/pm80xx_hwi.c | |||
| @@ -0,0 +1,4130 @@ | |||
| 1 | /* | ||
| 2 | * PMC-Sierra SPCv/ve 8088/8089 SAS/SATA based host adapters driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008-2009 PMC-Sierra, Inc., | ||
| 5 | * All rights reserved. | ||
| 6 | * | ||
| 7 | * Redistribution and use in source and binary forms, with or without | ||
| 8 | * modification, are permitted provided that the following conditions | ||
| 9 | * are met: | ||
| 10 | * 1. Redistributions of source code must retain the above copyright | ||
| 11 | * notice, this list of conditions, and the following disclaimer, | ||
| 12 | * without modification. | ||
| 13 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
| 14 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
| 15 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
| 16 | * including a substantially similar Disclaimer requirement for further | ||
| 17 | * binary redistribution. | ||
| 18 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
| 19 | * of any contributors may be used to endorse or promote products derived | ||
| 20 | * from this software without specific prior written permission. | ||
| 21 | * | ||
| 22 | * Alternatively, this software may be distributed under the terms of the | ||
| 23 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
| 24 | * Software Foundation. | ||
| 25 | * | ||
| 26 | * NO WARRANTY | ||
| 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
| 30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 31 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 33 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
| 35 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
| 36 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 37 | * POSSIBILITY OF SUCH DAMAGES. | ||
| 38 | * | ||
| 39 | */ | ||
| 40 | #include <linux/slab.h> | ||
| 41 | #include "pm8001_sas.h" | ||
| 42 | #include "pm80xx_hwi.h" | ||
| 43 | #include "pm8001_chips.h" | ||
| 44 | #include "pm8001_ctl.h" | ||
| 45 | |||
| 46 | #define SMP_DIRECT 1 | ||
| 47 | #define SMP_INDIRECT 2 | ||
| 48 | /** | ||
| 49 | * read_main_config_table - read the configure table and save it. | ||
| 50 | * @pm8001_ha: our hba card information | ||
| 51 | */ | ||
| 52 | static void read_main_config_table(struct pm8001_hba_info *pm8001_ha) | ||
| 53 | { | ||
| 54 | void __iomem *address = pm8001_ha->main_cfg_tbl_addr; | ||
| 55 | |||
| 56 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature = | ||
| 57 | pm8001_mr32(address, MAIN_SIGNATURE_OFFSET); | ||
| 58 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev = | ||
| 59 | pm8001_mr32(address, MAIN_INTERFACE_REVISION); | ||
| 60 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev = | ||
| 61 | pm8001_mr32(address, MAIN_FW_REVISION); | ||
| 62 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_out_io = | ||
| 63 | pm8001_mr32(address, MAIN_MAX_OUTSTANDING_IO_OFFSET); | ||
| 64 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.max_sgl = | ||
| 65 | pm8001_mr32(address, MAIN_MAX_SGL_OFFSET); | ||
| 66 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.ctrl_cap_flag = | ||
| 67 | pm8001_mr32(address, MAIN_CNTRL_CAP_OFFSET); | ||
| 68 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset = | ||
| 69 | pm8001_mr32(address, MAIN_GST_OFFSET); | ||
| 70 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset = | ||
| 71 | pm8001_mr32(address, MAIN_IBQ_OFFSET); | ||
| 72 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.outbound_queue_offset = | ||
| 73 | pm8001_mr32(address, MAIN_OBQ_OFFSET); | ||
| 74 | |||
| 75 | /* read Error Dump Offset and Length */ | ||
| 76 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_offset0 = | ||
| 77 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_OFFSET); | ||
| 78 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_length0 = | ||
| 79 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP0_LENGTH); | ||
| 80 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_offset1 = | ||
| 81 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_OFFSET); | ||
| 82 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_dump_length1 = | ||
| 83 | pm8001_mr32(address, MAIN_FATAL_ERROR_RDUMP1_LENGTH); | ||
| 84 | |||
| 85 | /* read GPIO LED settings from the configuration table */ | ||
| 86 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping = | ||
| 87 | pm8001_mr32(address, MAIN_GPIO_LED_FLAGS_OFFSET); | ||
| 88 | |||
| 89 | /* read analog Setting offset from the configuration table */ | ||
| 90 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.analog_setup_table_offset = | ||
| 91 | pm8001_mr32(address, MAIN_ANALOG_SETUP_OFFSET); | ||
| 92 | |||
| 93 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset = | ||
| 94 | pm8001_mr32(address, MAIN_INT_VECTOR_TABLE_OFFSET); | ||
| 95 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset = | ||
| 96 | pm8001_mr32(address, MAIN_SAS_PHY_ATTR_TABLE_OFFSET); | ||
| 97 | } | ||
| 98 | |||
| 99 | /** | ||
| 100 | * read_general_status_table - read the general status table and save it. | ||
| 101 | * @pm8001_ha: our hba card information | ||
| 102 | */ | ||
| 103 | static void read_general_status_table(struct pm8001_hba_info *pm8001_ha) | ||
| 104 | { | ||
| 105 | void __iomem *address = pm8001_ha->general_stat_tbl_addr; | ||
| 106 | pm8001_ha->gs_tbl.pm80xx_tbl.gst_len_mpistate = | ||
| 107 | pm8001_mr32(address, GST_GSTLEN_MPIS_OFFSET); | ||
| 108 | pm8001_ha->gs_tbl.pm80xx_tbl.iq_freeze_state0 = | ||
| 109 | pm8001_mr32(address, GST_IQ_FREEZE_STATE0_OFFSET); | ||
| 110 | pm8001_ha->gs_tbl.pm80xx_tbl.iq_freeze_state1 = | ||
| 111 | pm8001_mr32(address, GST_IQ_FREEZE_STATE1_OFFSET); | ||
| 112 | pm8001_ha->gs_tbl.pm80xx_tbl.msgu_tcnt = | ||
| 113 | pm8001_mr32(address, GST_MSGUTCNT_OFFSET); | ||
| 114 | pm8001_ha->gs_tbl.pm80xx_tbl.iop_tcnt = | ||
| 115 | pm8001_mr32(address, GST_IOPTCNT_OFFSET); | ||
| 116 | pm8001_ha->gs_tbl.pm80xx_tbl.gpio_input_val = | ||
| 117 | pm8001_mr32(address, GST_GPIO_INPUT_VAL); | ||
| 118 | pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[0] = | ||
| 119 | pm8001_mr32(address, GST_RERRINFO_OFFSET0); | ||
| 120 | pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[1] = | ||
| 121 | pm8001_mr32(address, GST_RERRINFO_OFFSET1); | ||
| 122 | pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[2] = | ||
| 123 | pm8001_mr32(address, GST_RERRINFO_OFFSET2); | ||
| 124 | pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[3] = | ||
| 125 | pm8001_mr32(address, GST_RERRINFO_OFFSET3); | ||
| 126 | pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[4] = | ||
| 127 | pm8001_mr32(address, GST_RERRINFO_OFFSET4); | ||
| 128 | pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[5] = | ||
| 129 | pm8001_mr32(address, GST_RERRINFO_OFFSET5); | ||
| 130 | pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[6] = | ||
| 131 | pm8001_mr32(address, GST_RERRINFO_OFFSET6); | ||
| 132 | pm8001_ha->gs_tbl.pm80xx_tbl.recover_err_info[7] = | ||
| 133 | pm8001_mr32(address, GST_RERRINFO_OFFSET7); | ||
| 134 | } | ||
| 135 | /** | ||
| 136 | * read_phy_attr_table - read the phy attribute table and save it. | ||
| 137 | * @pm8001_ha: our hba card information | ||
| 138 | */ | ||
| 139 | static void read_phy_attr_table(struct pm8001_hba_info *pm8001_ha) | ||
| 140 | { | ||
| 141 | void __iomem *address = pm8001_ha->pspa_q_tbl_addr; | ||
| 142 | pm8001_ha->phy_attr_table.phystart1_16[0] = | ||
| 143 | pm8001_mr32(address, PSPA_PHYSTATE0_OFFSET); | ||
| 144 | pm8001_ha->phy_attr_table.phystart1_16[1] = | ||
| 145 | pm8001_mr32(address, PSPA_PHYSTATE1_OFFSET); | ||
| 146 | pm8001_ha->phy_attr_table.phystart1_16[2] = | ||
| 147 | pm8001_mr32(address, PSPA_PHYSTATE2_OFFSET); | ||
| 148 | pm8001_ha->phy_attr_table.phystart1_16[3] = | ||
| 149 | pm8001_mr32(address, PSPA_PHYSTATE3_OFFSET); | ||
| 150 | pm8001_ha->phy_attr_table.phystart1_16[4] = | ||
| 151 | pm8001_mr32(address, PSPA_PHYSTATE4_OFFSET); | ||
| 152 | pm8001_ha->phy_attr_table.phystart1_16[5] = | ||
| 153 | pm8001_mr32(address, PSPA_PHYSTATE5_OFFSET); | ||
| 154 | pm8001_ha->phy_attr_table.phystart1_16[6] = | ||
| 155 | pm8001_mr32(address, PSPA_PHYSTATE6_OFFSET); | ||
| 156 | pm8001_ha->phy_attr_table.phystart1_16[7] = | ||
| 157 | pm8001_mr32(address, PSPA_PHYSTATE7_OFFSET); | ||
| 158 | pm8001_ha->phy_attr_table.phystart1_16[8] = | ||
| 159 | pm8001_mr32(address, PSPA_PHYSTATE8_OFFSET); | ||
| 160 | pm8001_ha->phy_attr_table.phystart1_16[9] = | ||
| 161 | pm8001_mr32(address, PSPA_PHYSTATE9_OFFSET); | ||
| 162 | pm8001_ha->phy_attr_table.phystart1_16[10] = | ||
| 163 | pm8001_mr32(address, PSPA_PHYSTATE10_OFFSET); | ||
| 164 | pm8001_ha->phy_attr_table.phystart1_16[11] = | ||
| 165 | pm8001_mr32(address, PSPA_PHYSTATE11_OFFSET); | ||
| 166 | pm8001_ha->phy_attr_table.phystart1_16[12] = | ||
| 167 | pm8001_mr32(address, PSPA_PHYSTATE12_OFFSET); | ||
| 168 | pm8001_ha->phy_attr_table.phystart1_16[13] = | ||
| 169 | pm8001_mr32(address, PSPA_PHYSTATE13_OFFSET); | ||
| 170 | pm8001_ha->phy_attr_table.phystart1_16[14] = | ||
| 171 | pm8001_mr32(address, PSPA_PHYSTATE14_OFFSET); | ||
| 172 | pm8001_ha->phy_attr_table.phystart1_16[15] = | ||
| 173 | pm8001_mr32(address, PSPA_PHYSTATE15_OFFSET); | ||
| 174 | |||
| 175 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[0] = | ||
| 176 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID0_OFFSET); | ||
| 177 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[1] = | ||
| 178 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID1_OFFSET); | ||
| 179 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[2] = | ||
| 180 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID2_OFFSET); | ||
| 181 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[3] = | ||
| 182 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID3_OFFSET); | ||
| 183 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[4] = | ||
| 184 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID4_OFFSET); | ||
| 185 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[5] = | ||
| 186 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID5_OFFSET); | ||
| 187 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[6] = | ||
| 188 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID6_OFFSET); | ||
| 189 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[7] = | ||
| 190 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID7_OFFSET); | ||
| 191 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[8] = | ||
| 192 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID8_OFFSET); | ||
| 193 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[9] = | ||
| 194 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID9_OFFSET); | ||
| 195 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[10] = | ||
| 196 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID10_OFFSET); | ||
| 197 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[11] = | ||
| 198 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID11_OFFSET); | ||
| 199 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[12] = | ||
| 200 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID12_OFFSET); | ||
| 201 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[13] = | ||
| 202 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID13_OFFSET); | ||
| 203 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[14] = | ||
| 204 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID14_OFFSET); | ||
| 205 | pm8001_ha->phy_attr_table.outbound_hw_event_pid1_16[15] = | ||
| 206 | pm8001_mr32(address, PSPA_OB_HW_EVENT_PID15_OFFSET); | ||
| 207 | |||
| 208 | } | ||
| 209 | |||
| 210 | /** | ||
| 211 | * read_inbnd_queue_table - read the inbound queue table and save it. | ||
| 212 | * @pm8001_ha: our hba card information | ||
| 213 | */ | ||
| 214 | static void read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha) | ||
| 215 | { | ||
| 216 | int i; | ||
| 217 | void __iomem *address = pm8001_ha->inbnd_q_tbl_addr; | ||
| 218 | for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { | ||
| 219 | u32 offset = i * 0x20; | ||
| 220 | pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = | ||
| 221 | get_pci_bar_index(pm8001_mr32(address, | ||
| 222 | (offset + IB_PIPCI_BAR))); | ||
| 223 | pm8001_ha->inbnd_q_tbl[i].pi_offset = | ||
| 224 | pm8001_mr32(address, (offset + IB_PIPCI_BAR_OFFSET)); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | /** | ||
| 229 | * read_outbnd_queue_table - read the outbound queue table and save it. | ||
| 230 | * @pm8001_ha: our hba card information | ||
| 231 | */ | ||
| 232 | static void read_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha) | ||
| 233 | { | ||
| 234 | int i; | ||
| 235 | void __iomem *address = pm8001_ha->outbnd_q_tbl_addr; | ||
| 236 | for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) { | ||
| 237 | u32 offset = i * 0x24; | ||
| 238 | pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = | ||
| 239 | get_pci_bar_index(pm8001_mr32(address, | ||
| 240 | (offset + OB_CIPCI_BAR))); | ||
| 241 | pm8001_ha->outbnd_q_tbl[i].ci_offset = | ||
| 242 | pm8001_mr32(address, (offset + OB_CIPCI_BAR_OFFSET)); | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | /** | ||
| 247 | * init_default_table_values - init the default table. | ||
| 248 | * @pm8001_ha: our hba card information | ||
| 249 | */ | ||
| 250 | static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) | ||
| 251 | { | ||
| 252 | int i; | ||
| 253 | u32 offsetib, offsetob; | ||
| 254 | void __iomem *addressib = pm8001_ha->inbnd_q_tbl_addr; | ||
| 255 | void __iomem *addressob = pm8001_ha->outbnd_q_tbl_addr; | ||
| 256 | |||
| 257 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr = | ||
| 258 | pm8001_ha->memoryMap.region[AAP1].phys_addr_hi; | ||
| 259 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_event_log_addr = | ||
| 260 | pm8001_ha->memoryMap.region[AAP1].phys_addr_lo; | ||
| 261 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size = | ||
| 262 | PM8001_EVENT_LOG_SIZE; | ||
| 263 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_severity = 0x01; | ||
| 264 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_pcs_event_log_addr = | ||
| 265 | pm8001_ha->memoryMap.region[IOP].phys_addr_hi; | ||
| 266 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_pcs_event_log_addr = | ||
| 267 | pm8001_ha->memoryMap.region[IOP].phys_addr_lo; | ||
| 268 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size = | ||
| 269 | PM8001_EVENT_LOG_SIZE; | ||
| 270 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity = 0x01; | ||
| 271 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt = 0x01; | ||
| 272 | |||
| 273 | /* Disable end to end CRC checking */ | ||
| 274 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump = (0x1 << 16); | ||
| 275 | |||
| 276 | for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) { | ||
| 277 | pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = | ||
| 278 | PM8001_MPI_QUEUE | (64 << 16) | (0x00<<30); | ||
| 279 | pm8001_ha->inbnd_q_tbl[i].upper_base_addr = | ||
| 280 | pm8001_ha->memoryMap.region[IB + i].phys_addr_hi; | ||
| 281 | pm8001_ha->inbnd_q_tbl[i].lower_base_addr = | ||
| 282 | pm8001_ha->memoryMap.region[IB + i].phys_addr_lo; | ||
| 283 | pm8001_ha->inbnd_q_tbl[i].base_virt = | ||
| 284 | (u8 *)pm8001_ha->memoryMap.region[IB + i].virt_ptr; | ||
| 285 | pm8001_ha->inbnd_q_tbl[i].total_length = | ||
| 286 | pm8001_ha->memoryMap.region[IB + i].total_len; | ||
| 287 | pm8001_ha->inbnd_q_tbl[i].ci_upper_base_addr = | ||
| 288 | pm8001_ha->memoryMap.region[CI + i].phys_addr_hi; | ||
| 289 | pm8001_ha->inbnd_q_tbl[i].ci_lower_base_addr = | ||
| 290 | pm8001_ha->memoryMap.region[CI + i].phys_addr_lo; | ||
| 291 | pm8001_ha->inbnd_q_tbl[i].ci_virt = | ||
| 292 | pm8001_ha->memoryMap.region[CI + i].virt_ptr; | ||
| 293 | offsetib = i * 0x20; | ||
| 294 | pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = | ||
| 295 | get_pci_bar_index(pm8001_mr32(addressib, | ||
| 296 | (offsetib + 0x14))); | ||
| 297 | pm8001_ha->inbnd_q_tbl[i].pi_offset = | ||
| 298 | pm8001_mr32(addressib, (offsetib + 0x18)); | ||
| 299 | pm8001_ha->inbnd_q_tbl[i].producer_idx = 0; | ||
| 300 | pm8001_ha->inbnd_q_tbl[i].consumer_index = 0; | ||
| 301 | } | ||
| 302 | for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) { | ||
| 303 | pm8001_ha->outbnd_q_tbl[i].element_size_cnt = | ||
| 304 | PM8001_MPI_QUEUE | (64 << 16) | (0x01<<30); | ||
| 305 | pm8001_ha->outbnd_q_tbl[i].upper_base_addr = | ||
| 306 | pm8001_ha->memoryMap.region[OB + i].phys_addr_hi; | ||
| 307 | pm8001_ha->outbnd_q_tbl[i].lower_base_addr = | ||
| 308 | pm8001_ha->memoryMap.region[OB + i].phys_addr_lo; | ||
| 309 | pm8001_ha->outbnd_q_tbl[i].base_virt = | ||
| 310 | (u8 *)pm8001_ha->memoryMap.region[OB + i].virt_ptr; | ||
| 311 | pm8001_ha->outbnd_q_tbl[i].total_length = | ||
| 312 | pm8001_ha->memoryMap.region[OB + i].total_len; | ||
| 313 | pm8001_ha->outbnd_q_tbl[i].pi_upper_base_addr = | ||
| 314 | pm8001_ha->memoryMap.region[PI + i].phys_addr_hi; | ||
| 315 | pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr = | ||
| 316 | pm8001_ha->memoryMap.region[PI + i].phys_addr_lo; | ||
| 317 | /* interrupt vector based on oq */ | ||
| 318 | pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = (i << 24); | ||
| 319 | pm8001_ha->outbnd_q_tbl[i].pi_virt = | ||
| 320 | pm8001_ha->memoryMap.region[PI + i].virt_ptr; | ||
| 321 | offsetob = i * 0x24; | ||
| 322 | pm8001_ha->outbnd_q_tbl[i].ci_pci_bar = | ||
| 323 | get_pci_bar_index(pm8001_mr32(addressob, | ||
| 324 | offsetob + 0x14)); | ||
| 325 | pm8001_ha->outbnd_q_tbl[i].ci_offset = | ||
| 326 | pm8001_mr32(addressob, (offsetob + 0x18)); | ||
| 327 | pm8001_ha->outbnd_q_tbl[i].consumer_idx = 0; | ||
| 328 | pm8001_ha->outbnd_q_tbl[i].producer_index = 0; | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | /** | ||
| 333 | * update_main_config_table - update the main default table to the HBA. | ||
| 334 | * @pm8001_ha: our hba card information | ||
| 335 | */ | ||
| 336 | static void update_main_config_table(struct pm8001_hba_info *pm8001_ha) | ||
| 337 | { | ||
| 338 | void __iomem *address = pm8001_ha->main_cfg_tbl_addr; | ||
| 339 | pm8001_mw32(address, MAIN_IQNPPD_HPPD_OFFSET, | ||
| 340 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_q_nppd_hppd); | ||
| 341 | pm8001_mw32(address, MAIN_EVENT_LOG_ADDR_HI, | ||
| 342 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_event_log_addr); | ||
| 343 | pm8001_mw32(address, MAIN_EVENT_LOG_ADDR_LO, | ||
| 344 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_event_log_addr); | ||
| 345 | pm8001_mw32(address, MAIN_EVENT_LOG_BUFF_SIZE, | ||
| 346 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_size); | ||
| 347 | pm8001_mw32(address, MAIN_EVENT_LOG_OPTION, | ||
| 348 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.event_log_severity); | ||
| 349 | pm8001_mw32(address, MAIN_PCS_EVENT_LOG_ADDR_HI, | ||
| 350 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.upper_pcs_event_log_addr); | ||
| 351 | pm8001_mw32(address, MAIN_PCS_EVENT_LOG_ADDR_LO, | ||
| 352 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.lower_pcs_event_log_addr); | ||
| 353 | pm8001_mw32(address, MAIN_PCS_EVENT_LOG_BUFF_SIZE, | ||
| 354 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size); | ||
| 355 | pm8001_mw32(address, MAIN_PCS_EVENT_LOG_OPTION, | ||
| 356 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity); | ||
| 357 | pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT, | ||
| 358 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt); | ||
| 359 | pm8001_mw32(address, MAIN_EVENT_CRC_CHECK, | ||
| 360 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.crc_core_dump); | ||
| 361 | |||
| 362 | /* SPCv specific */ | ||
| 363 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping &= 0xCFFFFFFF; | ||
| 364 | /* Set GPIOLED to 0x2 for LED indicator */ | ||
| 365 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping |= 0x20000000; | ||
| 366 | pm8001_mw32(address, MAIN_GPIO_LED_FLAGS_OFFSET, | ||
| 367 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.gpio_led_mapping); | ||
| 368 | |||
| 369 | pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER, | ||
| 370 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer); | ||
| 371 | pm8001_mw32(address, MAIN_INT_REASSERTION_DELAY, | ||
| 372 | pm8001_ha->main_cfg_tbl.pm80xx_tbl.interrupt_reassertion_delay); | ||
| 373 | } | ||
| 374 | |||
| 375 | /** | ||
| 376 | * update_inbnd_queue_table - update the inbound queue table to the HBA. | ||
| 377 | * @pm8001_ha: our hba card information | ||
| 378 | */ | ||
| 379 | static void update_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha, | ||
| 380 | int number) | ||
| 381 | { | ||
| 382 | void __iomem *address = pm8001_ha->inbnd_q_tbl_addr; | ||
| 383 | u16 offset = number * 0x20; | ||
| 384 | pm8001_mw32(address, offset + IB_PROPERITY_OFFSET, | ||
| 385 | pm8001_ha->inbnd_q_tbl[number].element_pri_size_cnt); | ||
| 386 | pm8001_mw32(address, offset + IB_BASE_ADDR_HI_OFFSET, | ||
| 387 | pm8001_ha->inbnd_q_tbl[number].upper_base_addr); | ||
| 388 | pm8001_mw32(address, offset + IB_BASE_ADDR_LO_OFFSET, | ||
| 389 | pm8001_ha->inbnd_q_tbl[number].lower_base_addr); | ||
| 390 | pm8001_mw32(address, offset + IB_CI_BASE_ADDR_HI_OFFSET, | ||
| 391 | pm8001_ha->inbnd_q_tbl[number].ci_upper_base_addr); | ||
| 392 | pm8001_mw32(address, offset + IB_CI_BASE_ADDR_LO_OFFSET, | ||
| 393 | pm8001_ha->inbnd_q_tbl[number].ci_lower_base_addr); | ||
| 394 | } | ||
| 395 | |||
| 396 | /** | ||
| 397 | * update_outbnd_queue_table - update the outbound queue table to the HBA. | ||
| 398 | * @pm8001_ha: our hba card information | ||
| 399 | */ | ||
| 400 | static void update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha, | ||
| 401 | int number) | ||
| 402 | { | ||
| 403 | void __iomem *address = pm8001_ha->outbnd_q_tbl_addr; | ||
| 404 | u16 offset = number * 0x24; | ||
| 405 | pm8001_mw32(address, offset + OB_PROPERITY_OFFSET, | ||
| 406 | pm8001_ha->outbnd_q_tbl[number].element_size_cnt); | ||
| 407 | pm8001_mw32(address, offset + OB_BASE_ADDR_HI_OFFSET, | ||
| 408 | pm8001_ha->outbnd_q_tbl[number].upper_base_addr); | ||
| 409 | pm8001_mw32(address, offset + OB_BASE_ADDR_LO_OFFSET, | ||
| 410 | pm8001_ha->outbnd_q_tbl[number].lower_base_addr); | ||
| 411 | pm8001_mw32(address, offset + OB_PI_BASE_ADDR_HI_OFFSET, | ||
| 412 | pm8001_ha->outbnd_q_tbl[number].pi_upper_base_addr); | ||
| 413 | pm8001_mw32(address, offset + OB_PI_BASE_ADDR_LO_OFFSET, | ||
| 414 | pm8001_ha->outbnd_q_tbl[number].pi_lower_base_addr); | ||
| 415 | pm8001_mw32(address, offset + OB_INTERRUPT_COALES_OFFSET, | ||
| 416 | pm8001_ha->outbnd_q_tbl[number].interrup_vec_cnt_delay); | ||
| 417 | } | ||
| 418 | |||
| 419 | /** | ||
| 420 | * mpi_init_check - check firmware initialization status. | ||
| 421 | * @pm8001_ha: our hba card information | ||
| 422 | */ | ||
| 423 | static int mpi_init_check(struct pm8001_hba_info *pm8001_ha) | ||
| 424 | { | ||
| 425 | u32 max_wait_count; | ||
| 426 | u32 value; | ||
| 427 | u32 gst_len_mpistate; | ||
| 428 | |||
| 429 | /* Write bit0=1 to Inbound DoorBell Register to tell the SPC FW the | ||
| 430 | table is updated */ | ||
| 431 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_UPDATE); | ||
| 432 | /* wait until Inbound DoorBell Clear Register toggled */ | ||
| 433 | max_wait_count = 2 * 1000 * 1000;/* 2 sec for spcv/ve */ | ||
| 434 | do { | ||
| 435 | udelay(1); | ||
| 436 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); | ||
| 437 | value &= SPCv_MSGU_CFG_TABLE_UPDATE; | ||
| 438 | } while ((value != 0) && (--max_wait_count)); | ||
| 439 | |||
| 440 | if (!max_wait_count) | ||
| 441 | return -1; | ||
| 442 | /* check the MPI-State for initialization upto 100ms*/ | ||
| 443 | max_wait_count = 100 * 1000;/* 100 msec */ | ||
| 444 | do { | ||
| 445 | udelay(1); | ||
| 446 | gst_len_mpistate = | ||
| 447 | pm8001_mr32(pm8001_ha->general_stat_tbl_addr, | ||
| 448 | GST_GSTLEN_MPIS_OFFSET); | ||
| 449 | } while ((GST_MPI_STATE_INIT != | ||
| 450 | (gst_len_mpistate & GST_MPI_STATE_MASK)) && (--max_wait_count)); | ||
| 451 | if (!max_wait_count) | ||
| 452 | return -1; | ||
| 453 | |||
| 454 | /* check MPI Initialization error */ | ||
| 455 | gst_len_mpistate = gst_len_mpistate >> 16; | ||
| 456 | if (0x0000 != gst_len_mpistate) | ||
| 457 | return -1; | ||
| 458 | |||
| 459 | return 0; | ||
| 460 | } | ||
| 461 | |||
| 462 | /** | ||
| 463 | * check_fw_ready - The LLDD check if the FW is ready, if not, return error. | ||
| 464 | * @pm8001_ha: our hba card information | ||
| 465 | */ | ||
| 466 | static int check_fw_ready(struct pm8001_hba_info *pm8001_ha) | ||
| 467 | { | ||
| 468 | u32 value; | ||
| 469 | u32 max_wait_count; | ||
| 470 | u32 max_wait_time; | ||
| 471 | int ret = 0; | ||
| 472 | |||
| 473 | /* reset / PCIe ready */ | ||
| 474 | max_wait_time = max_wait_count = 100 * 1000; /* 100 milli sec */ | ||
| 475 | do { | ||
| 476 | udelay(1); | ||
| 477 | value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); | ||
| 478 | } while ((value == 0xFFFFFFFF) && (--max_wait_count)); | ||
| 479 | |||
| 480 | /* check ila status */ | ||
| 481 | max_wait_time = max_wait_count = 1000 * 1000; /* 1000 milli sec */ | ||
| 482 | do { | ||
| 483 | udelay(1); | ||
| 484 | value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); | ||
| 485 | } while (((value & SCRATCH_PAD_ILA_READY) != | ||
| 486 | SCRATCH_PAD_ILA_READY) && (--max_wait_count)); | ||
| 487 | if (!max_wait_count) | ||
| 488 | ret = -1; | ||
| 489 | else { | ||
| 490 | PM8001_MSG_DBG(pm8001_ha, | ||
| 491 | pm8001_printk(" ila ready status in %d millisec\n", | ||
| 492 | (max_wait_time - max_wait_count))); | ||
| 493 | } | ||
| 494 | |||
| 495 | /* check RAAE status */ | ||
| 496 | max_wait_time = max_wait_count = 1800 * 1000; /* 1800 milli sec */ | ||
| 497 | do { | ||
| 498 | udelay(1); | ||
| 499 | value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); | ||
| 500 | } while (((value & SCRATCH_PAD_RAAE_READY) != | ||
| 501 | SCRATCH_PAD_RAAE_READY) && (--max_wait_count)); | ||
| 502 | if (!max_wait_count) | ||
| 503 | ret = -1; | ||
| 504 | else { | ||
| 505 | PM8001_MSG_DBG(pm8001_ha, | ||
| 506 | pm8001_printk(" raae ready status in %d millisec\n", | ||
| 507 | (max_wait_time - max_wait_count))); | ||
| 508 | } | ||
| 509 | |||
| 510 | /* check iop0 status */ | ||
| 511 | max_wait_time = max_wait_count = 600 * 1000; /* 600 milli sec */ | ||
| 512 | do { | ||
| 513 | udelay(1); | ||
| 514 | value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); | ||
| 515 | } while (((value & SCRATCH_PAD_IOP0_READY) != SCRATCH_PAD_IOP0_READY) && | ||
| 516 | (--max_wait_count)); | ||
| 517 | if (!max_wait_count) | ||
| 518 | ret = -1; | ||
| 519 | else { | ||
| 520 | PM8001_MSG_DBG(pm8001_ha, | ||
| 521 | pm8001_printk(" iop0 ready status in %d millisec\n", | ||
| 522 | (max_wait_time - max_wait_count))); | ||
| 523 | } | ||
| 524 | |||
| 525 | /* check iop1 status only for 16 port controllers */ | ||
| 526 | if ((pm8001_ha->chip_id != chip_8008) && | ||
| 527 | (pm8001_ha->chip_id != chip_8009)) { | ||
| 528 | /* 200 milli sec */ | ||
| 529 | max_wait_time = max_wait_count = 200 * 1000; | ||
| 530 | do { | ||
| 531 | udelay(1); | ||
| 532 | value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1); | ||
| 533 | } while (((value & SCRATCH_PAD_IOP1_READY) != | ||
| 534 | SCRATCH_PAD_IOP1_READY) && (--max_wait_count)); | ||
| 535 | if (!max_wait_count) | ||
| 536 | ret = -1; | ||
| 537 | else { | ||
| 538 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 539 | "iop1 ready status in %d millisec\n", | ||
| 540 | (max_wait_time - max_wait_count))); | ||
| 541 | } | ||
| 542 | } | ||
| 543 | |||
| 544 | return ret; | ||
| 545 | } | ||
| 546 | |||
| 547 | static void init_pci_device_addresses(struct pm8001_hba_info *pm8001_ha) | ||
| 548 | { | ||
| 549 | void __iomem *base_addr; | ||
| 550 | u32 value; | ||
| 551 | u32 offset; | ||
| 552 | u32 pcibar; | ||
| 553 | u32 pcilogic; | ||
| 554 | |||
| 555 | value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_0); | ||
| 556 | offset = value & 0x03FFFFFF; /* scratch pad 0 TBL address */ | ||
| 557 | |||
| 558 | PM8001_INIT_DBG(pm8001_ha, | ||
| 559 | pm8001_printk("Scratchpad 0 Offset: 0x%x value 0x%x\n", | ||
| 560 | offset, value)); | ||
| 561 | pcilogic = (value & 0xFC000000) >> 26; | ||
| 562 | pcibar = get_pci_bar_index(pcilogic); | ||
| 563 | PM8001_INIT_DBG(pm8001_ha, | ||
| 564 | pm8001_printk("Scratchpad 0 PCI BAR: %d\n", pcibar)); | ||
| 565 | pm8001_ha->main_cfg_tbl_addr = base_addr = | ||
| 566 | pm8001_ha->io_mem[pcibar].memvirtaddr + offset; | ||
| 567 | pm8001_ha->general_stat_tbl_addr = | ||
| 568 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x18) & | ||
| 569 | 0xFFFFFF); | ||
| 570 | pm8001_ha->inbnd_q_tbl_addr = | ||
| 571 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C) & | ||
| 572 | 0xFFFFFF); | ||
| 573 | pm8001_ha->outbnd_q_tbl_addr = | ||
| 574 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x20) & | ||
| 575 | 0xFFFFFF); | ||
| 576 | pm8001_ha->ivt_tbl_addr = | ||
| 577 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C) & | ||
| 578 | 0xFFFFFF); | ||
| 579 | pm8001_ha->pspa_q_tbl_addr = | ||
| 580 | base_addr + (pm8001_cr32(pm8001_ha, pcibar, offset + 0x90) & | ||
| 581 | 0xFFFFFF); | ||
| 582 | |||
| 583 | PM8001_INIT_DBG(pm8001_ha, | ||
| 584 | pm8001_printk("GST OFFSET 0x%x\n", | ||
| 585 | pm8001_cr32(pm8001_ha, pcibar, offset + 0x18))); | ||
| 586 | PM8001_INIT_DBG(pm8001_ha, | ||
| 587 | pm8001_printk("INBND OFFSET 0x%x\n", | ||
| 588 | pm8001_cr32(pm8001_ha, pcibar, offset + 0x1C))); | ||
| 589 | PM8001_INIT_DBG(pm8001_ha, | ||
| 590 | pm8001_printk("OBND OFFSET 0x%x\n", | ||
| 591 | pm8001_cr32(pm8001_ha, pcibar, offset + 0x20))); | ||
| 592 | PM8001_INIT_DBG(pm8001_ha, | ||
| 593 | pm8001_printk("IVT OFFSET 0x%x\n", | ||
| 594 | pm8001_cr32(pm8001_ha, pcibar, offset + 0x8C))); | ||
| 595 | PM8001_INIT_DBG(pm8001_ha, | ||
| 596 | pm8001_printk("PSPA OFFSET 0x%x\n", | ||
| 597 | pm8001_cr32(pm8001_ha, pcibar, offset + 0x90))); | ||
| 598 | PM8001_INIT_DBG(pm8001_ha, | ||
| 599 | pm8001_printk("addr - main cfg %p general status %p\n", | ||
| 600 | pm8001_ha->main_cfg_tbl_addr, | ||
| 601 | pm8001_ha->general_stat_tbl_addr)); | ||
| 602 | PM8001_INIT_DBG(pm8001_ha, | ||
| 603 | pm8001_printk("addr - inbnd %p obnd %p\n", | ||
| 604 | pm8001_ha->inbnd_q_tbl_addr, | ||
| 605 | pm8001_ha->outbnd_q_tbl_addr)); | ||
| 606 | PM8001_INIT_DBG(pm8001_ha, | ||
| 607 | pm8001_printk("addr - pspa %p ivt %p\n", | ||
| 608 | pm8001_ha->pspa_q_tbl_addr, | ||
| 609 | pm8001_ha->ivt_tbl_addr)); | ||
| 610 | } | ||
| 611 | |||
| 612 | /** | ||
| 613 | * pm80xx_set_thermal_config - support the thermal configuration | ||
| 614 | * @pm8001_ha: our hba card information. | ||
| 615 | */ | ||
| 616 | int | ||
| 617 | pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) | ||
| 618 | { | ||
| 619 | struct set_ctrl_cfg_req payload; | ||
| 620 | struct inbound_queue_table *circularQ; | ||
| 621 | int rc; | ||
| 622 | u32 tag; | ||
| 623 | u32 opc = OPC_INB_SET_CONTROLLER_CONFIG; | ||
| 624 | |||
| 625 | memset(&payload, 0, sizeof(struct set_ctrl_cfg_req)); | ||
| 626 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
| 627 | if (rc) | ||
| 628 | return -1; | ||
| 629 | |||
| 630 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 631 | payload.tag = cpu_to_le32(tag); | ||
| 632 | payload.cfg_pg[0] = (THERMAL_LOG_ENABLE << 9) | | ||
| 633 | (THERMAL_ENABLE << 8) | THERMAL_OP_CODE; | ||
| 634 | payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8); | ||
| 635 | |||
| 636 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
| 637 | return rc; | ||
| 638 | |||
| 639 | } | ||
| 640 | |||
| 641 | /** | ||
| 642 | * pm80xx_set_sas_protocol_timer_config - support the SAS Protocol | ||
| 643 | * Timer configuration page | ||
| 644 | * @pm8001_ha: our hba card information. | ||
| 645 | */ | ||
| 646 | static int | ||
| 647 | pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha) | ||
| 648 | { | ||
| 649 | struct set_ctrl_cfg_req payload; | ||
| 650 | struct inbound_queue_table *circularQ; | ||
| 651 | SASProtocolTimerConfig_t SASConfigPage; | ||
| 652 | int rc; | ||
| 653 | u32 tag; | ||
| 654 | u32 opc = OPC_INB_SET_CONTROLLER_CONFIG; | ||
| 655 | |||
| 656 | memset(&payload, 0, sizeof(struct set_ctrl_cfg_req)); | ||
| 657 | memset(&SASConfigPage, 0, sizeof(SASProtocolTimerConfig_t)); | ||
| 658 | |||
| 659 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
| 660 | |||
| 661 | if (rc) | ||
| 662 | return -1; | ||
| 663 | |||
| 664 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 665 | payload.tag = cpu_to_le32(tag); | ||
| 666 | |||
| 667 | SASConfigPage.pageCode = SAS_PROTOCOL_TIMER_CONFIG_PAGE; | ||
| 668 | SASConfigPage.MST_MSI = 3 << 15; | ||
| 669 | SASConfigPage.STP_SSP_MCT_TMO = (STP_MCT_TMO << 16) | SSP_MCT_TMO; | ||
| 670 | SASConfigPage.STP_FRM_TMO = (SAS_MAX_OPEN_TIME << 24) | | ||
| 671 | (SMP_MAX_CONN_TIMER << 16) | STP_FRM_TIMER; | ||
| 672 | SASConfigPage.STP_IDLE_TMO = STP_IDLE_TIME; | ||
| 673 | |||
| 674 | if (SASConfigPage.STP_IDLE_TMO > 0x3FFFFFF) | ||
| 675 | SASConfigPage.STP_IDLE_TMO = 0x3FFFFFF; | ||
| 676 | |||
| 677 | |||
| 678 | SASConfigPage.OPNRJT_RTRY_INTVL = (SAS_MFD << 16) | | ||
| 679 | SAS_OPNRJT_RTRY_INTVL; | ||
| 680 | SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO = (SAS_DOPNRJT_RTRY_TMO << 16) | ||
| 681 | | SAS_COPNRJT_RTRY_TMO; | ||
| 682 | SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR = (SAS_DOPNRJT_RTRY_THR << 16) | ||
| 683 | | SAS_COPNRJT_RTRY_THR; | ||
| 684 | SASConfigPage.MAX_AIP = SAS_MAX_AIP; | ||
| 685 | |||
| 686 | PM8001_INIT_DBG(pm8001_ha, | ||
| 687 | pm8001_printk("SASConfigPage.pageCode " | ||
| 688 | "0x%08x\n", SASConfigPage.pageCode)); | ||
| 689 | PM8001_INIT_DBG(pm8001_ha, | ||
| 690 | pm8001_printk("SASConfigPage.MST_MSI " | ||
| 691 | " 0x%08x\n", SASConfigPage.MST_MSI)); | ||
| 692 | PM8001_INIT_DBG(pm8001_ha, | ||
| 693 | pm8001_printk("SASConfigPage.STP_SSP_MCT_TMO " | ||
| 694 | " 0x%08x\n", SASConfigPage.STP_SSP_MCT_TMO)); | ||
| 695 | PM8001_INIT_DBG(pm8001_ha, | ||
| 696 | pm8001_printk("SASConfigPage.STP_FRM_TMO " | ||
| 697 | " 0x%08x\n", SASConfigPage.STP_FRM_TMO)); | ||
| 698 | PM8001_INIT_DBG(pm8001_ha, | ||
| 699 | pm8001_printk("SASConfigPage.STP_IDLE_TMO " | ||
| 700 | " 0x%08x\n", SASConfigPage.STP_IDLE_TMO)); | ||
| 701 | PM8001_INIT_DBG(pm8001_ha, | ||
| 702 | pm8001_printk("SASConfigPage.OPNRJT_RTRY_INTVL " | ||
| 703 | " 0x%08x\n", SASConfigPage.OPNRJT_RTRY_INTVL)); | ||
| 704 | PM8001_INIT_DBG(pm8001_ha, | ||
| 705 | pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO " | ||
| 706 | " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_TMO)); | ||
| 707 | PM8001_INIT_DBG(pm8001_ha, | ||
| 708 | pm8001_printk("SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR " | ||
| 709 | " 0x%08x\n", SASConfigPage.Data_Cmd_OPNRJT_RTRY_THR)); | ||
| 710 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("SASConfigPage.MAX_AIP " | ||
| 711 | " 0x%08x\n", SASConfigPage.MAX_AIP)); | ||
| 712 | |||
| 713 | memcpy(&payload.cfg_pg, &SASConfigPage, | ||
| 714 | sizeof(SASProtocolTimerConfig_t)); | ||
| 715 | |||
| 716 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
| 717 | |||
| 718 | return rc; | ||
| 719 | } | ||
| 720 | |||
| 721 | /** | ||
| 722 | * pm80xx_get_encrypt_info - Check for encryption | ||
| 723 | * @pm8001_ha: our hba card information. | ||
| 724 | */ | ||
| 725 | static int | ||
| 726 | pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) | ||
| 727 | { | ||
| 728 | u32 scratch3_value; | ||
| 729 | int ret; | ||
| 730 | |||
| 731 | /* Read encryption status from SCRATCH PAD 3 */ | ||
| 732 | scratch3_value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3); | ||
| 733 | |||
| 734 | if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) == | ||
| 735 | SCRATCH_PAD3_ENC_READY) { | ||
| 736 | if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED) | ||
| 737 | pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS; | ||
| 738 | if ((scratch3_value & SCRATCH_PAD3_SM_MASK) == | ||
| 739 | SCRATCH_PAD3_SMF_ENABLED) | ||
| 740 | pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF; | ||
| 741 | if ((scratch3_value & SCRATCH_PAD3_SM_MASK) == | ||
| 742 | SCRATCH_PAD3_SMA_ENABLED) | ||
| 743 | pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA; | ||
| 744 | if ((scratch3_value & SCRATCH_PAD3_SM_MASK) == | ||
| 745 | SCRATCH_PAD3_SMB_ENABLED) | ||
| 746 | pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB; | ||
| 747 | pm8001_ha->encrypt_info.status = 0; | ||
| 748 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk( | ||
| 749 | "Encryption: SCRATCH_PAD3_ENC_READY 0x%08X." | ||
| 750 | "Cipher mode 0x%x Sec mode 0x%x status 0x%x\n", | ||
| 751 | scratch3_value, pm8001_ha->encrypt_info.cipher_mode, | ||
| 752 | pm8001_ha->encrypt_info.sec_mode, | ||
| 753 | pm8001_ha->encrypt_info.status)); | ||
| 754 | ret = 0; | ||
| 755 | } else if ((scratch3_value & SCRATCH_PAD3_ENC_READY) == | ||
| 756 | SCRATCH_PAD3_ENC_DISABLED) { | ||
| 757 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk( | ||
| 758 | "Encryption: SCRATCH_PAD3_ENC_DISABLED 0x%08X\n", | ||
| 759 | scratch3_value)); | ||
| 760 | pm8001_ha->encrypt_info.status = 0xFFFFFFFF; | ||
| 761 | pm8001_ha->encrypt_info.cipher_mode = 0; | ||
| 762 | pm8001_ha->encrypt_info.sec_mode = 0; | ||
| 763 | return 0; | ||
| 764 | } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) == | ||
| 765 | SCRATCH_PAD3_ENC_DIS_ERR) { | ||
| 766 | pm8001_ha->encrypt_info.status = | ||
| 767 | (scratch3_value & SCRATCH_PAD3_ERR_CODE) >> 16; | ||
| 768 | if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED) | ||
| 769 | pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS; | ||
| 770 | if ((scratch3_value & SCRATCH_PAD3_SM_MASK) == | ||
| 771 | SCRATCH_PAD3_SMF_ENABLED) | ||
| 772 | pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF; | ||
| 773 | if ((scratch3_value & SCRATCH_PAD3_SM_MASK) == | ||
| 774 | SCRATCH_PAD3_SMA_ENABLED) | ||
| 775 | pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA; | ||
| 776 | if ((scratch3_value & SCRATCH_PAD3_SM_MASK) == | ||
| 777 | SCRATCH_PAD3_SMB_ENABLED) | ||
| 778 | pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB; | ||
| 779 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk( | ||
| 780 | "Encryption: SCRATCH_PAD3_DIS_ERR 0x%08X." | ||
| 781 | "Cipher mode 0x%x sec mode 0x%x status 0x%x\n", | ||
| 782 | scratch3_value, pm8001_ha->encrypt_info.cipher_mode, | ||
| 783 | pm8001_ha->encrypt_info.sec_mode, | ||
| 784 | pm8001_ha->encrypt_info.status)); | ||
| 785 | ret = -1; | ||
| 786 | } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) == | ||
| 787 | SCRATCH_PAD3_ENC_ENA_ERR) { | ||
| 788 | |||
| 789 | pm8001_ha->encrypt_info.status = | ||
| 790 | (scratch3_value & SCRATCH_PAD3_ERR_CODE) >> 16; | ||
| 791 | if (scratch3_value & SCRATCH_PAD3_XTS_ENABLED) | ||
| 792 | pm8001_ha->encrypt_info.cipher_mode = CIPHER_MODE_XTS; | ||
| 793 | if ((scratch3_value & SCRATCH_PAD3_SM_MASK) == | ||
| 794 | SCRATCH_PAD3_SMF_ENABLED) | ||
| 795 | pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMF; | ||
| 796 | if ((scratch3_value & SCRATCH_PAD3_SM_MASK) == | ||
| 797 | SCRATCH_PAD3_SMA_ENABLED) | ||
| 798 | pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMA; | ||
| 799 | if ((scratch3_value & SCRATCH_PAD3_SM_MASK) == | ||
| 800 | SCRATCH_PAD3_SMB_ENABLED) | ||
| 801 | pm8001_ha->encrypt_info.sec_mode = SEC_MODE_SMB; | ||
| 802 | |||
| 803 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk( | ||
| 804 | "Encryption: SCRATCH_PAD3_ENA_ERR 0x%08X." | ||
| 805 | "Cipher mode 0x%x sec mode 0x%x status 0x%x\n", | ||
| 806 | scratch3_value, pm8001_ha->encrypt_info.cipher_mode, | ||
| 807 | pm8001_ha->encrypt_info.sec_mode, | ||
| 808 | pm8001_ha->encrypt_info.status)); | ||
| 809 | ret = -1; | ||
| 810 | } | ||
| 811 | return ret; | ||
| 812 | } | ||
| 813 | |||
| 814 | /** | ||
| 815 | * pm80xx_encrypt_update - update flash with encryption informtion | ||
| 816 | * @pm8001_ha: our hba card information. | ||
| 817 | */ | ||
| 818 | static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha) | ||
| 819 | { | ||
| 820 | struct kek_mgmt_req payload; | ||
| 821 | struct inbound_queue_table *circularQ; | ||
| 822 | int rc; | ||
| 823 | u32 tag; | ||
| 824 | u32 opc = OPC_INB_KEK_MANAGEMENT; | ||
| 825 | |||
| 826 | memset(&payload, 0, sizeof(struct kek_mgmt_req)); | ||
| 827 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
| 828 | if (rc) | ||
| 829 | return -1; | ||
| 830 | |||
| 831 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 832 | payload.tag = cpu_to_le32(tag); | ||
| 833 | /* Currently only one key is used. New KEK index is 1. | ||
| 834 | * Current KEK index is 1. Store KEK to NVRAM is 1. | ||
| 835 | */ | ||
| 836 | payload.new_curidx_ksop = ((1 << 24) | (1 << 16) | (1 << 8) | | ||
| 837 | KEK_MGMT_SUBOP_KEYCARDUPDATE); | ||
| 838 | |||
| 839 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
| 840 | |||
| 841 | return rc; | ||
| 842 | } | ||
| 843 | |||
| 844 | /** | ||
| 845 | * pm8001_chip_init - the main init function that initialize whole PM8001 chip. | ||
| 846 | * @pm8001_ha: our hba card information | ||
| 847 | */ | ||
| 848 | static int pm80xx_chip_init(struct pm8001_hba_info *pm8001_ha) | ||
| 849 | { | ||
| 850 | int ret; | ||
| 851 | u8 i = 0; | ||
| 852 | |||
| 853 | /* check the firmware status */ | ||
| 854 | if (-1 == check_fw_ready(pm8001_ha)) { | ||
| 855 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 856 | pm8001_printk("Firmware is not ready!\n")); | ||
| 857 | return -EBUSY; | ||
| 858 | } | ||
| 859 | |||
| 860 | /* Initialize pci space address eg: mpi offset */ | ||
| 861 | init_pci_device_addresses(pm8001_ha); | ||
| 862 | init_default_table_values(pm8001_ha); | ||
| 863 | read_main_config_table(pm8001_ha); | ||
| 864 | read_general_status_table(pm8001_ha); | ||
| 865 | read_inbnd_queue_table(pm8001_ha); | ||
| 866 | read_outbnd_queue_table(pm8001_ha); | ||
| 867 | read_phy_attr_table(pm8001_ha); | ||
| 868 | |||
| 869 | /* update main config table ,inbound table and outbound table */ | ||
| 870 | update_main_config_table(pm8001_ha); | ||
| 871 | for (i = 0; i < PM8001_MAX_SPCV_INB_NUM; i++) | ||
| 872 | update_inbnd_queue_table(pm8001_ha, i); | ||
| 873 | for (i = 0; i < PM8001_MAX_SPCV_OUTB_NUM; i++) | ||
| 874 | update_outbnd_queue_table(pm8001_ha, i); | ||
| 875 | |||
| 876 | /* notify firmware update finished and check initialization status */ | ||
| 877 | if (0 == mpi_init_check(pm8001_ha)) { | ||
| 878 | PM8001_INIT_DBG(pm8001_ha, | ||
| 879 | pm8001_printk("MPI initialize successful!\n")); | ||
| 880 | } else | ||
| 881 | return -EBUSY; | ||
| 882 | |||
| 883 | /* send SAS protocol timer configuration page to FW */ | ||
| 884 | ret = pm80xx_set_sas_protocol_timer_config(pm8001_ha); | ||
| 885 | |||
| 886 | /* Check for encryption */ | ||
| 887 | if (pm8001_ha->chip->encrypt) { | ||
| 888 | PM8001_INIT_DBG(pm8001_ha, | ||
| 889 | pm8001_printk("Checking for encryption\n")); | ||
| 890 | ret = pm80xx_get_encrypt_info(pm8001_ha); | ||
| 891 | if (ret == -1) { | ||
| 892 | PM8001_INIT_DBG(pm8001_ha, | ||
| 893 | pm8001_printk("Encryption error !!\n")); | ||
| 894 | if (pm8001_ha->encrypt_info.status == 0x81) { | ||
| 895 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk( | ||
| 896 | "Encryption enabled with error." | ||
| 897 | "Saving encryption key to flash\n")); | ||
| 898 | pm80xx_encrypt_update(pm8001_ha); | ||
| 899 | } | ||
| 900 | } | ||
| 901 | } | ||
| 902 | return 0; | ||
| 903 | } | ||
| 904 | |||
| 905 | static int mpi_uninit_check(struct pm8001_hba_info *pm8001_ha) | ||
| 906 | { | ||
| 907 | u32 max_wait_count; | ||
| 908 | u32 value; | ||
| 909 | u32 gst_len_mpistate; | ||
| 910 | init_pci_device_addresses(pm8001_ha); | ||
| 911 | /* Write bit1=1 to Inbound DoorBell Register to tell the SPC FW the | ||
| 912 | table is stop */ | ||
| 913 | pm8001_cw32(pm8001_ha, 0, MSGU_IBDB_SET, SPCv_MSGU_CFG_TABLE_RESET); | ||
| 914 | |||
| 915 | /* wait until Inbound DoorBell Clear Register toggled */ | ||
| 916 | max_wait_count = 2 * 1000 * 1000; /* 2 sec for spcv/ve */ | ||
| 917 | do { | ||
| 918 | udelay(1); | ||
| 919 | value = pm8001_cr32(pm8001_ha, 0, MSGU_IBDB_SET); | ||
| 920 | value &= SPCv_MSGU_CFG_TABLE_RESET; | ||
| 921 | } while ((value != 0) && (--max_wait_count)); | ||
| 922 | |||
| 923 | if (!max_wait_count) { | ||
| 924 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 925 | pm8001_printk("TIMEOUT:IBDB value/=%x\n", value)); | ||
| 926 | return -1; | ||
| 927 | } | ||
| 928 | |||
| 929 | /* check the MPI-State for termination in progress */ | ||
| 930 | /* wait until Inbound DoorBell Clear Register toggled */ | ||
| 931 | max_wait_count = 2 * 1000 * 1000; /* 2 sec for spcv/ve */ | ||
| 932 | do { | ||
| 933 | udelay(1); | ||
| 934 | gst_len_mpistate = | ||
| 935 | pm8001_mr32(pm8001_ha->general_stat_tbl_addr, | ||
| 936 | GST_GSTLEN_MPIS_OFFSET); | ||
| 937 | if (GST_MPI_STATE_UNINIT == | ||
| 938 | (gst_len_mpistate & GST_MPI_STATE_MASK)) | ||
| 939 | break; | ||
| 940 | } while (--max_wait_count); | ||
| 941 | if (!max_wait_count) { | ||
| 942 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 943 | pm8001_printk(" TIME OUT MPI State = 0x%x\n", | ||
| 944 | gst_len_mpistate & GST_MPI_STATE_MASK)); | ||
| 945 | return -1; | ||
| 946 | } | ||
| 947 | |||
| 948 | return 0; | ||
| 949 | } | ||
| 950 | |||
| 951 | /** | ||
| 952 | * pm8001_chip_soft_rst - soft reset the PM8001 chip, so that the clear all | ||
| 953 | * the FW register status to the originated status. | ||
| 954 | * @pm8001_ha: our hba card information | ||
| 955 | */ | ||
| 956 | |||
| 957 | static int | ||
| 958 | pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) | ||
| 959 | { | ||
| 960 | u32 regval; | ||
| 961 | u32 bootloader_state; | ||
| 962 | |||
| 963 | /* Check if MPI is in ready state to reset */ | ||
| 964 | if (mpi_uninit_check(pm8001_ha) != 0) { | ||
| 965 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 966 | pm8001_printk("MPI state is not ready\n")); | ||
| 967 | return -1; | ||
| 968 | } | ||
| 969 | |||
| 970 | /* checked for reset register normal state; 0x0 */ | ||
| 971 | regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET); | ||
| 972 | PM8001_INIT_DBG(pm8001_ha, | ||
| 973 | pm8001_printk("reset register before write : 0x%x\n", regval)); | ||
| 974 | |||
| 975 | pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, SPCv_NORMAL_RESET_VALUE); | ||
| 976 | mdelay(500); | ||
| 977 | |||
| 978 | regval = pm8001_cr32(pm8001_ha, 0, SPC_REG_SOFT_RESET); | ||
| 979 | PM8001_INIT_DBG(pm8001_ha, | ||
| 980 | pm8001_printk("reset register after write 0x%x\n", regval)); | ||
| 981 | |||
| 982 | if ((regval & SPCv_SOFT_RESET_READ_MASK) == | ||
| 983 | SPCv_SOFT_RESET_NORMAL_RESET_OCCURED) { | ||
| 984 | PM8001_MSG_DBG(pm8001_ha, | ||
| 985 | pm8001_printk(" soft reset successful [regval: 0x%x]\n", | ||
| 986 | regval)); | ||
| 987 | } else { | ||
| 988 | PM8001_MSG_DBG(pm8001_ha, | ||
| 989 | pm8001_printk(" soft reset failed [regval: 0x%x]\n", | ||
| 990 | regval)); | ||
| 991 | |||
| 992 | /* check bootloader is successfully executed or in HDA mode */ | ||
| 993 | bootloader_state = | ||
| 994 | pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1) & | ||
| 995 | SCRATCH_PAD1_BOOTSTATE_MASK; | ||
| 996 | |||
| 997 | if (bootloader_state == SCRATCH_PAD1_BOOTSTATE_HDA_SEEPROM) { | ||
| 998 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 999 | "Bootloader state - HDA mode SEEPROM\n")); | ||
| 1000 | } else if (bootloader_state == | ||
| 1001 | SCRATCH_PAD1_BOOTSTATE_HDA_BOOTSTRAP) { | ||
| 1002 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 1003 | "Bootloader state - HDA mode Bootstrap Pin\n")); | ||
| 1004 | } else if (bootloader_state == | ||
| 1005 | SCRATCH_PAD1_BOOTSTATE_HDA_SOFTRESET) { | ||
| 1006 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 1007 | "Bootloader state - HDA mode soft reset\n")); | ||
| 1008 | } else if (bootloader_state == | ||
| 1009 | SCRATCH_PAD1_BOOTSTATE_CRIT_ERROR) { | ||
| 1010 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 1011 | "Bootloader state-HDA mode critical error\n")); | ||
| 1012 | } | ||
| 1013 | return -EBUSY; | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | /* check the firmware status after reset */ | ||
| 1017 | if (-1 == check_fw_ready(pm8001_ha)) { | ||
| 1018 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1019 | pm8001_printk("Firmware is not ready!\n")); | ||
| 1020 | return -EBUSY; | ||
| 1021 | } | ||
| 1022 | PM8001_INIT_DBG(pm8001_ha, | ||
| 1023 | pm8001_printk("SPCv soft reset Complete\n")); | ||
| 1024 | return 0; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | static void pm80xx_hw_chip_rst(struct pm8001_hba_info *pm8001_ha) | ||
| 1028 | { | ||
| 1029 | u32 i; | ||
| 1030 | |||
| 1031 | PM8001_INIT_DBG(pm8001_ha, | ||
| 1032 | pm8001_printk("chip reset start\n")); | ||
| 1033 | |||
| 1034 | /* do SPCv chip reset. */ | ||
| 1035 | pm8001_cw32(pm8001_ha, 0, SPC_REG_SOFT_RESET, 0x11); | ||
| 1036 | PM8001_INIT_DBG(pm8001_ha, | ||
| 1037 | pm8001_printk("SPC soft reset Complete\n")); | ||
| 1038 | |||
| 1039 | /* Check this ..whether delay is required or no */ | ||
| 1040 | /* delay 10 usec */ | ||
| 1041 | udelay(10); | ||
| 1042 | |||
| 1043 | /* wait for 20 msec until the firmware gets reloaded */ | ||
| 1044 | i = 20; | ||
| 1045 | do { | ||
| 1046 | mdelay(1); | ||
| 1047 | } while ((--i) != 0); | ||
| 1048 | |||
| 1049 | PM8001_INIT_DBG(pm8001_ha, | ||
| 1050 | pm8001_printk("chip reset finished\n")); | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | /** | ||
| 1054 | * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt | ||
| 1055 | * @pm8001_ha: our hba card information | ||
| 1056 | */ | ||
| 1057 | static void | ||
| 1058 | pm80xx_chip_intx_interrupt_enable(struct pm8001_hba_info *pm8001_ha) | ||
| 1059 | { | ||
| 1060 | pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, ODMR_CLEAR_ALL); | ||
| 1061 | pm8001_cw32(pm8001_ha, 0, MSGU_ODCR, ODCR_CLEAR_ALL); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | /** | ||
| 1065 | * pm8001_chip_intx_interrupt_disable- disable PM8001 chip interrupt | ||
| 1066 | * @pm8001_ha: our hba card information | ||
| 1067 | */ | ||
| 1068 | static void | ||
| 1069 | pm80xx_chip_intx_interrupt_disable(struct pm8001_hba_info *pm8001_ha) | ||
| 1070 | { | ||
| 1071 | pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, ODMR_MASK_ALL); | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | /** | ||
| 1075 | * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt | ||
| 1076 | * @pm8001_ha: our hba card information | ||
| 1077 | */ | ||
| 1078 | static void | ||
| 1079 | pm80xx_chip_interrupt_enable(struct pm8001_hba_info *pm8001_ha, u8 vec) | ||
| 1080 | { | ||
| 1081 | #ifdef PM8001_USE_MSIX | ||
| 1082 | u32 mask; | ||
| 1083 | mask = (u32)(1 << vec); | ||
| 1084 | |||
| 1085 | pm8001_cw32(pm8001_ha, 0, MSGU_ODMR_CLR, (u32)(mask & 0xFFFFFFFF)); | ||
| 1086 | return; | ||
| 1087 | #endif | ||
| 1088 | pm80xx_chip_intx_interrupt_enable(pm8001_ha); | ||
| 1089 | |||
| 1090 | } | ||
| 1091 | |||
| 1092 | /** | ||
| 1093 | * pm8001_chip_interrupt_disable- disable PM8001 chip interrupt | ||
| 1094 | * @pm8001_ha: our hba card information | ||
| 1095 | */ | ||
| 1096 | static void | ||
| 1097 | pm80xx_chip_interrupt_disable(struct pm8001_hba_info *pm8001_ha, u8 vec) | ||
| 1098 | { | ||
| 1099 | #ifdef PM8001_USE_MSIX | ||
| 1100 | u32 mask; | ||
| 1101 | if (vec == 0xFF) | ||
| 1102 | mask = 0xFFFFFFFF; | ||
| 1103 | else | ||
| 1104 | mask = (u32)(1 << vec); | ||
| 1105 | pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, (u32)(mask & 0xFFFFFFFF)); | ||
| 1106 | return; | ||
| 1107 | #endif | ||
| 1108 | pm80xx_chip_intx_interrupt_disable(pm8001_ha); | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, | ||
| 1112 | struct pm8001_device *pm8001_ha_dev) | ||
| 1113 | { | ||
| 1114 | int res; | ||
| 1115 | u32 ccb_tag; | ||
| 1116 | struct pm8001_ccb_info *ccb; | ||
| 1117 | struct sas_task *task = NULL; | ||
| 1118 | struct task_abort_req task_abort; | ||
| 1119 | struct inbound_queue_table *circularQ; | ||
| 1120 | u32 opc = OPC_INB_SATA_ABORT; | ||
| 1121 | int ret; | ||
| 1122 | |||
| 1123 | if (!pm8001_ha_dev) { | ||
| 1124 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("dev is null\n")); | ||
| 1125 | return; | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | task = sas_alloc_slow_task(GFP_ATOMIC); | ||
| 1129 | |||
| 1130 | if (!task) { | ||
| 1131 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot " | ||
| 1132 | "allocate task\n")); | ||
| 1133 | return; | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | task->task_done = pm8001_task_done; | ||
| 1137 | |||
| 1138 | res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); | ||
| 1139 | if (res) | ||
| 1140 | return; | ||
| 1141 | |||
| 1142 | ccb = &pm8001_ha->ccb_info[ccb_tag]; | ||
| 1143 | ccb->device = pm8001_ha_dev; | ||
| 1144 | ccb->ccb_tag = ccb_tag; | ||
| 1145 | ccb->task = task; | ||
| 1146 | |||
| 1147 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 1148 | |||
| 1149 | memset(&task_abort, 0, sizeof(task_abort)); | ||
| 1150 | task_abort.abort_all = cpu_to_le32(1); | ||
| 1151 | task_abort.device_id = cpu_to_le32(pm8001_ha_dev->device_id); | ||
| 1152 | task_abort.tag = cpu_to_le32(ccb_tag); | ||
| 1153 | |||
| 1154 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); | ||
| 1155 | |||
| 1156 | } | ||
| 1157 | |||
| 1158 | static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, | ||
| 1159 | struct pm8001_device *pm8001_ha_dev) | ||
| 1160 | { | ||
| 1161 | struct sata_start_req sata_cmd; | ||
| 1162 | int res; | ||
| 1163 | u32 ccb_tag; | ||
| 1164 | struct pm8001_ccb_info *ccb; | ||
| 1165 | struct sas_task *task = NULL; | ||
| 1166 | struct host_to_dev_fis fis; | ||
| 1167 | struct domain_device *dev; | ||
| 1168 | struct inbound_queue_table *circularQ; | ||
| 1169 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | ||
| 1170 | |||
| 1171 | task = sas_alloc_slow_task(GFP_ATOMIC); | ||
| 1172 | |||
| 1173 | if (!task) { | ||
| 1174 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1175 | pm8001_printk("cannot allocate task !!!\n")); | ||
| 1176 | return; | ||
| 1177 | } | ||
| 1178 | task->task_done = pm8001_task_done; | ||
| 1179 | |||
| 1180 | res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); | ||
| 1181 | if (res) { | ||
| 1182 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1183 | pm8001_printk("cannot allocate tag !!!\n")); | ||
| 1184 | return; | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | /* allocate domain device by ourselves as libsas | ||
| 1188 | * is not going to provide any | ||
| 1189 | */ | ||
| 1190 | dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC); | ||
| 1191 | if (!dev) { | ||
| 1192 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1193 | pm8001_printk("Domain device cannot be allocated\n")); | ||
| 1194 | sas_free_task(task); | ||
| 1195 | return; | ||
| 1196 | } else { | ||
| 1197 | task->dev = dev; | ||
| 1198 | task->dev->lldd_dev = pm8001_ha_dev; | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | ccb = &pm8001_ha->ccb_info[ccb_tag]; | ||
| 1202 | ccb->device = pm8001_ha_dev; | ||
| 1203 | ccb->ccb_tag = ccb_tag; | ||
| 1204 | ccb->task = task; | ||
| 1205 | pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG; | ||
| 1206 | pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG; | ||
| 1207 | |||
| 1208 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | ||
| 1209 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 1210 | |||
| 1211 | /* construct read log FIS */ | ||
| 1212 | memset(&fis, 0, sizeof(struct host_to_dev_fis)); | ||
| 1213 | fis.fis_type = 0x27; | ||
| 1214 | fis.flags = 0x80; | ||
| 1215 | fis.command = ATA_CMD_READ_LOG_EXT; | ||
| 1216 | fis.lbal = 0x10; | ||
| 1217 | fis.sector_count = 0x1; | ||
| 1218 | |||
| 1219 | sata_cmd.tag = cpu_to_le32(ccb_tag); | ||
| 1220 | sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); | ||
| 1221 | sata_cmd.ncqtag_atap_dir_m_dad |= ((0x1 << 7) | (0x5 << 9)); | ||
| 1222 | memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); | ||
| 1223 | |||
| 1224 | res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); | ||
| 1225 | |||
| 1226 | } | ||
| 1227 | |||
| 1228 | /** | ||
| 1229 | * mpi_ssp_completion- process the event that FW response to the SSP request. | ||
| 1230 | * @pm8001_ha: our hba card information | ||
| 1231 | * @piomb: the message contents of this outbound message. | ||
| 1232 | * | ||
| 1233 | * When FW has completed a ssp request for example a IO request, after it has | ||
| 1234 | * filled the SG data with the data, it will trigger this event represent | ||
| 1235 | * that he has finished the job,please check the coresponding buffer. | ||
| 1236 | * So we will tell the caller who maybe waiting the result to tell upper layer | ||
| 1237 | * that the task has been finished. | ||
| 1238 | */ | ||
| 1239 | static void | ||
| 1240 | mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha , void *piomb) | ||
| 1241 | { | ||
| 1242 | struct sas_task *t; | ||
| 1243 | struct pm8001_ccb_info *ccb; | ||
| 1244 | unsigned long flags; | ||
| 1245 | u32 status; | ||
| 1246 | u32 param; | ||
| 1247 | u32 tag; | ||
| 1248 | struct ssp_completion_resp *psspPayload; | ||
| 1249 | struct task_status_struct *ts; | ||
| 1250 | struct ssp_response_iu *iu; | ||
| 1251 | struct pm8001_device *pm8001_dev; | ||
| 1252 | psspPayload = (struct ssp_completion_resp *)(piomb + 4); | ||
| 1253 | status = le32_to_cpu(psspPayload->status); | ||
| 1254 | tag = le32_to_cpu(psspPayload->tag); | ||
| 1255 | ccb = &pm8001_ha->ccb_info[tag]; | ||
| 1256 | if ((status == IO_ABORTED) && ccb->open_retry) { | ||
| 1257 | /* Being completed by another */ | ||
| 1258 | ccb->open_retry = 0; | ||
| 1259 | return; | ||
| 1260 | } | ||
| 1261 | pm8001_dev = ccb->device; | ||
| 1262 | param = le32_to_cpu(psspPayload->param); | ||
| 1263 | t = ccb->task; | ||
| 1264 | |||
| 1265 | if (status && status != IO_UNDERFLOW) | ||
| 1266 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1267 | pm8001_printk("sas IO status 0x%x\n", status)); | ||
| 1268 | if (unlikely(!t || !t->lldd_task || !t->dev)) | ||
| 1269 | return; | ||
| 1270 | ts = &t->task_status; | ||
| 1271 | switch (status) { | ||
| 1272 | case IO_SUCCESS: | ||
| 1273 | PM8001_IO_DBG(pm8001_ha, | ||
| 1274 | pm8001_printk("IO_SUCCESS ,param = 0x%x\n", | ||
| 1275 | param)); | ||
| 1276 | if (param == 0) { | ||
| 1277 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1278 | ts->stat = SAM_STAT_GOOD; | ||
| 1279 | } else { | ||
| 1280 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1281 | ts->stat = SAS_PROTO_RESPONSE; | ||
| 1282 | ts->residual = param; | ||
| 1283 | iu = &psspPayload->ssp_resp_iu; | ||
| 1284 | sas_ssp_task_response(pm8001_ha->dev, t, iu); | ||
| 1285 | } | ||
| 1286 | if (pm8001_dev) | ||
| 1287 | pm8001_dev->running_req--; | ||
| 1288 | break; | ||
| 1289 | case IO_ABORTED: | ||
| 1290 | PM8001_IO_DBG(pm8001_ha, | ||
| 1291 | pm8001_printk("IO_ABORTED IOMB Tag\n")); | ||
| 1292 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1293 | ts->stat = SAS_ABORTED_TASK; | ||
| 1294 | break; | ||
| 1295 | case IO_UNDERFLOW: | ||
| 1296 | /* SSP Completion with error */ | ||
| 1297 | PM8001_IO_DBG(pm8001_ha, | ||
| 1298 | pm8001_printk("IO_UNDERFLOW ,param = 0x%x\n", | ||
| 1299 | param)); | ||
| 1300 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1301 | ts->stat = SAS_DATA_UNDERRUN; | ||
| 1302 | ts->residual = param; | ||
| 1303 | if (pm8001_dev) | ||
| 1304 | pm8001_dev->running_req--; | ||
| 1305 | break; | ||
| 1306 | case IO_NO_DEVICE: | ||
| 1307 | PM8001_IO_DBG(pm8001_ha, | ||
| 1308 | pm8001_printk("IO_NO_DEVICE\n")); | ||
| 1309 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 1310 | ts->stat = SAS_PHY_DOWN; | ||
| 1311 | break; | ||
| 1312 | case IO_XFER_ERROR_BREAK: | ||
| 1313 | PM8001_IO_DBG(pm8001_ha, | ||
| 1314 | pm8001_printk("IO_XFER_ERROR_BREAK\n")); | ||
| 1315 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1316 | ts->stat = SAS_OPEN_REJECT; | ||
| 1317 | /* Force the midlayer to retry */ | ||
| 1318 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 1319 | break; | ||
| 1320 | case IO_XFER_ERROR_PHY_NOT_READY: | ||
| 1321 | PM8001_IO_DBG(pm8001_ha, | ||
| 1322 | pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); | ||
| 1323 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1324 | ts->stat = SAS_OPEN_REJECT; | ||
| 1325 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 1326 | break; | ||
| 1327 | case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: | ||
| 1328 | PM8001_IO_DBG(pm8001_ha, | ||
| 1329 | pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); | ||
| 1330 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1331 | ts->stat = SAS_OPEN_REJECT; | ||
| 1332 | ts->open_rej_reason = SAS_OREJ_EPROTO; | ||
| 1333 | break; | ||
| 1334 | case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: | ||
| 1335 | PM8001_IO_DBG(pm8001_ha, | ||
| 1336 | pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); | ||
| 1337 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1338 | ts->stat = SAS_OPEN_REJECT; | ||
| 1339 | ts->open_rej_reason = SAS_OREJ_UNKNOWN; | ||
| 1340 | break; | ||
| 1341 | case IO_OPEN_CNX_ERROR_BREAK: | ||
| 1342 | PM8001_IO_DBG(pm8001_ha, | ||
| 1343 | pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); | ||
| 1344 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1345 | ts->stat = SAS_OPEN_REJECT; | ||
| 1346 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 1347 | break; | ||
| 1348 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | ||
| 1349 | case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: | ||
| 1350 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO: | ||
| 1351 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: | ||
| 1352 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: | ||
| 1353 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: | ||
| 1354 | PM8001_IO_DBG(pm8001_ha, | ||
| 1355 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); | ||
| 1356 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1357 | ts->stat = SAS_OPEN_REJECT; | ||
| 1358 | ts->open_rej_reason = SAS_OREJ_UNKNOWN; | ||
| 1359 | if (!t->uldd_task) | ||
| 1360 | pm8001_handle_event(pm8001_ha, | ||
| 1361 | pm8001_dev, | ||
| 1362 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); | ||
| 1363 | break; | ||
| 1364 | case IO_OPEN_CNX_ERROR_BAD_DESTINATION: | ||
| 1365 | PM8001_IO_DBG(pm8001_ha, | ||
| 1366 | pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); | ||
| 1367 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1368 | ts->stat = SAS_OPEN_REJECT; | ||
| 1369 | ts->open_rej_reason = SAS_OREJ_BAD_DEST; | ||
| 1370 | break; | ||
| 1371 | case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: | ||
| 1372 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 1373 | "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); | ||
| 1374 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1375 | ts->stat = SAS_OPEN_REJECT; | ||
| 1376 | ts->open_rej_reason = SAS_OREJ_CONN_RATE; | ||
| 1377 | break; | ||
| 1378 | case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: | ||
| 1379 | PM8001_IO_DBG(pm8001_ha, | ||
| 1380 | pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); | ||
| 1381 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 1382 | ts->stat = SAS_OPEN_REJECT; | ||
| 1383 | ts->open_rej_reason = SAS_OREJ_WRONG_DEST; | ||
| 1384 | break; | ||
| 1385 | case IO_XFER_ERROR_NAK_RECEIVED: | ||
| 1386 | PM8001_IO_DBG(pm8001_ha, | ||
| 1387 | pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); | ||
| 1388 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1389 | ts->stat = SAS_OPEN_REJECT; | ||
| 1390 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 1391 | break; | ||
| 1392 | case IO_XFER_ERROR_ACK_NAK_TIMEOUT: | ||
| 1393 | PM8001_IO_DBG(pm8001_ha, | ||
| 1394 | pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); | ||
| 1395 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1396 | ts->stat = SAS_NAK_R_ERR; | ||
| 1397 | break; | ||
| 1398 | case IO_XFER_ERROR_DMA: | ||
| 1399 | PM8001_IO_DBG(pm8001_ha, | ||
| 1400 | pm8001_printk("IO_XFER_ERROR_DMA\n")); | ||
| 1401 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1402 | ts->stat = SAS_OPEN_REJECT; | ||
| 1403 | break; | ||
| 1404 | case IO_XFER_OPEN_RETRY_TIMEOUT: | ||
| 1405 | PM8001_IO_DBG(pm8001_ha, | ||
| 1406 | pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); | ||
| 1407 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1408 | ts->stat = SAS_OPEN_REJECT; | ||
| 1409 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 1410 | break; | ||
| 1411 | case IO_XFER_ERROR_OFFSET_MISMATCH: | ||
| 1412 | PM8001_IO_DBG(pm8001_ha, | ||
| 1413 | pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n")); | ||
| 1414 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1415 | ts->stat = SAS_OPEN_REJECT; | ||
| 1416 | break; | ||
| 1417 | case IO_PORT_IN_RESET: | ||
| 1418 | PM8001_IO_DBG(pm8001_ha, | ||
| 1419 | pm8001_printk("IO_PORT_IN_RESET\n")); | ||
| 1420 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1421 | ts->stat = SAS_OPEN_REJECT; | ||
| 1422 | break; | ||
| 1423 | case IO_DS_NON_OPERATIONAL: | ||
| 1424 | PM8001_IO_DBG(pm8001_ha, | ||
| 1425 | pm8001_printk("IO_DS_NON_OPERATIONAL\n")); | ||
| 1426 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1427 | ts->stat = SAS_OPEN_REJECT; | ||
| 1428 | if (!t->uldd_task) | ||
| 1429 | pm8001_handle_event(pm8001_ha, | ||
| 1430 | pm8001_dev, | ||
| 1431 | IO_DS_NON_OPERATIONAL); | ||
| 1432 | break; | ||
| 1433 | case IO_DS_IN_RECOVERY: | ||
| 1434 | PM8001_IO_DBG(pm8001_ha, | ||
| 1435 | pm8001_printk("IO_DS_IN_RECOVERY\n")); | ||
| 1436 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1437 | ts->stat = SAS_OPEN_REJECT; | ||
| 1438 | break; | ||
| 1439 | case IO_TM_TAG_NOT_FOUND: | ||
| 1440 | PM8001_IO_DBG(pm8001_ha, | ||
| 1441 | pm8001_printk("IO_TM_TAG_NOT_FOUND\n")); | ||
| 1442 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1443 | ts->stat = SAS_OPEN_REJECT; | ||
| 1444 | break; | ||
| 1445 | case IO_SSP_EXT_IU_ZERO_LEN_ERROR: | ||
| 1446 | PM8001_IO_DBG(pm8001_ha, | ||
| 1447 | pm8001_printk("IO_SSP_EXT_IU_ZERO_LEN_ERROR\n")); | ||
| 1448 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1449 | ts->stat = SAS_OPEN_REJECT; | ||
| 1450 | break; | ||
| 1451 | case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY: | ||
| 1452 | PM8001_IO_DBG(pm8001_ha, | ||
| 1453 | pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n")); | ||
| 1454 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1455 | ts->stat = SAS_OPEN_REJECT; | ||
| 1456 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 1457 | break; | ||
| 1458 | default: | ||
| 1459 | PM8001_IO_DBG(pm8001_ha, | ||
| 1460 | pm8001_printk("Unknown status 0x%x\n", status)); | ||
| 1461 | /* not allowed case. Therefore, return failed status */ | ||
| 1462 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1463 | ts->stat = SAS_OPEN_REJECT; | ||
| 1464 | break; | ||
| 1465 | } | ||
| 1466 | PM8001_IO_DBG(pm8001_ha, | ||
| 1467 | pm8001_printk("scsi_status = 0x%x\n ", | ||
| 1468 | psspPayload->ssp_resp_iu.status)); | ||
| 1469 | spin_lock_irqsave(&t->task_state_lock, flags); | ||
| 1470 | t->task_state_flags &= ~SAS_TASK_STATE_PENDING; | ||
| 1471 | t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | ||
| 1472 | t->task_state_flags |= SAS_TASK_STATE_DONE; | ||
| 1473 | if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { | ||
| 1474 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 1475 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( | ||
| 1476 | "task 0x%p done with io_status 0x%x resp 0x%x " | ||
| 1477 | "stat 0x%x but aborted by upper layer!\n", | ||
| 1478 | t, status, ts->resp, ts->stat)); | ||
| 1479 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 1480 | } else { | ||
| 1481 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 1482 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 1483 | mb();/* in order to force CPU ordering */ | ||
| 1484 | t->task_done(t); | ||
| 1485 | } | ||
| 1486 | } | ||
| 1487 | |||
| 1488 | /*See the comments for mpi_ssp_completion */ | ||
| 1489 | static void mpi_ssp_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | ||
| 1490 | { | ||
| 1491 | struct sas_task *t; | ||
| 1492 | unsigned long flags; | ||
| 1493 | struct task_status_struct *ts; | ||
| 1494 | struct pm8001_ccb_info *ccb; | ||
| 1495 | struct pm8001_device *pm8001_dev; | ||
| 1496 | struct ssp_event_resp *psspPayload = | ||
| 1497 | (struct ssp_event_resp *)(piomb + 4); | ||
| 1498 | u32 event = le32_to_cpu(psspPayload->event); | ||
| 1499 | u32 tag = le32_to_cpu(psspPayload->tag); | ||
| 1500 | u32 port_id = le32_to_cpu(psspPayload->port_id); | ||
| 1501 | |||
| 1502 | ccb = &pm8001_ha->ccb_info[tag]; | ||
| 1503 | t = ccb->task; | ||
| 1504 | pm8001_dev = ccb->device; | ||
| 1505 | if (event) | ||
| 1506 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1507 | pm8001_printk("sas IO status 0x%x\n", event)); | ||
| 1508 | if (unlikely(!t || !t->lldd_task || !t->dev)) | ||
| 1509 | return; | ||
| 1510 | ts = &t->task_status; | ||
| 1511 | PM8001_IO_DBG(pm8001_ha, | ||
| 1512 | pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n", | ||
| 1513 | port_id, tag, event)); | ||
| 1514 | switch (event) { | ||
| 1515 | case IO_OVERFLOW: | ||
| 1516 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n");) | ||
| 1517 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1518 | ts->stat = SAS_DATA_OVERRUN; | ||
| 1519 | ts->residual = 0; | ||
| 1520 | if (pm8001_dev) | ||
| 1521 | pm8001_dev->running_req--; | ||
| 1522 | break; | ||
| 1523 | case IO_XFER_ERROR_BREAK: | ||
| 1524 | PM8001_IO_DBG(pm8001_ha, | ||
| 1525 | pm8001_printk("IO_XFER_ERROR_BREAK\n")); | ||
| 1526 | pm8001_handle_event(pm8001_ha, t, IO_XFER_ERROR_BREAK); | ||
| 1527 | return; | ||
| 1528 | case IO_XFER_ERROR_PHY_NOT_READY: | ||
| 1529 | PM8001_IO_DBG(pm8001_ha, | ||
| 1530 | pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); | ||
| 1531 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1532 | ts->stat = SAS_OPEN_REJECT; | ||
| 1533 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 1534 | break; | ||
| 1535 | case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: | ||
| 1536 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 1537 | "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); | ||
| 1538 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1539 | ts->stat = SAS_OPEN_REJECT; | ||
| 1540 | ts->open_rej_reason = SAS_OREJ_EPROTO; | ||
| 1541 | break; | ||
| 1542 | case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: | ||
| 1543 | PM8001_IO_DBG(pm8001_ha, | ||
| 1544 | pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); | ||
| 1545 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1546 | ts->stat = SAS_OPEN_REJECT; | ||
| 1547 | ts->open_rej_reason = SAS_OREJ_UNKNOWN; | ||
| 1548 | break; | ||
| 1549 | case IO_OPEN_CNX_ERROR_BREAK: | ||
| 1550 | PM8001_IO_DBG(pm8001_ha, | ||
| 1551 | pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); | ||
| 1552 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1553 | ts->stat = SAS_OPEN_REJECT; | ||
| 1554 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 1555 | break; | ||
| 1556 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | ||
| 1557 | case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: | ||
| 1558 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO: | ||
| 1559 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: | ||
| 1560 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: | ||
| 1561 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: | ||
| 1562 | PM8001_IO_DBG(pm8001_ha, | ||
| 1563 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); | ||
| 1564 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1565 | ts->stat = SAS_OPEN_REJECT; | ||
| 1566 | ts->open_rej_reason = SAS_OREJ_UNKNOWN; | ||
| 1567 | if (!t->uldd_task) | ||
| 1568 | pm8001_handle_event(pm8001_ha, | ||
| 1569 | pm8001_dev, | ||
| 1570 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); | ||
| 1571 | break; | ||
| 1572 | case IO_OPEN_CNX_ERROR_BAD_DESTINATION: | ||
| 1573 | PM8001_IO_DBG(pm8001_ha, | ||
| 1574 | pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); | ||
| 1575 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1576 | ts->stat = SAS_OPEN_REJECT; | ||
| 1577 | ts->open_rej_reason = SAS_OREJ_BAD_DEST; | ||
| 1578 | break; | ||
| 1579 | case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: | ||
| 1580 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 1581 | "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); | ||
| 1582 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1583 | ts->stat = SAS_OPEN_REJECT; | ||
| 1584 | ts->open_rej_reason = SAS_OREJ_CONN_RATE; | ||
| 1585 | break; | ||
| 1586 | case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: | ||
| 1587 | PM8001_IO_DBG(pm8001_ha, | ||
| 1588 | pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); | ||
| 1589 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1590 | ts->stat = SAS_OPEN_REJECT; | ||
| 1591 | ts->open_rej_reason = SAS_OREJ_WRONG_DEST; | ||
| 1592 | break; | ||
| 1593 | case IO_XFER_ERROR_NAK_RECEIVED: | ||
| 1594 | PM8001_IO_DBG(pm8001_ha, | ||
| 1595 | pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); | ||
| 1596 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1597 | ts->stat = SAS_OPEN_REJECT; | ||
| 1598 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 1599 | break; | ||
| 1600 | case IO_XFER_ERROR_ACK_NAK_TIMEOUT: | ||
| 1601 | PM8001_IO_DBG(pm8001_ha, | ||
| 1602 | pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); | ||
| 1603 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1604 | ts->stat = SAS_NAK_R_ERR; | ||
| 1605 | break; | ||
| 1606 | case IO_XFER_OPEN_RETRY_TIMEOUT: | ||
| 1607 | PM8001_IO_DBG(pm8001_ha, | ||
| 1608 | pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); | ||
| 1609 | pm8001_handle_event(pm8001_ha, t, IO_XFER_OPEN_RETRY_TIMEOUT); | ||
| 1610 | return; | ||
| 1611 | case IO_XFER_ERROR_UNEXPECTED_PHASE: | ||
| 1612 | PM8001_IO_DBG(pm8001_ha, | ||
| 1613 | pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n")); | ||
| 1614 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1615 | ts->stat = SAS_DATA_OVERRUN; | ||
| 1616 | break; | ||
| 1617 | case IO_XFER_ERROR_XFER_RDY_OVERRUN: | ||
| 1618 | PM8001_IO_DBG(pm8001_ha, | ||
| 1619 | pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n")); | ||
| 1620 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1621 | ts->stat = SAS_DATA_OVERRUN; | ||
| 1622 | break; | ||
| 1623 | case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED: | ||
| 1624 | PM8001_IO_DBG(pm8001_ha, | ||
| 1625 | pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n")); | ||
| 1626 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1627 | ts->stat = SAS_DATA_OVERRUN; | ||
| 1628 | break; | ||
| 1629 | case IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT: | ||
| 1630 | PM8001_IO_DBG(pm8001_ha, | ||
| 1631 | pm8001_printk("IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT\n")); | ||
| 1632 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1633 | ts->stat = SAS_DATA_OVERRUN; | ||
| 1634 | break; | ||
| 1635 | case IO_XFER_ERROR_OFFSET_MISMATCH: | ||
| 1636 | PM8001_IO_DBG(pm8001_ha, | ||
| 1637 | pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n")); | ||
| 1638 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1639 | ts->stat = SAS_DATA_OVERRUN; | ||
| 1640 | break; | ||
| 1641 | case IO_XFER_ERROR_XFER_ZERO_DATA_LEN: | ||
| 1642 | PM8001_IO_DBG(pm8001_ha, | ||
| 1643 | pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n")); | ||
| 1644 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1645 | ts->stat = SAS_DATA_OVERRUN; | ||
| 1646 | break; | ||
| 1647 | case IO_XFER_ERROR_INTERNAL_CRC_ERROR: | ||
| 1648 | PM8001_IO_DBG(pm8001_ha, | ||
| 1649 | pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n")); | ||
| 1650 | /* TBC: used default set values */ | ||
| 1651 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1652 | ts->stat = SAS_DATA_OVERRUN; | ||
| 1653 | break; | ||
| 1654 | case IO_XFER_CMD_FRAME_ISSUED: | ||
| 1655 | PM8001_IO_DBG(pm8001_ha, | ||
| 1656 | pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n")); | ||
| 1657 | return; | ||
| 1658 | default: | ||
| 1659 | PM8001_IO_DBG(pm8001_ha, | ||
| 1660 | pm8001_printk("Unknown status 0x%x\n", event)); | ||
| 1661 | /* not allowed case. Therefore, return failed status */ | ||
| 1662 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1663 | ts->stat = SAS_DATA_OVERRUN; | ||
| 1664 | break; | ||
| 1665 | } | ||
| 1666 | spin_lock_irqsave(&t->task_state_lock, flags); | ||
| 1667 | t->task_state_flags &= ~SAS_TASK_STATE_PENDING; | ||
| 1668 | t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | ||
| 1669 | t->task_state_flags |= SAS_TASK_STATE_DONE; | ||
| 1670 | if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { | ||
| 1671 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 1672 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( | ||
| 1673 | "task 0x%p done with event 0x%x resp 0x%x " | ||
| 1674 | "stat 0x%x but aborted by upper layer!\n", | ||
| 1675 | t, event, ts->resp, ts->stat)); | ||
| 1676 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 1677 | } else { | ||
| 1678 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 1679 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 1680 | mb();/* in order to force CPU ordering */ | ||
| 1681 | t->task_done(t); | ||
| 1682 | } | ||
| 1683 | } | ||
| 1684 | |||
| 1685 | /*See the comments for mpi_ssp_completion */ | ||
| 1686 | static void | ||
| 1687 | mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 1688 | { | ||
| 1689 | struct sas_task *t; | ||
| 1690 | struct pm8001_ccb_info *ccb; | ||
| 1691 | u32 param; | ||
| 1692 | u32 status; | ||
| 1693 | u32 tag; | ||
| 1694 | struct sata_completion_resp *psataPayload; | ||
| 1695 | struct task_status_struct *ts; | ||
| 1696 | struct ata_task_resp *resp ; | ||
| 1697 | u32 *sata_resp; | ||
| 1698 | struct pm8001_device *pm8001_dev; | ||
| 1699 | unsigned long flags; | ||
| 1700 | |||
| 1701 | psataPayload = (struct sata_completion_resp *)(piomb + 4); | ||
| 1702 | status = le32_to_cpu(psataPayload->status); | ||
| 1703 | tag = le32_to_cpu(psataPayload->tag); | ||
| 1704 | |||
| 1705 | if (!tag) { | ||
| 1706 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1707 | pm8001_printk("tag null\n")); | ||
| 1708 | return; | ||
| 1709 | } | ||
| 1710 | ccb = &pm8001_ha->ccb_info[tag]; | ||
| 1711 | param = le32_to_cpu(psataPayload->param); | ||
| 1712 | if (ccb) { | ||
| 1713 | t = ccb->task; | ||
| 1714 | pm8001_dev = ccb->device; | ||
| 1715 | } else { | ||
| 1716 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1717 | pm8001_printk("ccb null\n")); | ||
| 1718 | return; | ||
| 1719 | } | ||
| 1720 | |||
| 1721 | if (t) { | ||
| 1722 | if (t->dev && (t->dev->lldd_dev)) | ||
| 1723 | pm8001_dev = t->dev->lldd_dev; | ||
| 1724 | } else { | ||
| 1725 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1726 | pm8001_printk("task null\n")); | ||
| 1727 | return; | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | if ((pm8001_dev && !(pm8001_dev->id & NCQ_READ_LOG_FLAG)) | ||
| 1731 | && unlikely(!t || !t->lldd_task || !t->dev)) { | ||
| 1732 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1733 | pm8001_printk("task or dev null\n")); | ||
| 1734 | return; | ||
| 1735 | } | ||
| 1736 | |||
| 1737 | ts = &t->task_status; | ||
| 1738 | if (!ts) { | ||
| 1739 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 1740 | pm8001_printk("ts null\n")); | ||
| 1741 | return; | ||
| 1742 | } | ||
| 1743 | |||
| 1744 | switch (status) { | ||
| 1745 | case IO_SUCCESS: | ||
| 1746 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); | ||
| 1747 | if (param == 0) { | ||
| 1748 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1749 | ts->stat = SAM_STAT_GOOD; | ||
| 1750 | /* check if response is for SEND READ LOG */ | ||
| 1751 | if (pm8001_dev && | ||
| 1752 | (pm8001_dev->id & NCQ_READ_LOG_FLAG)) { | ||
| 1753 | /* set new bit for abort_all */ | ||
| 1754 | pm8001_dev->id |= NCQ_ABORT_ALL_FLAG; | ||
| 1755 | /* clear bit for read log */ | ||
| 1756 | pm8001_dev->id = pm8001_dev->id & 0x7FFFFFFF; | ||
| 1757 | pm80xx_send_abort_all(pm8001_ha, pm8001_dev); | ||
| 1758 | /* Free the tag */ | ||
| 1759 | pm8001_tag_free(pm8001_ha, tag); | ||
| 1760 | sas_free_task(t); | ||
| 1761 | return; | ||
| 1762 | } | ||
| 1763 | } else { | ||
| 1764 | u8 len; | ||
| 1765 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1766 | ts->stat = SAS_PROTO_RESPONSE; | ||
| 1767 | ts->residual = param; | ||
| 1768 | PM8001_IO_DBG(pm8001_ha, | ||
| 1769 | pm8001_printk("SAS_PROTO_RESPONSE len = %d\n", | ||
| 1770 | param)); | ||
| 1771 | sata_resp = &psataPayload->sata_resp[0]; | ||
| 1772 | resp = (struct ata_task_resp *)ts->buf; | ||
| 1773 | if (t->ata_task.dma_xfer == 0 && | ||
| 1774 | t->data_dir == PCI_DMA_FROMDEVICE) { | ||
| 1775 | len = sizeof(struct pio_setup_fis); | ||
| 1776 | PM8001_IO_DBG(pm8001_ha, | ||
| 1777 | pm8001_printk("PIO read len = %d\n", len)); | ||
| 1778 | } else if (t->ata_task.use_ncq) { | ||
| 1779 | len = sizeof(struct set_dev_bits_fis); | ||
| 1780 | PM8001_IO_DBG(pm8001_ha, | ||
| 1781 | pm8001_printk("FPDMA len = %d\n", len)); | ||
| 1782 | } else { | ||
| 1783 | len = sizeof(struct dev_to_host_fis); | ||
| 1784 | PM8001_IO_DBG(pm8001_ha, | ||
| 1785 | pm8001_printk("other len = %d\n", len)); | ||
| 1786 | } | ||
| 1787 | if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) { | ||
| 1788 | resp->frame_len = len; | ||
| 1789 | memcpy(&resp->ending_fis[0], sata_resp, len); | ||
| 1790 | ts->buf_valid_size = sizeof(*resp); | ||
| 1791 | } else | ||
| 1792 | PM8001_IO_DBG(pm8001_ha, | ||
| 1793 | pm8001_printk("response to large\n")); | ||
| 1794 | } | ||
| 1795 | if (pm8001_dev) | ||
| 1796 | pm8001_dev->running_req--; | ||
| 1797 | break; | ||
| 1798 | case IO_ABORTED: | ||
| 1799 | PM8001_IO_DBG(pm8001_ha, | ||
| 1800 | pm8001_printk("IO_ABORTED IOMB Tag\n")); | ||
| 1801 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1802 | ts->stat = SAS_ABORTED_TASK; | ||
| 1803 | if (pm8001_dev) | ||
| 1804 | pm8001_dev->running_req--; | ||
| 1805 | break; | ||
| 1806 | /* following cases are to do cases */ | ||
| 1807 | case IO_UNDERFLOW: | ||
| 1808 | /* SATA Completion with error */ | ||
| 1809 | PM8001_IO_DBG(pm8001_ha, | ||
| 1810 | pm8001_printk("IO_UNDERFLOW param = %d\n", param)); | ||
| 1811 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1812 | ts->stat = SAS_DATA_UNDERRUN; | ||
| 1813 | ts->residual = param; | ||
| 1814 | if (pm8001_dev) | ||
| 1815 | pm8001_dev->running_req--; | ||
| 1816 | break; | ||
| 1817 | case IO_NO_DEVICE: | ||
| 1818 | PM8001_IO_DBG(pm8001_ha, | ||
| 1819 | pm8001_printk("IO_NO_DEVICE\n")); | ||
| 1820 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 1821 | ts->stat = SAS_PHY_DOWN; | ||
| 1822 | break; | ||
| 1823 | case IO_XFER_ERROR_BREAK: | ||
| 1824 | PM8001_IO_DBG(pm8001_ha, | ||
| 1825 | pm8001_printk("IO_XFER_ERROR_BREAK\n")); | ||
| 1826 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1827 | ts->stat = SAS_INTERRUPTED; | ||
| 1828 | break; | ||
| 1829 | case IO_XFER_ERROR_PHY_NOT_READY: | ||
| 1830 | PM8001_IO_DBG(pm8001_ha, | ||
| 1831 | pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); | ||
| 1832 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1833 | ts->stat = SAS_OPEN_REJECT; | ||
| 1834 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 1835 | break; | ||
| 1836 | case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: | ||
| 1837 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 1838 | "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); | ||
| 1839 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1840 | ts->stat = SAS_OPEN_REJECT; | ||
| 1841 | ts->open_rej_reason = SAS_OREJ_EPROTO; | ||
| 1842 | break; | ||
| 1843 | case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: | ||
| 1844 | PM8001_IO_DBG(pm8001_ha, | ||
| 1845 | pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); | ||
| 1846 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1847 | ts->stat = SAS_OPEN_REJECT; | ||
| 1848 | ts->open_rej_reason = SAS_OREJ_UNKNOWN; | ||
| 1849 | break; | ||
| 1850 | case IO_OPEN_CNX_ERROR_BREAK: | ||
| 1851 | PM8001_IO_DBG(pm8001_ha, | ||
| 1852 | pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); | ||
| 1853 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1854 | ts->stat = SAS_OPEN_REJECT; | ||
| 1855 | ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; | ||
| 1856 | break; | ||
| 1857 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | ||
| 1858 | case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: | ||
| 1859 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO: | ||
| 1860 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: | ||
| 1861 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: | ||
| 1862 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: | ||
| 1863 | PM8001_IO_DBG(pm8001_ha, | ||
| 1864 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); | ||
| 1865 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1866 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 1867 | if (!t->uldd_task) { | ||
| 1868 | pm8001_handle_event(pm8001_ha, | ||
| 1869 | pm8001_dev, | ||
| 1870 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); | ||
| 1871 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 1872 | ts->stat = SAS_QUEUE_FULL; | ||
| 1873 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 1874 | mb();/*in order to force CPU ordering*/ | ||
| 1875 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 1876 | t->task_done(t); | ||
| 1877 | spin_lock_irq(&pm8001_ha->lock); | ||
| 1878 | return; | ||
| 1879 | } | ||
| 1880 | break; | ||
| 1881 | case IO_OPEN_CNX_ERROR_BAD_DESTINATION: | ||
| 1882 | PM8001_IO_DBG(pm8001_ha, | ||
| 1883 | pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); | ||
| 1884 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 1885 | ts->stat = SAS_OPEN_REJECT; | ||
| 1886 | ts->open_rej_reason = SAS_OREJ_BAD_DEST; | ||
| 1887 | if (!t->uldd_task) { | ||
| 1888 | pm8001_handle_event(pm8001_ha, | ||
| 1889 | pm8001_dev, | ||
| 1890 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); | ||
| 1891 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 1892 | ts->stat = SAS_QUEUE_FULL; | ||
| 1893 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 1894 | mb();/*ditto*/ | ||
| 1895 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 1896 | t->task_done(t); | ||
| 1897 | spin_lock_irq(&pm8001_ha->lock); | ||
| 1898 | return; | ||
| 1899 | } | ||
| 1900 | break; | ||
| 1901 | case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: | ||
| 1902 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 1903 | "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); | ||
| 1904 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1905 | ts->stat = SAS_OPEN_REJECT; | ||
| 1906 | ts->open_rej_reason = SAS_OREJ_CONN_RATE; | ||
| 1907 | break; | ||
| 1908 | case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: | ||
| 1909 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 1910 | "IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n")); | ||
| 1911 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1912 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 1913 | if (!t->uldd_task) { | ||
| 1914 | pm8001_handle_event(pm8001_ha, | ||
| 1915 | pm8001_dev, | ||
| 1916 | IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY); | ||
| 1917 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 1918 | ts->stat = SAS_QUEUE_FULL; | ||
| 1919 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 1920 | mb();/* ditto*/ | ||
| 1921 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 1922 | t->task_done(t); | ||
| 1923 | spin_lock_irq(&pm8001_ha->lock); | ||
| 1924 | return; | ||
| 1925 | } | ||
| 1926 | break; | ||
| 1927 | case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: | ||
| 1928 | PM8001_IO_DBG(pm8001_ha, | ||
| 1929 | pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); | ||
| 1930 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1931 | ts->stat = SAS_OPEN_REJECT; | ||
| 1932 | ts->open_rej_reason = SAS_OREJ_WRONG_DEST; | ||
| 1933 | break; | ||
| 1934 | case IO_XFER_ERROR_NAK_RECEIVED: | ||
| 1935 | PM8001_IO_DBG(pm8001_ha, | ||
| 1936 | pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); | ||
| 1937 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1938 | ts->stat = SAS_NAK_R_ERR; | ||
| 1939 | break; | ||
| 1940 | case IO_XFER_ERROR_ACK_NAK_TIMEOUT: | ||
| 1941 | PM8001_IO_DBG(pm8001_ha, | ||
| 1942 | pm8001_printk("IO_XFER_ERROR_ACK_NAK_TIMEOUT\n")); | ||
| 1943 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1944 | ts->stat = SAS_NAK_R_ERR; | ||
| 1945 | break; | ||
| 1946 | case IO_XFER_ERROR_DMA: | ||
| 1947 | PM8001_IO_DBG(pm8001_ha, | ||
| 1948 | pm8001_printk("IO_XFER_ERROR_DMA\n")); | ||
| 1949 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1950 | ts->stat = SAS_ABORTED_TASK; | ||
| 1951 | break; | ||
| 1952 | case IO_XFER_ERROR_SATA_LINK_TIMEOUT: | ||
| 1953 | PM8001_IO_DBG(pm8001_ha, | ||
| 1954 | pm8001_printk("IO_XFER_ERROR_SATA_LINK_TIMEOUT\n")); | ||
| 1955 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 1956 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 1957 | break; | ||
| 1958 | case IO_XFER_ERROR_REJECTED_NCQ_MODE: | ||
| 1959 | PM8001_IO_DBG(pm8001_ha, | ||
| 1960 | pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n")); | ||
| 1961 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1962 | ts->stat = SAS_DATA_UNDERRUN; | ||
| 1963 | break; | ||
| 1964 | case IO_XFER_OPEN_RETRY_TIMEOUT: | ||
| 1965 | PM8001_IO_DBG(pm8001_ha, | ||
| 1966 | pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); | ||
| 1967 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1968 | ts->stat = SAS_OPEN_TO; | ||
| 1969 | break; | ||
| 1970 | case IO_PORT_IN_RESET: | ||
| 1971 | PM8001_IO_DBG(pm8001_ha, | ||
| 1972 | pm8001_printk("IO_PORT_IN_RESET\n")); | ||
| 1973 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1974 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 1975 | break; | ||
| 1976 | case IO_DS_NON_OPERATIONAL: | ||
| 1977 | PM8001_IO_DBG(pm8001_ha, | ||
| 1978 | pm8001_printk("IO_DS_NON_OPERATIONAL\n")); | ||
| 1979 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1980 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 1981 | if (!t->uldd_task) { | ||
| 1982 | pm8001_handle_event(pm8001_ha, pm8001_dev, | ||
| 1983 | IO_DS_NON_OPERATIONAL); | ||
| 1984 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 1985 | ts->stat = SAS_QUEUE_FULL; | ||
| 1986 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 1987 | mb();/*ditto*/ | ||
| 1988 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 1989 | t->task_done(t); | ||
| 1990 | spin_lock_irq(&pm8001_ha->lock); | ||
| 1991 | return; | ||
| 1992 | } | ||
| 1993 | break; | ||
| 1994 | case IO_DS_IN_RECOVERY: | ||
| 1995 | PM8001_IO_DBG(pm8001_ha, | ||
| 1996 | pm8001_printk("IO_DS_IN_RECOVERY\n")); | ||
| 1997 | ts->resp = SAS_TASK_COMPLETE; | ||
| 1998 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 1999 | break; | ||
| 2000 | case IO_DS_IN_ERROR: | ||
| 2001 | PM8001_IO_DBG(pm8001_ha, | ||
| 2002 | pm8001_printk("IO_DS_IN_ERROR\n")); | ||
| 2003 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2004 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 2005 | if (!t->uldd_task) { | ||
| 2006 | pm8001_handle_event(pm8001_ha, pm8001_dev, | ||
| 2007 | IO_DS_IN_ERROR); | ||
| 2008 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 2009 | ts->stat = SAS_QUEUE_FULL; | ||
| 2010 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2011 | mb();/*ditto*/ | ||
| 2012 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 2013 | t->task_done(t); | ||
| 2014 | spin_lock_irq(&pm8001_ha->lock); | ||
| 2015 | return; | ||
| 2016 | } | ||
| 2017 | break; | ||
| 2018 | case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY: | ||
| 2019 | PM8001_IO_DBG(pm8001_ha, | ||
| 2020 | pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n")); | ||
| 2021 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2022 | ts->stat = SAS_OPEN_REJECT; | ||
| 2023 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 2024 | default: | ||
| 2025 | PM8001_IO_DBG(pm8001_ha, | ||
| 2026 | pm8001_printk("Unknown status 0x%x\n", status)); | ||
| 2027 | /* not allowed case. Therefore, return failed status */ | ||
| 2028 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2029 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 2030 | break; | ||
| 2031 | } | ||
| 2032 | spin_lock_irqsave(&t->task_state_lock, flags); | ||
| 2033 | t->task_state_flags &= ~SAS_TASK_STATE_PENDING; | ||
| 2034 | t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | ||
| 2035 | t->task_state_flags |= SAS_TASK_STATE_DONE; | ||
| 2036 | if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { | ||
| 2037 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 2038 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2039 | pm8001_printk("task 0x%p done with io_status 0x%x" | ||
| 2040 | " resp 0x%x stat 0x%x but aborted by upper layer!\n", | ||
| 2041 | t, status, ts->resp, ts->stat)); | ||
| 2042 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2043 | } else if (t->uldd_task) { | ||
| 2044 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 2045 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2046 | mb();/* ditto */ | ||
| 2047 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 2048 | t->task_done(t); | ||
| 2049 | spin_lock_irq(&pm8001_ha->lock); | ||
| 2050 | } else if (!t->uldd_task) { | ||
| 2051 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 2052 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2053 | mb();/*ditto*/ | ||
| 2054 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 2055 | t->task_done(t); | ||
| 2056 | spin_lock_irq(&pm8001_ha->lock); | ||
| 2057 | } | ||
| 2058 | } | ||
| 2059 | |||
| 2060 | /*See the comments for mpi_ssp_completion */ | ||
| 2061 | static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) | ||
| 2062 | { | ||
| 2063 | struct sas_task *t; | ||
| 2064 | struct task_status_struct *ts; | ||
| 2065 | struct pm8001_ccb_info *ccb; | ||
| 2066 | struct pm8001_device *pm8001_dev; | ||
| 2067 | struct sata_event_resp *psataPayload = | ||
| 2068 | (struct sata_event_resp *)(piomb + 4); | ||
| 2069 | u32 event = le32_to_cpu(psataPayload->event); | ||
| 2070 | u32 tag = le32_to_cpu(psataPayload->tag); | ||
| 2071 | u32 port_id = le32_to_cpu(psataPayload->port_id); | ||
| 2072 | u32 dev_id = le32_to_cpu(psataPayload->device_id); | ||
| 2073 | unsigned long flags; | ||
| 2074 | |||
| 2075 | ccb = &pm8001_ha->ccb_info[tag]; | ||
| 2076 | |||
| 2077 | if (ccb) { | ||
| 2078 | t = ccb->task; | ||
| 2079 | pm8001_dev = ccb->device; | ||
| 2080 | } else { | ||
| 2081 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2082 | pm8001_printk("No CCB !!!. returning\n")); | ||
| 2083 | return; | ||
| 2084 | } | ||
| 2085 | if (event) | ||
| 2086 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2087 | pm8001_printk("SATA EVENT 0x%x\n", event)); | ||
| 2088 | |||
| 2089 | /* Check if this is NCQ error */ | ||
| 2090 | if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) { | ||
| 2091 | /* find device using device id */ | ||
| 2092 | pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id); | ||
| 2093 | /* send read log extension */ | ||
| 2094 | if (pm8001_dev) | ||
| 2095 | pm80xx_send_read_log(pm8001_ha, pm8001_dev); | ||
| 2096 | return; | ||
| 2097 | } | ||
| 2098 | |||
| 2099 | if (unlikely(!t || !t->lldd_task || !t->dev)) { | ||
| 2100 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2101 | pm8001_printk("task or dev null\n")); | ||
| 2102 | return; | ||
| 2103 | } | ||
| 2104 | |||
| 2105 | ts = &t->task_status; | ||
| 2106 | PM8001_IO_DBG(pm8001_ha, | ||
| 2107 | pm8001_printk("port_id:0x%x, tag:0x%x, event:0x%x\n", | ||
| 2108 | port_id, tag, event)); | ||
| 2109 | switch (event) { | ||
| 2110 | case IO_OVERFLOW: | ||
| 2111 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); | ||
| 2112 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2113 | ts->stat = SAS_DATA_OVERRUN; | ||
| 2114 | ts->residual = 0; | ||
| 2115 | if (pm8001_dev) | ||
| 2116 | pm8001_dev->running_req--; | ||
| 2117 | break; | ||
| 2118 | case IO_XFER_ERROR_BREAK: | ||
| 2119 | PM8001_IO_DBG(pm8001_ha, | ||
| 2120 | pm8001_printk("IO_XFER_ERROR_BREAK\n")); | ||
| 2121 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2122 | ts->stat = SAS_INTERRUPTED; | ||
| 2123 | break; | ||
| 2124 | case IO_XFER_ERROR_PHY_NOT_READY: | ||
| 2125 | PM8001_IO_DBG(pm8001_ha, | ||
| 2126 | pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); | ||
| 2127 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2128 | ts->stat = SAS_OPEN_REJECT; | ||
| 2129 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 2130 | break; | ||
| 2131 | case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: | ||
| 2132 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 2133 | "IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); | ||
| 2134 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2135 | ts->stat = SAS_OPEN_REJECT; | ||
| 2136 | ts->open_rej_reason = SAS_OREJ_EPROTO; | ||
| 2137 | break; | ||
| 2138 | case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: | ||
| 2139 | PM8001_IO_DBG(pm8001_ha, | ||
| 2140 | pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); | ||
| 2141 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2142 | ts->stat = SAS_OPEN_REJECT; | ||
| 2143 | ts->open_rej_reason = SAS_OREJ_UNKNOWN; | ||
| 2144 | break; | ||
| 2145 | case IO_OPEN_CNX_ERROR_BREAK: | ||
| 2146 | PM8001_IO_DBG(pm8001_ha, | ||
| 2147 | pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); | ||
| 2148 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2149 | ts->stat = SAS_OPEN_REJECT; | ||
| 2150 | ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; | ||
| 2151 | break; | ||
| 2152 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | ||
| 2153 | case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: | ||
| 2154 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO: | ||
| 2155 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: | ||
| 2156 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: | ||
| 2157 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: | ||
| 2158 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2159 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); | ||
| 2160 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 2161 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 2162 | if (!t->uldd_task) { | ||
| 2163 | pm8001_handle_event(pm8001_ha, | ||
| 2164 | pm8001_dev, | ||
| 2165 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); | ||
| 2166 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2167 | ts->stat = SAS_QUEUE_FULL; | ||
| 2168 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2169 | mb();/*ditto*/ | ||
| 2170 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 2171 | t->task_done(t); | ||
| 2172 | spin_lock_irq(&pm8001_ha->lock); | ||
| 2173 | return; | ||
| 2174 | } | ||
| 2175 | break; | ||
| 2176 | case IO_OPEN_CNX_ERROR_BAD_DESTINATION: | ||
| 2177 | PM8001_IO_DBG(pm8001_ha, | ||
| 2178 | pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); | ||
| 2179 | ts->resp = SAS_TASK_UNDELIVERED; | ||
| 2180 | ts->stat = SAS_OPEN_REJECT; | ||
| 2181 | ts->open_rej_reason = SAS_OREJ_BAD_DEST; | ||
| 2182 | break; | ||
| 2183 | case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: | ||
| 2184 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 2185 | "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); | ||
| 2186 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2187 | ts->stat = SAS_OPEN_REJECT; | ||
| 2188 | ts->open_rej_reason = SAS_OREJ_CONN_RATE; | ||
| 2189 | break; | ||
| 2190 | case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: | ||
| 2191 | PM8001_IO_DBG(pm8001_ha, | ||
| 2192 | pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); | ||
| 2193 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2194 | ts->stat = SAS_OPEN_REJECT; | ||
| 2195 | ts->open_rej_reason = SAS_OREJ_WRONG_DEST; | ||
| 2196 | break; | ||
| 2197 | case IO_XFER_ERROR_NAK_RECEIVED: | ||
| 2198 | PM8001_IO_DBG(pm8001_ha, | ||
| 2199 | pm8001_printk("IO_XFER_ERROR_NAK_RECEIVED\n")); | ||
| 2200 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2201 | ts->stat = SAS_NAK_R_ERR; | ||
| 2202 | break; | ||
| 2203 | case IO_XFER_ERROR_PEER_ABORTED: | ||
| 2204 | PM8001_IO_DBG(pm8001_ha, | ||
| 2205 | pm8001_printk("IO_XFER_ERROR_PEER_ABORTED\n")); | ||
| 2206 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2207 | ts->stat = SAS_NAK_R_ERR; | ||
| 2208 | break; | ||
| 2209 | case IO_XFER_ERROR_REJECTED_NCQ_MODE: | ||
| 2210 | PM8001_IO_DBG(pm8001_ha, | ||
| 2211 | pm8001_printk("IO_XFER_ERROR_REJECTED_NCQ_MODE\n")); | ||
| 2212 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2213 | ts->stat = SAS_DATA_UNDERRUN; | ||
| 2214 | break; | ||
| 2215 | case IO_XFER_OPEN_RETRY_TIMEOUT: | ||
| 2216 | PM8001_IO_DBG(pm8001_ha, | ||
| 2217 | pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); | ||
| 2218 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2219 | ts->stat = SAS_OPEN_TO; | ||
| 2220 | break; | ||
| 2221 | case IO_XFER_ERROR_UNEXPECTED_PHASE: | ||
| 2222 | PM8001_IO_DBG(pm8001_ha, | ||
| 2223 | pm8001_printk("IO_XFER_ERROR_UNEXPECTED_PHASE\n")); | ||
| 2224 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2225 | ts->stat = SAS_OPEN_TO; | ||
| 2226 | break; | ||
| 2227 | case IO_XFER_ERROR_XFER_RDY_OVERRUN: | ||
| 2228 | PM8001_IO_DBG(pm8001_ha, | ||
| 2229 | pm8001_printk("IO_XFER_ERROR_XFER_RDY_OVERRUN\n")); | ||
| 2230 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2231 | ts->stat = SAS_OPEN_TO; | ||
| 2232 | break; | ||
| 2233 | case IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED: | ||
| 2234 | PM8001_IO_DBG(pm8001_ha, | ||
| 2235 | pm8001_printk("IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED\n")); | ||
| 2236 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2237 | ts->stat = SAS_OPEN_TO; | ||
| 2238 | break; | ||
| 2239 | case IO_XFER_ERROR_OFFSET_MISMATCH: | ||
| 2240 | PM8001_IO_DBG(pm8001_ha, | ||
| 2241 | pm8001_printk("IO_XFER_ERROR_OFFSET_MISMATCH\n")); | ||
| 2242 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2243 | ts->stat = SAS_OPEN_TO; | ||
| 2244 | break; | ||
| 2245 | case IO_XFER_ERROR_XFER_ZERO_DATA_LEN: | ||
| 2246 | PM8001_IO_DBG(pm8001_ha, | ||
| 2247 | pm8001_printk("IO_XFER_ERROR_XFER_ZERO_DATA_LEN\n")); | ||
| 2248 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2249 | ts->stat = SAS_OPEN_TO; | ||
| 2250 | break; | ||
| 2251 | case IO_XFER_CMD_FRAME_ISSUED: | ||
| 2252 | PM8001_IO_DBG(pm8001_ha, | ||
| 2253 | pm8001_printk("IO_XFER_CMD_FRAME_ISSUED\n")); | ||
| 2254 | break; | ||
| 2255 | case IO_XFER_PIO_SETUP_ERROR: | ||
| 2256 | PM8001_IO_DBG(pm8001_ha, | ||
| 2257 | pm8001_printk("IO_XFER_PIO_SETUP_ERROR\n")); | ||
| 2258 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2259 | ts->stat = SAS_OPEN_TO; | ||
| 2260 | break; | ||
| 2261 | case IO_XFER_ERROR_INTERNAL_CRC_ERROR: | ||
| 2262 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2263 | pm8001_printk("IO_XFR_ERROR_INTERNAL_CRC_ERROR\n")); | ||
| 2264 | /* TBC: used default set values */ | ||
| 2265 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2266 | ts->stat = SAS_OPEN_TO; | ||
| 2267 | break; | ||
| 2268 | case IO_XFER_DMA_ACTIVATE_TIMEOUT: | ||
| 2269 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2270 | pm8001_printk("IO_XFR_DMA_ACTIVATE_TIMEOUT\n")); | ||
| 2271 | /* TBC: used default set values */ | ||
| 2272 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2273 | ts->stat = SAS_OPEN_TO; | ||
| 2274 | break; | ||
| 2275 | default: | ||
| 2276 | PM8001_IO_DBG(pm8001_ha, | ||
| 2277 | pm8001_printk("Unknown status 0x%x\n", event)); | ||
| 2278 | /* not allowed case. Therefore, return failed status */ | ||
| 2279 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2280 | ts->stat = SAS_OPEN_TO; | ||
| 2281 | break; | ||
| 2282 | } | ||
| 2283 | spin_lock_irqsave(&t->task_state_lock, flags); | ||
| 2284 | t->task_state_flags &= ~SAS_TASK_STATE_PENDING; | ||
| 2285 | t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | ||
| 2286 | t->task_state_flags |= SAS_TASK_STATE_DONE; | ||
| 2287 | if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { | ||
| 2288 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 2289 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2290 | pm8001_printk("task 0x%p done with io_status 0x%x" | ||
| 2291 | " resp 0x%x stat 0x%x but aborted by upper layer!\n", | ||
| 2292 | t, event, ts->resp, ts->stat)); | ||
| 2293 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2294 | } else if (t->uldd_task) { | ||
| 2295 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 2296 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2297 | mb();/* ditto */ | ||
| 2298 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 2299 | t->task_done(t); | ||
| 2300 | spin_lock_irq(&pm8001_ha->lock); | ||
| 2301 | } else if (!t->uldd_task) { | ||
| 2302 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 2303 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2304 | mb();/*ditto*/ | ||
| 2305 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 2306 | t->task_done(t); | ||
| 2307 | spin_lock_irq(&pm8001_ha->lock); | ||
| 2308 | } | ||
| 2309 | } | ||
| 2310 | |||
| 2311 | /*See the comments for mpi_ssp_completion */ | ||
| 2312 | static void | ||
| 2313 | mpi_smp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 2314 | { | ||
| 2315 | u32 param, i; | ||
| 2316 | struct sas_task *t; | ||
| 2317 | struct pm8001_ccb_info *ccb; | ||
| 2318 | unsigned long flags; | ||
| 2319 | u32 status; | ||
| 2320 | u32 tag; | ||
| 2321 | struct smp_completion_resp *psmpPayload; | ||
| 2322 | struct task_status_struct *ts; | ||
| 2323 | struct pm8001_device *pm8001_dev; | ||
| 2324 | char *pdma_respaddr = NULL; | ||
| 2325 | |||
| 2326 | psmpPayload = (struct smp_completion_resp *)(piomb + 4); | ||
| 2327 | status = le32_to_cpu(psmpPayload->status); | ||
| 2328 | tag = le32_to_cpu(psmpPayload->tag); | ||
| 2329 | |||
| 2330 | ccb = &pm8001_ha->ccb_info[tag]; | ||
| 2331 | param = le32_to_cpu(psmpPayload->param); | ||
| 2332 | t = ccb->task; | ||
| 2333 | ts = &t->task_status; | ||
| 2334 | pm8001_dev = ccb->device; | ||
| 2335 | if (status) | ||
| 2336 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 2337 | pm8001_printk("smp IO status 0x%x\n", status)); | ||
| 2338 | if (unlikely(!t || !t->lldd_task || !t->dev)) | ||
| 2339 | return; | ||
| 2340 | |||
| 2341 | switch (status) { | ||
| 2342 | |||
| 2343 | case IO_SUCCESS: | ||
| 2344 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_SUCCESS\n")); | ||
| 2345 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2346 | ts->stat = SAM_STAT_GOOD; | ||
| 2347 | if (pm8001_dev) | ||
| 2348 | pm8001_dev->running_req--; | ||
| 2349 | if (pm8001_ha->smp_exp_mode == SMP_DIRECT) { | ||
| 2350 | PM8001_IO_DBG(pm8001_ha, | ||
| 2351 | pm8001_printk("DIRECT RESPONSE Length:%d\n", | ||
| 2352 | param)); | ||
| 2353 | pdma_respaddr = (char *)(phys_to_virt(cpu_to_le64 | ||
| 2354 | ((u64)sg_dma_address | ||
| 2355 | (&t->smp_task.smp_resp)))); | ||
| 2356 | for (i = 0; i < param; i++) { | ||
| 2357 | *(pdma_respaddr+i) = psmpPayload->_r_a[i]; | ||
| 2358 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 2359 | "SMP Byte%d DMA data 0x%x psmp 0x%x\n", | ||
| 2360 | i, *(pdma_respaddr+i), | ||
| 2361 | psmpPayload->_r_a[i])); | ||
| 2362 | } | ||
| 2363 | } | ||
| 2364 | break; | ||
| 2365 | case IO_ABORTED: | ||
| 2366 | PM8001_IO_DBG(pm8001_ha, | ||
| 2367 | pm8001_printk("IO_ABORTED IOMB\n")); | ||
| 2368 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2369 | ts->stat = SAS_ABORTED_TASK; | ||
| 2370 | if (pm8001_dev) | ||
| 2371 | pm8001_dev->running_req--; | ||
| 2372 | break; | ||
| 2373 | case IO_OVERFLOW: | ||
| 2374 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_UNDERFLOW\n")); | ||
| 2375 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2376 | ts->stat = SAS_DATA_OVERRUN; | ||
| 2377 | ts->residual = 0; | ||
| 2378 | if (pm8001_dev) | ||
| 2379 | pm8001_dev->running_req--; | ||
| 2380 | break; | ||
| 2381 | case IO_NO_DEVICE: | ||
| 2382 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("IO_NO_DEVICE\n")); | ||
| 2383 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2384 | ts->stat = SAS_PHY_DOWN; | ||
| 2385 | break; | ||
| 2386 | case IO_ERROR_HW_TIMEOUT: | ||
| 2387 | PM8001_IO_DBG(pm8001_ha, | ||
| 2388 | pm8001_printk("IO_ERROR_HW_TIMEOUT\n")); | ||
| 2389 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2390 | ts->stat = SAM_STAT_BUSY; | ||
| 2391 | break; | ||
| 2392 | case IO_XFER_ERROR_BREAK: | ||
| 2393 | PM8001_IO_DBG(pm8001_ha, | ||
| 2394 | pm8001_printk("IO_XFER_ERROR_BREAK\n")); | ||
| 2395 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2396 | ts->stat = SAM_STAT_BUSY; | ||
| 2397 | break; | ||
| 2398 | case IO_XFER_ERROR_PHY_NOT_READY: | ||
| 2399 | PM8001_IO_DBG(pm8001_ha, | ||
| 2400 | pm8001_printk("IO_XFER_ERROR_PHY_NOT_READY\n")); | ||
| 2401 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2402 | ts->stat = SAM_STAT_BUSY; | ||
| 2403 | break; | ||
| 2404 | case IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: | ||
| 2405 | PM8001_IO_DBG(pm8001_ha, | ||
| 2406 | pm8001_printk("IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED\n")); | ||
| 2407 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2408 | ts->stat = SAS_OPEN_REJECT; | ||
| 2409 | ts->open_rej_reason = SAS_OREJ_UNKNOWN; | ||
| 2410 | break; | ||
| 2411 | case IO_OPEN_CNX_ERROR_ZONE_VIOLATION: | ||
| 2412 | PM8001_IO_DBG(pm8001_ha, | ||
| 2413 | pm8001_printk("IO_OPEN_CNX_ERROR_ZONE_VIOLATION\n")); | ||
| 2414 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2415 | ts->stat = SAS_OPEN_REJECT; | ||
| 2416 | ts->open_rej_reason = SAS_OREJ_UNKNOWN; | ||
| 2417 | break; | ||
| 2418 | case IO_OPEN_CNX_ERROR_BREAK: | ||
| 2419 | PM8001_IO_DBG(pm8001_ha, | ||
| 2420 | pm8001_printk("IO_OPEN_CNX_ERROR_BREAK\n")); | ||
| 2421 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2422 | ts->stat = SAS_OPEN_REJECT; | ||
| 2423 | ts->open_rej_reason = SAS_OREJ_RSVD_CONT0; | ||
| 2424 | break; | ||
| 2425 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: | ||
| 2426 | case IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED: | ||
| 2427 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO: | ||
| 2428 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST: | ||
| 2429 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE: | ||
| 2430 | case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED: | ||
| 2431 | PM8001_IO_DBG(pm8001_ha, | ||
| 2432 | pm8001_printk("IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS\n")); | ||
| 2433 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2434 | ts->stat = SAS_OPEN_REJECT; | ||
| 2435 | ts->open_rej_reason = SAS_OREJ_UNKNOWN; | ||
| 2436 | pm8001_handle_event(pm8001_ha, | ||
| 2437 | pm8001_dev, | ||
| 2438 | IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); | ||
| 2439 | break; | ||
| 2440 | case IO_OPEN_CNX_ERROR_BAD_DESTINATION: | ||
| 2441 | PM8001_IO_DBG(pm8001_ha, | ||
| 2442 | pm8001_printk("IO_OPEN_CNX_ERROR_BAD_DESTINATION\n")); | ||
| 2443 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2444 | ts->stat = SAS_OPEN_REJECT; | ||
| 2445 | ts->open_rej_reason = SAS_OREJ_BAD_DEST; | ||
| 2446 | break; | ||
| 2447 | case IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: | ||
| 2448 | PM8001_IO_DBG(pm8001_ha, pm8001_printk(\ | ||
| 2449 | "IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED\n")); | ||
| 2450 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2451 | ts->stat = SAS_OPEN_REJECT; | ||
| 2452 | ts->open_rej_reason = SAS_OREJ_CONN_RATE; | ||
| 2453 | break; | ||
| 2454 | case IO_OPEN_CNX_ERROR_WRONG_DESTINATION: | ||
| 2455 | PM8001_IO_DBG(pm8001_ha, | ||
| 2456 | pm8001_printk("IO_OPEN_CNX_ERROR_WRONG_DESTINATION\n")); | ||
| 2457 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2458 | ts->stat = SAS_OPEN_REJECT; | ||
| 2459 | ts->open_rej_reason = SAS_OREJ_WRONG_DEST; | ||
| 2460 | break; | ||
| 2461 | case IO_XFER_ERROR_RX_FRAME: | ||
| 2462 | PM8001_IO_DBG(pm8001_ha, | ||
| 2463 | pm8001_printk("IO_XFER_ERROR_RX_FRAME\n")); | ||
| 2464 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2465 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 2466 | break; | ||
| 2467 | case IO_XFER_OPEN_RETRY_TIMEOUT: | ||
| 2468 | PM8001_IO_DBG(pm8001_ha, | ||
| 2469 | pm8001_printk("IO_XFER_OPEN_RETRY_TIMEOUT\n")); | ||
| 2470 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2471 | ts->stat = SAS_OPEN_REJECT; | ||
| 2472 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 2473 | break; | ||
| 2474 | case IO_ERROR_INTERNAL_SMP_RESOURCE: | ||
| 2475 | PM8001_IO_DBG(pm8001_ha, | ||
| 2476 | pm8001_printk("IO_ERROR_INTERNAL_SMP_RESOURCE\n")); | ||
| 2477 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2478 | ts->stat = SAS_QUEUE_FULL; | ||
| 2479 | break; | ||
| 2480 | case IO_PORT_IN_RESET: | ||
| 2481 | PM8001_IO_DBG(pm8001_ha, | ||
| 2482 | pm8001_printk("IO_PORT_IN_RESET\n")); | ||
| 2483 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2484 | ts->stat = SAS_OPEN_REJECT; | ||
| 2485 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 2486 | break; | ||
| 2487 | case IO_DS_NON_OPERATIONAL: | ||
| 2488 | PM8001_IO_DBG(pm8001_ha, | ||
| 2489 | pm8001_printk("IO_DS_NON_OPERATIONAL\n")); | ||
| 2490 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2491 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 2492 | break; | ||
| 2493 | case IO_DS_IN_RECOVERY: | ||
| 2494 | PM8001_IO_DBG(pm8001_ha, | ||
| 2495 | pm8001_printk("IO_DS_IN_RECOVERY\n")); | ||
| 2496 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2497 | ts->stat = SAS_OPEN_REJECT; | ||
| 2498 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 2499 | break; | ||
| 2500 | case IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY: | ||
| 2501 | PM8001_IO_DBG(pm8001_ha, | ||
| 2502 | pm8001_printk("IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY\n")); | ||
| 2503 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2504 | ts->stat = SAS_OPEN_REJECT; | ||
| 2505 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | ||
| 2506 | break; | ||
| 2507 | default: | ||
| 2508 | PM8001_IO_DBG(pm8001_ha, | ||
| 2509 | pm8001_printk("Unknown status 0x%x\n", status)); | ||
| 2510 | ts->resp = SAS_TASK_COMPLETE; | ||
| 2511 | ts->stat = SAS_DEV_NO_RESPONSE; | ||
| 2512 | /* not allowed case. Therefore, return failed status */ | ||
| 2513 | break; | ||
| 2514 | } | ||
| 2515 | spin_lock_irqsave(&t->task_state_lock, flags); | ||
| 2516 | t->task_state_flags &= ~SAS_TASK_STATE_PENDING; | ||
| 2517 | t->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | ||
| 2518 | t->task_state_flags |= SAS_TASK_STATE_DONE; | ||
| 2519 | if (unlikely((t->task_state_flags & SAS_TASK_STATE_ABORTED))) { | ||
| 2520 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 2521 | PM8001_FAIL_DBG(pm8001_ha, pm8001_printk( | ||
| 2522 | "task 0x%p done with io_status 0x%x resp 0x%x" | ||
| 2523 | "stat 0x%x but aborted by upper layer!\n", | ||
| 2524 | t, status, ts->resp, ts->stat)); | ||
| 2525 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2526 | } else { | ||
| 2527 | spin_unlock_irqrestore(&t->task_state_lock, flags); | ||
| 2528 | pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); | ||
| 2529 | mb();/* in order to force CPU ordering */ | ||
| 2530 | t->task_done(t); | ||
| 2531 | } | ||
| 2532 | } | ||
| 2533 | |||
| 2534 | /** | ||
| 2535 | * pm80xx_hw_event_ack_req- For PM8001,some events need to acknowage to FW. | ||
| 2536 | * @pm8001_ha: our hba card information | ||
| 2537 | * @Qnum: the outbound queue message number. | ||
| 2538 | * @SEA: source of event to ack | ||
| 2539 | * @port_id: port id. | ||
| 2540 | * @phyId: phy id. | ||
| 2541 | * @param0: parameter 0. | ||
| 2542 | * @param1: parameter 1. | ||
| 2543 | */ | ||
| 2544 | static void pm80xx_hw_event_ack_req(struct pm8001_hba_info *pm8001_ha, | ||
| 2545 | u32 Qnum, u32 SEA, u32 port_id, u32 phyId, u32 param0, u32 param1) | ||
| 2546 | { | ||
| 2547 | struct hw_event_ack_req payload; | ||
| 2548 | u32 opc = OPC_INB_SAS_HW_EVENT_ACK; | ||
| 2549 | |||
| 2550 | struct inbound_queue_table *circularQ; | ||
| 2551 | |||
| 2552 | memset((u8 *)&payload, 0, sizeof(payload)); | ||
| 2553 | circularQ = &pm8001_ha->inbnd_q_tbl[Qnum]; | ||
| 2554 | payload.tag = cpu_to_le32(1); | ||
| 2555 | payload.phyid_sea_portid = cpu_to_le32(((SEA & 0xFFFF) << 8) | | ||
| 2556 | ((phyId & 0xFF) << 24) | (port_id & 0xFF)); | ||
| 2557 | payload.param0 = cpu_to_le32(param0); | ||
| 2558 | payload.param1 = cpu_to_le32(param1); | ||
| 2559 | pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
| 2560 | } | ||
| 2561 | |||
| 2562 | static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, | ||
| 2563 | u32 phyId, u32 phy_op); | ||
| 2564 | |||
| 2565 | /** | ||
| 2566 | * hw_event_sas_phy_up -FW tells me a SAS phy up event. | ||
| 2567 | * @pm8001_ha: our hba card information | ||
| 2568 | * @piomb: IO message buffer | ||
| 2569 | */ | ||
| 2570 | static void | ||
| 2571 | hw_event_sas_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 2572 | { | ||
| 2573 | struct hw_event_resp *pPayload = | ||
| 2574 | (struct hw_event_resp *)(piomb + 4); | ||
| 2575 | u32 lr_status_evt_portid = | ||
| 2576 | le32_to_cpu(pPayload->lr_status_evt_portid); | ||
| 2577 | u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate); | ||
| 2578 | |||
| 2579 | u8 link_rate = | ||
| 2580 | (u8)((lr_status_evt_portid & 0xF0000000) >> 28); | ||
| 2581 | u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF); | ||
| 2582 | u8 phy_id = | ||
| 2583 | (u8)((phyid_npip_portstate & 0xFF0000) >> 16); | ||
| 2584 | u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F); | ||
| 2585 | |||
| 2586 | struct pm8001_port *port = &pm8001_ha->port[port_id]; | ||
| 2587 | struct sas_ha_struct *sas_ha = pm8001_ha->sas; | ||
| 2588 | struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; | ||
| 2589 | unsigned long flags; | ||
| 2590 | u8 deviceType = pPayload->sas_identify.dev_type; | ||
| 2591 | port->port_state = portstate; | ||
| 2592 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 2593 | "portid:%d; phyid:%d; linkrate:%d; " | ||
| 2594 | "portstate:%x; devicetype:%x\n", | ||
| 2595 | port_id, phy_id, link_rate, portstate, deviceType)); | ||
| 2596 | |||
| 2597 | switch (deviceType) { | ||
| 2598 | case SAS_PHY_UNUSED: | ||
| 2599 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2600 | pm8001_printk("device type no device.\n")); | ||
| 2601 | break; | ||
| 2602 | case SAS_END_DEVICE: | ||
| 2603 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk("end device.\n")); | ||
| 2604 | pm80xx_chip_phy_ctl_req(pm8001_ha, phy_id, | ||
| 2605 | PHY_NOTIFY_ENABLE_SPINUP); | ||
| 2606 | port->port_attached = 1; | ||
| 2607 | pm8001_get_lrate_mode(phy, link_rate); | ||
| 2608 | break; | ||
| 2609 | case SAS_EDGE_EXPANDER_DEVICE: | ||
| 2610 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2611 | pm8001_printk("expander device.\n")); | ||
| 2612 | port->port_attached = 1; | ||
| 2613 | pm8001_get_lrate_mode(phy, link_rate); | ||
| 2614 | break; | ||
| 2615 | case SAS_FANOUT_EXPANDER_DEVICE: | ||
| 2616 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2617 | pm8001_printk("fanout expander device.\n")); | ||
| 2618 | port->port_attached = 1; | ||
| 2619 | pm8001_get_lrate_mode(phy, link_rate); | ||
| 2620 | break; | ||
| 2621 | default: | ||
| 2622 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2623 | pm8001_printk("unknown device type(%x)\n", deviceType)); | ||
| 2624 | break; | ||
| 2625 | } | ||
| 2626 | phy->phy_type |= PORT_TYPE_SAS; | ||
| 2627 | phy->identify.device_type = deviceType; | ||
| 2628 | phy->phy_attached = 1; | ||
| 2629 | if (phy->identify.device_type == SAS_END_DEVICE) | ||
| 2630 | phy->identify.target_port_protocols = SAS_PROTOCOL_SSP; | ||
| 2631 | else if (phy->identify.device_type != SAS_PHY_UNUSED) | ||
| 2632 | phy->identify.target_port_protocols = SAS_PROTOCOL_SMP; | ||
| 2633 | phy->sas_phy.oob_mode = SAS_OOB_MODE; | ||
| 2634 | sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); | ||
| 2635 | spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); | ||
| 2636 | memcpy(phy->frame_rcvd, &pPayload->sas_identify, | ||
| 2637 | sizeof(struct sas_identify_frame)-4); | ||
| 2638 | phy->frame_rcvd_size = sizeof(struct sas_identify_frame) - 4; | ||
| 2639 | pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr); | ||
| 2640 | spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); | ||
| 2641 | if (pm8001_ha->flags == PM8001F_RUN_TIME) | ||
| 2642 | mdelay(200);/*delay a moment to wait disk to spinup*/ | ||
| 2643 | pm8001_bytes_dmaed(pm8001_ha, phy_id); | ||
| 2644 | } | ||
| 2645 | |||
| 2646 | /** | ||
| 2647 | * hw_event_sata_phy_up -FW tells me a SATA phy up event. | ||
| 2648 | * @pm8001_ha: our hba card information | ||
| 2649 | * @piomb: IO message buffer | ||
| 2650 | */ | ||
| 2651 | static void | ||
| 2652 | hw_event_sata_phy_up(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 2653 | { | ||
| 2654 | struct hw_event_resp *pPayload = | ||
| 2655 | (struct hw_event_resp *)(piomb + 4); | ||
| 2656 | u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate); | ||
| 2657 | u32 lr_status_evt_portid = | ||
| 2658 | le32_to_cpu(pPayload->lr_status_evt_portid); | ||
| 2659 | u8 link_rate = | ||
| 2660 | (u8)((lr_status_evt_portid & 0xF0000000) >> 28); | ||
| 2661 | u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF); | ||
| 2662 | u8 phy_id = | ||
| 2663 | (u8)((phyid_npip_portstate & 0xFF0000) >> 16); | ||
| 2664 | |||
| 2665 | u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F); | ||
| 2666 | |||
| 2667 | struct pm8001_port *port = &pm8001_ha->port[port_id]; | ||
| 2668 | struct sas_ha_struct *sas_ha = pm8001_ha->sas; | ||
| 2669 | struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; | ||
| 2670 | unsigned long flags; | ||
| 2671 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 2672 | "port id %d, phy id %d link_rate %d portstate 0x%x\n", | ||
| 2673 | port_id, phy_id, link_rate, portstate)); | ||
| 2674 | |||
| 2675 | port->port_state = portstate; | ||
| 2676 | port->port_attached = 1; | ||
| 2677 | pm8001_get_lrate_mode(phy, link_rate); | ||
| 2678 | phy->phy_type |= PORT_TYPE_SATA; | ||
| 2679 | phy->phy_attached = 1; | ||
| 2680 | phy->sas_phy.oob_mode = SATA_OOB_MODE; | ||
| 2681 | sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_DONE); | ||
| 2682 | spin_lock_irqsave(&phy->sas_phy.frame_rcvd_lock, flags); | ||
| 2683 | memcpy(phy->frame_rcvd, ((u8 *)&pPayload->sata_fis - 4), | ||
| 2684 | sizeof(struct dev_to_host_fis)); | ||
| 2685 | phy->frame_rcvd_size = sizeof(struct dev_to_host_fis); | ||
| 2686 | phy->identify.target_port_protocols = SAS_PROTOCOL_SATA; | ||
| 2687 | phy->identify.device_type = SAS_SATA_DEV; | ||
| 2688 | pm8001_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr); | ||
| 2689 | spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); | ||
| 2690 | pm8001_bytes_dmaed(pm8001_ha, phy_id); | ||
| 2691 | } | ||
| 2692 | |||
| 2693 | /** | ||
| 2694 | * hw_event_phy_down -we should notify the libsas the phy is down. | ||
| 2695 | * @pm8001_ha: our hba card information | ||
| 2696 | * @piomb: IO message buffer | ||
| 2697 | */ | ||
| 2698 | static void | ||
| 2699 | hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 2700 | { | ||
| 2701 | struct hw_event_resp *pPayload = | ||
| 2702 | (struct hw_event_resp *)(piomb + 4); | ||
| 2703 | |||
| 2704 | u32 lr_status_evt_portid = | ||
| 2705 | le32_to_cpu(pPayload->lr_status_evt_portid); | ||
| 2706 | u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF); | ||
| 2707 | u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate); | ||
| 2708 | u8 phy_id = | ||
| 2709 | (u8)((phyid_npip_portstate & 0xFF0000) >> 16); | ||
| 2710 | u8 portstate = (u8)(phyid_npip_portstate & 0x0000000F); | ||
| 2711 | |||
| 2712 | struct pm8001_port *port = &pm8001_ha->port[port_id]; | ||
| 2713 | struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; | ||
| 2714 | port->port_state = portstate; | ||
| 2715 | phy->phy_type = 0; | ||
| 2716 | phy->identify.device_type = 0; | ||
| 2717 | phy->phy_attached = 0; | ||
| 2718 | memset(&phy->dev_sas_addr, 0, SAS_ADDR_SIZE); | ||
| 2719 | switch (portstate) { | ||
| 2720 | case PORT_VALID: | ||
| 2721 | break; | ||
| 2722 | case PORT_INVALID: | ||
| 2723 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2724 | pm8001_printk(" PortInvalid portID %d\n", port_id)); | ||
| 2725 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2726 | pm8001_printk(" Last phy Down and port invalid\n")); | ||
| 2727 | port->port_attached = 0; | ||
| 2728 | pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, | ||
| 2729 | port_id, phy_id, 0, 0); | ||
| 2730 | break; | ||
| 2731 | case PORT_IN_RESET: | ||
| 2732 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2733 | pm8001_printk(" Port In Reset portID %d\n", port_id)); | ||
| 2734 | break; | ||
| 2735 | case PORT_NOT_ESTABLISHED: | ||
| 2736 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2737 | pm8001_printk(" phy Down and PORT_NOT_ESTABLISHED\n")); | ||
| 2738 | port->port_attached = 0; | ||
| 2739 | break; | ||
| 2740 | case PORT_LOSTCOMM: | ||
| 2741 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2742 | pm8001_printk(" phy Down and PORT_LOSTCOMM\n")); | ||
| 2743 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2744 | pm8001_printk(" Last phy Down and port invalid\n")); | ||
| 2745 | port->port_attached = 0; | ||
| 2746 | pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_PHY_DOWN, | ||
| 2747 | port_id, phy_id, 0, 0); | ||
| 2748 | break; | ||
| 2749 | default: | ||
| 2750 | port->port_attached = 0; | ||
| 2751 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2752 | pm8001_printk(" phy Down and(default) = 0x%x\n", | ||
| 2753 | portstate)); | ||
| 2754 | break; | ||
| 2755 | |||
| 2756 | } | ||
| 2757 | } | ||
| 2758 | |||
| 2759 | static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 2760 | { | ||
| 2761 | struct phy_start_resp *pPayload = | ||
| 2762 | (struct phy_start_resp *)(piomb + 4); | ||
| 2763 | u32 status = | ||
| 2764 | le32_to_cpu(pPayload->status); | ||
| 2765 | u32 phy_id = | ||
| 2766 | le32_to_cpu(pPayload->phyid); | ||
| 2767 | struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; | ||
| 2768 | |||
| 2769 | PM8001_INIT_DBG(pm8001_ha, | ||
| 2770 | pm8001_printk("phy start resp status:0x%x, phyid:0x%x\n", | ||
| 2771 | status, phy_id)); | ||
| 2772 | if (status == 0) { | ||
| 2773 | phy->phy_state = 1; | ||
| 2774 | if (pm8001_ha->flags == PM8001F_RUN_TIME) | ||
| 2775 | complete(phy->enable_completion); | ||
| 2776 | } | ||
| 2777 | return 0; | ||
| 2778 | |||
| 2779 | } | ||
| 2780 | |||
| 2781 | /** | ||
| 2782 | * mpi_thermal_hw_event -The hw event has come. | ||
| 2783 | * @pm8001_ha: our hba card information | ||
| 2784 | * @piomb: IO message buffer | ||
| 2785 | */ | ||
| 2786 | static int mpi_thermal_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 2787 | { | ||
| 2788 | struct thermal_hw_event *pPayload = | ||
| 2789 | (struct thermal_hw_event *)(piomb + 4); | ||
| 2790 | |||
| 2791 | u32 thermal_event = le32_to_cpu(pPayload->thermal_event); | ||
| 2792 | u32 rht_lht = le32_to_cpu(pPayload->rht_lht); | ||
| 2793 | |||
| 2794 | if (thermal_event & 0x40) { | ||
| 2795 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 2796 | "Thermal Event: Local high temperature violated!\n")); | ||
| 2797 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 2798 | "Thermal Event: Measured local high temperature %d\n", | ||
| 2799 | ((rht_lht & 0xFF00) >> 8))); | ||
| 2800 | } | ||
| 2801 | if (thermal_event & 0x10) { | ||
| 2802 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 2803 | "Thermal Event: Remote high temperature violated!\n")); | ||
| 2804 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 2805 | "Thermal Event: Measured remote high temperature %d\n", | ||
| 2806 | ((rht_lht & 0xFF000000) >> 24))); | ||
| 2807 | } | ||
| 2808 | return 0; | ||
| 2809 | } | ||
| 2810 | |||
| 2811 | /** | ||
| 2812 | * mpi_hw_event -The hw event has come. | ||
| 2813 | * @pm8001_ha: our hba card information | ||
| 2814 | * @piomb: IO message buffer | ||
| 2815 | */ | ||
| 2816 | static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 2817 | { | ||
| 2818 | unsigned long flags; | ||
| 2819 | struct hw_event_resp *pPayload = | ||
| 2820 | (struct hw_event_resp *)(piomb + 4); | ||
| 2821 | u32 lr_status_evt_portid = | ||
| 2822 | le32_to_cpu(pPayload->lr_status_evt_portid); | ||
| 2823 | u32 phyid_npip_portstate = le32_to_cpu(pPayload->phyid_npip_portstate); | ||
| 2824 | u8 port_id = (u8)(lr_status_evt_portid & 0x000000FF); | ||
| 2825 | u8 phy_id = | ||
| 2826 | (u8)((phyid_npip_portstate & 0xFF0000) >> 16); | ||
| 2827 | u16 eventType = | ||
| 2828 | (u16)((lr_status_evt_portid & 0x00FFFF00) >> 8); | ||
| 2829 | u8 status = | ||
| 2830 | (u8)((lr_status_evt_portid & 0x0F000000) >> 24); | ||
| 2831 | |||
| 2832 | struct sas_ha_struct *sas_ha = pm8001_ha->sas; | ||
| 2833 | struct pm8001_phy *phy = &pm8001_ha->phy[phy_id]; | ||
| 2834 | struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; | ||
| 2835 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2836 | pm8001_printk("portid:%d phyid:%d event:0x%x status:0x%x\n", | ||
| 2837 | port_id, phy_id, eventType, status)); | ||
| 2838 | |||
| 2839 | switch (eventType) { | ||
| 2840 | |||
| 2841 | case HW_EVENT_SAS_PHY_UP: | ||
| 2842 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2843 | pm8001_printk("HW_EVENT_PHY_START_STATUS\n")); | ||
| 2844 | hw_event_sas_phy_up(pm8001_ha, piomb); | ||
| 2845 | break; | ||
| 2846 | case HW_EVENT_SATA_PHY_UP: | ||
| 2847 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2848 | pm8001_printk("HW_EVENT_SATA_PHY_UP\n")); | ||
| 2849 | hw_event_sata_phy_up(pm8001_ha, piomb); | ||
| 2850 | break; | ||
| 2851 | case HW_EVENT_SATA_SPINUP_HOLD: | ||
| 2852 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2853 | pm8001_printk("HW_EVENT_SATA_SPINUP_HOLD\n")); | ||
| 2854 | sas_ha->notify_phy_event(&phy->sas_phy, PHYE_SPINUP_HOLD); | ||
| 2855 | break; | ||
| 2856 | case HW_EVENT_PHY_DOWN: | ||
| 2857 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2858 | pm8001_printk("HW_EVENT_PHY_DOWN\n")); | ||
| 2859 | sas_ha->notify_phy_event(&phy->sas_phy, PHYE_LOSS_OF_SIGNAL); | ||
| 2860 | phy->phy_attached = 0; | ||
| 2861 | phy->phy_state = 0; | ||
| 2862 | hw_event_phy_down(pm8001_ha, piomb); | ||
| 2863 | break; | ||
| 2864 | case HW_EVENT_PORT_INVALID: | ||
| 2865 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2866 | pm8001_printk("HW_EVENT_PORT_INVALID\n")); | ||
| 2867 | sas_phy_disconnected(sas_phy); | ||
| 2868 | phy->phy_attached = 0; | ||
| 2869 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | ||
| 2870 | break; | ||
| 2871 | /* the broadcast change primitive received, tell the LIBSAS this event | ||
| 2872 | to revalidate the sas domain*/ | ||
| 2873 | case HW_EVENT_BROADCAST_CHANGE: | ||
| 2874 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2875 | pm8001_printk("HW_EVENT_BROADCAST_CHANGE\n")); | ||
| 2876 | pm80xx_hw_event_ack_req(pm8001_ha, 0, HW_EVENT_BROADCAST_CHANGE, | ||
| 2877 | port_id, phy_id, 1, 0); | ||
| 2878 | spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); | ||
| 2879 | sas_phy->sas_prim = HW_EVENT_BROADCAST_CHANGE; | ||
| 2880 | spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); | ||
| 2881 | sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); | ||
| 2882 | break; | ||
| 2883 | case HW_EVENT_PHY_ERROR: | ||
| 2884 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2885 | pm8001_printk("HW_EVENT_PHY_ERROR\n")); | ||
| 2886 | sas_phy_disconnected(&phy->sas_phy); | ||
| 2887 | phy->phy_attached = 0; | ||
| 2888 | sas_ha->notify_phy_event(&phy->sas_phy, PHYE_OOB_ERROR); | ||
| 2889 | break; | ||
| 2890 | case HW_EVENT_BROADCAST_EXP: | ||
| 2891 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2892 | pm8001_printk("HW_EVENT_BROADCAST_EXP\n")); | ||
| 2893 | spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); | ||
| 2894 | sas_phy->sas_prim = HW_EVENT_BROADCAST_EXP; | ||
| 2895 | spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); | ||
| 2896 | sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); | ||
| 2897 | break; | ||
| 2898 | case HW_EVENT_LINK_ERR_INVALID_DWORD: | ||
| 2899 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2900 | pm8001_printk("HW_EVENT_LINK_ERR_INVALID_DWORD\n")); | ||
| 2901 | pm80xx_hw_event_ack_req(pm8001_ha, 0, | ||
| 2902 | HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 0); | ||
| 2903 | sas_phy_disconnected(sas_phy); | ||
| 2904 | phy->phy_attached = 0; | ||
| 2905 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | ||
| 2906 | break; | ||
| 2907 | case HW_EVENT_LINK_ERR_DISPARITY_ERROR: | ||
| 2908 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2909 | pm8001_printk("HW_EVENT_LINK_ERR_DISPARITY_ERROR\n")); | ||
| 2910 | pm80xx_hw_event_ack_req(pm8001_ha, 0, | ||
| 2911 | HW_EVENT_LINK_ERR_DISPARITY_ERROR, | ||
| 2912 | port_id, phy_id, 0, 0); | ||
| 2913 | sas_phy_disconnected(sas_phy); | ||
| 2914 | phy->phy_attached = 0; | ||
| 2915 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | ||
| 2916 | break; | ||
| 2917 | case HW_EVENT_LINK_ERR_CODE_VIOLATION: | ||
| 2918 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2919 | pm8001_printk("HW_EVENT_LINK_ERR_CODE_VIOLATION\n")); | ||
| 2920 | pm80xx_hw_event_ack_req(pm8001_ha, 0, | ||
| 2921 | HW_EVENT_LINK_ERR_CODE_VIOLATION, | ||
| 2922 | port_id, phy_id, 0, 0); | ||
| 2923 | sas_phy_disconnected(sas_phy); | ||
| 2924 | phy->phy_attached = 0; | ||
| 2925 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | ||
| 2926 | break; | ||
| 2927 | case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH: | ||
| 2928 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 2929 | "HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH\n")); | ||
| 2930 | pm80xx_hw_event_ack_req(pm8001_ha, 0, | ||
| 2931 | HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH, | ||
| 2932 | port_id, phy_id, 0, 0); | ||
| 2933 | sas_phy_disconnected(sas_phy); | ||
| 2934 | phy->phy_attached = 0; | ||
| 2935 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | ||
| 2936 | break; | ||
| 2937 | case HW_EVENT_MALFUNCTION: | ||
| 2938 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2939 | pm8001_printk("HW_EVENT_MALFUNCTION\n")); | ||
| 2940 | break; | ||
| 2941 | case HW_EVENT_BROADCAST_SES: | ||
| 2942 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2943 | pm8001_printk("HW_EVENT_BROADCAST_SES\n")); | ||
| 2944 | spin_lock_irqsave(&sas_phy->sas_prim_lock, flags); | ||
| 2945 | sas_phy->sas_prim = HW_EVENT_BROADCAST_SES; | ||
| 2946 | spin_unlock_irqrestore(&sas_phy->sas_prim_lock, flags); | ||
| 2947 | sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); | ||
| 2948 | break; | ||
| 2949 | case HW_EVENT_INBOUND_CRC_ERROR: | ||
| 2950 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2951 | pm8001_printk("HW_EVENT_INBOUND_CRC_ERROR\n")); | ||
| 2952 | pm80xx_hw_event_ack_req(pm8001_ha, 0, | ||
| 2953 | HW_EVENT_INBOUND_CRC_ERROR, | ||
| 2954 | port_id, phy_id, 0, 0); | ||
| 2955 | break; | ||
| 2956 | case HW_EVENT_HARD_RESET_RECEIVED: | ||
| 2957 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2958 | pm8001_printk("HW_EVENT_HARD_RESET_RECEIVED\n")); | ||
| 2959 | sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); | ||
| 2960 | break; | ||
| 2961 | case HW_EVENT_ID_FRAME_TIMEOUT: | ||
| 2962 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2963 | pm8001_printk("HW_EVENT_ID_FRAME_TIMEOUT\n")); | ||
| 2964 | sas_phy_disconnected(sas_phy); | ||
| 2965 | phy->phy_attached = 0; | ||
| 2966 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | ||
| 2967 | break; | ||
| 2968 | case HW_EVENT_LINK_ERR_PHY_RESET_FAILED: | ||
| 2969 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2970 | pm8001_printk("HW_EVENT_LINK_ERR_PHY_RESET_FAILED\n")); | ||
| 2971 | pm80xx_hw_event_ack_req(pm8001_ha, 0, | ||
| 2972 | HW_EVENT_LINK_ERR_PHY_RESET_FAILED, | ||
| 2973 | port_id, phy_id, 0, 0); | ||
| 2974 | sas_phy_disconnected(sas_phy); | ||
| 2975 | phy->phy_attached = 0; | ||
| 2976 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | ||
| 2977 | break; | ||
| 2978 | case HW_EVENT_PORT_RESET_TIMER_TMO: | ||
| 2979 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2980 | pm8001_printk("HW_EVENT_PORT_RESET_TIMER_TMO\n")); | ||
| 2981 | sas_phy_disconnected(sas_phy); | ||
| 2982 | phy->phy_attached = 0; | ||
| 2983 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | ||
| 2984 | break; | ||
| 2985 | case HW_EVENT_PORT_RECOVERY_TIMER_TMO: | ||
| 2986 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2987 | pm8001_printk("HW_EVENT_PORT_RECOVERY_TIMER_TMO\n")); | ||
| 2988 | pm80xx_hw_event_ack_req(pm8001_ha, 0, | ||
| 2989 | HW_EVENT_PORT_RECOVERY_TIMER_TMO, | ||
| 2990 | port_id, phy_id, 0, 0); | ||
| 2991 | sas_phy_disconnected(sas_phy); | ||
| 2992 | phy->phy_attached = 0; | ||
| 2993 | sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); | ||
| 2994 | break; | ||
| 2995 | case HW_EVENT_PORT_RECOVER: | ||
| 2996 | PM8001_MSG_DBG(pm8001_ha, | ||
| 2997 | pm8001_printk("HW_EVENT_PORT_RECOVER\n")); | ||
| 2998 | break; | ||
| 2999 | case HW_EVENT_PORT_RESET_COMPLETE: | ||
| 3000 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3001 | pm8001_printk("HW_EVENT_PORT_RESET_COMPLETE\n")); | ||
| 3002 | break; | ||
| 3003 | case EVENT_BROADCAST_ASYNCH_EVENT: | ||
| 3004 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3005 | pm8001_printk("EVENT_BROADCAST_ASYNCH_EVENT\n")); | ||
| 3006 | break; | ||
| 3007 | default: | ||
| 3008 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3009 | pm8001_printk("Unknown event type 0x%x\n", eventType)); | ||
| 3010 | break; | ||
| 3011 | } | ||
| 3012 | return 0; | ||
| 3013 | } | ||
| 3014 | |||
| 3015 | /** | ||
| 3016 | * mpi_phy_stop_resp - SPCv specific | ||
| 3017 | * @pm8001_ha: our hba card information | ||
| 3018 | * @piomb: IO message buffer | ||
| 3019 | */ | ||
| 3020 | static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 3021 | { | ||
| 3022 | struct phy_stop_resp *pPayload = | ||
| 3023 | (struct phy_stop_resp *)(piomb + 4); | ||
| 3024 | u32 status = | ||
| 3025 | le32_to_cpu(pPayload->status); | ||
| 3026 | u32 phyid = | ||
| 3027 | le32_to_cpu(pPayload->phyid); | ||
| 3028 | struct pm8001_phy *phy = &pm8001_ha->phy[phyid]; | ||
| 3029 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3030 | pm8001_printk("phy:0x%x status:0x%x\n", | ||
| 3031 | phyid, status)); | ||
| 3032 | if (status == 0) | ||
| 3033 | phy->phy_state = 0; | ||
| 3034 | return 0; | ||
| 3035 | } | ||
| 3036 | |||
| 3037 | /** | ||
| 3038 | * mpi_set_controller_config_resp - SPCv specific | ||
| 3039 | * @pm8001_ha: our hba card information | ||
| 3040 | * @piomb: IO message buffer | ||
| 3041 | */ | ||
| 3042 | static int mpi_set_controller_config_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 3043 | void *piomb) | ||
| 3044 | { | ||
| 3045 | struct set_ctrl_cfg_resp *pPayload = | ||
| 3046 | (struct set_ctrl_cfg_resp *)(piomb + 4); | ||
| 3047 | u32 status = le32_to_cpu(pPayload->status); | ||
| 3048 | u32 err_qlfr_pgcd = le32_to_cpu(pPayload->err_qlfr_pgcd); | ||
| 3049 | |||
| 3050 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3051 | "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n", | ||
| 3052 | status, err_qlfr_pgcd)); | ||
| 3053 | |||
| 3054 | return 0; | ||
| 3055 | } | ||
| 3056 | |||
| 3057 | /** | ||
| 3058 | * mpi_get_controller_config_resp - SPCv specific | ||
| 3059 | * @pm8001_ha: our hba card information | ||
| 3060 | * @piomb: IO message buffer | ||
| 3061 | */ | ||
| 3062 | static int mpi_get_controller_config_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 3063 | void *piomb) | ||
| 3064 | { | ||
| 3065 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3066 | pm8001_printk(" pm80xx_addition_functionality\n")); | ||
| 3067 | |||
| 3068 | return 0; | ||
| 3069 | } | ||
| 3070 | |||
| 3071 | /** | ||
| 3072 | * mpi_get_phy_profile_resp - SPCv specific | ||
| 3073 | * @pm8001_ha: our hba card information | ||
| 3074 | * @piomb: IO message buffer | ||
| 3075 | */ | ||
| 3076 | static int mpi_get_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 3077 | void *piomb) | ||
| 3078 | { | ||
| 3079 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3080 | pm8001_printk(" pm80xx_addition_functionality\n")); | ||
| 3081 | |||
| 3082 | return 0; | ||
| 3083 | } | ||
| 3084 | |||
| 3085 | /** | ||
| 3086 | * mpi_flash_op_ext_resp - SPCv specific | ||
| 3087 | * @pm8001_ha: our hba card information | ||
| 3088 | * @piomb: IO message buffer | ||
| 3089 | */ | ||
| 3090 | static int mpi_flash_op_ext_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 3091 | { | ||
| 3092 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3093 | pm8001_printk(" pm80xx_addition_functionality\n")); | ||
| 3094 | |||
| 3095 | return 0; | ||
| 3096 | } | ||
| 3097 | |||
| 3098 | /** | ||
| 3099 | * mpi_set_phy_profile_resp - SPCv specific | ||
| 3100 | * @pm8001_ha: our hba card information | ||
| 3101 | * @piomb: IO message buffer | ||
| 3102 | */ | ||
| 3103 | static int mpi_set_phy_profile_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 3104 | void *piomb) | ||
| 3105 | { | ||
| 3106 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3107 | pm8001_printk(" pm80xx_addition_functionality\n")); | ||
| 3108 | |||
| 3109 | return 0; | ||
| 3110 | } | ||
| 3111 | |||
| 3112 | /** | ||
| 3113 | * mpi_kek_management_resp - SPCv specific | ||
| 3114 | * @pm8001_ha: our hba card information | ||
| 3115 | * @piomb: IO message buffer | ||
| 3116 | */ | ||
| 3117 | static int mpi_kek_management_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 3118 | void *piomb) | ||
| 3119 | { | ||
| 3120 | struct kek_mgmt_resp *pPayload = (struct kek_mgmt_resp *)(piomb + 4); | ||
| 3121 | |||
| 3122 | u32 status = le32_to_cpu(pPayload->status); | ||
| 3123 | u32 kidx_new_curr_ksop = le32_to_cpu(pPayload->kidx_new_curr_ksop); | ||
| 3124 | u32 err_qlfr = le32_to_cpu(pPayload->err_qlfr); | ||
| 3125 | |||
| 3126 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3127 | "KEK MGMT RESP. Status 0x%x idx_ksop 0x%x err_qlfr 0x%x\n", | ||
| 3128 | status, kidx_new_curr_ksop, err_qlfr)); | ||
| 3129 | |||
| 3130 | return 0; | ||
| 3131 | } | ||
| 3132 | |||
| 3133 | /** | ||
| 3134 | * mpi_dek_management_resp - SPCv specific | ||
| 3135 | * @pm8001_ha: our hba card information | ||
| 3136 | * @piomb: IO message buffer | ||
| 3137 | */ | ||
| 3138 | static int mpi_dek_management_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 3139 | void *piomb) | ||
| 3140 | { | ||
| 3141 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3142 | pm8001_printk(" pm80xx_addition_functionality\n")); | ||
| 3143 | |||
| 3144 | return 0; | ||
| 3145 | } | ||
| 3146 | |||
| 3147 | /** | ||
| 3148 | * ssp_coalesced_comp_resp - SPCv specific | ||
| 3149 | * @pm8001_ha: our hba card information | ||
| 3150 | * @piomb: IO message buffer | ||
| 3151 | */ | ||
| 3152 | static int ssp_coalesced_comp_resp(struct pm8001_hba_info *pm8001_ha, | ||
| 3153 | void *piomb) | ||
| 3154 | { | ||
| 3155 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3156 | pm8001_printk(" pm80xx_addition_functionality\n")); | ||
| 3157 | |||
| 3158 | return 0; | ||
| 3159 | } | ||
| 3160 | |||
| 3161 | /** | ||
| 3162 | * process_one_iomb - process one outbound Queue memory block | ||
| 3163 | * @pm8001_ha: our hba card information | ||
| 3164 | * @piomb: IO message buffer | ||
| 3165 | */ | ||
| 3166 | static void process_one_iomb(struct pm8001_hba_info *pm8001_ha, void *piomb) | ||
| 3167 | { | ||
| 3168 | __le32 pHeader = *(__le32 *)piomb; | ||
| 3169 | u32 opc = (u32)((le32_to_cpu(pHeader)) & 0xFFF); | ||
| 3170 | |||
| 3171 | switch (opc) { | ||
| 3172 | case OPC_OUB_ECHO: | ||
| 3173 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk("OPC_OUB_ECHO\n")); | ||
| 3174 | break; | ||
| 3175 | case OPC_OUB_HW_EVENT: | ||
| 3176 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3177 | pm8001_printk("OPC_OUB_HW_EVENT\n")); | ||
| 3178 | mpi_hw_event(pm8001_ha, piomb); | ||
| 3179 | break; | ||
| 3180 | case OPC_OUB_THERM_HW_EVENT: | ||
| 3181 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3182 | pm8001_printk("OPC_OUB_THERMAL_EVENT\n")); | ||
| 3183 | mpi_thermal_hw_event(pm8001_ha, piomb); | ||
| 3184 | break; | ||
| 3185 | case OPC_OUB_SSP_COMP: | ||
| 3186 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3187 | pm8001_printk("OPC_OUB_SSP_COMP\n")); | ||
| 3188 | mpi_ssp_completion(pm8001_ha, piomb); | ||
| 3189 | break; | ||
| 3190 | case OPC_OUB_SMP_COMP: | ||
| 3191 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3192 | pm8001_printk("OPC_OUB_SMP_COMP\n")); | ||
| 3193 | mpi_smp_completion(pm8001_ha, piomb); | ||
| 3194 | break; | ||
| 3195 | case OPC_OUB_LOCAL_PHY_CNTRL: | ||
| 3196 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3197 | pm8001_printk("OPC_OUB_LOCAL_PHY_CNTRL\n")); | ||
| 3198 | pm8001_mpi_local_phy_ctl(pm8001_ha, piomb); | ||
| 3199 | break; | ||
| 3200 | case OPC_OUB_DEV_REGIST: | ||
| 3201 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3202 | pm8001_printk("OPC_OUB_DEV_REGIST\n")); | ||
| 3203 | pm8001_mpi_reg_resp(pm8001_ha, piomb); | ||
| 3204 | break; | ||
| 3205 | case OPC_OUB_DEREG_DEV: | ||
| 3206 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3207 | pm8001_printk("unresgister the deviece\n")); | ||
| 3208 | pm8001_mpi_dereg_resp(pm8001_ha, piomb); | ||
| 3209 | break; | ||
| 3210 | case OPC_OUB_GET_DEV_HANDLE: | ||
| 3211 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3212 | pm8001_printk("OPC_OUB_GET_DEV_HANDLE\n")); | ||
| 3213 | break; | ||
| 3214 | case OPC_OUB_SATA_COMP: | ||
| 3215 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3216 | pm8001_printk("OPC_OUB_SATA_COMP\n")); | ||
| 3217 | mpi_sata_completion(pm8001_ha, piomb); | ||
| 3218 | break; | ||
| 3219 | case OPC_OUB_SATA_EVENT: | ||
| 3220 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3221 | pm8001_printk("OPC_OUB_SATA_EVENT\n")); | ||
| 3222 | mpi_sata_event(pm8001_ha, piomb); | ||
| 3223 | break; | ||
| 3224 | case OPC_OUB_SSP_EVENT: | ||
| 3225 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3226 | pm8001_printk("OPC_OUB_SSP_EVENT\n")); | ||
| 3227 | mpi_ssp_event(pm8001_ha, piomb); | ||
| 3228 | break; | ||
| 3229 | case OPC_OUB_DEV_HANDLE_ARRIV: | ||
| 3230 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3231 | pm8001_printk("OPC_OUB_DEV_HANDLE_ARRIV\n")); | ||
| 3232 | /*This is for target*/ | ||
| 3233 | break; | ||
| 3234 | case OPC_OUB_SSP_RECV_EVENT: | ||
| 3235 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3236 | pm8001_printk("OPC_OUB_SSP_RECV_EVENT\n")); | ||
| 3237 | /*This is for target*/ | ||
| 3238 | break; | ||
| 3239 | case OPC_OUB_FW_FLASH_UPDATE: | ||
| 3240 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3241 | pm8001_printk("OPC_OUB_FW_FLASH_UPDATE\n")); | ||
| 3242 | pm8001_mpi_fw_flash_update_resp(pm8001_ha, piomb); | ||
| 3243 | break; | ||
| 3244 | case OPC_OUB_GPIO_RESPONSE: | ||
| 3245 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3246 | pm8001_printk("OPC_OUB_GPIO_RESPONSE\n")); | ||
| 3247 | break; | ||
| 3248 | case OPC_OUB_GPIO_EVENT: | ||
| 3249 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3250 | pm8001_printk("OPC_OUB_GPIO_EVENT\n")); | ||
| 3251 | break; | ||
| 3252 | case OPC_OUB_GENERAL_EVENT: | ||
| 3253 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3254 | pm8001_printk("OPC_OUB_GENERAL_EVENT\n")); | ||
| 3255 | pm8001_mpi_general_event(pm8001_ha, piomb); | ||
| 3256 | break; | ||
| 3257 | case OPC_OUB_SSP_ABORT_RSP: | ||
| 3258 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3259 | pm8001_printk("OPC_OUB_SSP_ABORT_RSP\n")); | ||
| 3260 | pm8001_mpi_task_abort_resp(pm8001_ha, piomb); | ||
| 3261 | break; | ||
| 3262 | case OPC_OUB_SATA_ABORT_RSP: | ||
| 3263 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3264 | pm8001_printk("OPC_OUB_SATA_ABORT_RSP\n")); | ||
| 3265 | pm8001_mpi_task_abort_resp(pm8001_ha, piomb); | ||
| 3266 | break; | ||
| 3267 | case OPC_OUB_SAS_DIAG_MODE_START_END: | ||
| 3268 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3269 | pm8001_printk("OPC_OUB_SAS_DIAG_MODE_START_END\n")); | ||
| 3270 | break; | ||
| 3271 | case OPC_OUB_SAS_DIAG_EXECUTE: | ||
| 3272 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3273 | pm8001_printk("OPC_OUB_SAS_DIAG_EXECUTE\n")); | ||
| 3274 | break; | ||
| 3275 | case OPC_OUB_GET_TIME_STAMP: | ||
| 3276 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3277 | pm8001_printk("OPC_OUB_GET_TIME_STAMP\n")); | ||
| 3278 | break; | ||
| 3279 | case OPC_OUB_SAS_HW_EVENT_ACK: | ||
| 3280 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3281 | pm8001_printk("OPC_OUB_SAS_HW_EVENT_ACK\n")); | ||
| 3282 | break; | ||
| 3283 | case OPC_OUB_PORT_CONTROL: | ||
| 3284 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3285 | pm8001_printk("OPC_OUB_PORT_CONTROL\n")); | ||
| 3286 | break; | ||
| 3287 | case OPC_OUB_SMP_ABORT_RSP: | ||
| 3288 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3289 | pm8001_printk("OPC_OUB_SMP_ABORT_RSP\n")); | ||
| 3290 | pm8001_mpi_task_abort_resp(pm8001_ha, piomb); | ||
| 3291 | break; | ||
| 3292 | case OPC_OUB_GET_NVMD_DATA: | ||
| 3293 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3294 | pm8001_printk("OPC_OUB_GET_NVMD_DATA\n")); | ||
| 3295 | pm8001_mpi_get_nvmd_resp(pm8001_ha, piomb); | ||
| 3296 | break; | ||
| 3297 | case OPC_OUB_SET_NVMD_DATA: | ||
| 3298 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3299 | pm8001_printk("OPC_OUB_SET_NVMD_DATA\n")); | ||
| 3300 | pm8001_mpi_set_nvmd_resp(pm8001_ha, piomb); | ||
| 3301 | break; | ||
| 3302 | case OPC_OUB_DEVICE_HANDLE_REMOVAL: | ||
| 3303 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3304 | pm8001_printk("OPC_OUB_DEVICE_HANDLE_REMOVAL\n")); | ||
| 3305 | break; | ||
| 3306 | case OPC_OUB_SET_DEVICE_STATE: | ||
| 3307 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3308 | pm8001_printk("OPC_OUB_SET_DEVICE_STATE\n")); | ||
| 3309 | pm8001_mpi_set_dev_state_resp(pm8001_ha, piomb); | ||
| 3310 | break; | ||
| 3311 | case OPC_OUB_GET_DEVICE_STATE: | ||
| 3312 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3313 | pm8001_printk("OPC_OUB_GET_DEVICE_STATE\n")); | ||
| 3314 | break; | ||
| 3315 | case OPC_OUB_SET_DEV_INFO: | ||
| 3316 | PM8001_MSG_DBG(pm8001_ha, | ||
| 3317 | pm8001_printk("OPC_OUB_SET_DEV_INFO\n")); | ||
| 3318 | break; | ||
| 3319 | /* spcv specifc commands */ | ||
| 3320 | case OPC_OUB_PHY_START_RESP: | ||
| 3321 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3322 | "OPC_OUB_PHY_START_RESP opcode:%x\n", opc)); | ||
| 3323 | mpi_phy_start_resp(pm8001_ha, piomb); | ||
| 3324 | break; | ||
| 3325 | case OPC_OUB_PHY_STOP_RESP: | ||
| 3326 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3327 | "OPC_OUB_PHY_STOP_RESP opcode:%x\n", opc)); | ||
| 3328 | mpi_phy_stop_resp(pm8001_ha, piomb); | ||
| 3329 | break; | ||
| 3330 | case OPC_OUB_SET_CONTROLLER_CONFIG: | ||
| 3331 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3332 | "OPC_OUB_SET_CONTROLLER_CONFIG opcode:%x\n", opc)); | ||
| 3333 | mpi_set_controller_config_resp(pm8001_ha, piomb); | ||
| 3334 | break; | ||
| 3335 | case OPC_OUB_GET_CONTROLLER_CONFIG: | ||
| 3336 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3337 | "OPC_OUB_GET_CONTROLLER_CONFIG opcode:%x\n", opc)); | ||
| 3338 | mpi_get_controller_config_resp(pm8001_ha, piomb); | ||
| 3339 | break; | ||
| 3340 | case OPC_OUB_GET_PHY_PROFILE: | ||
| 3341 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3342 | "OPC_OUB_GET_PHY_PROFILE opcode:%x\n", opc)); | ||
| 3343 | mpi_get_phy_profile_resp(pm8001_ha, piomb); | ||
| 3344 | break; | ||
| 3345 | case OPC_OUB_FLASH_OP_EXT: | ||
| 3346 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3347 | "OPC_OUB_FLASH_OP_EXT opcode:%x\n", opc)); | ||
| 3348 | mpi_flash_op_ext_resp(pm8001_ha, piomb); | ||
| 3349 | break; | ||
| 3350 | case OPC_OUB_SET_PHY_PROFILE: | ||
| 3351 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3352 | "OPC_OUB_SET_PHY_PROFILE opcode:%x\n", opc)); | ||
| 3353 | mpi_set_phy_profile_resp(pm8001_ha, piomb); | ||
| 3354 | break; | ||
| 3355 | case OPC_OUB_KEK_MANAGEMENT_RESP: | ||
| 3356 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3357 | "OPC_OUB_KEK_MANAGEMENT_RESP opcode:%x\n", opc)); | ||
| 3358 | mpi_kek_management_resp(pm8001_ha, piomb); | ||
| 3359 | break; | ||
| 3360 | case OPC_OUB_DEK_MANAGEMENT_RESP: | ||
| 3361 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3362 | "OPC_OUB_DEK_MANAGEMENT_RESP opcode:%x\n", opc)); | ||
| 3363 | mpi_dek_management_resp(pm8001_ha, piomb); | ||
| 3364 | break; | ||
| 3365 | case OPC_OUB_SSP_COALESCED_COMP_RESP: | ||
| 3366 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3367 | "OPC_OUB_SSP_COALESCED_COMP_RESP opcode:%x\n", opc)); | ||
| 3368 | ssp_coalesced_comp_resp(pm8001_ha, piomb); | ||
| 3369 | break; | ||
| 3370 | default: | ||
| 3371 | PM8001_MSG_DBG(pm8001_ha, pm8001_printk( | ||
| 3372 | "Unknown outbound Queue IOMB OPC = 0x%x\n", opc)); | ||
| 3373 | break; | ||
| 3374 | } | ||
| 3375 | } | ||
| 3376 | |||
| 3377 | static int process_oq(struct pm8001_hba_info *pm8001_ha, u8 vec) | ||
| 3378 | { | ||
| 3379 | struct outbound_queue_table *circularQ; | ||
| 3380 | void *pMsg1 = NULL; | ||
| 3381 | u8 uninitialized_var(bc); | ||
| 3382 | u32 ret = MPI_IO_STATUS_FAIL; | ||
| 3383 | unsigned long flags; | ||
| 3384 | |||
| 3385 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
| 3386 | circularQ = &pm8001_ha->outbnd_q_tbl[vec]; | ||
| 3387 | do { | ||
| 3388 | ret = pm8001_mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc); | ||
| 3389 | if (MPI_IO_STATUS_SUCCESS == ret) { | ||
| 3390 | /* process the outbound message */ | ||
| 3391 | process_one_iomb(pm8001_ha, (void *)(pMsg1 - 4)); | ||
| 3392 | /* free the message from the outbound circular buffer */ | ||
| 3393 | pm8001_mpi_msg_free_set(pm8001_ha, pMsg1, | ||
| 3394 | circularQ, bc); | ||
| 3395 | } | ||
| 3396 | if (MPI_IO_STATUS_BUSY == ret) { | ||
| 3397 | /* Update the producer index from SPC */ | ||
| 3398 | circularQ->producer_index = | ||
| 3399 | cpu_to_le32(pm8001_read_32(circularQ->pi_virt)); | ||
| 3400 | if (le32_to_cpu(circularQ->producer_index) == | ||
| 3401 | circularQ->consumer_idx) | ||
| 3402 | /* OQ is empty */ | ||
| 3403 | break; | ||
| 3404 | } | ||
| 3405 | } while (1); | ||
| 3406 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
| 3407 | return ret; | ||
| 3408 | } | ||
| 3409 | |||
| 3410 | /* PCI_DMA_... to our direction translation. */ | ||
| 3411 | static const u8 data_dir_flags[] = { | ||
| 3412 | [PCI_DMA_BIDIRECTIONAL] = DATA_DIR_BYRECIPIENT,/* UNSPECIFIED */ | ||
| 3413 | [PCI_DMA_TODEVICE] = DATA_DIR_OUT,/* OUTBOUND */ | ||
| 3414 | [PCI_DMA_FROMDEVICE] = DATA_DIR_IN,/* INBOUND */ | ||
| 3415 | [PCI_DMA_NONE] = DATA_DIR_NONE,/* NO TRANSFER */ | ||
| 3416 | }; | ||
| 3417 | |||
| 3418 | static void build_smp_cmd(u32 deviceID, __le32 hTag, | ||
| 3419 | struct smp_req *psmp_cmd, int mode, int length) | ||
| 3420 | { | ||
| 3421 | psmp_cmd->tag = hTag; | ||
| 3422 | psmp_cmd->device_id = cpu_to_le32(deviceID); | ||
| 3423 | if (mode == SMP_DIRECT) { | ||
| 3424 | length = length - 4; /* subtract crc */ | ||
| 3425 | psmp_cmd->len_ip_ir = cpu_to_le32(length << 16); | ||
| 3426 | } else { | ||
| 3427 | psmp_cmd->len_ip_ir = cpu_to_le32(1|(1 << 1)); | ||
| 3428 | } | ||
| 3429 | } | ||
| 3430 | |||
| 3431 | /** | ||
| 3432 | * pm8001_chip_smp_req - send a SMP task to FW | ||
| 3433 | * @pm8001_ha: our hba card information. | ||
| 3434 | * @ccb: the ccb information this request used. | ||
| 3435 | */ | ||
| 3436 | static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, | ||
| 3437 | struct pm8001_ccb_info *ccb) | ||
| 3438 | { | ||
| 3439 | int elem, rc; | ||
| 3440 | struct sas_task *task = ccb->task; | ||
| 3441 | struct domain_device *dev = task->dev; | ||
| 3442 | struct pm8001_device *pm8001_dev = dev->lldd_dev; | ||
| 3443 | struct scatterlist *sg_req, *sg_resp; | ||
| 3444 | u32 req_len, resp_len; | ||
| 3445 | struct smp_req smp_cmd; | ||
| 3446 | u32 opc; | ||
| 3447 | struct inbound_queue_table *circularQ; | ||
| 3448 | char *preq_dma_addr = NULL; | ||
| 3449 | __le64 tmp_addr; | ||
| 3450 | u32 i, length; | ||
| 3451 | |||
| 3452 | memset(&smp_cmd, 0, sizeof(smp_cmd)); | ||
| 3453 | /* | ||
| 3454 | * DMA-map SMP request, response buffers | ||
| 3455 | */ | ||
| 3456 | sg_req = &task->smp_task.smp_req; | ||
| 3457 | elem = dma_map_sg(pm8001_ha->dev, sg_req, 1, PCI_DMA_TODEVICE); | ||
| 3458 | if (!elem) | ||
| 3459 | return -ENOMEM; | ||
| 3460 | req_len = sg_dma_len(sg_req); | ||
| 3461 | |||
| 3462 | sg_resp = &task->smp_task.smp_resp; | ||
| 3463 | elem = dma_map_sg(pm8001_ha->dev, sg_resp, 1, PCI_DMA_FROMDEVICE); | ||
| 3464 | if (!elem) { | ||
| 3465 | rc = -ENOMEM; | ||
| 3466 | goto err_out; | ||
| 3467 | } | ||
| 3468 | resp_len = sg_dma_len(sg_resp); | ||
| 3469 | /* must be in dwords */ | ||
| 3470 | if ((req_len & 0x3) || (resp_len & 0x3)) { | ||
| 3471 | rc = -EINVAL; | ||
| 3472 | goto err_out_2; | ||
| 3473 | } | ||
| 3474 | |||
| 3475 | opc = OPC_INB_SMP_REQUEST; | ||
| 3476 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 3477 | smp_cmd.tag = cpu_to_le32(ccb->ccb_tag); | ||
| 3478 | |||
| 3479 | length = sg_req->length; | ||
| 3480 | PM8001_IO_DBG(pm8001_ha, | ||
| 3481 | pm8001_printk("SMP Frame Length %d\n", sg_req->length)); | ||
| 3482 | if (!(length - 8)) | ||
| 3483 | pm8001_ha->smp_exp_mode = SMP_DIRECT; | ||
| 3484 | else | ||
| 3485 | pm8001_ha->smp_exp_mode = SMP_INDIRECT; | ||
| 3486 | |||
| 3487 | /* DIRECT MODE support only in spcv/ve */ | ||
| 3488 | pm8001_ha->smp_exp_mode = SMP_DIRECT; | ||
| 3489 | |||
| 3490 | tmp_addr = cpu_to_le64((u64)sg_dma_address(&task->smp_task.smp_req)); | ||
| 3491 | preq_dma_addr = (char *)phys_to_virt(tmp_addr); | ||
| 3492 | |||
| 3493 | /* INDIRECT MODE command settings. Use DMA */ | ||
| 3494 | if (pm8001_ha->smp_exp_mode == SMP_INDIRECT) { | ||
| 3495 | PM8001_IO_DBG(pm8001_ha, | ||
| 3496 | pm8001_printk("SMP REQUEST INDIRECT MODE\n")); | ||
| 3497 | /* for SPCv indirect mode. Place the top 4 bytes of | ||
| 3498 | * SMP Request header here. */ | ||
| 3499 | for (i = 0; i < 4; i++) | ||
| 3500 | smp_cmd.smp_req16[i] = *(preq_dma_addr + i); | ||
| 3501 | /* exclude top 4 bytes for SMP req header */ | ||
| 3502 | smp_cmd.long_smp_req.long_req_addr = | ||
| 3503 | cpu_to_le64((u64)sg_dma_address | ||
| 3504 | (&task->smp_task.smp_req) - 4); | ||
| 3505 | /* exclude 4 bytes for SMP req header and CRC */ | ||
| 3506 | smp_cmd.long_smp_req.long_req_size = | ||
| 3507 | cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-8); | ||
| 3508 | smp_cmd.long_smp_req.long_resp_addr = | ||
| 3509 | cpu_to_le64((u64)sg_dma_address | ||
| 3510 | (&task->smp_task.smp_resp)); | ||
| 3511 | smp_cmd.long_smp_req.long_resp_size = | ||
| 3512 | cpu_to_le32((u32)sg_dma_len | ||
| 3513 | (&task->smp_task.smp_resp)-4); | ||
| 3514 | } else { /* DIRECT MODE */ | ||
| 3515 | smp_cmd.long_smp_req.long_req_addr = | ||
| 3516 | cpu_to_le64((u64)sg_dma_address | ||
| 3517 | (&task->smp_task.smp_req)); | ||
| 3518 | smp_cmd.long_smp_req.long_req_size = | ||
| 3519 | cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_req)-4); | ||
| 3520 | smp_cmd.long_smp_req.long_resp_addr = | ||
| 3521 | cpu_to_le64((u64)sg_dma_address | ||
| 3522 | (&task->smp_task.smp_resp)); | ||
| 3523 | smp_cmd.long_smp_req.long_resp_size = | ||
| 3524 | cpu_to_le32 | ||
| 3525 | ((u32)sg_dma_len(&task->smp_task.smp_resp)-4); | ||
| 3526 | } | ||
| 3527 | if (pm8001_ha->smp_exp_mode == SMP_DIRECT) { | ||
| 3528 | PM8001_IO_DBG(pm8001_ha, | ||
| 3529 | pm8001_printk("SMP REQUEST DIRECT MODE\n")); | ||
| 3530 | for (i = 0; i < length; i++) | ||
| 3531 | if (i < 16) { | ||
| 3532 | smp_cmd.smp_req16[i] = *(preq_dma_addr+i); | ||
| 3533 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 3534 | "Byte[%d]:%x (DMA data:%x)\n", | ||
| 3535 | i, smp_cmd.smp_req16[i], | ||
| 3536 | *(preq_dma_addr))); | ||
| 3537 | } else { | ||
| 3538 | smp_cmd.smp_req[i] = *(preq_dma_addr+i); | ||
| 3539 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 3540 | "Byte[%d]:%x (DMA data:%x)\n", | ||
| 3541 | i, smp_cmd.smp_req[i], | ||
| 3542 | *(preq_dma_addr))); | ||
| 3543 | } | ||
| 3544 | } | ||
| 3545 | |||
| 3546 | build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, | ||
| 3547 | &smp_cmd, pm8001_ha->smp_exp_mode, length); | ||
| 3548 | pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0); | ||
| 3549 | return 0; | ||
| 3550 | |||
| 3551 | err_out_2: | ||
| 3552 | dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_resp, 1, | ||
| 3553 | PCI_DMA_FROMDEVICE); | ||
| 3554 | err_out: | ||
| 3555 | dma_unmap_sg(pm8001_ha->dev, &ccb->task->smp_task.smp_req, 1, | ||
| 3556 | PCI_DMA_TODEVICE); | ||
| 3557 | return rc; | ||
| 3558 | } | ||
| 3559 | |||
| 3560 | static int check_enc_sas_cmd(struct sas_task *task) | ||
| 3561 | { | ||
| 3562 | if ((task->ssp_task.cdb[0] == READ_10) | ||
| 3563 | || (task->ssp_task.cdb[0] == WRITE_10) | ||
| 3564 | || (task->ssp_task.cdb[0] == WRITE_VERIFY)) | ||
| 3565 | return 1; | ||
| 3566 | else | ||
| 3567 | return 0; | ||
| 3568 | } | ||
| 3569 | |||
| 3570 | static int check_enc_sat_cmd(struct sas_task *task) | ||
| 3571 | { | ||
| 3572 | int ret = 0; | ||
| 3573 | switch (task->ata_task.fis.command) { | ||
| 3574 | case ATA_CMD_FPDMA_READ: | ||
| 3575 | case ATA_CMD_READ_EXT: | ||
| 3576 | case ATA_CMD_READ: | ||
| 3577 | case ATA_CMD_FPDMA_WRITE: | ||
| 3578 | case ATA_CMD_WRITE_EXT: | ||
| 3579 | case ATA_CMD_WRITE: | ||
| 3580 | case ATA_CMD_PIO_READ: | ||
| 3581 | case ATA_CMD_PIO_READ_EXT: | ||
| 3582 | case ATA_CMD_PIO_WRITE: | ||
| 3583 | case ATA_CMD_PIO_WRITE_EXT: | ||
| 3584 | ret = 1; | ||
| 3585 | break; | ||
| 3586 | default: | ||
| 3587 | ret = 0; | ||
| 3588 | break; | ||
| 3589 | } | ||
| 3590 | return ret; | ||
| 3591 | } | ||
| 3592 | |||
| 3593 | /** | ||
| 3594 | * pm80xx_chip_ssp_io_req - send a SSP task to FW | ||
| 3595 | * @pm8001_ha: our hba card information. | ||
| 3596 | * @ccb: the ccb information this request used. | ||
| 3597 | */ | ||
| 3598 | static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, | ||
| 3599 | struct pm8001_ccb_info *ccb) | ||
| 3600 | { | ||
| 3601 | struct sas_task *task = ccb->task; | ||
| 3602 | struct domain_device *dev = task->dev; | ||
| 3603 | struct pm8001_device *pm8001_dev = dev->lldd_dev; | ||
| 3604 | struct ssp_ini_io_start_req ssp_cmd; | ||
| 3605 | u32 tag = ccb->ccb_tag; | ||
| 3606 | int ret; | ||
| 3607 | u64 phys_addr; | ||
| 3608 | struct inbound_queue_table *circularQ; | ||
| 3609 | static u32 inb; | ||
| 3610 | static u32 outb; | ||
| 3611 | u32 opc = OPC_INB_SSPINIIOSTART; | ||
| 3612 | memset(&ssp_cmd, 0, sizeof(ssp_cmd)); | ||
| 3613 | memcpy(ssp_cmd.ssp_iu.lun, task->ssp_task.LUN, 8); | ||
| 3614 | /* data address domain added for spcv; set to 0 by host, | ||
| 3615 | * used internally by controller | ||
| 3616 | * 0 for SAS 1.1 and SAS 2.0 compatible TLR | ||
| 3617 | */ | ||
| 3618 | ssp_cmd.dad_dir_m_tlr = | ||
| 3619 | cpu_to_le32(data_dir_flags[task->data_dir] << 8 | 0x0); | ||
| 3620 | ssp_cmd.data_len = cpu_to_le32(task->total_xfer_len); | ||
| 3621 | ssp_cmd.device_id = cpu_to_le32(pm8001_dev->device_id); | ||
| 3622 | ssp_cmd.tag = cpu_to_le32(tag); | ||
| 3623 | if (task->ssp_task.enable_first_burst) | ||
| 3624 | ssp_cmd.ssp_iu.efb_prio_attr |= 0x80; | ||
| 3625 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_prio << 3); | ||
| 3626 | ssp_cmd.ssp_iu.efb_prio_attr |= (task->ssp_task.task_attr & 7); | ||
| 3627 | memcpy(ssp_cmd.ssp_iu.cdb, task->ssp_task.cdb, 16); | ||
| 3628 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 3629 | |||
| 3630 | /* Check if encryption is set */ | ||
| 3631 | if (pm8001_ha->chip->encrypt && | ||
| 3632 | !(pm8001_ha->encrypt_info.status) && check_enc_sas_cmd(task)) { | ||
| 3633 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 3634 | "Encryption enabled.Sending Encrypt SAS command 0x%x\n", | ||
| 3635 | task->ssp_task.cdb[0])); | ||
| 3636 | opc = OPC_INB_SSP_INI_DIF_ENC_IO; | ||
| 3637 | /* enable encryption. 0 for SAS 1.1 and SAS 2.0 compatible TLR*/ | ||
| 3638 | ssp_cmd.dad_dir_m_tlr = cpu_to_le32 | ||
| 3639 | ((data_dir_flags[task->data_dir] << 8) | 0x20 | 0x0); | ||
| 3640 | |||
| 3641 | /* fill in PRD (scatter/gather) table, if any */ | ||
| 3642 | if (task->num_scatter > 1) { | ||
| 3643 | pm8001_chip_make_sg(task->scatter, | ||
| 3644 | ccb->n_elem, ccb->buf_prd); | ||
| 3645 | phys_addr = ccb->ccb_dma_handle + | ||
| 3646 | offsetof(struct pm8001_ccb_info, buf_prd[0]); | ||
| 3647 | ssp_cmd.enc_addr_low = | ||
| 3648 | cpu_to_le32(lower_32_bits(phys_addr)); | ||
| 3649 | ssp_cmd.enc_addr_high = | ||
| 3650 | cpu_to_le32(upper_32_bits(phys_addr)); | ||
| 3651 | ssp_cmd.enc_esgl = cpu_to_le32(1<<31); | ||
| 3652 | } else if (task->num_scatter == 1) { | ||
| 3653 | u64 dma_addr = sg_dma_address(task->scatter); | ||
| 3654 | ssp_cmd.enc_addr_low = | ||
| 3655 | cpu_to_le32(lower_32_bits(dma_addr)); | ||
| 3656 | ssp_cmd.enc_addr_high = | ||
| 3657 | cpu_to_le32(upper_32_bits(dma_addr)); | ||
| 3658 | ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len); | ||
| 3659 | ssp_cmd.enc_esgl = 0; | ||
| 3660 | } else if (task->num_scatter == 0) { | ||
| 3661 | ssp_cmd.enc_addr_low = 0; | ||
| 3662 | ssp_cmd.enc_addr_high = 0; | ||
| 3663 | ssp_cmd.enc_len = cpu_to_le32(task->total_xfer_len); | ||
| 3664 | ssp_cmd.enc_esgl = 0; | ||
| 3665 | } | ||
| 3666 | /* XTS mode. All other fields are 0 */ | ||
| 3667 | ssp_cmd.key_cmode = 0x6 << 4; | ||
| 3668 | /* set tweak values. Should be the start lba */ | ||
| 3669 | ssp_cmd.twk_val0 = cpu_to_le32((task->ssp_task.cdb[2] << 24) | | ||
| 3670 | (task->ssp_task.cdb[3] << 16) | | ||
| 3671 | (task->ssp_task.cdb[4] << 8) | | ||
| 3672 | (task->ssp_task.cdb[5])); | ||
| 3673 | } else { | ||
| 3674 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 3675 | "Sending Normal SAS command 0x%x inb q %x\n", | ||
| 3676 | task->ssp_task.cdb[0], inb)); | ||
| 3677 | /* fill in PRD (scatter/gather) table, if any */ | ||
| 3678 | if (task->num_scatter > 1) { | ||
| 3679 | pm8001_chip_make_sg(task->scatter, ccb->n_elem, | ||
| 3680 | ccb->buf_prd); | ||
| 3681 | phys_addr = ccb->ccb_dma_handle + | ||
| 3682 | offsetof(struct pm8001_ccb_info, buf_prd[0]); | ||
| 3683 | ssp_cmd.addr_low = | ||
| 3684 | cpu_to_le32(lower_32_bits(phys_addr)); | ||
| 3685 | ssp_cmd.addr_high = | ||
| 3686 | cpu_to_le32(upper_32_bits(phys_addr)); | ||
| 3687 | ssp_cmd.esgl = cpu_to_le32(1<<31); | ||
| 3688 | } else if (task->num_scatter == 1) { | ||
| 3689 | u64 dma_addr = sg_dma_address(task->scatter); | ||
| 3690 | ssp_cmd.addr_low = cpu_to_le32(lower_32_bits(dma_addr)); | ||
| 3691 | ssp_cmd.addr_high = | ||
| 3692 | cpu_to_le32(upper_32_bits(dma_addr)); | ||
| 3693 | ssp_cmd.len = cpu_to_le32(task->total_xfer_len); | ||
| 3694 | ssp_cmd.esgl = 0; | ||
| 3695 | } else if (task->num_scatter == 0) { | ||
| 3696 | ssp_cmd.addr_low = 0; | ||
| 3697 | ssp_cmd.addr_high = 0; | ||
| 3698 | ssp_cmd.len = cpu_to_le32(task->total_xfer_len); | ||
| 3699 | ssp_cmd.esgl = 0; | ||
| 3700 | } | ||
| 3701 | } | ||
| 3702 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &ssp_cmd, outb++); | ||
| 3703 | |||
| 3704 | /* rotate the outb queue */ | ||
| 3705 | outb = outb%PM8001_MAX_SPCV_OUTB_NUM; | ||
| 3706 | |||
| 3707 | return ret; | ||
| 3708 | } | ||
| 3709 | |||
| 3710 | static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, | ||
| 3711 | struct pm8001_ccb_info *ccb) | ||
| 3712 | { | ||
| 3713 | struct sas_task *task = ccb->task; | ||
| 3714 | struct domain_device *dev = task->dev; | ||
| 3715 | struct pm8001_device *pm8001_ha_dev = dev->lldd_dev; | ||
| 3716 | u32 tag = ccb->ccb_tag; | ||
| 3717 | int ret; | ||
| 3718 | static u32 inb; | ||
| 3719 | static u32 outb; | ||
| 3720 | struct sata_start_req sata_cmd; | ||
| 3721 | u32 hdr_tag, ncg_tag = 0; | ||
| 3722 | u64 phys_addr; | ||
| 3723 | u32 ATAP = 0x0; | ||
| 3724 | u32 dir; | ||
| 3725 | struct inbound_queue_table *circularQ; | ||
| 3726 | unsigned long flags; | ||
| 3727 | u32 opc = OPC_INB_SATA_HOST_OPSTART; | ||
| 3728 | memset(&sata_cmd, 0, sizeof(sata_cmd)); | ||
| 3729 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 3730 | |||
| 3731 | if (task->data_dir == PCI_DMA_NONE) { | ||
| 3732 | ATAP = 0x04; /* no data*/ | ||
| 3733 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("no data\n")); | ||
| 3734 | } else if (likely(!task->ata_task.device_control_reg_update)) { | ||
| 3735 | if (task->ata_task.dma_xfer) { | ||
| 3736 | ATAP = 0x06; /* DMA */ | ||
| 3737 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("DMA\n")); | ||
| 3738 | } else { | ||
| 3739 | ATAP = 0x05; /* PIO*/ | ||
| 3740 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("PIO\n")); | ||
| 3741 | } | ||
| 3742 | if (task->ata_task.use_ncq && | ||
| 3743 | dev->sata_dev.command_set != ATAPI_COMMAND_SET) { | ||
| 3744 | ATAP = 0x07; /* FPDMA */ | ||
| 3745 | PM8001_IO_DBG(pm8001_ha, pm8001_printk("FPDMA\n")); | ||
| 3746 | } | ||
| 3747 | } | ||
| 3748 | if (task->ata_task.use_ncq && pm8001_get_ncq_tag(task, &hdr_tag)) { | ||
| 3749 | task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3); | ||
| 3750 | ncg_tag = hdr_tag; | ||
| 3751 | } | ||
| 3752 | dir = data_dir_flags[task->data_dir] << 8; | ||
| 3753 | sata_cmd.tag = cpu_to_le32(tag); | ||
| 3754 | sata_cmd.device_id = cpu_to_le32(pm8001_ha_dev->device_id); | ||
| 3755 | sata_cmd.data_len = cpu_to_le32(task->total_xfer_len); | ||
| 3756 | |||
| 3757 | sata_cmd.sata_fis = task->ata_task.fis; | ||
| 3758 | if (likely(!task->ata_task.device_control_reg_update)) | ||
| 3759 | sata_cmd.sata_fis.flags |= 0x80;/* C=1: update ATA cmd reg */ | ||
| 3760 | sata_cmd.sata_fis.flags &= 0xF0;/* PM_PORT field shall be 0 */ | ||
| 3761 | |||
| 3762 | /* Check if encryption is set */ | ||
| 3763 | if (pm8001_ha->chip->encrypt && | ||
| 3764 | !(pm8001_ha->encrypt_info.status) && check_enc_sat_cmd(task)) { | ||
| 3765 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 3766 | "Encryption enabled.Sending Encrypt SATA cmd 0x%x\n", | ||
| 3767 | sata_cmd.sata_fis.command)); | ||
| 3768 | opc = OPC_INB_SATA_DIF_ENC_IO; | ||
| 3769 | |||
| 3770 | /* set encryption bit */ | ||
| 3771 | sata_cmd.ncqtag_atap_dir_m_dad = | ||
| 3772 | cpu_to_le32(((ncg_tag & 0xff)<<16)| | ||
| 3773 | ((ATAP & 0x3f) << 10) | 0x20 | dir); | ||
| 3774 | /* dad (bit 0-1) is 0 */ | ||
| 3775 | /* fill in PRD (scatter/gather) table, if any */ | ||
| 3776 | if (task->num_scatter > 1) { | ||
| 3777 | pm8001_chip_make_sg(task->scatter, | ||
| 3778 | ccb->n_elem, ccb->buf_prd); | ||
| 3779 | phys_addr = ccb->ccb_dma_handle + | ||
| 3780 | offsetof(struct pm8001_ccb_info, buf_prd[0]); | ||
| 3781 | sata_cmd.enc_addr_low = lower_32_bits(phys_addr); | ||
| 3782 | sata_cmd.enc_addr_high = upper_32_bits(phys_addr); | ||
| 3783 | sata_cmd.enc_esgl = cpu_to_le32(1 << 31); | ||
| 3784 | } else if (task->num_scatter == 1) { | ||
| 3785 | u64 dma_addr = sg_dma_address(task->scatter); | ||
| 3786 | sata_cmd.enc_addr_low = lower_32_bits(dma_addr); | ||
| 3787 | sata_cmd.enc_addr_high = upper_32_bits(dma_addr); | ||
| 3788 | sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len); | ||
| 3789 | sata_cmd.enc_esgl = 0; | ||
| 3790 | } else if (task->num_scatter == 0) { | ||
| 3791 | sata_cmd.enc_addr_low = 0; | ||
| 3792 | sata_cmd.enc_addr_high = 0; | ||
| 3793 | sata_cmd.enc_len = cpu_to_le32(task->total_xfer_len); | ||
| 3794 | sata_cmd.enc_esgl = 0; | ||
| 3795 | } | ||
| 3796 | /* XTS mode. All other fields are 0 */ | ||
| 3797 | sata_cmd.key_index_mode = 0x6 << 4; | ||
| 3798 | /* set tweak values. Should be the start lba */ | ||
| 3799 | sata_cmd.twk_val0 = | ||
| 3800 | cpu_to_le32((sata_cmd.sata_fis.lbal_exp << 24) | | ||
| 3801 | (sata_cmd.sata_fis.lbah << 16) | | ||
| 3802 | (sata_cmd.sata_fis.lbam << 8) | | ||
| 3803 | (sata_cmd.sata_fis.lbal)); | ||
| 3804 | sata_cmd.twk_val1 = | ||
| 3805 | cpu_to_le32((sata_cmd.sata_fis.lbah_exp << 8) | | ||
| 3806 | (sata_cmd.sata_fis.lbam_exp)); | ||
| 3807 | } else { | ||
| 3808 | PM8001_IO_DBG(pm8001_ha, pm8001_printk( | ||
| 3809 | "Sending Normal SATA command 0x%x inb %x\n", | ||
| 3810 | sata_cmd.sata_fis.command, inb)); | ||
| 3811 | /* dad (bit 0-1) is 0 */ | ||
| 3812 | sata_cmd.ncqtag_atap_dir_m_dad = | ||
| 3813 | cpu_to_le32(((ncg_tag & 0xff)<<16) | | ||
| 3814 | ((ATAP & 0x3f) << 10) | dir); | ||
| 3815 | |||
| 3816 | /* fill in PRD (scatter/gather) table, if any */ | ||
| 3817 | if (task->num_scatter > 1) { | ||
| 3818 | pm8001_chip_make_sg(task->scatter, | ||
| 3819 | ccb->n_elem, ccb->buf_prd); | ||
| 3820 | phys_addr = ccb->ccb_dma_handle + | ||
| 3821 | offsetof(struct pm8001_ccb_info, buf_prd[0]); | ||
| 3822 | sata_cmd.addr_low = lower_32_bits(phys_addr); | ||
| 3823 | sata_cmd.addr_high = upper_32_bits(phys_addr); | ||
| 3824 | sata_cmd.esgl = cpu_to_le32(1 << 31); | ||
| 3825 | } else if (task->num_scatter == 1) { | ||
| 3826 | u64 dma_addr = sg_dma_address(task->scatter); | ||
| 3827 | sata_cmd.addr_low = lower_32_bits(dma_addr); | ||
| 3828 | sata_cmd.addr_high = upper_32_bits(dma_addr); | ||
| 3829 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); | ||
| 3830 | sata_cmd.esgl = 0; | ||
| 3831 | } else if (task->num_scatter == 0) { | ||
| 3832 | sata_cmd.addr_low = 0; | ||
| 3833 | sata_cmd.addr_high = 0; | ||
| 3834 | sata_cmd.len = cpu_to_le32(task->total_xfer_len); | ||
| 3835 | sata_cmd.esgl = 0; | ||
| 3836 | } | ||
| 3837 | /* scsi cdb */ | ||
| 3838 | sata_cmd.atapi_scsi_cdb[0] = | ||
| 3839 | cpu_to_le32(((task->ata_task.atapi_packet[0]) | | ||
| 3840 | (task->ata_task.atapi_packet[1] << 8) | | ||
| 3841 | (task->ata_task.atapi_packet[2] << 16) | | ||
| 3842 | (task->ata_task.atapi_packet[3] << 24))); | ||
| 3843 | sata_cmd.atapi_scsi_cdb[1] = | ||
| 3844 | cpu_to_le32(((task->ata_task.atapi_packet[4]) | | ||
| 3845 | (task->ata_task.atapi_packet[5] << 8) | | ||
| 3846 | (task->ata_task.atapi_packet[6] << 16) | | ||
| 3847 | (task->ata_task.atapi_packet[7] << 24))); | ||
| 3848 | sata_cmd.atapi_scsi_cdb[2] = | ||
| 3849 | cpu_to_le32(((task->ata_task.atapi_packet[8]) | | ||
| 3850 | (task->ata_task.atapi_packet[9] << 8) | | ||
| 3851 | (task->ata_task.atapi_packet[10] << 16) | | ||
| 3852 | (task->ata_task.atapi_packet[11] << 24))); | ||
| 3853 | sata_cmd.atapi_scsi_cdb[3] = | ||
| 3854 | cpu_to_le32(((task->ata_task.atapi_packet[12]) | | ||
| 3855 | (task->ata_task.atapi_packet[13] << 8) | | ||
| 3856 | (task->ata_task.atapi_packet[14] << 16) | | ||
| 3857 | (task->ata_task.atapi_packet[15] << 24))); | ||
| 3858 | } | ||
| 3859 | |||
| 3860 | /* Check for read log for failed drive and return */ | ||
| 3861 | if (sata_cmd.sata_fis.command == 0x2f) { | ||
| 3862 | if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) || | ||
| 3863 | (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) || | ||
| 3864 | (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) { | ||
| 3865 | struct task_status_struct *ts; | ||
| 3866 | |||
| 3867 | pm8001_ha_dev->id &= 0xDFFFFFFF; | ||
| 3868 | ts = &task->task_status; | ||
| 3869 | |||
| 3870 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
| 3871 | ts->resp = SAS_TASK_COMPLETE; | ||
| 3872 | ts->stat = SAM_STAT_GOOD; | ||
| 3873 | task->task_state_flags &= ~SAS_TASK_STATE_PENDING; | ||
| 3874 | task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; | ||
| 3875 | task->task_state_flags |= SAS_TASK_STATE_DONE; | ||
| 3876 | if (unlikely((task->task_state_flags & | ||
| 3877 | SAS_TASK_STATE_ABORTED))) { | ||
| 3878 | spin_unlock_irqrestore(&task->task_state_lock, | ||
| 3879 | flags); | ||
| 3880 | PM8001_FAIL_DBG(pm8001_ha, | ||
| 3881 | pm8001_printk("task 0x%p resp 0x%x " | ||
| 3882 | " stat 0x%x but aborted by upper layer " | ||
| 3883 | "\n", task, ts->resp, ts->stat)); | ||
| 3884 | pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); | ||
| 3885 | return 0; | ||
| 3886 | } else if (task->uldd_task) { | ||
| 3887 | spin_unlock_irqrestore(&task->task_state_lock, | ||
| 3888 | flags); | ||
| 3889 | pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); | ||
| 3890 | mb();/* ditto */ | ||
| 3891 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 3892 | task->task_done(task); | ||
| 3893 | spin_lock_irq(&pm8001_ha->lock); | ||
| 3894 | return 0; | ||
| 3895 | } else if (!task->uldd_task) { | ||
| 3896 | spin_unlock_irqrestore(&task->task_state_lock, | ||
| 3897 | flags); | ||
| 3898 | pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); | ||
| 3899 | mb();/*ditto*/ | ||
| 3900 | spin_unlock_irq(&pm8001_ha->lock); | ||
| 3901 | task->task_done(task); | ||
| 3902 | spin_lock_irq(&pm8001_ha->lock); | ||
| 3903 | return 0; | ||
| 3904 | } | ||
| 3905 | } | ||
| 3906 | } | ||
| 3907 | |||
| 3908 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, | ||
| 3909 | &sata_cmd, outb++); | ||
| 3910 | |||
| 3911 | /* rotate the outb queue */ | ||
| 3912 | outb = outb%PM8001_MAX_SPCV_OUTB_NUM; | ||
| 3913 | return ret; | ||
| 3914 | } | ||
| 3915 | |||
| 3916 | /** | ||
| 3917 | * pm80xx_chip_phy_start_req - start phy via PHY_START COMMAND | ||
| 3918 | * @pm8001_ha: our hba card information. | ||
| 3919 | * @num: the inbound queue number | ||
| 3920 | * @phy_id: the phy id which we wanted to start up. | ||
| 3921 | */ | ||
| 3922 | static int | ||
| 3923 | pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id) | ||
| 3924 | { | ||
| 3925 | struct phy_start_req payload; | ||
| 3926 | struct inbound_queue_table *circularQ; | ||
| 3927 | int ret; | ||
| 3928 | u32 tag = 0x01; | ||
| 3929 | u32 opcode = OPC_INB_PHYSTART; | ||
| 3930 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 3931 | memset(&payload, 0, sizeof(payload)); | ||
| 3932 | payload.tag = cpu_to_le32(tag); | ||
| 3933 | |||
| 3934 | PM8001_INIT_DBG(pm8001_ha, | ||
| 3935 | pm8001_printk("PHY START REQ for phy_id %d\n", phy_id)); | ||
| 3936 | /* | ||
| 3937 | ** [0:7] PHY Identifier | ||
| 3938 | ** [8:11] link rate 1.5G, 3G, 6G | ||
| 3939 | ** [12:13] link mode 01b SAS mode; 10b SATA mode; 11b Auto mode | ||
| 3940 | ** [14] 0b disable spin up hold; 1b enable spin up hold | ||
| 3941 | ** [15] ob no change in current PHY analig setup 1b enable using SPAST | ||
| 3942 | */ | ||
| 3943 | payload.ase_sh_lm_slr_phyid = cpu_to_le32(SPINHOLD_DISABLE | | ||
| 3944 | LINKMODE_AUTO | LINKRATE_15 | | ||
| 3945 | LINKRATE_30 | LINKRATE_60 | phy_id); | ||
| 3946 | /* SSC Disable and SAS Analog ST configuration */ | ||
| 3947 | /** | ||
| 3948 | payload.ase_sh_lm_slr_phyid = | ||
| 3949 | cpu_to_le32(SSC_DISABLE_30 | SAS_ASE | SPINHOLD_DISABLE | | ||
| 3950 | LINKMODE_AUTO | LINKRATE_15 | LINKRATE_30 | LINKRATE_60 | | ||
| 3951 | phy_id); | ||
| 3952 | Have to add "SAS PHY Analog Setup SPASTI 1 Byte" Based on need | ||
| 3953 | **/ | ||
| 3954 | |||
| 3955 | payload.sas_identify.dev_type = SAS_END_DEVICE; | ||
| 3956 | payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL; | ||
| 3957 | memcpy(payload.sas_identify.sas_addr, | ||
| 3958 | pm8001_ha->sas_addr, SAS_ADDR_SIZE); | ||
| 3959 | payload.sas_identify.phy_id = phy_id; | ||
| 3960 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0); | ||
| 3961 | return ret; | ||
| 3962 | } | ||
| 3963 | |||
| 3964 | /** | ||
| 3965 | * pm8001_chip_phy_stop_req - start phy via PHY_STOP COMMAND | ||
| 3966 | * @pm8001_ha: our hba card information. | ||
| 3967 | * @num: the inbound queue number | ||
| 3968 | * @phy_id: the phy id which we wanted to start up. | ||
| 3969 | */ | ||
| 3970 | static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha, | ||
| 3971 | u8 phy_id) | ||
| 3972 | { | ||
| 3973 | struct phy_stop_req payload; | ||
| 3974 | struct inbound_queue_table *circularQ; | ||
| 3975 | int ret; | ||
| 3976 | u32 tag = 0x01; | ||
| 3977 | u32 opcode = OPC_INB_PHYSTOP; | ||
| 3978 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 3979 | memset(&payload, 0, sizeof(payload)); | ||
| 3980 | payload.tag = cpu_to_le32(tag); | ||
| 3981 | payload.phy_id = cpu_to_le32(phy_id); | ||
| 3982 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, &payload, 0); | ||
| 3983 | return ret; | ||
| 3984 | } | ||
| 3985 | |||
| 3986 | /** | ||
| 3987 | * see comments on pm8001_mpi_reg_resp. | ||
| 3988 | */ | ||
| 3989 | static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, | ||
| 3990 | struct pm8001_device *pm8001_dev, u32 flag) | ||
| 3991 | { | ||
| 3992 | struct reg_dev_req payload; | ||
| 3993 | u32 opc; | ||
| 3994 | u32 stp_sspsmp_sata = 0x4; | ||
| 3995 | struct inbound_queue_table *circularQ; | ||
| 3996 | u32 linkrate, phy_id; | ||
| 3997 | int rc, tag = 0xdeadbeef; | ||
| 3998 | struct pm8001_ccb_info *ccb; | ||
| 3999 | u8 retryFlag = 0x1; | ||
| 4000 | u16 firstBurstSize = 0; | ||
| 4001 | u16 ITNT = 2000; | ||
| 4002 | struct domain_device *dev = pm8001_dev->sas_device; | ||
| 4003 | struct domain_device *parent_dev = dev->parent; | ||
| 4004 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 4005 | |||
| 4006 | memset(&payload, 0, sizeof(payload)); | ||
| 4007 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
| 4008 | if (rc) | ||
| 4009 | return rc; | ||
| 4010 | ccb = &pm8001_ha->ccb_info[tag]; | ||
| 4011 | ccb->device = pm8001_dev; | ||
| 4012 | ccb->ccb_tag = tag; | ||
| 4013 | payload.tag = cpu_to_le32(tag); | ||
| 4014 | |||
| 4015 | if (flag == 1) { | ||
| 4016 | stp_sspsmp_sata = 0x02; /*direct attached sata */ | ||
| 4017 | } else { | ||
| 4018 | if (pm8001_dev->dev_type == SAS_SATA_DEV) | ||
| 4019 | stp_sspsmp_sata = 0x00; /* stp*/ | ||
| 4020 | else if (pm8001_dev->dev_type == SAS_END_DEVICE || | ||
| 4021 | pm8001_dev->dev_type == SAS_EDGE_EXPANDER_DEVICE || | ||
| 4022 | pm8001_dev->dev_type == SAS_FANOUT_EXPANDER_DEVICE) | ||
| 4023 | stp_sspsmp_sata = 0x01; /*ssp or smp*/ | ||
| 4024 | } | ||
| 4025 | if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) | ||
| 4026 | phy_id = parent_dev->ex_dev.ex_phy->phy_id; | ||
| 4027 | else | ||
| 4028 | phy_id = pm8001_dev->attached_phy; | ||
| 4029 | |||
| 4030 | opc = OPC_INB_REG_DEV; | ||
| 4031 | |||
| 4032 | linkrate = (pm8001_dev->sas_device->linkrate < dev->port->linkrate) ? | ||
| 4033 | pm8001_dev->sas_device->linkrate : dev->port->linkrate; | ||
| 4034 | |||
| 4035 | payload.phyid_portid = | ||
| 4036 | cpu_to_le32(((pm8001_dev->sas_device->port->id) & 0xFF) | | ||
| 4037 | ((phy_id & 0xFF) << 8)); | ||
| 4038 | |||
| 4039 | payload.dtype_dlr_mcn_ir_retry = cpu_to_le32((retryFlag & 0x01) | | ||
| 4040 | ((linkrate & 0x0F) << 24) | | ||
| 4041 | ((stp_sspsmp_sata & 0x03) << 28)); | ||
| 4042 | payload.firstburstsize_ITNexustimeout = | ||
| 4043 | cpu_to_le32(ITNT | (firstBurstSize * 0x10000)); | ||
| 4044 | |||
| 4045 | memcpy(payload.sas_addr, pm8001_dev->sas_device->sas_addr, | ||
| 4046 | SAS_ADDR_SIZE); | ||
| 4047 | |||
| 4048 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
| 4049 | |||
| 4050 | return rc; | ||
| 4051 | } | ||
| 4052 | |||
| 4053 | /** | ||
| 4054 | * pm80xx_chip_phy_ctl_req - support the local phy operation | ||
| 4055 | * @pm8001_ha: our hba card information. | ||
| 4056 | * @num: the inbound queue number | ||
| 4057 | * @phy_id: the phy id which we wanted to operate | ||
| 4058 | * @phy_op: | ||
| 4059 | */ | ||
| 4060 | static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha, | ||
| 4061 | u32 phyId, u32 phy_op) | ||
| 4062 | { | ||
| 4063 | struct local_phy_ctl_req payload; | ||
| 4064 | struct inbound_queue_table *circularQ; | ||
| 4065 | int ret; | ||
| 4066 | u32 opc = OPC_INB_LOCAL_PHY_CONTROL; | ||
| 4067 | memset(&payload, 0, sizeof(payload)); | ||
| 4068 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 4069 | payload.tag = cpu_to_le32(1); | ||
| 4070 | payload.phyop_phyid = | ||
| 4071 | cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF)); | ||
| 4072 | ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
| 4073 | return ret; | ||
| 4074 | } | ||
| 4075 | |||
| 4076 | static u32 pm80xx_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha) | ||
| 4077 | { | ||
| 4078 | u32 value; | ||
| 4079 | #ifdef PM8001_USE_MSIX | ||
| 4080 | return 1; | ||
| 4081 | #endif | ||
| 4082 | value = pm8001_cr32(pm8001_ha, 0, MSGU_ODR); | ||
| 4083 | if (value) | ||
| 4084 | return 1; | ||
| 4085 | return 0; | ||
| 4086 | |||
| 4087 | } | ||
| 4088 | |||
| 4089 | /** | ||
| 4090 | * pm8001_chip_isr - PM8001 isr handler. | ||
| 4091 | * @pm8001_ha: our hba card information. | ||
| 4092 | * @irq: irq number. | ||
| 4093 | * @stat: stat. | ||
| 4094 | */ | ||
| 4095 | static irqreturn_t | ||
| 4096 | pm80xx_chip_isr(struct pm8001_hba_info *pm8001_ha, u8 vec) | ||
| 4097 | { | ||
| 4098 | pm80xx_chip_interrupt_disable(pm8001_ha, vec); | ||
| 4099 | process_oq(pm8001_ha, vec); | ||
| 4100 | pm80xx_chip_interrupt_enable(pm8001_ha, vec); | ||
| 4101 | return IRQ_HANDLED; | ||
| 4102 | } | ||
| 4103 | |||
| 4104 | const struct pm8001_dispatch pm8001_80xx_dispatch = { | ||
| 4105 | .name = "pmc80xx", | ||
| 4106 | .chip_init = pm80xx_chip_init, | ||
| 4107 | .chip_soft_rst = pm80xx_chip_soft_rst, | ||
| 4108 | .chip_rst = pm80xx_hw_chip_rst, | ||
| 4109 | .chip_iounmap = pm8001_chip_iounmap, | ||
| 4110 | .isr = pm80xx_chip_isr, | ||
| 4111 | .is_our_interupt = pm80xx_chip_is_our_interupt, | ||
| 4112 | .isr_process_oq = process_oq, | ||
| 4113 | .interrupt_enable = pm80xx_chip_interrupt_enable, | ||
| 4114 | .interrupt_disable = pm80xx_chip_interrupt_disable, | ||
| 4115 | .make_prd = pm8001_chip_make_sg, | ||
| 4116 | .smp_req = pm80xx_chip_smp_req, | ||
| 4117 | .ssp_io_req = pm80xx_chip_ssp_io_req, | ||
| 4118 | .sata_req = pm80xx_chip_sata_req, | ||
| 4119 | .phy_start_req = pm80xx_chip_phy_start_req, | ||
| 4120 | .phy_stop_req = pm80xx_chip_phy_stop_req, | ||
| 4121 | .reg_dev_req = pm80xx_chip_reg_dev_req, | ||
| 4122 | .dereg_dev_req = pm8001_chip_dereg_dev_req, | ||
| 4123 | .phy_ctl_req = pm80xx_chip_phy_ctl_req, | ||
| 4124 | .task_abort = pm8001_chip_abort_task, | ||
| 4125 | .ssp_tm_req = pm8001_chip_ssp_tm_req, | ||
| 4126 | .get_nvmd_req = pm8001_chip_get_nvmd_req, | ||
| 4127 | .set_nvmd_req = pm8001_chip_set_nvmd_req, | ||
| 4128 | .fw_flash_update_req = pm8001_chip_fw_flash_update_req, | ||
| 4129 | .set_dev_state_req = pm8001_chip_set_dev_state_req, | ||
| 4130 | }; | ||
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h new file mode 100644 index 000000000000..2b760ba75d7b --- /dev/null +++ b/drivers/scsi/pm8001/pm80xx_hwi.h | |||
| @@ -0,0 +1,1523 @@ | |||
| 1 | /* | ||
| 2 | * PMC-Sierra SPCv/ve 8088/8089 SAS/SATA based host adapters driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008-2009 USI Co., Ltd. | ||
| 5 | * All rights reserved. | ||
| 6 | * | ||
| 7 | * Redistribution and use in source and binary forms, with or without | ||
| 8 | * modification, are permitted provided that the following conditions | ||
| 9 | * are met: | ||
| 10 | * 1. Redistributions of source code must retain the above copyright | ||
| 11 | * notice, this list of conditions, and the following disclaimer, | ||
| 12 | * without modification. | ||
| 13 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
| 14 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
| 15 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
| 16 | * including a substantially similar Disclaimer requirement for further | ||
| 17 | * binary redistribution. | ||
| 18 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
| 19 | * of any contributors may be used to endorse or promote products derived | ||
| 20 | * from this software without specific prior written permission. | ||
| 21 | * | ||
| 22 | * Alternatively, this software may be distributed under the terms of the | ||
| 23 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
| 24 | * Software Foundation. | ||
| 25 | * | ||
| 26 | * NO WARRANTY | ||
| 27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 28 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 29 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
| 30 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 31 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 33 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
| 35 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
| 36 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 37 | * POSSIBILITY OF SUCH DAMAGES. | ||
| 38 | * | ||
| 39 | */ | ||
| 40 | |||
| 41 | #ifndef _PMC8001_REG_H_ | ||
| 42 | #define _PMC8001_REG_H_ | ||
| 43 | |||
| 44 | #include <linux/types.h> | ||
| 45 | #include <scsi/libsas.h> | ||
| 46 | |||
| 47 | /* for Request Opcode of IOMB */ | ||
| 48 | #define OPC_INB_ECHO 1 /* 0x000 */ | ||
| 49 | #define OPC_INB_PHYSTART 4 /* 0x004 */ | ||
| 50 | #define OPC_INB_PHYSTOP 5 /* 0x005 */ | ||
| 51 | #define OPC_INB_SSPINIIOSTART 6 /* 0x006 */ | ||
| 52 | #define OPC_INB_SSPINITMSTART 7 /* 0x007 */ | ||
| 53 | /* 0x8 RESV IN SPCv */ | ||
| 54 | #define OPC_INB_RSVD 8 /* 0x008 */ | ||
| 55 | #define OPC_INB_DEV_HANDLE_ACCEPT 9 /* 0x009 */ | ||
| 56 | #define OPC_INB_SSPTGTIOSTART 10 /* 0x00A */ | ||
| 57 | #define OPC_INB_SSPTGTRSPSTART 11 /* 0x00B */ | ||
| 58 | /* 0xC, 0xD, 0xE removed in SPCv */ | ||
| 59 | #define OPC_INB_SSP_ABORT 15 /* 0x00F */ | ||
| 60 | #define OPC_INB_DEREG_DEV_HANDLE 16 /* 0x010 */ | ||
| 61 | #define OPC_INB_GET_DEV_HANDLE 17 /* 0x011 */ | ||
| 62 | #define OPC_INB_SMP_REQUEST 18 /* 0x012 */ | ||
| 63 | /* 0x13 SMP_RESPONSE is removed in SPCv */ | ||
| 64 | #define OPC_INB_SMP_ABORT 20 /* 0x014 */ | ||
| 65 | /* 0x16 RESV IN SPCv */ | ||
| 66 | #define OPC_INB_RSVD1 22 /* 0x016 */ | ||
| 67 | #define OPC_INB_SATA_HOST_OPSTART 23 /* 0x017 */ | ||
| 68 | #define OPC_INB_SATA_ABORT 24 /* 0x018 */ | ||
| 69 | #define OPC_INB_LOCAL_PHY_CONTROL 25 /* 0x019 */ | ||
| 70 | /* 0x1A RESV IN SPCv */ | ||
| 71 | #define OPC_INB_RSVD2 26 /* 0x01A */ | ||
| 72 | #define OPC_INB_FW_FLASH_UPDATE 32 /* 0x020 */ | ||
| 73 | #define OPC_INB_GPIO 34 /* 0x022 */ | ||
| 74 | #define OPC_INB_SAS_DIAG_MODE_START_END 35 /* 0x023 */ | ||
| 75 | #define OPC_INB_SAS_DIAG_EXECUTE 36 /* 0x024 */ | ||
| 76 | /* 0x25 RESV IN SPCv */ | ||
| 77 | #define OPC_INB_RSVD3 37 /* 0x025 */ | ||
| 78 | #define OPC_INB_GET_TIME_STAMP 38 /* 0x026 */ | ||
| 79 | #define OPC_INB_PORT_CONTROL 39 /* 0x027 */ | ||
| 80 | #define OPC_INB_GET_NVMD_DATA 40 /* 0x028 */ | ||
| 81 | #define OPC_INB_SET_NVMD_DATA 41 /* 0x029 */ | ||
| 82 | #define OPC_INB_SET_DEVICE_STATE 42 /* 0x02A */ | ||
| 83 | #define OPC_INB_GET_DEVICE_STATE 43 /* 0x02B */ | ||
| 84 | #define OPC_INB_SET_DEV_INFO 44 /* 0x02C */ | ||
| 85 | /* 0x2D RESV IN SPCv */ | ||
| 86 | #define OPC_INB_RSVD4 45 /* 0x02D */ | ||
| 87 | #define OPC_INB_SGPIO_REGISTER 46 /* 0x02E */ | ||
| 88 | #define OPC_INB_PCIE_DIAG_EXEC 47 /* 0x02F */ | ||
| 89 | #define OPC_INB_SET_CONTROLLER_CONFIG 48 /* 0x030 */ | ||
| 90 | #define OPC_INB_GET_CONTROLLER_CONFIG 49 /* 0x031 */ | ||
| 91 | #define OPC_INB_REG_DEV 50 /* 0x032 */ | ||
| 92 | #define OPC_INB_SAS_HW_EVENT_ACK 51 /* 0x033 */ | ||
| 93 | #define OPC_INB_GET_DEVICE_INFO 52 /* 0x034 */ | ||
| 94 | #define OPC_INB_GET_PHY_PROFILE 53 /* 0x035 */ | ||
| 95 | #define OPC_INB_FLASH_OP_EXT 54 /* 0x036 */ | ||
| 96 | #define OPC_INB_SET_PHY_PROFILE 55 /* 0x037 */ | ||
| 97 | #define OPC_INB_KEK_MANAGEMENT 256 /* 0x100 */ | ||
| 98 | #define OPC_INB_DEK_MANAGEMENT 257 /* 0x101 */ | ||
| 99 | #define OPC_INB_SSP_INI_DIF_ENC_IO 258 /* 0x102 */ | ||
| 100 | #define OPC_INB_SATA_DIF_ENC_IO 259 /* 0x103 */ | ||
| 101 | |||
| 102 | /* for Response Opcode of IOMB */ | ||
| 103 | #define OPC_OUB_ECHO 1 /* 0x001 */ | ||
| 104 | #define OPC_OUB_RSVD 4 /* 0x004 */ | ||
| 105 | #define OPC_OUB_SSP_COMP 5 /* 0x005 */ | ||
| 106 | #define OPC_OUB_SMP_COMP 6 /* 0x006 */ | ||
| 107 | #define OPC_OUB_LOCAL_PHY_CNTRL 7 /* 0x007 */ | ||
| 108 | #define OPC_OUB_RSVD1 10 /* 0x00A */ | ||
| 109 | #define OPC_OUB_DEREG_DEV 11 /* 0x00B */ | ||
| 110 | #define OPC_OUB_GET_DEV_HANDLE 12 /* 0x00C */ | ||
| 111 | #define OPC_OUB_SATA_COMP 13 /* 0x00D */ | ||
| 112 | #define OPC_OUB_SATA_EVENT 14 /* 0x00E */ | ||
| 113 | #define OPC_OUB_SSP_EVENT 15 /* 0x00F */ | ||
| 114 | #define OPC_OUB_RSVD2 16 /* 0x010 */ | ||
| 115 | /* 0x11 - SMP_RECEIVED Notification removed in SPCv*/ | ||
| 116 | #define OPC_OUB_SSP_RECV_EVENT 18 /* 0x012 */ | ||
| 117 | #define OPC_OUB_RSVD3 19 /* 0x013 */ | ||
| 118 | #define OPC_OUB_FW_FLASH_UPDATE 20 /* 0x014 */ | ||
| 119 | #define OPC_OUB_GPIO_RESPONSE 22 /* 0x016 */ | ||
| 120 | #define OPC_OUB_GPIO_EVENT 23 /* 0x017 */ | ||
| 121 | #define OPC_OUB_GENERAL_EVENT 24 /* 0x018 */ | ||
| 122 | #define OPC_OUB_SSP_ABORT_RSP 26 /* 0x01A */ | ||
| 123 | #define OPC_OUB_SATA_ABORT_RSP 27 /* 0x01B */ | ||
| 124 | #define OPC_OUB_SAS_DIAG_MODE_START_END 28 /* 0x01C */ | ||
| 125 | #define OPC_OUB_SAS_DIAG_EXECUTE 29 /* 0x01D */ | ||
| 126 | #define OPC_OUB_GET_TIME_STAMP 30 /* 0x01E */ | ||
| 127 | #define OPC_OUB_RSVD4 31 /* 0x01F */ | ||
| 128 | #define OPC_OUB_PORT_CONTROL 32 /* 0x020 */ | ||
| 129 | #define OPC_OUB_SKIP_ENTRY 33 /* 0x021 */ | ||
| 130 | #define OPC_OUB_SMP_ABORT_RSP 34 /* 0x022 */ | ||
| 131 | #define OPC_OUB_GET_NVMD_DATA 35 /* 0x023 */ | ||
| 132 | #define OPC_OUB_SET_NVMD_DATA 36 /* 0x024 */ | ||
| 133 | #define OPC_OUB_DEVICE_HANDLE_REMOVAL 37 /* 0x025 */ | ||
| 134 | #define OPC_OUB_SET_DEVICE_STATE 38 /* 0x026 */ | ||
| 135 | #define OPC_OUB_GET_DEVICE_STATE 39 /* 0x027 */ | ||
| 136 | #define OPC_OUB_SET_DEV_INFO 40 /* 0x028 */ | ||
| 137 | #define OPC_OUB_RSVD5 41 /* 0x029 */ | ||
| 138 | #define OPC_OUB_HW_EVENT 1792 /* 0x700 */ | ||
| 139 | #define OPC_OUB_DEV_HANDLE_ARRIV 1824 /* 0x720 */ | ||
| 140 | #define OPC_OUB_THERM_HW_EVENT 1840 /* 0x730 */ | ||
| 141 | #define OPC_OUB_SGPIO_RESP 2094 /* 0x82E */ | ||
| 142 | #define OPC_OUB_PCIE_DIAG_EXECUTE 2095 /* 0x82F */ | ||
| 143 | #define OPC_OUB_DEV_REGIST 2098 /* 0x832 */ | ||
| 144 | #define OPC_OUB_SAS_HW_EVENT_ACK 2099 /* 0x833 */ | ||
| 145 | #define OPC_OUB_GET_DEVICE_INFO 2100 /* 0x834 */ | ||
| 146 | /* spcv specific commands */ | ||
| 147 | #define OPC_OUB_PHY_START_RESP 2052 /* 0x804 */ | ||
| 148 | #define OPC_OUB_PHY_STOP_RESP 2053 /* 0x805 */ | ||
| 149 | #define OPC_OUB_SET_CONTROLLER_CONFIG 2096 /* 0x830 */ | ||
| 150 | #define OPC_OUB_GET_CONTROLLER_CONFIG 2097 /* 0x831 */ | ||
| 151 | #define OPC_OUB_GET_PHY_PROFILE 2101 /* 0x835 */ | ||
| 152 | #define OPC_OUB_FLASH_OP_EXT 2102 /* 0x836 */ | ||
| 153 | #define OPC_OUB_SET_PHY_PROFILE 2103 /* 0x837 */ | ||
| 154 | #define OPC_OUB_KEK_MANAGEMENT_RESP 2304 /* 0x900 */ | ||
| 155 | #define OPC_OUB_DEK_MANAGEMENT_RESP 2305 /* 0x901 */ | ||
| 156 | #define OPC_OUB_SSP_COALESCED_COMP_RESP 2306 /* 0x902 */ | ||
| 157 | |||
| 158 | /* for phy start*/ | ||
| 159 | #define SSC_DISABLE_15 (0x01 << 16) | ||
| 160 | #define SSC_DISABLE_30 (0x02 << 16) | ||
| 161 | #define SSC_DISABLE_60 (0x04 << 16) | ||
| 162 | #define SAS_ASE (0x01 << 15) | ||
| 163 | #define SPINHOLD_DISABLE (0x00 << 14) | ||
| 164 | #define SPINHOLD_ENABLE (0x01 << 14) | ||
| 165 | #define LINKMODE_SAS (0x01 << 12) | ||
| 166 | #define LINKMODE_DSATA (0x02 << 12) | ||
| 167 | #define LINKMODE_AUTO (0x03 << 12) | ||
| 168 | #define LINKRATE_15 (0x01 << 8) | ||
| 169 | #define LINKRATE_30 (0x02 << 8) | ||
| 170 | #define LINKRATE_60 (0x06 << 8) | ||
| 171 | |||
| 172 | /* Thermal related */ | ||
| 173 | #define THERMAL_ENABLE 0x1 | ||
| 174 | #define THERMAL_LOG_ENABLE 0x1 | ||
| 175 | #define THERMAL_OP_CODE 0x6 | ||
| 176 | #define LTEMPHIL 70 | ||
| 177 | #define RTEMPHIL 100 | ||
| 178 | |||
| 179 | /* Encryption info */ | ||
| 180 | #define SCRATCH_PAD3_ENC_DISABLED 0x00000000 | ||
| 181 | #define SCRATCH_PAD3_ENC_DIS_ERR 0x00000001 | ||
| 182 | #define SCRATCH_PAD3_ENC_ENA_ERR 0x00000002 | ||
| 183 | #define SCRATCH_PAD3_ENC_READY 0x00000003 | ||
| 184 | #define SCRATCH_PAD3_ENC_MASK SCRATCH_PAD3_ENC_READY | ||
| 185 | |||
| 186 | #define SCRATCH_PAD3_XTS_ENABLED (1 << 14) | ||
| 187 | #define SCRATCH_PAD3_SMA_ENABLED (1 << 4) | ||
| 188 | #define SCRATCH_PAD3_SMB_ENABLED (1 << 5) | ||
| 189 | #define SCRATCH_PAD3_SMF_ENABLED 0 | ||
| 190 | #define SCRATCH_PAD3_SM_MASK 0x000000F0 | ||
| 191 | #define SCRATCH_PAD3_ERR_CODE 0x00FF0000 | ||
| 192 | |||
| 193 | #define SEC_MODE_SMF 0x0 | ||
| 194 | #define SEC_MODE_SMA 0x100 | ||
| 195 | #define SEC_MODE_SMB 0x200 | ||
| 196 | #define CIPHER_MODE_ECB 0x00000001 | ||
| 197 | #define CIPHER_MODE_XTS 0x00000002 | ||
| 198 | #define KEK_MGMT_SUBOP_KEYCARDUPDATE 0x4 | ||
| 199 | |||
| 200 | /* SAS protocol timer configuration page */ | ||
| 201 | #define SAS_PROTOCOL_TIMER_CONFIG_PAGE 0x04 | ||
| 202 | #define STP_MCT_TMO 32 | ||
| 203 | #define SSP_MCT_TMO 32 | ||
| 204 | #define SAS_MAX_OPEN_TIME 5 | ||
| 205 | #define SMP_MAX_CONN_TIMER 0xFF | ||
| 206 | #define STP_FRM_TIMER 0 | ||
| 207 | #define STP_IDLE_TIME 5 /* 5 us; controller default */ | ||
| 208 | #define SAS_MFD 0 | ||
| 209 | #define SAS_OPNRJT_RTRY_INTVL 2 | ||
| 210 | #define SAS_DOPNRJT_RTRY_TMO 128 | ||
| 211 | #define SAS_COPNRJT_RTRY_TMO 128 | ||
| 212 | |||
| 213 | /* | ||
| 214 | Making ORR bigger than IT NEXUS LOSS which is 2000000us = 2 second. | ||
| 215 | Assuming a bigger value 3 second, 3000000/128 = 23437.5 where 128 | ||
| 216 | is DOPNRJT_RTRY_TMO | ||
| 217 | */ | ||
| 218 | #define SAS_DOPNRJT_RTRY_THR 23438 | ||
| 219 | #define SAS_COPNRJT_RTRY_THR 23438 | ||
| 220 | #define SAS_MAX_AIP 0x200000 | ||
| 221 | #define IT_NEXUS_TIMEOUT 0x7D0 | ||
| 222 | #define PORT_RECOVERY_TIMEOUT ((IT_NEXUS_TIMEOUT/100) + 30) | ||
| 223 | |||
| 224 | struct mpi_msg_hdr { | ||
| 225 | __le32 header; /* Bits [11:0] - Message operation code */ | ||
| 226 | /* Bits [15:12] - Message Category */ | ||
| 227 | /* Bits [21:16] - Outboundqueue ID for the | ||
| 228 | operation completion message */ | ||
| 229 | /* Bits [23:22] - Reserved */ | ||
| 230 | /* Bits [28:24] - Buffer Count, indicates how | ||
| 231 | many buffer are allocated for the massage */ | ||
| 232 | /* Bits [30:29] - Reserved */ | ||
| 233 | /* Bits [31] - Message Valid bit */ | ||
| 234 | } __attribute__((packed, aligned(4))); | ||
| 235 | |||
| 236 | /* | ||
| 237 | * brief the data structure of PHY Start Command | ||
| 238 | * use to describe enable the phy (128 bytes) | ||
| 239 | */ | ||
| 240 | struct phy_start_req { | ||
| 241 | __le32 tag; | ||
| 242 | __le32 ase_sh_lm_slr_phyid; | ||
| 243 | struct sas_identify_frame sas_identify; /* 28 Bytes */ | ||
| 244 | __le32 spasti; | ||
| 245 | u32 reserved[21]; | ||
| 246 | } __attribute__((packed, aligned(4))); | ||
| 247 | |||
| 248 | /* | ||
| 249 | * brief the data structure of PHY Start Command | ||
| 250 | * use to disable the phy (128 bytes) | ||
| 251 | */ | ||
| 252 | struct phy_stop_req { | ||
| 253 | __le32 tag; | ||
| 254 | __le32 phy_id; | ||
| 255 | u32 reserved[29]; | ||
| 256 | } __attribute__((packed, aligned(4))); | ||
| 257 | |||
| 258 | /* set device bits fis - device to host */ | ||
| 259 | struct set_dev_bits_fis { | ||
| 260 | u8 fis_type; /* 0xA1*/ | ||
| 261 | u8 n_i_pmport; | ||
| 262 | /* b7 : n Bit. Notification bit. If set device needs attention. */ | ||
| 263 | /* b6 : i Bit. Interrupt Bit */ | ||
| 264 | /* b5-b4: reserved2 */ | ||
| 265 | /* b3-b0: PM Port */ | ||
| 266 | u8 status; | ||
| 267 | u8 error; | ||
| 268 | u32 _r_a; | ||
| 269 | } __attribute__ ((packed)); | ||
| 270 | /* PIO setup FIS - device to host */ | ||
| 271 | struct pio_setup_fis { | ||
| 272 | u8 fis_type; /* 0x5f */ | ||
| 273 | u8 i_d_pmPort; | ||
| 274 | /* b7 : reserved */ | ||
| 275 | /* b6 : i bit. Interrupt bit */ | ||
| 276 | /* b5 : d bit. data transfer direction. set to 1 for device to host | ||
| 277 | xfer */ | ||
| 278 | /* b4 : reserved */ | ||
| 279 | /* b3-b0: PM Port */ | ||
| 280 | u8 status; | ||
| 281 | u8 error; | ||
| 282 | u8 lbal; | ||
| 283 | u8 lbam; | ||
| 284 | u8 lbah; | ||
| 285 | u8 device; | ||
| 286 | u8 lbal_exp; | ||
| 287 | u8 lbam_exp; | ||
| 288 | u8 lbah_exp; | ||
| 289 | u8 _r_a; | ||
| 290 | u8 sector_count; | ||
| 291 | u8 sector_count_exp; | ||
| 292 | u8 _r_b; | ||
| 293 | u8 e_status; | ||
| 294 | u8 _r_c[2]; | ||
| 295 | u8 transfer_count; | ||
| 296 | } __attribute__ ((packed)); | ||
| 297 | |||
| 298 | /* | ||
| 299 | * brief the data structure of SATA Completion Response | ||
| 300 | * use to describe the sata task response (64 bytes) | ||
| 301 | */ | ||
| 302 | struct sata_completion_resp { | ||
| 303 | __le32 tag; | ||
| 304 | __le32 status; | ||
| 305 | __le32 param; | ||
| 306 | u32 sata_resp[12]; | ||
| 307 | } __attribute__((packed, aligned(4))); | ||
| 308 | |||
| 309 | /* | ||
| 310 | * brief the data structure of SAS HW Event Notification | ||
| 311 | * use to alert the host about the hardware event(64 bytes) | ||
| 312 | */ | ||
| 313 | /* updated outbound struct for spcv */ | ||
| 314 | |||
| 315 | struct hw_event_resp { | ||
| 316 | __le32 lr_status_evt_portid; | ||
| 317 | __le32 evt_param; | ||
| 318 | __le32 phyid_npip_portstate; | ||
| 319 | struct sas_identify_frame sas_identify; | ||
| 320 | struct dev_to_host_fis sata_fis; | ||
| 321 | } __attribute__((packed, aligned(4))); | ||
| 322 | |||
| 323 | /* | ||
| 324 | * brief the data structure for thermal event notification | ||
| 325 | */ | ||
| 326 | |||
| 327 | struct thermal_hw_event { | ||
| 328 | __le32 thermal_event; | ||
| 329 | __le32 rht_lht; | ||
| 330 | } __attribute__((packed, aligned(4))); | ||
| 331 | |||
| 332 | /* | ||
| 333 | * brief the data structure of REGISTER DEVICE Command | ||
| 334 | * use to describe MPI REGISTER DEVICE Command (64 bytes) | ||
| 335 | */ | ||
| 336 | |||
| 337 | struct reg_dev_req { | ||
| 338 | __le32 tag; | ||
| 339 | __le32 phyid_portid; | ||
| 340 | __le32 dtype_dlr_mcn_ir_retry; | ||
| 341 | __le32 firstburstsize_ITNexustimeout; | ||
| 342 | u8 sas_addr[SAS_ADDR_SIZE]; | ||
| 343 | __le32 upper_device_id; | ||
| 344 | u32 reserved[24]; | ||
| 345 | } __attribute__((packed, aligned(4))); | ||
| 346 | |||
| 347 | /* | ||
| 348 | * brief the data structure of DEREGISTER DEVICE Command | ||
| 349 | * use to request spc to remove all internal resources associated | ||
| 350 | * with the device id (64 bytes) | ||
| 351 | */ | ||
| 352 | |||
| 353 | struct dereg_dev_req { | ||
| 354 | __le32 tag; | ||
| 355 | __le32 device_id; | ||
| 356 | u32 reserved[29]; | ||
| 357 | } __attribute__((packed, aligned(4))); | ||
| 358 | |||
| 359 | /* | ||
| 360 | * brief the data structure of DEVICE_REGISTRATION Response | ||
| 361 | * use to notify the completion of the device registration (64 bytes) | ||
| 362 | */ | ||
| 363 | struct dev_reg_resp { | ||
| 364 | __le32 tag; | ||
| 365 | __le32 status; | ||
| 366 | __le32 device_id; | ||
| 367 | u32 reserved[12]; | ||
| 368 | } __attribute__((packed, aligned(4))); | ||
| 369 | |||
| 370 | /* | ||
| 371 | * brief the data structure of Local PHY Control Command | ||
| 372 | * use to issue PHY CONTROL to local phy (64 bytes) | ||
| 373 | */ | ||
| 374 | struct local_phy_ctl_req { | ||
| 375 | __le32 tag; | ||
| 376 | __le32 phyop_phyid; | ||
| 377 | u32 reserved1[29]; | ||
| 378 | } __attribute__((packed, aligned(4))); | ||
| 379 | |||
| 380 | /** | ||
| 381 | * brief the data structure of Local Phy Control Response | ||
| 382 | * use to describe MPI Local Phy Control Response (64 bytes) | ||
| 383 | */ | ||
| 384 | struct local_phy_ctl_resp { | ||
| 385 | __le32 tag; | ||
| 386 | __le32 phyop_phyid; | ||
| 387 | __le32 status; | ||
| 388 | u32 reserved[12]; | ||
| 389 | } __attribute__((packed, aligned(4))); | ||
| 390 | |||
| 391 | #define OP_BITS 0x0000FF00 | ||
| 392 | #define ID_BITS 0x000000FF | ||
| 393 | |||
| 394 | /* | ||
| 395 | * brief the data structure of PORT Control Command | ||
| 396 | * use to control port properties (64 bytes) | ||
| 397 | */ | ||
| 398 | |||
| 399 | struct port_ctl_req { | ||
| 400 | __le32 tag; | ||
| 401 | __le32 portop_portid; | ||
| 402 | __le32 param0; | ||
| 403 | __le32 param1; | ||
| 404 | u32 reserved1[27]; | ||
| 405 | } __attribute__((packed, aligned(4))); | ||
| 406 | |||
| 407 | /* | ||
| 408 | * brief the data structure of HW Event Ack Command | ||
| 409 | * use to acknowledge receive HW event (64 bytes) | ||
| 410 | */ | ||
| 411 | struct hw_event_ack_req { | ||
| 412 | __le32 tag; | ||
| 413 | __le32 phyid_sea_portid; | ||
| 414 | __le32 param0; | ||
| 415 | __le32 param1; | ||
| 416 | u32 reserved1[27]; | ||
| 417 | } __attribute__((packed, aligned(4))); | ||
| 418 | |||
| 419 | /* | ||
| 420 | * brief the data structure of PHY_START Response Command | ||
| 421 | * indicates the completion of PHY_START command (64 bytes) | ||
| 422 | */ | ||
| 423 | struct phy_start_resp { | ||
| 424 | __le32 tag; | ||
| 425 | __le32 status; | ||
| 426 | __le32 phyid; | ||
| 427 | u32 reserved[12]; | ||
| 428 | } __attribute__((packed, aligned(4))); | ||
| 429 | |||
| 430 | /* | ||
| 431 | * brief the data structure of PHY_STOP Response Command | ||
| 432 | * indicates the completion of PHY_STOP command (64 bytes) | ||
| 433 | */ | ||
| 434 | struct phy_stop_resp { | ||
| 435 | __le32 tag; | ||
| 436 | __le32 status; | ||
| 437 | __le32 phyid; | ||
| 438 | u32 reserved[12]; | ||
| 439 | } __attribute__((packed, aligned(4))); | ||
| 440 | |||
| 441 | /* | ||
| 442 | * brief the data structure of SSP Completion Response | ||
| 443 | * use to indicate a SSP Completion (n bytes) | ||
| 444 | */ | ||
| 445 | struct ssp_completion_resp { | ||
| 446 | __le32 tag; | ||
| 447 | __le32 status; | ||
| 448 | __le32 param; | ||
| 449 | __le32 ssptag_rescv_rescpad; | ||
| 450 | struct ssp_response_iu ssp_resp_iu; | ||
| 451 | __le32 residual_count; | ||
| 452 | } __attribute__((packed, aligned(4))); | ||
| 453 | |||
| 454 | #define SSP_RESCV_BIT 0x00010000 | ||
| 455 | |||
| 456 | /* | ||
| 457 | * brief the data structure of SATA EVNET response | ||
| 458 | * use to indicate a SATA Completion (64 bytes) | ||
| 459 | */ | ||
| 460 | struct sata_event_resp { | ||
| 461 | __le32 tag; | ||
| 462 | __le32 event; | ||
| 463 | __le32 port_id; | ||
| 464 | __le32 device_id; | ||
| 465 | u32 reserved; | ||
| 466 | __le32 event_param0; | ||
| 467 | __le32 event_param1; | ||
| 468 | __le32 sata_addr_h32; | ||
| 469 | __le32 sata_addr_l32; | ||
| 470 | __le32 e_udt1_udt0_crc; | ||
| 471 | __le32 e_udt5_udt4_udt3_udt2; | ||
| 472 | __le32 a_udt1_udt0_crc; | ||
| 473 | __le32 a_udt5_udt4_udt3_udt2; | ||
| 474 | __le32 hwdevid_diferr; | ||
| 475 | __le32 err_framelen_byteoffset; | ||
| 476 | __le32 err_dataframe; | ||
| 477 | } __attribute__((packed, aligned(4))); | ||
| 478 | |||
| 479 | /* | ||
| 480 | * brief the data structure of SSP EVNET esponse | ||
| 481 | * use to indicate a SSP Completion (64 bytes) | ||
| 482 | */ | ||
| 483 | struct ssp_event_resp { | ||
| 484 | __le32 tag; | ||
| 485 | __le32 event; | ||
| 486 | __le32 port_id; | ||
| 487 | __le32 device_id; | ||
| 488 | __le32 ssp_tag; | ||
| 489 | __le32 event_param0; | ||
| 490 | __le32 event_param1; | ||
| 491 | __le32 sas_addr_h32; | ||
| 492 | __le32 sas_addr_l32; | ||
| 493 | __le32 e_udt1_udt0_crc; | ||
| 494 | __le32 e_udt5_udt4_udt3_udt2; | ||
| 495 | __le32 a_udt1_udt0_crc; | ||
| 496 | __le32 a_udt5_udt4_udt3_udt2; | ||
| 497 | __le32 hwdevid_diferr; | ||
| 498 | __le32 err_framelen_byteoffset; | ||
| 499 | __le32 err_dataframe; | ||
| 500 | } __attribute__((packed, aligned(4))); | ||
| 501 | |||
| 502 | /** | ||
| 503 | * brief the data structure of General Event Notification Response | ||
| 504 | * use to describe MPI General Event Notification Response (64 bytes) | ||
| 505 | */ | ||
| 506 | struct general_event_resp { | ||
| 507 | __le32 status; | ||
| 508 | __le32 inb_IOMB_payload[14]; | ||
| 509 | } __attribute__((packed, aligned(4))); | ||
| 510 | |||
| 511 | #define GENERAL_EVENT_PAYLOAD 14 | ||
| 512 | #define OPCODE_BITS 0x00000fff | ||
| 513 | |||
| 514 | /* | ||
| 515 | * brief the data structure of SMP Request Command | ||
| 516 | * use to describe MPI SMP REQUEST Command (64 bytes) | ||
| 517 | */ | ||
| 518 | struct smp_req { | ||
| 519 | __le32 tag; | ||
| 520 | __le32 device_id; | ||
| 521 | __le32 len_ip_ir; | ||
| 522 | /* Bits [0] - Indirect response */ | ||
| 523 | /* Bits [1] - Indirect Payload */ | ||
| 524 | /* Bits [15:2] - Reserved */ | ||
| 525 | /* Bits [23:16] - direct payload Len */ | ||
| 526 | /* Bits [31:24] - Reserved */ | ||
| 527 | u8 smp_req16[16]; | ||
| 528 | union { | ||
| 529 | u8 smp_req[32]; | ||
| 530 | struct { | ||
| 531 | __le64 long_req_addr;/* sg dma address, LE */ | ||
| 532 | __le32 long_req_size;/* LE */ | ||
| 533 | u32 _r_a; | ||
| 534 | __le64 long_resp_addr;/* sg dma address, LE */ | ||
| 535 | __le32 long_resp_size;/* LE */ | ||
| 536 | u32 _r_b; | ||
| 537 | } long_smp_req;/* sequencer extension */ | ||
| 538 | }; | ||
| 539 | __le32 rsvd[16]; | ||
| 540 | } __attribute__((packed, aligned(4))); | ||
| 541 | /* | ||
| 542 | * brief the data structure of SMP Completion Response | ||
| 543 | * use to describe MPI SMP Completion Response (64 bytes) | ||
| 544 | */ | ||
| 545 | struct smp_completion_resp { | ||
| 546 | __le32 tag; | ||
| 547 | __le32 status; | ||
| 548 | __le32 param; | ||
| 549 | u8 _r_a[252]; | ||
| 550 | } __attribute__((packed, aligned(4))); | ||
| 551 | |||
| 552 | /* | ||
| 553 | *brief the data structure of SSP SMP SATA Abort Command | ||
| 554 | * use to describe MPI SSP SMP & SATA Abort Command (64 bytes) | ||
| 555 | */ | ||
| 556 | struct task_abort_req { | ||
| 557 | __le32 tag; | ||
| 558 | __le32 device_id; | ||
| 559 | __le32 tag_to_abort; | ||
| 560 | __le32 abort_all; | ||
| 561 | u32 reserved[27]; | ||
| 562 | } __attribute__((packed, aligned(4))); | ||
| 563 | |||
| 564 | /* These flags used for SSP SMP & SATA Abort */ | ||
| 565 | #define ABORT_MASK 0x3 | ||
| 566 | #define ABORT_SINGLE 0x0 | ||
| 567 | #define ABORT_ALL 0x1 | ||
| 568 | |||
| 569 | /** | ||
| 570 | * brief the data structure of SSP SATA SMP Abort Response | ||
| 571 | * use to describe SSP SMP & SATA Abort Response ( 64 bytes) | ||
| 572 | */ | ||
| 573 | struct task_abort_resp { | ||
| 574 | __le32 tag; | ||
| 575 | __le32 status; | ||
| 576 | __le32 scp; | ||
| 577 | u32 reserved[12]; | ||
| 578 | } __attribute__((packed, aligned(4))); | ||
| 579 | |||
| 580 | /** | ||
| 581 | * brief the data structure of SAS Diagnostic Start/End Command | ||
| 582 | * use to describe MPI SAS Diagnostic Start/End Command (64 bytes) | ||
| 583 | */ | ||
| 584 | struct sas_diag_start_end_req { | ||
| 585 | __le32 tag; | ||
| 586 | __le32 operation_phyid; | ||
| 587 | u32 reserved[29]; | ||
| 588 | } __attribute__((packed, aligned(4))); | ||
| 589 | |||
| 590 | /** | ||
| 591 | * brief the data structure of SAS Diagnostic Execute Command | ||
| 592 | * use to describe MPI SAS Diagnostic Execute Command (64 bytes) | ||
| 593 | */ | ||
| 594 | struct sas_diag_execute_req { | ||
| 595 | __le32 tag; | ||
| 596 | __le32 cmdtype_cmddesc_phyid; | ||
| 597 | __le32 pat1_pat2; | ||
| 598 | __le32 threshold; | ||
| 599 | __le32 codepat_errmsk; | ||
| 600 | __le32 pmon; | ||
| 601 | __le32 pERF1CTL; | ||
| 602 | u32 reserved[24]; | ||
| 603 | } __attribute__((packed, aligned(4))); | ||
| 604 | |||
| 605 | #define SAS_DIAG_PARAM_BYTES 24 | ||
| 606 | |||
| 607 | /* | ||
| 608 | * brief the data structure of Set Device State Command | ||
| 609 | * use to describe MPI Set Device State Command (64 bytes) | ||
| 610 | */ | ||
| 611 | struct set_dev_state_req { | ||
| 612 | __le32 tag; | ||
| 613 | __le32 device_id; | ||
| 614 | __le32 nds; | ||
| 615 | u32 reserved[28]; | ||
| 616 | } __attribute__((packed, aligned(4))); | ||
| 617 | |||
| 618 | /* | ||
| 619 | * brief the data structure of SATA Start Command | ||
| 620 | * use to describe MPI SATA IO Start Command (64 bytes) | ||
| 621 | * Note: This structure is common for normal / encryption I/O | ||
| 622 | */ | ||
| 623 | |||
| 624 | struct sata_start_req { | ||
| 625 | __le32 tag; | ||
| 626 | __le32 device_id; | ||
| 627 | __le32 data_len; | ||
| 628 | __le32 ncqtag_atap_dir_m_dad; | ||
| 629 | struct host_to_dev_fis sata_fis; | ||
| 630 | u32 reserved1; | ||
| 631 | u32 reserved2; /* dword 11. rsvd for normal I/O. */ | ||
| 632 | /* EPLE Descl for enc I/O */ | ||
| 633 | u32 addr_low; /* dword 12. rsvd for enc I/O */ | ||
| 634 | u32 addr_high; /* dword 13. reserved for enc I/O */ | ||
| 635 | __le32 len; /* dword 14: length for normal I/O. */ | ||
| 636 | /* EPLE Desch for enc I/O */ | ||
| 637 | __le32 esgl; /* dword 15. rsvd for enc I/O */ | ||
| 638 | __le32 atapi_scsi_cdb[4]; /* dword 16-19. rsvd for enc I/O */ | ||
| 639 | /* The below fields are reserved for normal I/O */ | ||
| 640 | __le32 key_index_mode; /* dword 20 */ | ||
| 641 | __le32 sector_cnt_enss;/* dword 21 */ | ||
| 642 | __le32 keytagl; /* dword 22 */ | ||
| 643 | __le32 keytagh; /* dword 23 */ | ||
| 644 | __le32 twk_val0; /* dword 24 */ | ||
| 645 | __le32 twk_val1; /* dword 25 */ | ||
| 646 | __le32 twk_val2; /* dword 26 */ | ||
| 647 | __le32 twk_val3; /* dword 27 */ | ||
| 648 | __le32 enc_addr_low; /* dword 28. Encryption SGL address high */ | ||
| 649 | __le32 enc_addr_high; /* dword 29. Encryption SGL address low */ | ||
| 650 | __le32 enc_len; /* dword 30. Encryption length */ | ||
| 651 | __le32 enc_esgl; /* dword 31. Encryption esgl bit */ | ||
| 652 | } __attribute__((packed, aligned(4))); | ||
| 653 | |||
| 654 | /** | ||
| 655 | * brief the data structure of SSP INI TM Start Command | ||
| 656 | * use to describe MPI SSP INI TM Start Command (64 bytes) | ||
| 657 | */ | ||
| 658 | struct ssp_ini_tm_start_req { | ||
| 659 | __le32 tag; | ||
| 660 | __le32 device_id; | ||
| 661 | __le32 relate_tag; | ||
| 662 | __le32 tmf; | ||
| 663 | u8 lun[8]; | ||
| 664 | __le32 ds_ads_m; | ||
| 665 | u32 reserved[24]; | ||
| 666 | } __attribute__((packed, aligned(4))); | ||
| 667 | |||
| 668 | struct ssp_info_unit { | ||
| 669 | u8 lun[8];/* SCSI Logical Unit Number */ | ||
| 670 | u8 reserved1;/* reserved */ | ||
| 671 | u8 efb_prio_attr; | ||
| 672 | /* B7 : enabledFirstBurst */ | ||
| 673 | /* B6-3 : taskPriority */ | ||
| 674 | /* B2-0 : taskAttribute */ | ||
| 675 | u8 reserved2; /* reserved */ | ||
| 676 | u8 additional_cdb_len; | ||
| 677 | /* B7-2 : additional_cdb_len */ | ||
| 678 | /* B1-0 : reserved */ | ||
| 679 | u8 cdb[16];/* The SCSI CDB up to 16 bytes length */ | ||
| 680 | } __attribute__((packed, aligned(4))); | ||
| 681 | |||
| 682 | /** | ||
| 683 | * brief the data structure of SSP INI IO Start Command | ||
| 684 | * use to describe MPI SSP INI IO Start Command (64 bytes) | ||
| 685 | * Note: This structure is common for normal / encryption I/O | ||
| 686 | */ | ||
| 687 | struct ssp_ini_io_start_req { | ||
| 688 | __le32 tag; | ||
| 689 | __le32 device_id; | ||
| 690 | __le32 data_len; | ||
| 691 | __le32 dad_dir_m_tlr; | ||
| 692 | struct ssp_info_unit ssp_iu; | ||
| 693 | __le32 addr_low; /* dword 12: sgl low for normal I/O. */ | ||
| 694 | /* epl_descl for encryption I/O */ | ||
| 695 | __le32 addr_high; /* dword 13: sgl hi for normal I/O */ | ||
| 696 | /* dpl_descl for encryption I/O */ | ||
| 697 | __le32 len; /* dword 14: len for normal I/O. */ | ||
| 698 | /* edpl_desch for encryption I/O */ | ||
| 699 | __le32 esgl; /* dword 15: ESGL bit for normal I/O. */ | ||
| 700 | /* user defined tag mask for enc I/O */ | ||
| 701 | /* The below fields are reserved for normal I/O */ | ||
| 702 | u8 udt[12]; /* dword 16-18 */ | ||
| 703 | __le32 sectcnt_ios; /* dword 19 */ | ||
| 704 | __le32 key_cmode; /* dword 20 */ | ||
| 705 | __le32 ks_enss; /* dword 21 */ | ||
| 706 | __le32 keytagl; /* dword 22 */ | ||
| 707 | __le32 keytagh; /* dword 23 */ | ||
| 708 | __le32 twk_val0; /* dword 24 */ | ||
| 709 | __le32 twk_val1; /* dword 25 */ | ||
| 710 | __le32 twk_val2; /* dword 26 */ | ||
| 711 | __le32 twk_val3; /* dword 27 */ | ||
| 712 | __le32 enc_addr_low; /* dword 28: Encryption sgl addr low */ | ||
| 713 | __le32 enc_addr_high; /* dword 29: Encryption sgl addr hi */ | ||
| 714 | __le32 enc_len; /* dword 30: Encryption length */ | ||
| 715 | __le32 enc_esgl; /* dword 31: ESGL bit for encryption */ | ||
| 716 | } __attribute__((packed, aligned(4))); | ||
| 717 | |||
| 718 | /** | ||
| 719 | * brief the data structure for SSP_INI_DIF_ENC_IO COMMAND | ||
| 720 | * use to initiate SSP I/O operation with optional DIF/ENC | ||
| 721 | */ | ||
| 722 | struct ssp_dif_enc_io_req { | ||
| 723 | __le32 tag; | ||
| 724 | __le32 device_id; | ||
| 725 | __le32 data_len; | ||
| 726 | __le32 dirMTlr; | ||
| 727 | __le32 sspiu0; | ||
| 728 | __le32 sspiu1; | ||
| 729 | __le32 sspiu2; | ||
| 730 | __le32 sspiu3; | ||
| 731 | __le32 sspiu4; | ||
| 732 | __le32 sspiu5; | ||
| 733 | __le32 sspiu6; | ||
| 734 | __le32 epl_des; | ||
| 735 | __le32 dpl_desl_ndplr; | ||
| 736 | __le32 dpl_desh; | ||
| 737 | __le32 uum_uuv_bss_difbits; | ||
| 738 | u8 udt[12]; | ||
| 739 | __le32 sectcnt_ios; | ||
| 740 | __le32 key_cmode; | ||
| 741 | __le32 ks_enss; | ||
| 742 | __le32 keytagl; | ||
| 743 | __le32 keytagh; | ||
| 744 | __le32 twk_val0; | ||
| 745 | __le32 twk_val1; | ||
| 746 | __le32 twk_val2; | ||
| 747 | __le32 twk_val3; | ||
| 748 | __le32 addr_low; | ||
| 749 | __le32 addr_high; | ||
| 750 | __le32 len; | ||
| 751 | __le32 esgl; | ||
| 752 | } __attribute__((packed, aligned(4))); | ||
| 753 | |||
| 754 | /** | ||
| 755 | * brief the data structure of Firmware download | ||
| 756 | * use to describe MPI FW DOWNLOAD Command (64 bytes) | ||
| 757 | */ | ||
| 758 | struct fw_flash_Update_req { | ||
| 759 | __le32 tag; | ||
| 760 | __le32 cur_image_offset; | ||
| 761 | __le32 cur_image_len; | ||
| 762 | __le32 total_image_len; | ||
| 763 | u32 reserved0[7]; | ||
| 764 | __le32 sgl_addr_lo; | ||
| 765 | __le32 sgl_addr_hi; | ||
| 766 | __le32 len; | ||
| 767 | __le32 ext_reserved; | ||
| 768 | u32 reserved1[16]; | ||
| 769 | } __attribute__((packed, aligned(4))); | ||
| 770 | |||
| 771 | #define FWFLASH_IOMB_RESERVED_LEN 0x07 | ||
| 772 | /** | ||
| 773 | * brief the data structure of FW_FLASH_UPDATE Response | ||
| 774 | * use to describe MPI FW_FLASH_UPDATE Response (64 bytes) | ||
| 775 | * | ||
| 776 | */ | ||
| 777 | struct fw_flash_Update_resp { | ||
| 778 | __le32 tag; | ||
| 779 | __le32 status; | ||
| 780 | u32 reserved[13]; | ||
| 781 | } __attribute__((packed, aligned(4))); | ||
| 782 | |||
| 783 | /** | ||
| 784 | * brief the data structure of Get NVM Data Command | ||
| 785 | * use to get data from NVM in HBA(64 bytes) | ||
| 786 | */ | ||
| 787 | struct get_nvm_data_req { | ||
| 788 | __le32 tag; | ||
| 789 | __le32 len_ir_vpdd; | ||
| 790 | __le32 vpd_offset; | ||
| 791 | u32 reserved[8]; | ||
| 792 | __le32 resp_addr_lo; | ||
| 793 | __le32 resp_addr_hi; | ||
| 794 | __le32 resp_len; | ||
| 795 | u32 reserved1[17]; | ||
| 796 | } __attribute__((packed, aligned(4))); | ||
| 797 | |||
| 798 | struct set_nvm_data_req { | ||
| 799 | __le32 tag; | ||
| 800 | __le32 len_ir_vpdd; | ||
| 801 | __le32 vpd_offset; | ||
| 802 | u32 reserved[8]; | ||
| 803 | __le32 resp_addr_lo; | ||
| 804 | __le32 resp_addr_hi; | ||
| 805 | __le32 resp_len; | ||
| 806 | u32 reserved1[17]; | ||
| 807 | } __attribute__((packed, aligned(4))); | ||
| 808 | |||
| 809 | /** | ||
| 810 | * brief the data structure for SET CONTROLLER CONFIG COMMAND | ||
| 811 | * use to modify controller configuration | ||
| 812 | */ | ||
| 813 | struct set_ctrl_cfg_req { | ||
| 814 | __le32 tag; | ||
| 815 | __le32 cfg_pg[14]; | ||
| 816 | u32 reserved[16]; | ||
| 817 | } __attribute__((packed, aligned(4))); | ||
| 818 | |||
| 819 | /** | ||
| 820 | * brief the data structure for GET CONTROLLER CONFIG COMMAND | ||
| 821 | * use to get controller configuration page | ||
| 822 | */ | ||
| 823 | struct get_ctrl_cfg_req { | ||
| 824 | __le32 tag; | ||
| 825 | __le32 pgcd; | ||
| 826 | __le32 int_vec; | ||
| 827 | u32 reserved[28]; | ||
| 828 | } __attribute__((packed, aligned(4))); | ||
| 829 | |||
| 830 | /** | ||
| 831 | * brief the data structure for KEK_MANAGEMENT COMMAND | ||
| 832 | * use for KEK management | ||
| 833 | */ | ||
| 834 | struct kek_mgmt_req { | ||
| 835 | __le32 tag; | ||
| 836 | __le32 new_curidx_ksop; | ||
| 837 | u32 reserved; | ||
| 838 | __le32 kblob[12]; | ||
| 839 | u32 reserved1[16]; | ||
| 840 | } __attribute__((packed, aligned(4))); | ||
| 841 | |||
| 842 | /** | ||
| 843 | * brief the data structure for DEK_MANAGEMENT COMMAND | ||
| 844 | * use for DEK management | ||
| 845 | */ | ||
| 846 | struct dek_mgmt_req { | ||
| 847 | __le32 tag; | ||
| 848 | __le32 kidx_dsop; | ||
| 849 | __le32 dekidx; | ||
| 850 | __le32 addr_l; | ||
| 851 | __le32 addr_h; | ||
| 852 | __le32 nent; | ||
| 853 | __le32 dbf_tblsize; | ||
| 854 | u32 reserved[24]; | ||
| 855 | } __attribute__((packed, aligned(4))); | ||
| 856 | |||
| 857 | /** | ||
| 858 | * brief the data structure for SET PHY PROFILE COMMAND | ||
| 859 | * use to retrive phy specific information | ||
| 860 | */ | ||
| 861 | struct set_phy_profile_req { | ||
| 862 | __le32 tag; | ||
| 863 | __le32 ppc_phyid; | ||
| 864 | u32 reserved[29]; | ||
| 865 | } __attribute__((packed, aligned(4))); | ||
| 866 | |||
| 867 | /** | ||
| 868 | * brief the data structure for GET PHY PROFILE COMMAND | ||
| 869 | * use to retrive phy specific information | ||
| 870 | */ | ||
| 871 | struct get_phy_profile_req { | ||
| 872 | __le32 tag; | ||
| 873 | __le32 ppc_phyid; | ||
| 874 | __le32 profile[29]; | ||
| 875 | } __attribute__((packed, aligned(4))); | ||
| 876 | |||
| 877 | /** | ||
| 878 | * brief the data structure for EXT FLASH PARTITION | ||
| 879 | * use to manage ext flash partition | ||
| 880 | */ | ||
| 881 | struct ext_flash_partition_req { | ||
| 882 | __le32 tag; | ||
| 883 | __le32 cmd; | ||
| 884 | __le32 offset; | ||
| 885 | __le32 len; | ||
| 886 | u32 reserved[7]; | ||
| 887 | __le32 addr_low; | ||
| 888 | __le32 addr_high; | ||
| 889 | __le32 len1; | ||
| 890 | __le32 ext; | ||
| 891 | u32 reserved1[16]; | ||
| 892 | } __attribute__((packed, aligned(4))); | ||
| 893 | |||
| 894 | #define TWI_DEVICE 0x0 | ||
| 895 | #define C_SEEPROM 0x1 | ||
| 896 | #define VPD_FLASH 0x4 | ||
| 897 | #define AAP1_RDUMP 0x5 | ||
| 898 | #define IOP_RDUMP 0x6 | ||
| 899 | #define EXPAN_ROM 0x7 | ||
| 900 | |||
| 901 | #define IPMode 0x80000000 | ||
| 902 | #define NVMD_TYPE 0x0000000F | ||
| 903 | #define NVMD_STAT 0x0000FFFF | ||
| 904 | #define NVMD_LEN 0xFF000000 | ||
| 905 | /** | ||
| 906 | * brief the data structure of Get NVMD Data Response | ||
| 907 | * use to describe MPI Get NVMD Data Response (64 bytes) | ||
| 908 | */ | ||
| 909 | struct get_nvm_data_resp { | ||
| 910 | __le32 tag; | ||
| 911 | __le32 ir_tda_bn_dps_das_nvm; | ||
| 912 | __le32 dlen_status; | ||
| 913 | __le32 nvm_data[12]; | ||
| 914 | } __attribute__((packed, aligned(4))); | ||
| 915 | |||
| 916 | /** | ||
| 917 | * brief the data structure of SAS Diagnostic Start/End Response | ||
| 918 | * use to describe MPI SAS Diagnostic Start/End Response (64 bytes) | ||
| 919 | * | ||
| 920 | */ | ||
| 921 | struct sas_diag_start_end_resp { | ||
| 922 | __le32 tag; | ||
| 923 | __le32 status; | ||
| 924 | u32 reserved[13]; | ||
| 925 | } __attribute__((packed, aligned(4))); | ||
| 926 | |||
| 927 | /** | ||
| 928 | * brief the data structure of SAS Diagnostic Execute Response | ||
| 929 | * use to describe MPI SAS Diagnostic Execute Response (64 bytes) | ||
| 930 | * | ||
| 931 | */ | ||
| 932 | struct sas_diag_execute_resp { | ||
| 933 | __le32 tag; | ||
| 934 | __le32 cmdtype_cmddesc_phyid; | ||
| 935 | __le32 Status; | ||
| 936 | __le32 ReportData; | ||
| 937 | u32 reserved[11]; | ||
| 938 | } __attribute__((packed, aligned(4))); | ||
| 939 | |||
| 940 | /** | ||
| 941 | * brief the data structure of Set Device State Response | ||
| 942 | * use to describe MPI Set Device State Response (64 bytes) | ||
| 943 | * | ||
| 944 | */ | ||
| 945 | struct set_dev_state_resp { | ||
| 946 | __le32 tag; | ||
| 947 | __le32 status; | ||
| 948 | __le32 device_id; | ||
| 949 | __le32 pds_nds; | ||
| 950 | u32 reserved[11]; | ||
| 951 | } __attribute__((packed, aligned(4))); | ||
| 952 | |||
| 953 | /* new outbound structure for spcv - begins */ | ||
| 954 | /** | ||
| 955 | * brief the data structure for SET CONTROLLER CONFIG COMMAND | ||
| 956 | * use to modify controller configuration | ||
| 957 | */ | ||
| 958 | struct set_ctrl_cfg_resp { | ||
| 959 | __le32 tag; | ||
| 960 | __le32 status; | ||
| 961 | __le32 err_qlfr_pgcd; | ||
| 962 | u32 reserved[12]; | ||
| 963 | } __attribute__((packed, aligned(4))); | ||
| 964 | |||
| 965 | struct get_ctrl_cfg_resp { | ||
| 966 | __le32 tag; | ||
| 967 | __le32 status; | ||
| 968 | __le32 err_qlfr; | ||
| 969 | __le32 confg_page[12]; | ||
| 970 | } __attribute__((packed, aligned(4))); | ||
| 971 | |||
| 972 | struct kek_mgmt_resp { | ||
| 973 | __le32 tag; | ||
| 974 | __le32 status; | ||
| 975 | __le32 kidx_new_curr_ksop; | ||
| 976 | __le32 err_qlfr; | ||
| 977 | u32 reserved[11]; | ||
| 978 | } __attribute__((packed, aligned(4))); | ||
| 979 | |||
| 980 | struct dek_mgmt_resp { | ||
| 981 | __le32 tag; | ||
| 982 | __le32 status; | ||
| 983 | __le32 kekidx_tbls_dsop; | ||
| 984 | __le32 dekidx; | ||
| 985 | __le32 err_qlfr; | ||
| 986 | u32 reserved[10]; | ||
| 987 | } __attribute__((packed, aligned(4))); | ||
| 988 | |||
| 989 | struct get_phy_profile_resp { | ||
| 990 | __le32 tag; | ||
| 991 | __le32 status; | ||
| 992 | __le32 ppc_phyid; | ||
| 993 | __le32 ppc_specific_rsp[12]; | ||
| 994 | } __attribute__((packed, aligned(4))); | ||
| 995 | |||
| 996 | struct flash_op_ext_resp { | ||
| 997 | __le32 tag; | ||
| 998 | __le32 cmd; | ||
| 999 | __le32 status; | ||
| 1000 | __le32 epart_size; | ||
| 1001 | __le32 epart_sect_size; | ||
| 1002 | u32 reserved[10]; | ||
| 1003 | } __attribute__((packed, aligned(4))); | ||
| 1004 | |||
| 1005 | struct set_phy_profile_resp { | ||
| 1006 | __le32 tag; | ||
| 1007 | __le32 status; | ||
| 1008 | __le32 ppc_phyid; | ||
| 1009 | __le32 ppc_specific_rsp[12]; | ||
| 1010 | } __attribute__((packed, aligned(4))); | ||
| 1011 | |||
| 1012 | struct ssp_coalesced_comp_resp { | ||
| 1013 | __le32 coal_cnt; | ||
| 1014 | __le32 tag0; | ||
| 1015 | __le32 ssp_tag0; | ||
| 1016 | __le32 tag1; | ||
| 1017 | __le32 ssp_tag1; | ||
| 1018 | __le32 add_tag_ssp_tag[10]; | ||
| 1019 | } __attribute__((packed, aligned(4))); | ||
| 1020 | |||
| 1021 | /* new outbound structure for spcv - ends */ | ||
| 1022 | |||
| 1023 | /* brief data structure for SAS protocol timer configuration page. | ||
| 1024 | * | ||
| 1025 | */ | ||
| 1026 | struct SASProtocolTimerConfig { | ||
| 1027 | __le32 pageCode; /* 0 */ | ||
| 1028 | __le32 MST_MSI; /* 1 */ | ||
| 1029 | __le32 STP_SSP_MCT_TMO; /* 2 */ | ||
| 1030 | __le32 STP_FRM_TMO; /* 3 */ | ||
| 1031 | __le32 STP_IDLE_TMO; /* 4 */ | ||
| 1032 | __le32 OPNRJT_RTRY_INTVL; /* 5 */ | ||
| 1033 | __le32 Data_Cmd_OPNRJT_RTRY_TMO; /* 6 */ | ||
| 1034 | __le32 Data_Cmd_OPNRJT_RTRY_THR; /* 7 */ | ||
| 1035 | __le32 MAX_AIP; /* 8 */ | ||
| 1036 | } __attribute__((packed, aligned(4))); | ||
| 1037 | |||
| 1038 | typedef struct SASProtocolTimerConfig SASProtocolTimerConfig_t; | ||
| 1039 | |||
| 1040 | #define NDS_BITS 0x0F | ||
| 1041 | #define PDS_BITS 0xF0 | ||
| 1042 | |||
| 1043 | /* | ||
| 1044 | * HW Events type | ||
| 1045 | */ | ||
| 1046 | |||
| 1047 | #define HW_EVENT_RESET_START 0x01 | ||
| 1048 | #define HW_EVENT_CHIP_RESET_COMPLETE 0x02 | ||
| 1049 | #define HW_EVENT_PHY_STOP_STATUS 0x03 | ||
| 1050 | #define HW_EVENT_SAS_PHY_UP 0x04 | ||
| 1051 | #define HW_EVENT_SATA_PHY_UP 0x05 | ||
| 1052 | #define HW_EVENT_SATA_SPINUP_HOLD 0x06 | ||
| 1053 | #define HW_EVENT_PHY_DOWN 0x07 | ||
| 1054 | #define HW_EVENT_PORT_INVALID 0x08 | ||
| 1055 | #define HW_EVENT_BROADCAST_CHANGE 0x09 | ||
| 1056 | #define HW_EVENT_PHY_ERROR 0x0A | ||
| 1057 | #define HW_EVENT_BROADCAST_SES 0x0B | ||
| 1058 | #define HW_EVENT_INBOUND_CRC_ERROR 0x0C | ||
| 1059 | #define HW_EVENT_HARD_RESET_RECEIVED 0x0D | ||
| 1060 | #define HW_EVENT_MALFUNCTION 0x0E | ||
| 1061 | #define HW_EVENT_ID_FRAME_TIMEOUT 0x0F | ||
| 1062 | #define HW_EVENT_BROADCAST_EXP 0x10 | ||
| 1063 | #define HW_EVENT_PHY_START_STATUS 0x11 | ||
| 1064 | #define HW_EVENT_LINK_ERR_INVALID_DWORD 0x12 | ||
| 1065 | #define HW_EVENT_LINK_ERR_DISPARITY_ERROR 0x13 | ||
| 1066 | #define HW_EVENT_LINK_ERR_CODE_VIOLATION 0x14 | ||
| 1067 | #define HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH 0x15 | ||
| 1068 | #define HW_EVENT_LINK_ERR_PHY_RESET_FAILED 0x16 | ||
| 1069 | #define HW_EVENT_PORT_RECOVERY_TIMER_TMO 0x17 | ||
| 1070 | #define HW_EVENT_PORT_RECOVER 0x18 | ||
| 1071 | #define HW_EVENT_PORT_RESET_TIMER_TMO 0x19 | ||
| 1072 | #define HW_EVENT_PORT_RESET_COMPLETE 0x20 | ||
| 1073 | #define EVENT_BROADCAST_ASYNCH_EVENT 0x21 | ||
| 1074 | |||
| 1075 | /* port state */ | ||
| 1076 | #define PORT_NOT_ESTABLISHED 0x00 | ||
| 1077 | #define PORT_VALID 0x01 | ||
| 1078 | #define PORT_LOSTCOMM 0x02 | ||
| 1079 | #define PORT_IN_RESET 0x04 | ||
| 1080 | #define PORT_3RD_PARTY_RESET 0x07 | ||
| 1081 | #define PORT_INVALID 0x08 | ||
| 1082 | |||
| 1083 | /* | ||
| 1084 | * SSP/SMP/SATA IO Completion Status values | ||
| 1085 | */ | ||
| 1086 | |||
| 1087 | #define IO_SUCCESS 0x00 | ||
| 1088 | #define IO_ABORTED 0x01 | ||
| 1089 | #define IO_OVERFLOW 0x02 | ||
| 1090 | #define IO_UNDERFLOW 0x03 | ||
| 1091 | #define IO_FAILED 0x04 | ||
| 1092 | #define IO_ABORT_RESET 0x05 | ||
| 1093 | #define IO_NOT_VALID 0x06 | ||
| 1094 | #define IO_NO_DEVICE 0x07 | ||
| 1095 | #define IO_ILLEGAL_PARAMETER 0x08 | ||
| 1096 | #define IO_LINK_FAILURE 0x09 | ||
| 1097 | #define IO_PROG_ERROR 0x0A | ||
| 1098 | |||
| 1099 | #define IO_EDC_IN_ERROR 0x0B | ||
| 1100 | #define IO_EDC_OUT_ERROR 0x0C | ||
| 1101 | #define IO_ERROR_HW_TIMEOUT 0x0D | ||
| 1102 | #define IO_XFER_ERROR_BREAK 0x0E | ||
| 1103 | #define IO_XFER_ERROR_PHY_NOT_READY 0x0F | ||
| 1104 | #define IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED 0x10 | ||
| 1105 | #define IO_OPEN_CNX_ERROR_ZONE_VIOLATION 0x11 | ||
| 1106 | #define IO_OPEN_CNX_ERROR_BREAK 0x12 | ||
| 1107 | #define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS 0x13 | ||
| 1108 | #define IO_OPEN_CNX_ERROR_BAD_DESTINATION 0x14 | ||
| 1109 | #define IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED 0x15 | ||
| 1110 | #define IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY 0x16 | ||
| 1111 | #define IO_OPEN_CNX_ERROR_WRONG_DESTINATION 0x17 | ||
| 1112 | /* This error code 0x18 is not used on SPCv */ | ||
| 1113 | #define IO_OPEN_CNX_ERROR_UNKNOWN_ERROR 0x18 | ||
| 1114 | #define IO_XFER_ERROR_NAK_RECEIVED 0x19 | ||
| 1115 | #define IO_XFER_ERROR_ACK_NAK_TIMEOUT 0x1A | ||
| 1116 | #define IO_XFER_ERROR_PEER_ABORTED 0x1B | ||
| 1117 | #define IO_XFER_ERROR_RX_FRAME 0x1C | ||
| 1118 | #define IO_XFER_ERROR_DMA 0x1D | ||
| 1119 | #define IO_XFER_ERROR_CREDIT_TIMEOUT 0x1E | ||
| 1120 | #define IO_XFER_ERROR_SATA_LINK_TIMEOUT 0x1F | ||
| 1121 | #define IO_XFER_ERROR_SATA 0x20 | ||
| 1122 | |||
| 1123 | /* This error code 0x22 is not used on SPCv */ | ||
| 1124 | #define IO_XFER_ERROR_ABORTED_DUE_TO_SRST 0x22 | ||
| 1125 | #define IO_XFER_ERROR_REJECTED_NCQ_MODE 0x21 | ||
| 1126 | #define IO_XFER_ERROR_ABORTED_NCQ_MODE 0x23 | ||
| 1127 | #define IO_XFER_OPEN_RETRY_TIMEOUT 0x24 | ||
| 1128 | /* This error code 0x25 is not used on SPCv */ | ||
| 1129 | #define IO_XFER_SMP_RESP_CONNECTION_ERROR 0x25 | ||
| 1130 | #define IO_XFER_ERROR_UNEXPECTED_PHASE 0x26 | ||
| 1131 | #define IO_XFER_ERROR_XFER_RDY_OVERRUN 0x27 | ||
| 1132 | #define IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED 0x28 | ||
| 1133 | #define IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT 0x30 | ||
| 1134 | |||
| 1135 | /* The following error code 0x31 and 0x32 are not using (obsolete) */ | ||
| 1136 | #define IO_XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NAK 0x31 | ||
| 1137 | #define IO_XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK 0x32 | ||
| 1138 | |||
| 1139 | #define IO_XFER_ERROR_OFFSET_MISMATCH 0x34 | ||
| 1140 | #define IO_XFER_ERROR_XFER_ZERO_DATA_LEN 0x35 | ||
| 1141 | #define IO_XFER_CMD_FRAME_ISSUED 0x36 | ||
| 1142 | #define IO_ERROR_INTERNAL_SMP_RESOURCE 0x37 | ||
| 1143 | #define IO_PORT_IN_RESET 0x38 | ||
| 1144 | #define IO_DS_NON_OPERATIONAL 0x39 | ||
| 1145 | #define IO_DS_IN_RECOVERY 0x3A | ||
| 1146 | #define IO_TM_TAG_NOT_FOUND 0x3B | ||
| 1147 | #define IO_XFER_PIO_SETUP_ERROR 0x3C | ||
| 1148 | #define IO_SSP_EXT_IU_ZERO_LEN_ERROR 0x3D | ||
| 1149 | #define IO_DS_IN_ERROR 0x3E | ||
| 1150 | #define IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY 0x3F | ||
| 1151 | #define IO_ABORT_IN_PROGRESS 0x40 | ||
| 1152 | #define IO_ABORT_DELAYED 0x41 | ||
| 1153 | #define IO_INVALID_LENGTH 0x42 | ||
| 1154 | |||
| 1155 | /********** additional response event values *****************/ | ||
| 1156 | |||
| 1157 | #define IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY_ALT 0x43 | ||
| 1158 | #define IO_XFER_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED 0x44 | ||
| 1159 | #define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO 0x45 | ||
| 1160 | #define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST 0x46 | ||
| 1161 | #define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE 0x47 | ||
| 1162 | #define IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED 0x48 | ||
| 1163 | #define IO_DS_INVALID 0x49 | ||
| 1164 | /* WARNING: the value is not contiguous from here */ | ||
| 1165 | #define IO_XFER_ERR_LAST_PIO_DATAIN_CRC_ERR 0x52 | ||
| 1166 | #define IO_XFER_DMA_ACTIVATE_TIMEOUT 0x53 | ||
| 1167 | #define IO_XFER_ERROR_INTERNAL_CRC_ERROR 0x54 | ||
| 1168 | #define MPI_IO_RQE_BUSY_FULL 0x55 | ||
| 1169 | #define IO_XFER_ERR_EOB_DATA_OVERRUN 0x56 | ||
| 1170 | #define IO_XFR_ERROR_INVALID_SSP_RSP_FRAME 0x57 | ||
| 1171 | #define IO_OPEN_CNX_ERROR_OPEN_PREEMPTED 0x58 | ||
| 1172 | |||
| 1173 | #define MPI_ERR_IO_RESOURCE_UNAVAILABLE 0x1004 | ||
| 1174 | #define MPI_ERR_ATAPI_DEVICE_BUSY 0x1024 | ||
| 1175 | |||
| 1176 | #define IO_XFR_ERROR_DEK_KEY_CACHE_MISS 0x2040 | ||
| 1177 | /* | ||
| 1178 | * An encryption IO request failed due to DEK Key Tag mismatch. | ||
| 1179 | * The key tag supplied in the encryption IOMB does not match with | ||
| 1180 | * the Key Tag in the referenced DEK Entry. | ||
| 1181 | */ | ||
| 1182 | #define IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH 0x2041 | ||
| 1183 | #define IO_XFR_ERROR_CIPHER_MODE_INVALID 0x2042 | ||
| 1184 | /* | ||
| 1185 | * An encryption I/O request failed because the initial value (IV) | ||
| 1186 | * in the unwrapped DEK blob didn't match the IV used to unwrap it. | ||
| 1187 | */ | ||
| 1188 | #define IO_XFR_ERROR_DEK_IV_MISMATCH 0x2043 | ||
| 1189 | /* An encryption I/O request failed due to an internal RAM ECC or | ||
| 1190 | * interface error while unwrapping the DEK. */ | ||
| 1191 | #define IO_XFR_ERROR_DEK_RAM_INTERFACE_ERROR 0x2044 | ||
| 1192 | /* An encryption I/O request failed due to an internal RAM ECC or | ||
| 1193 | * interface error while unwrapping the DEK. */ | ||
| 1194 | #define IO_XFR_ERROR_INTERNAL_RAM 0x2045 | ||
| 1195 | /* | ||
| 1196 | * An encryption I/O request failed | ||
| 1197 | * because the DEK index specified in the I/O was outside the bounds of | ||
| 1198 | * the total number of entries in the host DEK table. | ||
| 1199 | */ | ||
| 1200 | #define IO_XFR_ERROR_DEK_INDEX_OUT_OF_BOUNDS0x2046 | ||
| 1201 | |||
| 1202 | /* define DIF IO response error status code */ | ||
| 1203 | #define IO_XFR_ERROR_DIF_MISMATCH 0x3000 | ||
| 1204 | #define IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH 0x3001 | ||
| 1205 | #define IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH 0x3002 | ||
| 1206 | #define IO_XFR_ERROR_DIF_CRC_MISMATCH 0x3003 | ||
| 1207 | |||
| 1208 | /* define operator management response status and error qualifier code */ | ||
| 1209 | #define OPR_MGMT_OP_NOT_SUPPORTED 0x2060 | ||
| 1210 | #define OPR_MGMT_MPI_ENC_ERR_OPR_PARAM_ILLEGAL 0x2061 | ||
| 1211 | #define OPR_MGMT_MPI_ENC_ERR_OPR_ID_NOT_FOUND 0x2062 | ||
| 1212 | #define OPR_MGMT_MPI_ENC_ERR_OPR_ROLE_NOT_MATCH 0x2063 | ||
| 1213 | #define OPR_MGMT_MPI_ENC_ERR_OPR_MAX_NUM_EXCEEDED 0x2064 | ||
| 1214 | #define OPR_MGMT_MPI_ENC_ERR_KEK_UNWRAP_FAIL 0x2022 | ||
| 1215 | #define OPR_MGMT_MPI_ENC_ERR_NVRAM_OPERATION_FAILURE 0x2023 | ||
| 1216 | /***************** additional response event values ***************/ | ||
| 1217 | |||
| 1218 | /* WARNING: This error code must always be the last number. | ||
| 1219 | * If you add error code, modify this code also | ||
| 1220 | * It is used as an index | ||
| 1221 | */ | ||
| 1222 | #define IO_ERROR_UNKNOWN_GENERIC 0x2023 | ||
| 1223 | |||
| 1224 | /* MSGU CONFIGURATION TABLE*/ | ||
| 1225 | |||
| 1226 | #define SPCv_MSGU_CFG_TABLE_UPDATE 0x01 | ||
| 1227 | #define SPCv_MSGU_CFG_TABLE_RESET 0x02 | ||
| 1228 | #define SPCv_MSGU_CFG_TABLE_FREEZE 0x04 | ||
| 1229 | #define SPCv_MSGU_CFG_TABLE_UNFREEZE 0x08 | ||
| 1230 | #define MSGU_IBDB_SET 0x00 | ||
| 1231 | #define MSGU_HOST_INT_STATUS 0x08 | ||
| 1232 | #define MSGU_HOST_INT_MASK 0x0C | ||
| 1233 | #define MSGU_IOPIB_INT_STATUS 0x18 | ||
| 1234 | #define MSGU_IOPIB_INT_MASK 0x1C | ||
| 1235 | #define MSGU_IBDB_CLEAR 0x20 | ||
| 1236 | |||
| 1237 | #define MSGU_MSGU_CONTROL 0x24 | ||
| 1238 | #define MSGU_ODR 0x20 | ||
| 1239 | #define MSGU_ODCR 0x28 | ||
| 1240 | |||
| 1241 | #define MSGU_ODMR 0x30 | ||
| 1242 | #define MSGU_ODMR_U 0x34 | ||
| 1243 | #define MSGU_ODMR_CLR 0x38 | ||
| 1244 | #define MSGU_ODMR_CLR_U 0x3C | ||
| 1245 | #define MSGU_OD_RSVD 0x40 | ||
| 1246 | |||
| 1247 | #define MSGU_SCRATCH_PAD_0 0x44 | ||
| 1248 | #define MSGU_SCRATCH_PAD_1 0x48 | ||
| 1249 | #define MSGU_SCRATCH_PAD_2 0x4C | ||
| 1250 | #define MSGU_SCRATCH_PAD_3 0x50 | ||
| 1251 | #define MSGU_HOST_SCRATCH_PAD_0 0x54 | ||
| 1252 | #define MSGU_HOST_SCRATCH_PAD_1 0x58 | ||
| 1253 | #define MSGU_HOST_SCRATCH_PAD_2 0x5C | ||
| 1254 | #define MSGU_HOST_SCRATCH_PAD_3 0x60 | ||
| 1255 | #define MSGU_HOST_SCRATCH_PAD_4 0x64 | ||
| 1256 | #define MSGU_HOST_SCRATCH_PAD_5 0x68 | ||
| 1257 | #define MSGU_HOST_SCRATCH_PAD_6 0x6C | ||
| 1258 | #define MSGU_HOST_SCRATCH_PAD_7 0x70 | ||
| 1259 | |||
| 1260 | /* bit definition for ODMR register */ | ||
| 1261 | #define ODMR_MASK_ALL 0xFFFFFFFF/* mask all | ||
| 1262 | interrupt vector */ | ||
| 1263 | #define ODMR_CLEAR_ALL 0 /* clear all | ||
| 1264 | interrupt vector */ | ||
| 1265 | /* bit definition for ODCR register */ | ||
| 1266 | #define ODCR_CLEAR_ALL 0xFFFFFFFF /* mask all | ||
| 1267 | interrupt vector*/ | ||
| 1268 | /* MSIX Interupts */ | ||
| 1269 | #define MSIX_TABLE_OFFSET 0x2000 | ||
| 1270 | #define MSIX_TABLE_ELEMENT_SIZE 0x10 | ||
| 1271 | #define MSIX_INTERRUPT_CONTROL_OFFSET 0xC | ||
| 1272 | #define MSIX_TABLE_BASE (MSIX_TABLE_OFFSET + \ | ||
| 1273 | MSIX_INTERRUPT_CONTROL_OFFSET) | ||
| 1274 | #define MSIX_INTERRUPT_DISABLE 0x1 | ||
| 1275 | #define MSIX_INTERRUPT_ENABLE 0x0 | ||
| 1276 | |||
| 1277 | /* state definition for Scratch Pad1 register */ | ||
| 1278 | #define SCRATCH_PAD_RAAE_READY 0x3 | ||
| 1279 | #define SCRATCH_PAD_ILA_READY 0xC | ||
| 1280 | #define SCRATCH_PAD_BOOT_LOAD_SUCCESS 0x0 | ||
| 1281 | #define SCRATCH_PAD_IOP0_READY 0xC00 | ||
| 1282 | #define SCRATCH_PAD_IOP1_READY 0x3000 | ||
| 1283 | |||
| 1284 | /* boot loader state */ | ||
| 1285 | #define SCRATCH_PAD1_BOOTSTATE_MASK 0x70 /* Bit 4-6 */ | ||
| 1286 | #define SCRATCH_PAD1_BOOTSTATE_SUCESS 0x0 /* Load successful */ | ||
| 1287 | #define SCRATCH_PAD1_BOOTSTATE_HDA_SEEPROM 0x10 /* HDA SEEPROM */ | ||
| 1288 | #define SCRATCH_PAD1_BOOTSTATE_HDA_BOOTSTRAP 0x20 /* HDA BootStrap Pins */ | ||
| 1289 | #define SCRATCH_PAD1_BOOTSTATE_HDA_SOFTRESET 0x30 /* HDA Soft Reset */ | ||
| 1290 | #define SCRATCH_PAD1_BOOTSTATE_CRIT_ERROR 0x40 /* HDA critical error */ | ||
| 1291 | #define SCRATCH_PAD1_BOOTSTATE_R1 0x50 /* Reserved */ | ||
| 1292 | #define SCRATCH_PAD1_BOOTSTATE_R2 0x60 /* Reserved */ | ||
| 1293 | #define SCRATCH_PAD1_BOOTSTATE_FATAL 0x70 /* Fatal Error */ | ||
| 1294 | |||
| 1295 | /* state definition for Scratch Pad2 register */ | ||
| 1296 | #define SCRATCH_PAD2_POR 0x00 /* power on state */ | ||
| 1297 | #define SCRATCH_PAD2_SFR 0x01 /* soft reset state */ | ||
| 1298 | #define SCRATCH_PAD2_ERR 0x02 /* error state */ | ||
| 1299 | #define SCRATCH_PAD2_RDY 0x03 /* ready state */ | ||
| 1300 | #define SCRATCH_PAD2_FWRDY_RST 0x04 /* FW rdy for soft reset flag */ | ||
| 1301 | #define SCRATCH_PAD2_IOPRDY_RST 0x08 /* IOP ready for soft reset */ | ||
| 1302 | #define SCRATCH_PAD2_STATE_MASK 0xFFFFFFF4 /* ScratchPad 2 | ||
| 1303 | Mask, bit1-0 State */ | ||
| 1304 | #define SCRATCH_PAD2_RESERVED 0x000003FC/* Scratch Pad1 | ||
| 1305 | Reserved bit 2 to 9 */ | ||
| 1306 | |||
| 1307 | #define SCRATCH_PAD_ERROR_MASK 0xFFFFFC00 /* Error mask bits */ | ||
| 1308 | #define SCRATCH_PAD_STATE_MASK 0x00000003 /* State Mask bits */ | ||
| 1309 | |||
| 1310 | /* main configuration offset - byte offset */ | ||
| 1311 | #define MAIN_SIGNATURE_OFFSET 0x00 /* DWORD 0x00 */ | ||
| 1312 | #define MAIN_INTERFACE_REVISION 0x04 /* DWORD 0x01 */ | ||
| 1313 | #define MAIN_FW_REVISION 0x08 /* DWORD 0x02 */ | ||
| 1314 | #define MAIN_MAX_OUTSTANDING_IO_OFFSET 0x0C /* DWORD 0x03 */ | ||
| 1315 | #define MAIN_MAX_SGL_OFFSET 0x10 /* DWORD 0x04 */ | ||
| 1316 | #define MAIN_CNTRL_CAP_OFFSET 0x14 /* DWORD 0x05 */ | ||
| 1317 | #define MAIN_GST_OFFSET 0x18 /* DWORD 0x06 */ | ||
| 1318 | #define MAIN_IBQ_OFFSET 0x1C /* DWORD 0x07 */ | ||
| 1319 | #define MAIN_OBQ_OFFSET 0x20 /* DWORD 0x08 */ | ||
| 1320 | #define MAIN_IQNPPD_HPPD_OFFSET 0x24 /* DWORD 0x09 */ | ||
| 1321 | |||
| 1322 | /* 0x28 - 0x4C - RSVD */ | ||
| 1323 | #define MAIN_EVENT_CRC_CHECK 0x48 /* DWORD 0x12 */ | ||
| 1324 | #define MAIN_EVENT_LOG_ADDR_HI 0x50 /* DWORD 0x14 */ | ||
| 1325 | #define MAIN_EVENT_LOG_ADDR_LO 0x54 /* DWORD 0x15 */ | ||
| 1326 | #define MAIN_EVENT_LOG_BUFF_SIZE 0x58 /* DWORD 0x16 */ | ||
| 1327 | #define MAIN_EVENT_LOG_OPTION 0x5C /* DWORD 0x17 */ | ||
| 1328 | #define MAIN_PCS_EVENT_LOG_ADDR_HI 0x60 /* DWORD 0x18 */ | ||
| 1329 | #define MAIN_PCS_EVENT_LOG_ADDR_LO 0x64 /* DWORD 0x19 */ | ||
| 1330 | #define MAIN_PCS_EVENT_LOG_BUFF_SIZE 0x68 /* DWORD 0x1A */ | ||
| 1331 | #define MAIN_PCS_EVENT_LOG_OPTION 0x6C /* DWORD 0x1B */ | ||
| 1332 | #define MAIN_FATAL_ERROR_INTERRUPT 0x70 /* DWORD 0x1C */ | ||
| 1333 | #define MAIN_FATAL_ERROR_RDUMP0_OFFSET 0x74 /* DWORD 0x1D */ | ||
| 1334 | #define MAIN_FATAL_ERROR_RDUMP0_LENGTH 0x78 /* DWORD 0x1E */ | ||
| 1335 | #define MAIN_FATAL_ERROR_RDUMP1_OFFSET 0x7C /* DWORD 0x1F */ | ||
| 1336 | #define MAIN_FATAL_ERROR_RDUMP1_LENGTH 0x80 /* DWORD 0x20 */ | ||
| 1337 | #define MAIN_GPIO_LED_FLAGS_OFFSET 0x84 /* DWORD 0x21 */ | ||
| 1338 | #define MAIN_ANALOG_SETUP_OFFSET 0x88 /* DWORD 0x22 */ | ||
| 1339 | |||
| 1340 | #define MAIN_INT_VECTOR_TABLE_OFFSET 0x8C /* DWORD 0x23 */ | ||
| 1341 | #define MAIN_SAS_PHY_ATTR_TABLE_OFFSET 0x90 /* DWORD 0x24 */ | ||
| 1342 | #define MAIN_PORT_RECOVERY_TIMER 0x94 /* DWORD 0x25 */ | ||
| 1343 | #define MAIN_INT_REASSERTION_DELAY 0x98 /* DWORD 0x26 */ | ||
| 1344 | |||
| 1345 | /* Gereral Status Table offset - byte offset */ | ||
| 1346 | #define GST_GSTLEN_MPIS_OFFSET 0x00 | ||
| 1347 | #define GST_IQ_FREEZE_STATE0_OFFSET 0x04 | ||
| 1348 | #define GST_IQ_FREEZE_STATE1_OFFSET 0x08 | ||
| 1349 | #define GST_MSGUTCNT_OFFSET 0x0C | ||
| 1350 | #define GST_IOPTCNT_OFFSET 0x10 | ||
| 1351 | /* 0x14 - 0x34 - RSVD */ | ||
| 1352 | #define GST_GPIO_INPUT_VAL 0x38 | ||
| 1353 | /* 0x3c - 0x40 - RSVD */ | ||
| 1354 | #define GST_RERRINFO_OFFSET0 0x44 | ||
| 1355 | #define GST_RERRINFO_OFFSET1 0x48 | ||
| 1356 | #define GST_RERRINFO_OFFSET2 0x4c | ||
| 1357 | #define GST_RERRINFO_OFFSET3 0x50 | ||
| 1358 | #define GST_RERRINFO_OFFSET4 0x54 | ||
| 1359 | #define GST_RERRINFO_OFFSET5 0x58 | ||
| 1360 | #define GST_RERRINFO_OFFSET6 0x5c | ||
| 1361 | #define GST_RERRINFO_OFFSET7 0x60 | ||
| 1362 | |||
| 1363 | /* General Status Table - MPI state */ | ||
| 1364 | #define GST_MPI_STATE_UNINIT 0x00 | ||
| 1365 | #define GST_MPI_STATE_INIT 0x01 | ||
| 1366 | #define GST_MPI_STATE_TERMINATION 0x02 | ||
| 1367 | #define GST_MPI_STATE_ERROR 0x03 | ||
| 1368 | #define GST_MPI_STATE_MASK 0x07 | ||
| 1369 | |||
| 1370 | /* Per SAS PHY Attributes */ | ||
| 1371 | |||
| 1372 | #define PSPA_PHYSTATE0_OFFSET 0x00 /* Dword V */ | ||
| 1373 | #define PSPA_OB_HW_EVENT_PID0_OFFSET 0x04 /* DWORD V+1 */ | ||
| 1374 | #define PSPA_PHYSTATE1_OFFSET 0x08 /* Dword V+2 */ | ||
| 1375 | #define PSPA_OB_HW_EVENT_PID1_OFFSET 0x0C /* DWORD V+3 */ | ||
| 1376 | #define PSPA_PHYSTATE2_OFFSET 0x10 /* Dword V+4 */ | ||
| 1377 | #define PSPA_OB_HW_EVENT_PID2_OFFSET 0x14 /* DWORD V+5 */ | ||
| 1378 | #define PSPA_PHYSTATE3_OFFSET 0x18 /* Dword V+6 */ | ||
| 1379 | #define PSPA_OB_HW_EVENT_PID3_OFFSET 0x1C /* DWORD V+7 */ | ||
| 1380 | #define PSPA_PHYSTATE4_OFFSET 0x20 /* Dword V+8 */ | ||
| 1381 | #define PSPA_OB_HW_EVENT_PID4_OFFSET 0x24 /* DWORD V+9 */ | ||
| 1382 | #define PSPA_PHYSTATE5_OFFSET 0x28 /* Dword V+10 */ | ||
| 1383 | #define PSPA_OB_HW_EVENT_PID5_OFFSET 0x2C /* DWORD V+11 */ | ||
| 1384 | #define PSPA_PHYSTATE6_OFFSET 0x30 /* Dword V+12 */ | ||
| 1385 | #define PSPA_OB_HW_EVENT_PID6_OFFSET 0x34 /* DWORD V+13 */ | ||
| 1386 | #define PSPA_PHYSTATE7_OFFSET 0x38 /* Dword V+14 */ | ||
| 1387 | #define PSPA_OB_HW_EVENT_PID7_OFFSET 0x3C /* DWORD V+15 */ | ||
| 1388 | #define PSPA_PHYSTATE8_OFFSET 0x40 /* DWORD V+16 */ | ||
| 1389 | #define PSPA_OB_HW_EVENT_PID8_OFFSET 0x44 /* DWORD V+17 */ | ||
| 1390 | #define PSPA_PHYSTATE9_OFFSET 0x48 /* DWORD V+18 */ | ||
| 1391 | #define PSPA_OB_HW_EVENT_PID9_OFFSET 0x4C /* DWORD V+19 */ | ||
| 1392 | #define PSPA_PHYSTATE10_OFFSET 0x50 /* DWORD V+20 */ | ||
| 1393 | #define PSPA_OB_HW_EVENT_PID10_OFFSET 0x54 /* DWORD V+21 */ | ||
| 1394 | #define PSPA_PHYSTATE11_OFFSET 0x58 /* DWORD V+22 */ | ||
| 1395 | #define PSPA_OB_HW_EVENT_PID11_OFFSET 0x5C /* DWORD V+23 */ | ||
| 1396 | #define PSPA_PHYSTATE12_OFFSET 0x60 /* DWORD V+24 */ | ||
| 1397 | #define PSPA_OB_HW_EVENT_PID12_OFFSET 0x64 /* DWORD V+25 */ | ||
| 1398 | #define PSPA_PHYSTATE13_OFFSET 0x68 /* DWORD V+26 */ | ||
| 1399 | #define PSPA_OB_HW_EVENT_PID13_OFFSET 0x6c /* DWORD V+27 */ | ||
| 1400 | #define PSPA_PHYSTATE14_OFFSET 0x70 /* DWORD V+28 */ | ||
| 1401 | #define PSPA_OB_HW_EVENT_PID14_OFFSET 0x74 /* DWORD V+29 */ | ||
| 1402 | #define PSPA_PHYSTATE15_OFFSET 0x78 /* DWORD V+30 */ | ||
| 1403 | #define PSPA_OB_HW_EVENT_PID15_OFFSET 0x7c /* DWORD V+31 */ | ||
| 1404 | /* end PSPA */ | ||
| 1405 | |||
| 1406 | /* inbound queue configuration offset - byte offset */ | ||
| 1407 | #define IB_PROPERITY_OFFSET 0x00 | ||
| 1408 | #define IB_BASE_ADDR_HI_OFFSET 0x04 | ||
| 1409 | #define IB_BASE_ADDR_LO_OFFSET 0x08 | ||
| 1410 | #define IB_CI_BASE_ADDR_HI_OFFSET 0x0C | ||
| 1411 | #define IB_CI_BASE_ADDR_LO_OFFSET 0x10 | ||
| 1412 | #define IB_PIPCI_BAR 0x14 | ||
| 1413 | #define IB_PIPCI_BAR_OFFSET 0x18 | ||
| 1414 | #define IB_RESERVED_OFFSET 0x1C | ||
| 1415 | |||
| 1416 | /* outbound queue configuration offset - byte offset */ | ||
| 1417 | #define OB_PROPERITY_OFFSET 0x00 | ||
| 1418 | #define OB_BASE_ADDR_HI_OFFSET 0x04 | ||
| 1419 | #define OB_BASE_ADDR_LO_OFFSET 0x08 | ||
| 1420 | #define OB_PI_BASE_ADDR_HI_OFFSET 0x0C | ||
| 1421 | #define OB_PI_BASE_ADDR_LO_OFFSET 0x10 | ||
| 1422 | #define OB_CIPCI_BAR 0x14 | ||
| 1423 | #define OB_CIPCI_BAR_OFFSET 0x18 | ||
| 1424 | #define OB_INTERRUPT_COALES_OFFSET 0x1C | ||
| 1425 | #define OB_DYNAMIC_COALES_OFFSET 0x20 | ||
| 1426 | #define OB_PROPERTY_INT_ENABLE 0x40000000 | ||
| 1427 | |||
| 1428 | #define MBIC_NMI_ENABLE_VPE0_IOP 0x000418 | ||
| 1429 | #define MBIC_NMI_ENABLE_VPE0_AAP1 0x000418 | ||
| 1430 | /* PCIE registers - BAR2(0x18), BAR1(win) 0x010000 */ | ||
| 1431 | #define PCIE_EVENT_INTERRUPT_ENABLE 0x003040 | ||
| 1432 | #define PCIE_EVENT_INTERRUPT 0x003044 | ||
| 1433 | #define PCIE_ERROR_INTERRUPT_ENABLE 0x003048 | ||
| 1434 | #define PCIE_ERROR_INTERRUPT 0x00304C | ||
| 1435 | |||
| 1436 | /* SPCV soft reset */ | ||
| 1437 | #define SPC_REG_SOFT_RESET 0x00001000 | ||
| 1438 | #define SPCv_NORMAL_RESET_VALUE 0x1 | ||
| 1439 | |||
| 1440 | #define SPCv_SOFT_RESET_READ_MASK 0xC0 | ||
| 1441 | #define SPCv_SOFT_RESET_NO_RESET 0x0 | ||
| 1442 | #define SPCv_SOFT_RESET_NORMAL_RESET_OCCURED 0x40 | ||
| 1443 | #define SPCv_SOFT_RESET_HDA_MODE_OCCURED 0x80 | ||
| 1444 | #define SPCv_SOFT_RESET_CHIP_RESET_OCCURED 0xC0 | ||
| 1445 | |||
| 1446 | /* signature definition for host scratch pad0 register */ | ||
| 1447 | #define SPC_SOFT_RESET_SIGNATURE 0x252acbcd | ||
| 1448 | /* Signature for Soft Reset */ | ||
| 1449 | |||
| 1450 | /* SPC Reset register - BAR4(0x20), BAR2(win) (need dynamic mapping) */ | ||
| 1451 | #define SPC_REG_RESET 0x000000/* reset register */ | ||
| 1452 | |||
| 1453 | /* bit definition for SPC_RESET register */ | ||
| 1454 | #define SPC_REG_RESET_OSSP 0x00000001 | ||
| 1455 | #define SPC_REG_RESET_RAAE 0x00000002 | ||
| 1456 | #define SPC_REG_RESET_PCS_SPBC 0x00000004 | ||
| 1457 | #define SPC_REG_RESET_PCS_IOP_SS 0x00000008 | ||
| 1458 | #define SPC_REG_RESET_PCS_AAP1_SS 0x00000010 | ||
| 1459 | #define SPC_REG_RESET_PCS_AAP2_SS 0x00000020 | ||
| 1460 | #define SPC_REG_RESET_PCS_LM 0x00000040 | ||
| 1461 | #define SPC_REG_RESET_PCS 0x00000080 | ||
| 1462 | #define SPC_REG_RESET_GSM 0x00000100 | ||
| 1463 | #define SPC_REG_RESET_DDR2 0x00010000 | ||
| 1464 | #define SPC_REG_RESET_BDMA_CORE 0x00020000 | ||
| 1465 | #define SPC_REG_RESET_BDMA_SXCBI 0x00040000 | ||
| 1466 | #define SPC_REG_RESET_PCIE_AL_SXCBI 0x00080000 | ||
| 1467 | #define SPC_REG_RESET_PCIE_PWR 0x00100000 | ||
| 1468 | #define SPC_REG_RESET_PCIE_SFT 0x00200000 | ||
| 1469 | #define SPC_REG_RESET_PCS_SXCBI 0x00400000 | ||
| 1470 | #define SPC_REG_RESET_LMS_SXCBI 0x00800000 | ||
| 1471 | #define SPC_REG_RESET_PMIC_SXCBI 0x01000000 | ||
| 1472 | #define SPC_REG_RESET_PMIC_CORE 0x02000000 | ||
| 1473 | #define SPC_REG_RESET_PCIE_PC_SXCBI 0x04000000 | ||
| 1474 | #define SPC_REG_RESET_DEVICE 0x80000000 | ||
| 1475 | |||
| 1476 | /* registers for BAR Shifting - BAR2(0x18), BAR1(win) */ | ||
| 1477 | #define SPCV_IBW_AXI_TRANSLATION_LOW 0x001010 | ||
| 1478 | |||
| 1479 | #define MBIC_AAP1_ADDR_BASE 0x060000 | ||
| 1480 | #define MBIC_IOP_ADDR_BASE 0x070000 | ||
| 1481 | #define GSM_ADDR_BASE 0x0700000 | ||
| 1482 | /* Dynamic map through Bar4 - 0x00700000 */ | ||
| 1483 | #define GSM_CONFIG_RESET 0x00000000 | ||
| 1484 | #define RAM_ECC_DB_ERR 0x00000018 | ||
| 1485 | #define GSM_READ_ADDR_PARITY_INDIC 0x00000058 | ||
| 1486 | #define GSM_WRITE_ADDR_PARITY_INDIC 0x00000060 | ||
| 1487 | #define GSM_WRITE_DATA_PARITY_INDIC 0x00000068 | ||
| 1488 | #define GSM_READ_ADDR_PARITY_CHECK 0x00000038 | ||
| 1489 | #define GSM_WRITE_ADDR_PARITY_CHECK 0x00000040 | ||
| 1490 | #define GSM_WRITE_DATA_PARITY_CHECK 0x00000048 | ||
| 1491 | |||
| 1492 | #define RB6_ACCESS_REG 0x6A0000 | ||
| 1493 | #define HDAC_EXEC_CMD 0x0002 | ||
| 1494 | #define HDA_C_PA 0xcb | ||
| 1495 | #define HDA_SEQ_ID_BITS 0x00ff0000 | ||
| 1496 | #define HDA_GSM_OFFSET_BITS 0x00FFFFFF | ||
| 1497 | #define HDA_GSM_CMD_OFFSET_BITS 0x42C0 | ||
| 1498 | #define HDA_GSM_RSP_OFFSET_BITS 0x42E0 | ||
| 1499 | |||
| 1500 | #define MBIC_AAP1_ADDR_BASE 0x060000 | ||
| 1501 | #define MBIC_IOP_ADDR_BASE 0x070000 | ||
| 1502 | #define GSM_ADDR_BASE 0x0700000 | ||
| 1503 | #define SPC_TOP_LEVEL_ADDR_BASE 0x000000 | ||
| 1504 | #define GSM_CONFIG_RESET_VALUE 0x00003b00 | ||
| 1505 | #define GPIO_ADDR_BASE 0x00090000 | ||
| 1506 | #define GPIO_GPIO_0_0UTPUT_CTL_OFFSET 0x0000010c | ||
| 1507 | |||
| 1508 | /* RB6 offset */ | ||
| 1509 | #define SPC_RB6_OFFSET 0x80C0 | ||
| 1510 | /* Magic number of soft reset for RB6 */ | ||
| 1511 | #define RB6_MAGIC_NUMBER_RST 0x1234 | ||
| 1512 | |||
| 1513 | /* Device Register status */ | ||
| 1514 | #define DEVREG_SUCCESS 0x00 | ||
| 1515 | #define DEVREG_FAILURE_OUT_OF_RESOURCE 0x01 | ||
| 1516 | #define DEVREG_FAILURE_DEVICE_ALREADY_REGISTERED 0x02 | ||
| 1517 | #define DEVREG_FAILURE_INVALID_PHY_ID 0x03 | ||
| 1518 | #define DEVREG_FAILURE_PHY_ID_ALREADY_REGISTERED 0x04 | ||
| 1519 | #define DEVREG_FAILURE_PORT_ID_OUT_OF_RANGE 0x05 | ||
| 1520 | #define DEVREG_FAILURE_PORT_NOT_VALID_STATE 0x06 | ||
| 1521 | #define DEVREG_FAILURE_DEVICE_TYPE_NOT_VALID 0x07 | ||
| 1522 | |||
| 1523 | #endif | ||
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 317a7fdc3b82..23d607218ae8 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig | |||
| @@ -24,7 +24,9 @@ config SCSI_QLA_FC | |||
| 24 | 24 | ||
| 25 | Firmware images can be retrieved from: | 25 | Firmware images can be retrieved from: |
| 26 | 26 | ||
| 27 | ftp://ftp.qlogic.com/outgoing/linux/firmware/ | 27 | http://ldriver.qlogic.com/firmware/ |
| 28 | |||
| 29 | They are also included in the linux-firmware tree as well. | ||
| 28 | 30 | ||
| 29 | config TCM_QLA2XXX | 31 | config TCM_QLA2XXX |
| 30 | tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs" | 32 | tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs" |
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 729b74389f83..937fed8cb038 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c | |||
| @@ -3003,12 +3003,10 @@ qlafx00_build_scsi_iocbs(srb_t *sp, struct cmd_type_7_fx00 *cmd_pkt, | |||
| 3003 | 3003 | ||
| 3004 | /* Set transfer direction */ | 3004 | /* Set transfer direction */ |
| 3005 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { | 3005 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { |
| 3006 | lcmd_pkt->cntrl_flags = | 3006 | lcmd_pkt->cntrl_flags = TMF_WRITE_DATA; |
| 3007 | __constant_cpu_to_le16(TMF_WRITE_DATA); | ||
| 3008 | vha->qla_stats.output_bytes += scsi_bufflen(cmd); | 3007 | vha->qla_stats.output_bytes += scsi_bufflen(cmd); |
| 3009 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | 3008 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { |
| 3010 | lcmd_pkt->cntrl_flags = | 3009 | lcmd_pkt->cntrl_flags = TMF_READ_DATA; |
| 3011 | __constant_cpu_to_le16(TMF_READ_DATA); | ||
| 3012 | vha->qla_stats.input_bytes += scsi_bufflen(cmd); | 3010 | vha->qla_stats.input_bytes += scsi_bufflen(cmd); |
| 3013 | } | 3011 | } |
| 3014 | 3012 | ||
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5307bf86d5e0..ad72c1d85111 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
| @@ -644,7 +644,7 @@ qla2x00_sp_free_dma(void *vha, void *ptr) | |||
| 644 | qla2x00_rel_sp(sp->fcport->vha, sp); | 644 | qla2x00_rel_sp(sp->fcport->vha, sp); |
| 645 | } | 645 | } |
| 646 | 646 | ||
| 647 | void | 647 | static void |
| 648 | qla2x00_sp_compl(void *data, void *ptr, int res) | 648 | qla2x00_sp_compl(void *data, void *ptr, int res) |
| 649 | { | 649 | { |
| 650 | struct qla_hw_data *ha = (struct qla_hw_data *)data; | 650 | struct qla_hw_data *ha = (struct qla_hw_data *)data; |
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index 14fec976f634..fad71ed067ec 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c | |||
| @@ -507,6 +507,7 @@ static int qla4xxx_send_mbox_iocb(struct scsi_qla_host *ha, struct mrb *mrb, | |||
| 507 | mrb->mbox_cmd = in_mbox[0]; | 507 | mrb->mbox_cmd = in_mbox[0]; |
| 508 | wmb(); | 508 | wmb(); |
| 509 | 509 | ||
| 510 | ha->iocb_cnt += mrb->iocb_cnt; | ||
| 510 | ha->isp_ops->queue_iocb(ha); | 511 | ha->isp_ops->queue_iocb(ha); |
| 511 | exit_mbox_iocb: | 512 | exit_mbox_iocb: |
| 512 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 513 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index a47f99957ba8..4d231c12463e 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
| @@ -2216,14 +2216,14 @@ static int qla4xxx_copy_to_fwddb_param(struct iscsi_bus_flash_session *sess, | |||
| 2216 | fw_ddb_entry->iscsi_def_time2retain = cpu_to_le16(sess->time2retain); | 2216 | fw_ddb_entry->iscsi_def_time2retain = cpu_to_le16(sess->time2retain); |
| 2217 | fw_ddb_entry->tgt_portal_grp = cpu_to_le16(sess->tpgt); | 2217 | fw_ddb_entry->tgt_portal_grp = cpu_to_le16(sess->tpgt); |
| 2218 | fw_ddb_entry->mss = cpu_to_le16(conn->max_segment_size); | 2218 | fw_ddb_entry->mss = cpu_to_le16(conn->max_segment_size); |
| 2219 | fw_ddb_entry->tcp_xmt_wsf = cpu_to_le16(conn->tcp_xmit_wsf); | 2219 | fw_ddb_entry->tcp_xmt_wsf = (uint8_t) cpu_to_le32(conn->tcp_xmit_wsf); |
| 2220 | fw_ddb_entry->tcp_rcv_wsf = cpu_to_le16(conn->tcp_recv_wsf); | 2220 | fw_ddb_entry->tcp_rcv_wsf = (uint8_t) cpu_to_le32(conn->tcp_recv_wsf); |
| 2221 | fw_ddb_entry->ipv4_tos = conn->ipv4_tos; | 2221 | fw_ddb_entry->ipv4_tos = conn->ipv4_tos; |
| 2222 | fw_ddb_entry->ipv6_flow_lbl = cpu_to_le16(conn->ipv6_flow_label); | 2222 | fw_ddb_entry->ipv6_flow_lbl = cpu_to_le16(conn->ipv6_flow_label); |
| 2223 | fw_ddb_entry->ka_timeout = cpu_to_le16(conn->keepalive_timeout); | 2223 | fw_ddb_entry->ka_timeout = cpu_to_le16(conn->keepalive_timeout); |
| 2224 | fw_ddb_entry->lcl_port = cpu_to_le16(conn->local_port); | 2224 | fw_ddb_entry->lcl_port = cpu_to_le16(conn->local_port); |
| 2225 | fw_ddb_entry->stat_sn = cpu_to_le16(conn->statsn); | 2225 | fw_ddb_entry->stat_sn = cpu_to_le32(conn->statsn); |
| 2226 | fw_ddb_entry->exp_stat_sn = cpu_to_le16(conn->exp_statsn); | 2226 | fw_ddb_entry->exp_stat_sn = cpu_to_le32(conn->exp_statsn); |
| 2227 | fw_ddb_entry->ddb_link = cpu_to_le16(sess->discovery_parent_type); | 2227 | fw_ddb_entry->ddb_link = cpu_to_le16(sess->discovery_parent_type); |
| 2228 | fw_ddb_entry->chap_tbl_idx = cpu_to_le16(sess->chap_out_idx); | 2228 | fw_ddb_entry->chap_tbl_idx = cpu_to_le16(sess->chap_out_idx); |
| 2229 | fw_ddb_entry->tsid = cpu_to_le16(sess->tsid); | 2229 | fw_ddb_entry->tsid = cpu_to_le16(sess->tsid); |
| @@ -5504,9 +5504,9 @@ static int qla4xxx_sysfs_ddb_is_non_persistent(struct device *dev, void *data) | |||
| 5504 | * If this is invoked as a result of a userspace call then the entry is marked | 5504 | * If this is invoked as a result of a userspace call then the entry is marked |
| 5505 | * as nonpersistent using flash_state field. | 5505 | * as nonpersistent using flash_state field. |
| 5506 | **/ | 5506 | **/ |
| 5507 | int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha, | 5507 | static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha, |
| 5508 | struct dev_db_entry *fw_ddb_entry, | 5508 | struct dev_db_entry *fw_ddb_entry, |
| 5509 | uint16_t *idx, int user) | 5509 | uint16_t *idx, int user) |
| 5510 | { | 5510 | { |
| 5511 | struct iscsi_bus_flash_session *fnode_sess = NULL; | 5511 | struct iscsi_bus_flash_session *fnode_sess = NULL; |
| 5512 | struct iscsi_bus_flash_conn *fnode_conn = NULL; | 5512 | struct iscsi_bus_flash_conn *fnode_conn = NULL; |
| @@ -5605,6 +5605,7 @@ static int qla4xxx_sysfs_ddb_add(struct Scsi_Host *shost, const char *buf, | |||
| 5605 | ql4_printk(KERN_ERR, ha, | 5605 | ql4_printk(KERN_ERR, ha, |
| 5606 | "%s: A non-persistent entry %s found\n", | 5606 | "%s: A non-persistent entry %s found\n", |
| 5607 | __func__, dev->kobj.name); | 5607 | __func__, dev->kobj.name); |
| 5608 | put_device(dev); | ||
| 5608 | goto exit_ddb_add; | 5609 | goto exit_ddb_add; |
| 5609 | } | 5610 | } |
| 5610 | 5611 | ||
| @@ -6112,8 +6113,7 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, | |||
| 6112 | int parent_type, parent_index = 0xffff; | 6113 | int parent_type, parent_index = 0xffff; |
| 6113 | int rc = 0; | 6114 | int rc = 0; |
| 6114 | 6115 | ||
| 6115 | dev = iscsi_find_flashnode_conn(fnode_sess, NULL, | 6116 | dev = iscsi_find_flashnode_conn(fnode_sess); |
| 6116 | iscsi_is_flashnode_conn_dev); | ||
| 6117 | if (!dev) | 6117 | if (!dev) |
| 6118 | return -EIO; | 6118 | return -EIO; |
| 6119 | 6119 | ||
| @@ -6276,8 +6276,7 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, | |||
| 6276 | rc = sprintf(buf, "\n"); | 6276 | rc = sprintf(buf, "\n"); |
| 6277 | break; | 6277 | break; |
| 6278 | case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX: | 6278 | case ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX: |
| 6279 | if ((fnode_sess->discovery_parent_idx) >= 0 && | 6279 | if (fnode_sess->discovery_parent_idx < MAX_DDB_ENTRIES) |
| 6280 | (fnode_sess->discovery_parent_idx < MAX_DDB_ENTRIES)) | ||
| 6281 | parent_index = fnode_sess->discovery_parent_idx; | 6280 | parent_index = fnode_sess->discovery_parent_idx; |
| 6282 | 6281 | ||
| 6283 | rc = sprintf(buf, "%u\n", parent_index); | 6282 | rc = sprintf(buf, "%u\n", parent_index); |
| @@ -6287,8 +6286,7 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, | |||
| 6287 | parent_type = ISCSI_DISC_PARENT_ISNS; | 6286 | parent_type = ISCSI_DISC_PARENT_ISNS; |
| 6288 | else if (fnode_sess->discovery_parent_type == DDB_NO_LINK) | 6287 | else if (fnode_sess->discovery_parent_type == DDB_NO_LINK) |
| 6289 | parent_type = ISCSI_DISC_PARENT_UNKNOWN; | 6288 | parent_type = ISCSI_DISC_PARENT_UNKNOWN; |
| 6290 | else if (fnode_sess->discovery_parent_type >= 0 && | 6289 | else if (fnode_sess->discovery_parent_type < MAX_DDB_ENTRIES) |
| 6291 | fnode_sess->discovery_parent_type < MAX_DDB_ENTRIES) | ||
| 6292 | parent_type = ISCSI_DISC_PARENT_SENDTGT; | 6290 | parent_type = ISCSI_DISC_PARENT_SENDTGT; |
| 6293 | else | 6291 | else |
| 6294 | parent_type = ISCSI_DISC_PARENT_UNKNOWN; | 6292 | parent_type = ISCSI_DISC_PARENT_UNKNOWN; |
| @@ -6349,6 +6347,8 @@ qla4xxx_sysfs_ddb_get_param(struct iscsi_bus_flash_session *fnode_sess, | |||
| 6349 | rc = -ENOSYS; | 6347 | rc = -ENOSYS; |
| 6350 | break; | 6348 | break; |
| 6351 | } | 6349 | } |
| 6350 | |||
| 6351 | put_device(dev); | ||
| 6352 | return rc; | 6352 | return rc; |
| 6353 | } | 6353 | } |
| 6354 | 6354 | ||
| @@ -6368,20 +6368,11 @@ qla4xxx_sysfs_ddb_set_param(struct iscsi_bus_flash_session *fnode_sess, | |||
| 6368 | { | 6368 | { |
| 6369 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); | 6369 | struct Scsi_Host *shost = iscsi_flash_session_to_shost(fnode_sess); |
| 6370 | struct scsi_qla_host *ha = to_qla_host(shost); | 6370 | struct scsi_qla_host *ha = to_qla_host(shost); |
| 6371 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
| 6372 | struct iscsi_flashnode_param_info *fnode_param; | 6371 | struct iscsi_flashnode_param_info *fnode_param; |
| 6373 | struct nlattr *attr; | 6372 | struct nlattr *attr; |
| 6374 | int rc = QLA_ERROR; | 6373 | int rc = QLA_ERROR; |
| 6375 | uint32_t rem = len; | 6374 | uint32_t rem = len; |
| 6376 | 6375 | ||
| 6377 | fw_ddb_entry = kzalloc(sizeof(*fw_ddb_entry), GFP_KERNEL); | ||
| 6378 | if (!fw_ddb_entry) { | ||
| 6379 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
| 6380 | "%s: Unable to allocate ddb buffer\n", | ||
| 6381 | __func__)); | ||
| 6382 | return -ENOMEM; | ||
| 6383 | } | ||
| 6384 | |||
| 6385 | nla_for_each_attr(attr, data, len, rem) { | 6376 | nla_for_each_attr(attr, data, len, rem) { |
| 6386 | fnode_param = nla_data(attr); | 6377 | fnode_param = nla_data(attr); |
| 6387 | 6378 | ||
| @@ -6590,16 +6581,11 @@ static int qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess) | |||
| 6590 | struct dev_db_entry *fw_ddb_entry = NULL; | 6581 | struct dev_db_entry *fw_ddb_entry = NULL; |
| 6591 | dma_addr_t fw_ddb_entry_dma; | 6582 | dma_addr_t fw_ddb_entry_dma; |
| 6592 | uint16_t *ddb_cookie = NULL; | 6583 | uint16_t *ddb_cookie = NULL; |
| 6593 | size_t ddb_size; | 6584 | size_t ddb_size = 0; |
| 6594 | void *pddb = NULL; | 6585 | void *pddb = NULL; |
| 6595 | int target_id; | 6586 | int target_id; |
| 6596 | int rc = 0; | 6587 | int rc = 0; |
| 6597 | 6588 | ||
| 6598 | if (!fnode_sess) { | ||
| 6599 | rc = -EINVAL; | ||
| 6600 | goto exit_ddb_del; | ||
| 6601 | } | ||
| 6602 | |||
| 6603 | if (fnode_sess->is_boot_target) { | 6589 | if (fnode_sess->is_boot_target) { |
| 6604 | rc = -EPERM; | 6590 | rc = -EPERM; |
| 6605 | DEBUG2(ql4_printk(KERN_ERR, ha, | 6591 | DEBUG2(ql4_printk(KERN_ERR, ha, |
| @@ -6631,8 +6617,7 @@ static int qla4xxx_sysfs_ddb_delete(struct iscsi_bus_flash_session *fnode_sess) | |||
| 6631 | 6617 | ||
| 6632 | dev_db_start_offset += (fnode_sess->target_id * | 6618 | dev_db_start_offset += (fnode_sess->target_id * |
| 6633 | sizeof(*fw_ddb_entry)); | 6619 | sizeof(*fw_ddb_entry)); |
| 6634 | dev_db_start_offset += (void *)&(fw_ddb_entry->cookie) - | 6620 | dev_db_start_offset += offsetof(struct dev_db_entry, cookie); |
| 6635 | (void *)fw_ddb_entry; | ||
| 6636 | 6621 | ||
| 6637 | ddb_size = sizeof(*ddb_cookie); | 6622 | ddb_size = sizeof(*ddb_cookie); |
| 6638 | } | 6623 | } |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index 83e0fec35d56..fe873cf7570d 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
| @@ -5,4 +5,4 @@ | |||
| 5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #define QLA4XXX_DRIVER_VERSION "5.03.00-k8" | 8 | #define QLA4XXX_DRIVER_VERSION "5.03.00-k9" |
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 5add6f4e7928..0a537a0515ca 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
| @@ -1997,24 +1997,39 @@ out: | |||
| 1997 | return ret; | 1997 | return ret; |
| 1998 | } | 1998 | } |
| 1999 | 1999 | ||
| 2000 | static unsigned int map_state(sector_t lba, unsigned int *num) | 2000 | static unsigned long lba_to_map_index(sector_t lba) |
| 2001 | { | ||
| 2002 | if (scsi_debug_unmap_alignment) { | ||
| 2003 | lba += scsi_debug_unmap_granularity - | ||
| 2004 | scsi_debug_unmap_alignment; | ||
| 2005 | } | ||
| 2006 | do_div(lba, scsi_debug_unmap_granularity); | ||
| 2007 | |||
| 2008 | return lba; | ||
| 2009 | } | ||
| 2010 | |||
| 2011 | static sector_t map_index_to_lba(unsigned long index) | ||
| 2001 | { | 2012 | { |
| 2002 | unsigned int granularity, alignment, mapped; | 2013 | return index * scsi_debug_unmap_granularity - |
| 2003 | sector_t block, next, end; | 2014 | scsi_debug_unmap_alignment; |
| 2015 | } | ||
| 2004 | 2016 | ||
| 2005 | granularity = scsi_debug_unmap_granularity; | 2017 | static unsigned int map_state(sector_t lba, unsigned int *num) |
| 2006 | alignment = granularity - scsi_debug_unmap_alignment; | 2018 | { |
| 2007 | block = lba + alignment; | 2019 | sector_t end; |
| 2008 | do_div(block, granularity); | 2020 | unsigned int mapped; |
| 2021 | unsigned long index; | ||
| 2022 | unsigned long next; | ||
| 2009 | 2023 | ||
| 2010 | mapped = test_bit(block, map_storep); | 2024 | index = lba_to_map_index(lba); |
| 2025 | mapped = test_bit(index, map_storep); | ||
| 2011 | 2026 | ||
| 2012 | if (mapped) | 2027 | if (mapped) |
| 2013 | next = find_next_zero_bit(map_storep, map_size, block); | 2028 | next = find_next_zero_bit(map_storep, map_size, index); |
| 2014 | else | 2029 | else |
| 2015 | next = find_next_bit(map_storep, map_size, block); | 2030 | next = find_next_bit(map_storep, map_size, index); |
| 2016 | 2031 | ||
| 2017 | end = next * granularity - scsi_debug_unmap_alignment; | 2032 | end = min_t(sector_t, sdebug_store_sectors, map_index_to_lba(next)); |
| 2018 | *num = end - lba; | 2033 | *num = end - lba; |
| 2019 | 2034 | ||
| 2020 | return mapped; | 2035 | return mapped; |
| @@ -2022,47 +2037,37 @@ static unsigned int map_state(sector_t lba, unsigned int *num) | |||
| 2022 | 2037 | ||
| 2023 | static void map_region(sector_t lba, unsigned int len) | 2038 | static void map_region(sector_t lba, unsigned int len) |
| 2024 | { | 2039 | { |
| 2025 | unsigned int granularity, alignment; | ||
| 2026 | sector_t end = lba + len; | 2040 | sector_t end = lba + len; |
| 2027 | 2041 | ||
| 2028 | granularity = scsi_debug_unmap_granularity; | ||
| 2029 | alignment = granularity - scsi_debug_unmap_alignment; | ||
| 2030 | |||
| 2031 | while (lba < end) { | 2042 | while (lba < end) { |
| 2032 | sector_t block, rem; | 2043 | unsigned long index = lba_to_map_index(lba); |
| 2033 | |||
| 2034 | block = lba + alignment; | ||
| 2035 | rem = do_div(block, granularity); | ||
| 2036 | 2044 | ||
| 2037 | if (block < map_size) | 2045 | if (index < map_size) |
| 2038 | set_bit(block, map_storep); | 2046 | set_bit(index, map_storep); |
| 2039 | 2047 | ||
| 2040 | lba += granularity - rem; | 2048 | lba = map_index_to_lba(index + 1); |
| 2041 | } | 2049 | } |
| 2042 | } | 2050 | } |
| 2043 | 2051 | ||
| 2044 | static void unmap_region(sector_t lba, unsigned int len) | 2052 | static void unmap_region(sector_t lba, unsigned int len) |
| 2045 | { | 2053 | { |
| 2046 | unsigned int granularity, alignment; | ||
| 2047 | sector_t end = lba + len; | 2054 | sector_t end = lba + len; |
| 2048 | 2055 | ||
| 2049 | granularity = scsi_debug_unmap_granularity; | ||
| 2050 | alignment = granularity - scsi_debug_unmap_alignment; | ||
| 2051 | |||
| 2052 | while (lba < end) { | 2056 | while (lba < end) { |
| 2053 | sector_t block, rem; | 2057 | unsigned long index = lba_to_map_index(lba); |
| 2054 | |||
| 2055 | block = lba + alignment; | ||
| 2056 | rem = do_div(block, granularity); | ||
| 2057 | 2058 | ||
| 2058 | if (rem == 0 && lba + granularity < end && block < map_size) { | 2059 | if (lba == map_index_to_lba(index) && |
| 2059 | clear_bit(block, map_storep); | 2060 | lba + scsi_debug_unmap_granularity <= end && |
| 2060 | if (scsi_debug_lbprz) | 2061 | index < map_size) { |
| 2062 | clear_bit(index, map_storep); | ||
| 2063 | if (scsi_debug_lbprz) { | ||
| 2061 | memset(fake_storep + | 2064 | memset(fake_storep + |
| 2062 | block * scsi_debug_sector_size, 0, | 2065 | lba * scsi_debug_sector_size, 0, |
| 2063 | scsi_debug_sector_size); | 2066 | scsi_debug_sector_size * |
| 2067 | scsi_debug_unmap_granularity); | ||
| 2068 | } | ||
| 2064 | } | 2069 | } |
| 2065 | lba += granularity - rem; | 2070 | lba = map_index_to_lba(index + 1); |
| 2066 | } | 2071 | } |
| 2067 | } | 2072 | } |
| 2068 | 2073 | ||
| @@ -2089,7 +2094,7 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, | |||
| 2089 | 2094 | ||
| 2090 | write_lock_irqsave(&atomic_rw, iflags); | 2095 | write_lock_irqsave(&atomic_rw, iflags); |
| 2091 | ret = do_device_access(SCpnt, devip, lba, num, 1); | 2096 | ret = do_device_access(SCpnt, devip, lba, num, 1); |
| 2092 | if (scsi_debug_unmap_granularity) | 2097 | if (scsi_debug_lbp()) |
| 2093 | map_region(lba, num); | 2098 | map_region(lba, num); |
| 2094 | write_unlock_irqrestore(&atomic_rw, iflags); | 2099 | write_unlock_irqrestore(&atomic_rw, iflags); |
| 2095 | if (-1 == ret) | 2100 | if (-1 == ret) |
| @@ -2122,7 +2127,7 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba, | |||
| 2122 | 2127 | ||
| 2123 | write_lock_irqsave(&atomic_rw, iflags); | 2128 | write_lock_irqsave(&atomic_rw, iflags); |
| 2124 | 2129 | ||
| 2125 | if (unmap && scsi_debug_unmap_granularity) { | 2130 | if (unmap && scsi_debug_lbp()) { |
| 2126 | unmap_region(lba, num); | 2131 | unmap_region(lba, num); |
| 2127 | goto out; | 2132 | goto out; |
| 2128 | } | 2133 | } |
| @@ -2146,7 +2151,7 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba, | |||
| 2146 | fake_storep + (lba * scsi_debug_sector_size), | 2151 | fake_storep + (lba * scsi_debug_sector_size), |
| 2147 | scsi_debug_sector_size); | 2152 | scsi_debug_sector_size); |
| 2148 | 2153 | ||
| 2149 | if (scsi_debug_unmap_granularity) | 2154 | if (scsi_debug_lbp()) |
| 2150 | map_region(lba, num); | 2155 | map_region(lba, num); |
| 2151 | out: | 2156 | out: |
| 2152 | write_unlock_irqrestore(&atomic_rw, iflags); | 2157 | write_unlock_irqrestore(&atomic_rw, iflags); |
| @@ -3389,8 +3394,6 @@ static int __init scsi_debug_init(void) | |||
| 3389 | 3394 | ||
| 3390 | /* Logical Block Provisioning */ | 3395 | /* Logical Block Provisioning */ |
| 3391 | if (scsi_debug_lbp()) { | 3396 | if (scsi_debug_lbp()) { |
| 3392 | unsigned int map_bytes; | ||
| 3393 | |||
| 3394 | scsi_debug_unmap_max_blocks = | 3397 | scsi_debug_unmap_max_blocks = |
| 3395 | clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU); | 3398 | clamp(scsi_debug_unmap_max_blocks, 0U, 0xffffffffU); |
| 3396 | 3399 | ||
| @@ -3401,16 +3404,16 @@ static int __init scsi_debug_init(void) | |||
| 3401 | clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU); | 3404 | clamp(scsi_debug_unmap_granularity, 1U, 0xffffffffU); |
| 3402 | 3405 | ||
| 3403 | if (scsi_debug_unmap_alignment && | 3406 | if (scsi_debug_unmap_alignment && |
| 3404 | scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) { | 3407 | scsi_debug_unmap_granularity <= |
| 3408 | scsi_debug_unmap_alignment) { | ||
| 3405 | printk(KERN_ERR | 3409 | printk(KERN_ERR |
| 3406 | "%s: ERR: unmap_granularity < unmap_alignment\n", | 3410 | "%s: ERR: unmap_granularity <= unmap_alignment\n", |
| 3407 | __func__); | 3411 | __func__); |
| 3408 | return -EINVAL; | 3412 | return -EINVAL; |
| 3409 | } | 3413 | } |
| 3410 | 3414 | ||
| 3411 | map_size = (sdebug_store_sectors / scsi_debug_unmap_granularity); | 3415 | map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1; |
| 3412 | map_bytes = map_size >> 3; | 3416 | map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long)); |
| 3413 | map_storep = vmalloc(map_bytes); | ||
| 3414 | 3417 | ||
| 3415 | printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n", | 3418 | printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n", |
| 3416 | map_size); | 3419 | map_size); |
| @@ -3421,7 +3424,7 @@ static int __init scsi_debug_init(void) | |||
| 3421 | goto free_vm; | 3424 | goto free_vm; |
| 3422 | } | 3425 | } |
| 3423 | 3426 | ||
| 3424 | memset(map_storep, 0x0, map_bytes); | 3427 | bitmap_zero(map_storep, map_size); |
| 3425 | 3428 | ||
| 3426 | /* Map first 1KB for partition table */ | 3429 | /* Map first 1KB for partition table */ |
| 3427 | if (scsi_debug_num_parts) | 3430 | if (scsi_debug_num_parts) |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index c1b05a83d403..f43de1e56420 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/blkdev.h> | 26 | #include <linux/blkdev.h> |
| 27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
| 28 | #include <linux/jiffies.h> | ||
| 28 | 29 | ||
| 29 | #include <scsi/scsi.h> | 30 | #include <scsi/scsi.h> |
| 30 | #include <scsi/scsi_cmnd.h> | 31 | #include <scsi/scsi_cmnd.h> |
| @@ -791,32 +792,48 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
| 791 | struct scsi_device *sdev = scmd->device; | 792 | struct scsi_device *sdev = scmd->device; |
| 792 | struct Scsi_Host *shost = sdev->host; | 793 | struct Scsi_Host *shost = sdev->host; |
| 793 | DECLARE_COMPLETION_ONSTACK(done); | 794 | DECLARE_COMPLETION_ONSTACK(done); |
| 794 | unsigned long timeleft; | 795 | unsigned long timeleft = timeout; |
| 795 | struct scsi_eh_save ses; | 796 | struct scsi_eh_save ses; |
| 797 | const unsigned long stall_for = msecs_to_jiffies(100); | ||
| 796 | int rtn; | 798 | int rtn; |
| 797 | 799 | ||
| 800 | retry: | ||
| 798 | scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes); | 801 | scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes); |
| 799 | shost->eh_action = &done; | 802 | shost->eh_action = &done; |
| 800 | 803 | ||
| 801 | scsi_log_send(scmd); | 804 | scsi_log_send(scmd); |
| 802 | scmd->scsi_done = scsi_eh_done; | 805 | scmd->scsi_done = scsi_eh_done; |
| 803 | shost->hostt->queuecommand(shost, scmd); | 806 | rtn = shost->hostt->queuecommand(shost, scmd); |
| 804 | 807 | if (rtn) { | |
| 805 | timeleft = wait_for_completion_timeout(&done, timeout); | 808 | if (timeleft > stall_for) { |
| 809 | scsi_eh_restore_cmnd(scmd, &ses); | ||
| 810 | timeleft -= stall_for; | ||
| 811 | msleep(jiffies_to_msecs(stall_for)); | ||
| 812 | goto retry; | ||
| 813 | } | ||
| 814 | /* signal not to enter either branch of the if () below */ | ||
| 815 | timeleft = 0; | ||
| 816 | rtn = NEEDS_RETRY; | ||
| 817 | } else { | ||
| 818 | timeleft = wait_for_completion_timeout(&done, timeout); | ||
| 819 | } | ||
| 806 | 820 | ||
| 807 | shost->eh_action = NULL; | 821 | shost->eh_action = NULL; |
| 808 | 822 | ||
| 809 | scsi_log_completion(scmd, SUCCESS); | 823 | scsi_log_completion(scmd, rtn); |
| 810 | 824 | ||
| 811 | SCSI_LOG_ERROR_RECOVERY(3, | 825 | SCSI_LOG_ERROR_RECOVERY(3, |
| 812 | printk("%s: scmd: %p, timeleft: %ld\n", | 826 | printk("%s: scmd: %p, timeleft: %ld\n", |
| 813 | __func__, scmd, timeleft)); | 827 | __func__, scmd, timeleft)); |
| 814 | 828 | ||
| 815 | /* | 829 | /* |
| 816 | * If there is time left scsi_eh_done got called, and we will | 830 | * If there is time left scsi_eh_done got called, and we will examine |
| 817 | * examine the actual status codes to see whether the command | 831 | * the actual status codes to see whether the command actually did |
| 818 | * actually did complete normally, else tell the host to forget | 832 | * complete normally, else if we have a zero return and no time left, |
| 819 | * about this command. | 833 | * the command must still be pending, so abort it and return FAILED. |
| 834 | * If we never actually managed to issue the command, because | ||
| 835 | * ->queuecommand() kept returning non zero, use the rtn = FAILED | ||
| 836 | * value above (so don't execute either branch of the if) | ||
| 820 | */ | 837 | */ |
| 821 | if (timeleft) { | 838 | if (timeleft) { |
| 822 | rtn = scsi_eh_completed_normally(scmd); | 839 | rtn = scsi_eh_completed_normally(scmd); |
| @@ -837,7 +854,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
| 837 | rtn = FAILED; | 854 | rtn = FAILED; |
| 838 | break; | 855 | break; |
| 839 | } | 856 | } |
| 840 | } else { | 857 | } else if (!rtn) { |
| 841 | scsi_abort_eh_cmnd(scmd); | 858 | scsi_abort_eh_cmnd(scmd); |
| 842 | rtn = FAILED; | 859 | rtn = FAILED; |
| 843 | } | 860 | } |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index c31187d79343..86d522004a20 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -276,11 +276,10 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | |||
| 276 | } | 276 | } |
| 277 | EXPORT_SYMBOL(scsi_execute); | 277 | EXPORT_SYMBOL(scsi_execute); |
| 278 | 278 | ||
| 279 | 279 | int scsi_execute_req_flags(struct scsi_device *sdev, const unsigned char *cmd, | |
| 280 | int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | ||
| 281 | int data_direction, void *buffer, unsigned bufflen, | 280 | int data_direction, void *buffer, unsigned bufflen, |
| 282 | struct scsi_sense_hdr *sshdr, int timeout, int retries, | 281 | struct scsi_sense_hdr *sshdr, int timeout, int retries, |
| 283 | int *resid) | 282 | int *resid, int flags) |
| 284 | { | 283 | { |
| 285 | char *sense = NULL; | 284 | char *sense = NULL; |
| 286 | int result; | 285 | int result; |
| @@ -291,14 +290,14 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | |||
| 291 | return DRIVER_ERROR << 24; | 290 | return DRIVER_ERROR << 24; |
| 292 | } | 291 | } |
| 293 | result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, | 292 | result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, |
| 294 | sense, timeout, retries, 0, resid); | 293 | sense, timeout, retries, flags, resid); |
| 295 | if (sshdr) | 294 | if (sshdr) |
| 296 | scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); | 295 | scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); |
| 297 | 296 | ||
| 298 | kfree(sense); | 297 | kfree(sense); |
| 299 | return result; | 298 | return result; |
| 300 | } | 299 | } |
| 301 | EXPORT_SYMBOL(scsi_execute_req); | 300 | EXPORT_SYMBOL(scsi_execute_req_flags); |
| 302 | 301 | ||
| 303 | /* | 302 | /* |
| 304 | * Function: scsi_init_cmd_errh() | 303 | * Function: scsi_init_cmd_errh() |
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c index 8f6b12cbd224..42539ee2cb11 100644 --- a/drivers/scsi/scsi_pm.c +++ b/drivers/scsi/scsi_pm.c | |||
| @@ -144,33 +144,83 @@ static int scsi_bus_restore(struct device *dev) | |||
| 144 | 144 | ||
| 145 | #ifdef CONFIG_PM_RUNTIME | 145 | #ifdef CONFIG_PM_RUNTIME |
| 146 | 146 | ||
| 147 | static int sdev_blk_runtime_suspend(struct scsi_device *sdev, | ||
| 148 | int (*cb)(struct device *)) | ||
| 149 | { | ||
| 150 | int err; | ||
| 151 | |||
| 152 | err = blk_pre_runtime_suspend(sdev->request_queue); | ||
| 153 | if (err) | ||
| 154 | return err; | ||
| 155 | if (cb) | ||
| 156 | err = cb(&sdev->sdev_gendev); | ||
| 157 | blk_post_runtime_suspend(sdev->request_queue, err); | ||
| 158 | |||
| 159 | return err; | ||
| 160 | } | ||
| 161 | |||
| 162 | static int sdev_runtime_suspend(struct device *dev) | ||
| 163 | { | ||
| 164 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 165 | int (*cb)(struct device *) = pm ? pm->runtime_suspend : NULL; | ||
| 166 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 167 | int err; | ||
| 168 | |||
| 169 | if (sdev->request_queue->dev) | ||
| 170 | return sdev_blk_runtime_suspend(sdev, cb); | ||
| 171 | |||
| 172 | err = scsi_dev_type_suspend(dev, cb); | ||
| 173 | if (err == -EAGAIN) | ||
| 174 | pm_schedule_suspend(dev, jiffies_to_msecs( | ||
| 175 | round_jiffies_up_relative(HZ/10))); | ||
| 176 | return err; | ||
| 177 | } | ||
| 178 | |||
| 147 | static int scsi_runtime_suspend(struct device *dev) | 179 | static int scsi_runtime_suspend(struct device *dev) |
| 148 | { | 180 | { |
| 149 | int err = 0; | 181 | int err = 0; |
| 150 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | ||
| 151 | 182 | ||
| 152 | dev_dbg(dev, "scsi_runtime_suspend\n"); | 183 | dev_dbg(dev, "scsi_runtime_suspend\n"); |
| 153 | if (scsi_is_sdev_device(dev)) { | 184 | if (scsi_is_sdev_device(dev)) |
| 154 | err = scsi_dev_type_suspend(dev, | 185 | err = sdev_runtime_suspend(dev); |
| 155 | pm ? pm->runtime_suspend : NULL); | ||
| 156 | if (err == -EAGAIN) | ||
| 157 | pm_schedule_suspend(dev, jiffies_to_msecs( | ||
| 158 | round_jiffies_up_relative(HZ/10))); | ||
| 159 | } | ||
| 160 | 186 | ||
| 161 | /* Insert hooks here for targets, hosts, and transport classes */ | 187 | /* Insert hooks here for targets, hosts, and transport classes */ |
| 162 | 188 | ||
| 163 | return err; | 189 | return err; |
| 164 | } | 190 | } |
| 165 | 191 | ||
| 166 | static int scsi_runtime_resume(struct device *dev) | 192 | static int sdev_blk_runtime_resume(struct scsi_device *sdev, |
| 193 | int (*cb)(struct device *)) | ||
| 167 | { | 194 | { |
| 168 | int err = 0; | 195 | int err = 0; |
| 196 | |||
| 197 | blk_pre_runtime_resume(sdev->request_queue); | ||
| 198 | if (cb) | ||
| 199 | err = cb(&sdev->sdev_gendev); | ||
| 200 | blk_post_runtime_resume(sdev->request_queue, err); | ||
| 201 | |||
| 202 | return err; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int sdev_runtime_resume(struct device *dev) | ||
| 206 | { | ||
| 207 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 169 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; | 208 | const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; |
| 209 | int (*cb)(struct device *) = pm ? pm->runtime_resume : NULL; | ||
| 210 | |||
| 211 | if (sdev->request_queue->dev) | ||
| 212 | return sdev_blk_runtime_resume(sdev, cb); | ||
| 213 | else | ||
| 214 | return scsi_dev_type_resume(dev, cb); | ||
| 215 | } | ||
| 216 | |||
| 217 | static int scsi_runtime_resume(struct device *dev) | ||
| 218 | { | ||
| 219 | int err = 0; | ||
| 170 | 220 | ||
| 171 | dev_dbg(dev, "scsi_runtime_resume\n"); | 221 | dev_dbg(dev, "scsi_runtime_resume\n"); |
| 172 | if (scsi_is_sdev_device(dev)) | 222 | if (scsi_is_sdev_device(dev)) |
| 173 | err = scsi_dev_type_resume(dev, pm ? pm->runtime_resume : NULL); | 223 | err = sdev_runtime_resume(dev); |
| 174 | 224 | ||
| 175 | /* Insert hooks here for targets, hosts, and transport classes */ | 225 | /* Insert hooks here for targets, hosts, and transport classes */ |
| 176 | 226 | ||
| @@ -185,10 +235,18 @@ static int scsi_runtime_idle(struct device *dev) | |||
| 185 | 235 | ||
| 186 | /* Insert hooks here for targets, hosts, and transport classes */ | 236 | /* Insert hooks here for targets, hosts, and transport classes */ |
| 187 | 237 | ||
| 188 | if (scsi_is_sdev_device(dev)) | 238 | if (scsi_is_sdev_device(dev)) { |
| 189 | err = pm_schedule_suspend(dev, 100); | 239 | struct scsi_device *sdev = to_scsi_device(dev); |
| 190 | else | 240 | |
| 241 | if (sdev->request_queue->dev) { | ||
| 242 | pm_runtime_mark_last_busy(dev); | ||
| 243 | err = pm_runtime_autosuspend(dev); | ||
| 244 | } else { | ||
| 245 | err = pm_runtime_suspend(dev); | ||
| 246 | } | ||
| 247 | } else { | ||
| 191 | err = pm_runtime_suspend(dev); | 248 | err = pm_runtime_suspend(dev); |
| 249 | } | ||
| 192 | return err; | 250 | return err; |
| 193 | } | 251 | } |
| 194 | 252 | ||
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 47799a33d6ca..133926b1bb78 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
| @@ -1019,8 +1019,7 @@ exit_match_index: | |||
| 1019 | /** | 1019 | /** |
| 1020 | * iscsi_get_flashnode_by_index -finds flashnode session entry by index | 1020 | * iscsi_get_flashnode_by_index -finds flashnode session entry by index |
| 1021 | * @shost: pointer to host data | 1021 | * @shost: pointer to host data |
| 1022 | * @data: pointer to data containing value to use for comparison | 1022 | * @idx: index to match |
| 1023 | * @fn: function pointer that does actual comparison | ||
| 1024 | * | 1023 | * |
| 1025 | * Finds the flashnode session object for the passed index | 1024 | * Finds the flashnode session object for the passed index |
| 1026 | * | 1025 | * |
| @@ -1029,13 +1028,13 @@ exit_match_index: | |||
| 1029 | * %NULL on failure | 1028 | * %NULL on failure |
| 1030 | */ | 1029 | */ |
| 1031 | static struct iscsi_bus_flash_session * | 1030 | static struct iscsi_bus_flash_session * |
| 1032 | iscsi_get_flashnode_by_index(struct Scsi_Host *shost, void *data, | 1031 | iscsi_get_flashnode_by_index(struct Scsi_Host *shost, uint32_t idx) |
| 1033 | int (*fn)(struct device *dev, void *data)) | ||
| 1034 | { | 1032 | { |
| 1035 | struct iscsi_bus_flash_session *fnode_sess = NULL; | 1033 | struct iscsi_bus_flash_session *fnode_sess = NULL; |
| 1036 | struct device *dev; | 1034 | struct device *dev; |
| 1037 | 1035 | ||
| 1038 | dev = device_find_child(&shost->shost_gendev, data, fn); | 1036 | dev = device_find_child(&shost->shost_gendev, &idx, |
| 1037 | flashnode_match_index); | ||
| 1039 | if (dev) | 1038 | if (dev) |
| 1040 | fnode_sess = iscsi_dev_to_flash_session(dev); | 1039 | fnode_sess = iscsi_dev_to_flash_session(dev); |
| 1041 | 1040 | ||
| @@ -1059,18 +1058,13 @@ struct device * | |||
| 1059 | iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data, | 1058 | iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data, |
| 1060 | int (*fn)(struct device *dev, void *data)) | 1059 | int (*fn)(struct device *dev, void *data)) |
| 1061 | { | 1060 | { |
| 1062 | struct device *dev; | 1061 | return device_find_child(&shost->shost_gendev, data, fn); |
| 1063 | |||
| 1064 | dev = device_find_child(&shost->shost_gendev, data, fn); | ||
| 1065 | return dev; | ||
| 1066 | } | 1062 | } |
| 1067 | EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess); | 1063 | EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess); |
| 1068 | 1064 | ||
| 1069 | /** | 1065 | /** |
| 1070 | * iscsi_find_flashnode_conn - finds flashnode connection entry | 1066 | * iscsi_find_flashnode_conn - finds flashnode connection entry |
| 1071 | * @fnode_sess: pointer to parent flashnode session entry | 1067 | * @fnode_sess: pointer to parent flashnode session entry |
| 1072 | * @data: pointer to data containing value to use for comparison | ||
| 1073 | * @fn: function pointer that does actual comparison | ||
| 1074 | * | 1068 | * |
| 1075 | * Finds the flashnode connection object comparing the data passed using logic | 1069 | * Finds the flashnode connection object comparing the data passed using logic |
| 1076 | * defined in passed function pointer | 1070 | * defined in passed function pointer |
| @@ -1080,14 +1074,10 @@ EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess); | |||
| 1080 | * %NULL on failure | 1074 | * %NULL on failure |
| 1081 | */ | 1075 | */ |
| 1082 | struct device * | 1076 | struct device * |
| 1083 | iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess, | 1077 | iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess) |
| 1084 | void *data, | ||
| 1085 | int (*fn)(struct device *dev, void *data)) | ||
| 1086 | { | 1078 | { |
| 1087 | struct device *dev; | 1079 | return device_find_child(&fnode_sess->dev, NULL, |
| 1088 | 1080 | iscsi_is_flashnode_conn_dev); | |
| 1089 | dev = device_find_child(&fnode_sess->dev, data, fn); | ||
| 1090 | return dev; | ||
| 1091 | } | 1081 | } |
| 1092 | EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn); | 1082 | EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn); |
| 1093 | 1083 | ||
| @@ -2808,7 +2798,7 @@ static int iscsi_set_flashnode_param(struct iscsi_transport *transport, | |||
| 2808 | struct iscsi_bus_flash_session *fnode_sess; | 2798 | struct iscsi_bus_flash_session *fnode_sess; |
| 2809 | struct iscsi_bus_flash_conn *fnode_conn; | 2799 | struct iscsi_bus_flash_conn *fnode_conn; |
| 2810 | struct device *dev; | 2800 | struct device *dev; |
| 2811 | uint32_t *idx; | 2801 | uint32_t idx; |
| 2812 | int err = 0; | 2802 | int err = 0; |
| 2813 | 2803 | ||
| 2814 | if (!transport->set_flashnode_param) { | 2804 | if (!transport->set_flashnode_param) { |
| @@ -2824,25 +2814,27 @@ static int iscsi_set_flashnode_param(struct iscsi_transport *transport, | |||
| 2824 | goto put_host; | 2814 | goto put_host; |
| 2825 | } | 2815 | } |
| 2826 | 2816 | ||
| 2827 | idx = &ev->u.set_flashnode.flashnode_idx; | 2817 | idx = ev->u.set_flashnode.flashnode_idx; |
| 2828 | fnode_sess = iscsi_get_flashnode_by_index(shost, idx, | 2818 | fnode_sess = iscsi_get_flashnode_by_index(shost, idx); |
| 2829 | flashnode_match_index); | ||
| 2830 | if (!fnode_sess) { | 2819 | if (!fnode_sess) { |
| 2831 | pr_err("%s could not find flashnode %u for host no %u\n", | 2820 | pr_err("%s could not find flashnode %u for host no %u\n", |
| 2832 | __func__, *idx, ev->u.set_flashnode.host_no); | 2821 | __func__, idx, ev->u.set_flashnode.host_no); |
| 2833 | err = -ENODEV; | 2822 | err = -ENODEV; |
| 2834 | goto put_host; | 2823 | goto put_host; |
| 2835 | } | 2824 | } |
| 2836 | 2825 | ||
| 2837 | dev = iscsi_find_flashnode_conn(fnode_sess, NULL, | 2826 | dev = iscsi_find_flashnode_conn(fnode_sess); |
| 2838 | iscsi_is_flashnode_conn_dev); | ||
| 2839 | if (!dev) { | 2827 | if (!dev) { |
| 2840 | err = -ENODEV; | 2828 | err = -ENODEV; |
| 2841 | goto put_host; | 2829 | goto put_sess; |
| 2842 | } | 2830 | } |
| 2843 | 2831 | ||
| 2844 | fnode_conn = iscsi_dev_to_flash_conn(dev); | 2832 | fnode_conn = iscsi_dev_to_flash_conn(dev); |
| 2845 | err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len); | 2833 | err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len); |
| 2834 | put_device(dev); | ||
| 2835 | |||
| 2836 | put_sess: | ||
| 2837 | put_device(&fnode_sess->dev); | ||
| 2846 | 2838 | ||
| 2847 | put_host: | 2839 | put_host: |
| 2848 | scsi_host_put(shost); | 2840 | scsi_host_put(shost); |
| @@ -2891,7 +2883,7 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport, | |||
| 2891 | { | 2883 | { |
| 2892 | struct Scsi_Host *shost; | 2884 | struct Scsi_Host *shost; |
| 2893 | struct iscsi_bus_flash_session *fnode_sess; | 2885 | struct iscsi_bus_flash_session *fnode_sess; |
| 2894 | uint32_t *idx; | 2886 | uint32_t idx; |
| 2895 | int err = 0; | 2887 | int err = 0; |
| 2896 | 2888 | ||
| 2897 | if (!transport->del_flashnode) { | 2889 | if (!transport->del_flashnode) { |
| @@ -2907,17 +2899,17 @@ static int iscsi_del_flashnode(struct iscsi_transport *transport, | |||
| 2907 | goto put_host; | 2899 | goto put_host; |
| 2908 | } | 2900 | } |
| 2909 | 2901 | ||
| 2910 | idx = &ev->u.del_flashnode.flashnode_idx; | 2902 | idx = ev->u.del_flashnode.flashnode_idx; |
| 2911 | fnode_sess = iscsi_get_flashnode_by_index(shost, idx, | 2903 | fnode_sess = iscsi_get_flashnode_by_index(shost, idx); |
| 2912 | flashnode_match_index); | ||
| 2913 | if (!fnode_sess) { | 2904 | if (!fnode_sess) { |
| 2914 | pr_err("%s could not find flashnode %u for host no %u\n", | 2905 | pr_err("%s could not find flashnode %u for host no %u\n", |
| 2915 | __func__, *idx, ev->u.del_flashnode.host_no); | 2906 | __func__, idx, ev->u.del_flashnode.host_no); |
| 2916 | err = -ENODEV; | 2907 | err = -ENODEV; |
| 2917 | goto put_host; | 2908 | goto put_host; |
| 2918 | } | 2909 | } |
| 2919 | 2910 | ||
| 2920 | err = transport->del_flashnode(fnode_sess); | 2911 | err = transport->del_flashnode(fnode_sess); |
| 2912 | put_device(&fnode_sess->dev); | ||
| 2921 | 2913 | ||
| 2922 | put_host: | 2914 | put_host: |
| 2923 | scsi_host_put(shost); | 2915 | scsi_host_put(shost); |
| @@ -2933,7 +2925,7 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport, | |||
| 2933 | struct iscsi_bus_flash_session *fnode_sess; | 2925 | struct iscsi_bus_flash_session *fnode_sess; |
| 2934 | struct iscsi_bus_flash_conn *fnode_conn; | 2926 | struct iscsi_bus_flash_conn *fnode_conn; |
| 2935 | struct device *dev; | 2927 | struct device *dev; |
| 2936 | uint32_t *idx; | 2928 | uint32_t idx; |
| 2937 | int err = 0; | 2929 | int err = 0; |
| 2938 | 2930 | ||
| 2939 | if (!transport->login_flashnode) { | 2931 | if (!transport->login_flashnode) { |
| @@ -2949,25 +2941,27 @@ static int iscsi_login_flashnode(struct iscsi_transport *transport, | |||
| 2949 | goto put_host; | 2941 | goto put_host; |
| 2950 | } | 2942 | } |
| 2951 | 2943 | ||
| 2952 | idx = &ev->u.login_flashnode.flashnode_idx; | 2944 | idx = ev->u.login_flashnode.flashnode_idx; |
| 2953 | fnode_sess = iscsi_get_flashnode_by_index(shost, idx, | 2945 | fnode_sess = iscsi_get_flashnode_by_index(shost, idx); |
| 2954 | flashnode_match_index); | ||
| 2955 | if (!fnode_sess) { | 2946 | if (!fnode_sess) { |
| 2956 | pr_err("%s could not find flashnode %u for host no %u\n", | 2947 | pr_err("%s could not find flashnode %u for host no %u\n", |
| 2957 | __func__, *idx, ev->u.login_flashnode.host_no); | 2948 | __func__, idx, ev->u.login_flashnode.host_no); |
| 2958 | err = -ENODEV; | 2949 | err = -ENODEV; |
| 2959 | goto put_host; | 2950 | goto put_host; |
| 2960 | } | 2951 | } |
| 2961 | 2952 | ||
| 2962 | dev = iscsi_find_flashnode_conn(fnode_sess, NULL, | 2953 | dev = iscsi_find_flashnode_conn(fnode_sess); |
| 2963 | iscsi_is_flashnode_conn_dev); | ||
| 2964 | if (!dev) { | 2954 | if (!dev) { |
| 2965 | err = -ENODEV; | 2955 | err = -ENODEV; |
| 2966 | goto put_host; | 2956 | goto put_sess; |
| 2967 | } | 2957 | } |
| 2968 | 2958 | ||
| 2969 | fnode_conn = iscsi_dev_to_flash_conn(dev); | 2959 | fnode_conn = iscsi_dev_to_flash_conn(dev); |
| 2970 | err = transport->login_flashnode(fnode_sess, fnode_conn); | 2960 | err = transport->login_flashnode(fnode_sess, fnode_conn); |
| 2961 | put_device(dev); | ||
| 2962 | |||
| 2963 | put_sess: | ||
| 2964 | put_device(&fnode_sess->dev); | ||
| 2971 | 2965 | ||
| 2972 | put_host: | 2966 | put_host: |
| 2973 | scsi_host_put(shost); | 2967 | scsi_host_put(shost); |
| @@ -2983,7 +2977,7 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport, | |||
| 2983 | struct iscsi_bus_flash_session *fnode_sess; | 2977 | struct iscsi_bus_flash_session *fnode_sess; |
| 2984 | struct iscsi_bus_flash_conn *fnode_conn; | 2978 | struct iscsi_bus_flash_conn *fnode_conn; |
| 2985 | struct device *dev; | 2979 | struct device *dev; |
| 2986 | uint32_t *idx; | 2980 | uint32_t idx; |
| 2987 | int err = 0; | 2981 | int err = 0; |
| 2988 | 2982 | ||
| 2989 | if (!transport->logout_flashnode) { | 2983 | if (!transport->logout_flashnode) { |
| @@ -2999,26 +2993,28 @@ static int iscsi_logout_flashnode(struct iscsi_transport *transport, | |||
| 2999 | goto put_host; | 2993 | goto put_host; |
| 3000 | } | 2994 | } |
| 3001 | 2995 | ||
| 3002 | idx = &ev->u.logout_flashnode.flashnode_idx; | 2996 | idx = ev->u.logout_flashnode.flashnode_idx; |
| 3003 | fnode_sess = iscsi_get_flashnode_by_index(shost, idx, | 2997 | fnode_sess = iscsi_get_flashnode_by_index(shost, idx); |
| 3004 | flashnode_match_index); | ||
| 3005 | if (!fnode_sess) { | 2998 | if (!fnode_sess) { |
| 3006 | pr_err("%s could not find flashnode %u for host no %u\n", | 2999 | pr_err("%s could not find flashnode %u for host no %u\n", |
| 3007 | __func__, *idx, ev->u.logout_flashnode.host_no); | 3000 | __func__, idx, ev->u.logout_flashnode.host_no); |
| 3008 | err = -ENODEV; | 3001 | err = -ENODEV; |
| 3009 | goto put_host; | 3002 | goto put_host; |
| 3010 | } | 3003 | } |
| 3011 | 3004 | ||
| 3012 | dev = iscsi_find_flashnode_conn(fnode_sess, NULL, | 3005 | dev = iscsi_find_flashnode_conn(fnode_sess); |
| 3013 | iscsi_is_flashnode_conn_dev); | ||
| 3014 | if (!dev) { | 3006 | if (!dev) { |
| 3015 | err = -ENODEV; | 3007 | err = -ENODEV; |
| 3016 | goto put_host; | 3008 | goto put_sess; |
| 3017 | } | 3009 | } |
| 3018 | 3010 | ||
| 3019 | fnode_conn = iscsi_dev_to_flash_conn(dev); | 3011 | fnode_conn = iscsi_dev_to_flash_conn(dev); |
| 3020 | 3012 | ||
| 3021 | err = transport->logout_flashnode(fnode_sess, fnode_conn); | 3013 | err = transport->logout_flashnode(fnode_sess, fnode_conn); |
| 3014 | put_device(dev); | ||
| 3015 | |||
| 3016 | put_sess: | ||
| 3017 | put_device(&fnode_sess->dev); | ||
| 3022 | 3018 | ||
| 3023 | put_host: | 3019 | put_host: |
| 3024 | scsi_host_put(shost); | 3020 | scsi_host_put(shost); |
| @@ -3985,8 +3981,10 @@ static __init int iscsi_transport_init(void) | |||
| 3985 | } | 3981 | } |
| 3986 | 3982 | ||
| 3987 | iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh"); | 3983 | iscsi_eh_timer_workq = create_singlethread_workqueue("iscsi_eh"); |
| 3988 | if (!iscsi_eh_timer_workq) | 3984 | if (!iscsi_eh_timer_workq) { |
| 3985 | err = -ENOMEM; | ||
| 3989 | goto release_nls; | 3986 | goto release_nls; |
| 3987 | } | ||
| 3990 | 3988 | ||
| 3991 | return 0; | 3989 | return 0; |
| 3992 | 3990 | ||
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e6689776b4f6..c1c555242d0d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -142,6 +142,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, | |||
| 142 | char *buffer_data; | 142 | char *buffer_data; |
| 143 | struct scsi_mode_data data; | 143 | struct scsi_mode_data data; |
| 144 | struct scsi_sense_hdr sshdr; | 144 | struct scsi_sense_hdr sshdr; |
| 145 | const char *temp = "temporary "; | ||
| 145 | int len; | 146 | int len; |
| 146 | 147 | ||
| 147 | if (sdp->type != TYPE_DISK) | 148 | if (sdp->type != TYPE_DISK) |
| @@ -150,6 +151,13 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, | |||
| 150 | * it's not worth the risk */ | 151 | * it's not worth the risk */ |
| 151 | return -EINVAL; | 152 | return -EINVAL; |
| 152 | 153 | ||
| 154 | if (strncmp(buf, temp, sizeof(temp) - 1) == 0) { | ||
| 155 | buf += sizeof(temp) - 1; | ||
| 156 | sdkp->cache_override = 1; | ||
| 157 | } else { | ||
| 158 | sdkp->cache_override = 0; | ||
| 159 | } | ||
| 160 | |||
| 153 | for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) { | 161 | for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) { |
| 154 | len = strlen(sd_cache_types[i]); | 162 | len = strlen(sd_cache_types[i]); |
| 155 | if (strncmp(sd_cache_types[i], buf, len) == 0 && | 163 | if (strncmp(sd_cache_types[i], buf, len) == 0 && |
| @@ -162,6 +170,13 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, | |||
| 162 | return -EINVAL; | 170 | return -EINVAL; |
| 163 | rcd = ct & 0x01 ? 1 : 0; | 171 | rcd = ct & 0x01 ? 1 : 0; |
| 164 | wce = ct & 0x02 ? 1 : 0; | 172 | wce = ct & 0x02 ? 1 : 0; |
| 173 | |||
| 174 | if (sdkp->cache_override) { | ||
| 175 | sdkp->WCE = wce; | ||
| 176 | sdkp->RCD = rcd; | ||
| 177 | return count; | ||
| 178 | } | ||
| 179 | |||
| 165 | if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT, | 180 | if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT, |
| 166 | SD_MAX_RETRIES, &data, NULL)) | 181 | SD_MAX_RETRIES, &data, NULL)) |
| 167 | return -EINVAL; | 182 | return -EINVAL; |
| @@ -1121,10 +1136,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode) | |||
| 1121 | 1136 | ||
| 1122 | sdev = sdkp->device; | 1137 | sdev = sdkp->device; |
| 1123 | 1138 | ||
| 1124 | retval = scsi_autopm_get_device(sdev); | ||
| 1125 | if (retval) | ||
| 1126 | goto error_autopm; | ||
| 1127 | |||
| 1128 | /* | 1139 | /* |
| 1129 | * If the device is in error recovery, wait until it is done. | 1140 | * If the device is in error recovery, wait until it is done. |
| 1130 | * If the device is offline, then disallow any access to it. | 1141 | * If the device is offline, then disallow any access to it. |
| @@ -1169,8 +1180,6 @@ static int sd_open(struct block_device *bdev, fmode_t mode) | |||
| 1169 | return 0; | 1180 | return 0; |
| 1170 | 1181 | ||
| 1171 | error_out: | 1182 | error_out: |
| 1172 | scsi_autopm_put_device(sdev); | ||
| 1173 | error_autopm: | ||
| 1174 | scsi_disk_put(sdkp); | 1183 | scsi_disk_put(sdkp); |
| 1175 | return retval; | 1184 | return retval; |
| 1176 | } | 1185 | } |
| @@ -1205,7 +1214,6 @@ static void sd_release(struct gendisk *disk, fmode_t mode) | |||
| 1205 | * XXX is followed by a "rmmod sd_mod"? | 1214 | * XXX is followed by a "rmmod sd_mod"? |
| 1206 | */ | 1215 | */ |
| 1207 | 1216 | ||
| 1208 | scsi_autopm_put_device(sdev); | ||
| 1209 | scsi_disk_put(sdkp); | 1217 | scsi_disk_put(sdkp); |
| 1210 | } | 1218 | } |
| 1211 | 1219 | ||
| @@ -1366,14 +1374,9 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing) | |||
| 1366 | retval = -ENODEV; | 1374 | retval = -ENODEV; |
| 1367 | 1375 | ||
| 1368 | if (scsi_block_when_processing_errors(sdp)) { | 1376 | if (scsi_block_when_processing_errors(sdp)) { |
| 1369 | retval = scsi_autopm_get_device(sdp); | ||
| 1370 | if (retval) | ||
| 1371 | goto out; | ||
| 1372 | |||
| 1373 | sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL); | 1377 | sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL); |
| 1374 | retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES, | 1378 | retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES, |
| 1375 | sshdr); | 1379 | sshdr); |
| 1376 | scsi_autopm_put_device(sdp); | ||
| 1377 | } | 1380 | } |
| 1378 | 1381 | ||
| 1379 | /* failed to execute TUR, assume media not present */ | 1382 | /* failed to execute TUR, assume media not present */ |
| @@ -1423,8 +1426,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp) | |||
| 1423 | * Leave the rest of the command zero to indicate | 1426 | * Leave the rest of the command zero to indicate |
| 1424 | * flush everything. | 1427 | * flush everything. |
| 1425 | */ | 1428 | */ |
| 1426 | res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, | 1429 | res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, |
| 1427 | SD_FLUSH_TIMEOUT, SD_MAX_RETRIES, NULL); | 1430 | &sshdr, SD_FLUSH_TIMEOUT, |
| 1431 | SD_MAX_RETRIES, NULL, REQ_PM); | ||
| 1428 | if (res == 0) | 1432 | if (res == 0) |
| 1429 | break; | 1433 | break; |
| 1430 | } | 1434 | } |
| @@ -2318,6 +2322,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
| 2318 | int old_rcd = sdkp->RCD; | 2322 | int old_rcd = sdkp->RCD; |
| 2319 | int old_dpofua = sdkp->DPOFUA; | 2323 | int old_dpofua = sdkp->DPOFUA; |
| 2320 | 2324 | ||
| 2325 | |||
| 2326 | if (sdkp->cache_override) | ||
| 2327 | return; | ||
| 2328 | |||
| 2321 | first_len = 4; | 2329 | first_len = 4; |
| 2322 | if (sdp->skip_ms_page_8) { | 2330 | if (sdp->skip_ms_page_8) { |
| 2323 | if (sdp->type == TYPE_RBC) | 2331 | if (sdp->type == TYPE_RBC) |
| @@ -2811,6 +2819,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) | |||
| 2811 | sdkp->capacity = 0; | 2819 | sdkp->capacity = 0; |
| 2812 | sdkp->media_present = 1; | 2820 | sdkp->media_present = 1; |
| 2813 | sdkp->write_prot = 0; | 2821 | sdkp->write_prot = 0; |
| 2822 | sdkp->cache_override = 0; | ||
| 2814 | sdkp->WCE = 0; | 2823 | sdkp->WCE = 0; |
| 2815 | sdkp->RCD = 0; | 2824 | sdkp->RCD = 0; |
| 2816 | sdkp->ATO = 0; | 2825 | sdkp->ATO = 0; |
| @@ -2837,6 +2846,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) | |||
| 2837 | 2846 | ||
| 2838 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", | 2847 | sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", |
| 2839 | sdp->removable ? "removable " : ""); | 2848 | sdp->removable ? "removable " : ""); |
| 2849 | blk_pm_runtime_init(sdp->request_queue, dev); | ||
| 2840 | scsi_autopm_put_device(sdp); | 2850 | scsi_autopm_put_device(sdp); |
| 2841 | put_device(&sdkp->dev); | 2851 | put_device(&sdkp->dev); |
| 2842 | } | 2852 | } |
| @@ -3020,8 +3030,8 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) | |||
| 3020 | if (!scsi_device_online(sdp)) | 3030 | if (!scsi_device_online(sdp)) |
| 3021 | return -ENODEV; | 3031 | return -ENODEV; |
| 3022 | 3032 | ||
| 3023 | res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, | 3033 | res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, |
| 3024 | SD_TIMEOUT, SD_MAX_RETRIES, NULL); | 3034 | SD_TIMEOUT, SD_MAX_RETRIES, NULL, REQ_PM); |
| 3025 | if (res) { | 3035 | if (res) { |
| 3026 | sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n"); | 3036 | sd_printk(KERN_WARNING, sdkp, "START_STOP FAILED\n"); |
| 3027 | sd_print_result(sdkp, res); | 3037 | sd_print_result(sdkp, res); |
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 74a1e4ca5401..2386aeb41fe8 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h | |||
| @@ -73,6 +73,7 @@ struct scsi_disk { | |||
| 73 | u8 protection_type;/* Data Integrity Field */ | 73 | u8 protection_type;/* Data Integrity Field */ |
| 74 | u8 provisioning_mode; | 74 | u8 provisioning_mode; |
| 75 | unsigned ATO : 1; /* state of disk ATO bit */ | 75 | unsigned ATO : 1; /* state of disk ATO bit */ |
| 76 | unsigned cache_override : 1; /* temp override of WCE,RCD */ | ||
| 76 | unsigned WCE : 1; /* state of disk WCE bit */ | 77 | unsigned WCE : 1; /* state of disk WCE bit */ |
| 77 | unsigned RCD : 1; /* state of disk RCD bit, unused */ | 78 | unsigned RCD : 1; /* state of disk RCD bit, unused */ |
| 78 | unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ | 79 | unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ |
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index 04998f36e507..6174ca4ea275 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c | |||
| @@ -93,14 +93,6 @@ static int sd_dif_type1_verify(struct blk_integrity_exchg *bix, csum_fn *fn) | |||
| 93 | if (sdt->app_tag == 0xffff) | 93 | if (sdt->app_tag == 0xffff) |
| 94 | return 0; | 94 | return 0; |
| 95 | 95 | ||
| 96 | /* Bad ref tag received from disk */ | ||
| 97 | if (sdt->ref_tag == 0xffffffff) { | ||
| 98 | printk(KERN_ERR | ||
| 99 | "%s: bad phys ref tag on sector %lu\n", | ||
| 100 | bix->disk_name, (unsigned long)sector); | ||
| 101 | return -EIO; | ||
| 102 | } | ||
| 103 | |||
| 104 | if (be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { | 96 | if (be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { |
| 105 | printk(KERN_ERR | 97 | printk(KERN_ERR |
| 106 | "%s: ref tag error on sector %lu (rcvd %u)\n", | 98 | "%s: ref tag error on sector %lu (rcvd %u)\n", |
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index 0371047c5922..35faf24c6044 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig | |||
| @@ -57,3 +57,14 @@ config SCSI_UFSHCD_PCI | |||
| 57 | If you have a controller with this interface, say Y or M here. | 57 | If you have a controller with this interface, say Y or M here. |
| 58 | 58 | ||
| 59 | If unsure, say N. | 59 | If unsure, say N. |
| 60 | |||
| 61 | config SCSI_UFSHCD_PLATFORM | ||
| 62 | tristate "Platform bus based UFS Controller support" | ||
| 63 | depends on SCSI_UFSHCD | ||
| 64 | ---help--- | ||
| 65 | This selects the UFS host controller support. Select this if | ||
| 66 | you have an UFS controller on Platform bus. | ||
| 67 | |||
| 68 | If you have a controller with this interface, say Y or M here. | ||
| 69 | |||
| 70 | If unsure, say N. | ||
diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 9eda0dfbd6df..1e5bd48457d6 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | # UFSHCD makefile | 1 | # UFSHCD makefile |
| 2 | obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o | 2 | obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o |
| 3 | obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o | 3 | obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o |
| 4 | obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o | ||
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c new file mode 100644 index 000000000000..03319acd9c72 --- /dev/null +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c | |||
| @@ -0,0 +1,217 @@ | |||
| 1 | /* | ||
| 2 | * Universal Flash Storage Host controller Platform bus based glue driver | ||
| 3 | * | ||
| 4 | * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c | ||
| 5 | * Copyright (C) 2011-2013 Samsung India Software Operations | ||
| 6 | * | ||
| 7 | * Authors: | ||
| 8 | * Santosh Yaraganavi <santosh.sy@samsung.com> | ||
| 9 | * Vinayak Holikatti <h.vinayak@samsung.com> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or | ||
| 12 | * modify it under the terms of the GNU General Public License | ||
| 13 | * as published by the Free Software Foundation; either version 2 | ||
| 14 | * of the License, or (at your option) any later version. | ||
| 15 | * See the COPYING file in the top-level directory or visit | ||
| 16 | * <http://www.gnu.org/licenses/gpl-2.0.html> | ||
| 17 | * | ||
| 18 | * This program is distributed in the hope that it will be useful, | ||
| 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 21 | * GNU General Public License for more details. | ||
| 22 | * | ||
| 23 | * This program is provided "AS IS" and "WITH ALL FAULTS" and | ||
| 24 | * without warranty of any kind. You are solely responsible for | ||
| 25 | * determining the appropriateness of using and distributing | ||
| 26 | * the program and assume all risks associated with your exercise | ||
| 27 | * of rights with respect to the program, including but not limited | ||
| 28 | * to infringement of third party rights, the risks and costs of | ||
| 29 | * program errors, damage to or loss of data, programs or equipment, | ||
| 30 | * and unavailability or interruption of operations. Under no | ||
| 31 | * circumstances will the contributor of this Program be liable for | ||
| 32 | * any damages of any kind arising from your use or distribution of | ||
| 33 | * this program. | ||
| 34 | */ | ||
| 35 | |||
| 36 | #include "ufshcd.h" | ||
| 37 | #include <linux/platform_device.h> | ||
| 38 | |||
| 39 | #ifdef CONFIG_PM | ||
| 40 | /** | ||
| 41 | * ufshcd_pltfrm_suspend - suspend power management function | ||
| 42 | * @dev: pointer to device handle | ||
| 43 | * | ||
| 44 | * | ||
| 45 | * Returns 0 | ||
| 46 | */ | ||
| 47 | static int ufshcd_pltfrm_suspend(struct device *dev) | ||
| 48 | { | ||
| 49 | struct platform_device *pdev = to_platform_device(dev); | ||
| 50 | struct ufs_hba *hba = platform_get_drvdata(pdev); | ||
| 51 | |||
| 52 | /* | ||
| 53 | * TODO: | ||
| 54 | * 1. Call ufshcd_suspend | ||
| 55 | * 2. Do bus specific power management | ||
| 56 | */ | ||
| 57 | |||
| 58 | disable_irq(hba->irq); | ||
| 59 | |||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | /** | ||
| 64 | * ufshcd_pltfrm_resume - resume power management function | ||
| 65 | * @dev: pointer to device handle | ||
| 66 | * | ||
| 67 | * Returns 0 | ||
| 68 | */ | ||
| 69 | static int ufshcd_pltfrm_resume(struct device *dev) | ||
| 70 | { | ||
| 71 | struct platform_device *pdev = to_platform_device(dev); | ||
| 72 | struct ufs_hba *hba = platform_get_drvdata(pdev); | ||
| 73 | |||
| 74 | /* | ||
| 75 | * TODO: | ||
| 76 | * 1. Call ufshcd_resume. | ||
| 77 | * 2. Do bus specific wake up | ||
| 78 | */ | ||
| 79 | |||
| 80 | enable_irq(hba->irq); | ||
| 81 | |||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | #else | ||
| 85 | #define ufshcd_pltfrm_suspend NULL | ||
| 86 | #define ufshcd_pltfrm_resume NULL | ||
| 87 | #endif | ||
| 88 | |||
| 89 | /** | ||
| 90 | * ufshcd_pltfrm_probe - probe routine of the driver | ||
| 91 | * @pdev: pointer to Platform device handle | ||
| 92 | * | ||
| 93 | * Returns 0 on success, non-zero value on failure | ||
| 94 | */ | ||
| 95 | static int ufshcd_pltfrm_probe(struct platform_device *pdev) | ||
| 96 | { | ||
| 97 | struct ufs_hba *hba; | ||
| 98 | void __iomem *mmio_base; | ||
| 99 | struct resource *mem_res; | ||
| 100 | struct resource *irq_res; | ||
| 101 | resource_size_t mem_size; | ||
| 102 | int err; | ||
| 103 | struct device *dev = &pdev->dev; | ||
| 104 | |||
| 105 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 106 | if (!mem_res) { | ||
| 107 | dev_err(&pdev->dev, | ||
| 108 | "Memory resource not available\n"); | ||
| 109 | err = -ENODEV; | ||
| 110 | goto out_error; | ||
| 111 | } | ||
| 112 | |||
| 113 | mem_size = resource_size(mem_res); | ||
| 114 | if (!request_mem_region(mem_res->start, mem_size, "ufshcd")) { | ||
| 115 | dev_err(&pdev->dev, | ||
| 116 | "Cannot reserve the memory resource\n"); | ||
| 117 | err = -EBUSY; | ||
| 118 | goto out_error; | ||
| 119 | } | ||
| 120 | |||
| 121 | mmio_base = ioremap_nocache(mem_res->start, mem_size); | ||
| 122 | if (!mmio_base) { | ||
| 123 | dev_err(&pdev->dev, "memory map failed\n"); | ||
| 124 | err = -ENOMEM; | ||
| 125 | goto out_release_regions; | ||
| 126 | } | ||
| 127 | |||
| 128 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
| 129 | if (!irq_res) { | ||
| 130 | dev_err(&pdev->dev, "IRQ resource not available\n"); | ||
| 131 | err = -ENODEV; | ||
| 132 | goto out_iounmap; | ||
| 133 | } | ||
| 134 | |||
| 135 | err = dma_set_coherent_mask(dev, dev->coherent_dma_mask); | ||
| 136 | if (err) { | ||
| 137 | dev_err(&pdev->dev, "set dma mask failed\n"); | ||
| 138 | goto out_iounmap; | ||
| 139 | } | ||
| 140 | |||
| 141 | err = ufshcd_init(&pdev->dev, &hba, mmio_base, irq_res->start); | ||
| 142 | if (err) { | ||
| 143 | dev_err(&pdev->dev, "Intialization failed\n"); | ||
| 144 | goto out_iounmap; | ||
| 145 | } | ||
| 146 | |||
| 147 | platform_set_drvdata(pdev, hba); | ||
| 148 | |||
| 149 | return 0; | ||
| 150 | |||
| 151 | out_iounmap: | ||
| 152 | iounmap(mmio_base); | ||
| 153 | out_release_regions: | ||
| 154 | release_mem_region(mem_res->start, mem_size); | ||
| 155 | out_error: | ||
| 156 | return err; | ||
| 157 | } | ||
| 158 | |||
| 159 | /** | ||
| 160 | * ufshcd_pltfrm_remove - remove platform driver routine | ||
| 161 | * @pdev: pointer to platform device handle | ||
| 162 | * | ||
| 163 | * Returns 0 on success, non-zero value on failure | ||
| 164 | */ | ||
| 165 | static int ufshcd_pltfrm_remove(struct platform_device *pdev) | ||
| 166 | { | ||
| 167 | struct resource *mem_res; | ||
| 168 | resource_size_t mem_size; | ||
| 169 | struct ufs_hba *hba = platform_get_drvdata(pdev); | ||
| 170 | |||
| 171 | disable_irq(hba->irq); | ||
| 172 | |||
| 173 | /* Some buggy controllers raise interrupt after | ||
| 174 | * the resources are removed. So first we unregister the | ||
| 175 | * irq handler and then the resources used by driver | ||
| 176 | */ | ||
| 177 | |||
| 178 | free_irq(hba->irq, hba); | ||
| 179 | ufshcd_remove(hba); | ||
| 180 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 181 | if (!mem_res) | ||
| 182 | dev_err(&pdev->dev, "ufshcd: Memory resource not available\n"); | ||
| 183 | else { | ||
| 184 | mem_size = resource_size(mem_res); | ||
| 185 | release_mem_region(mem_res->start, mem_size); | ||
| 186 | } | ||
| 187 | platform_set_drvdata(pdev, NULL); | ||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | static const struct of_device_id ufs_of_match[] = { | ||
| 192 | { .compatible = "jedec,ufs-1.1"}, | ||
| 193 | }; | ||
| 194 | |||
| 195 | static const struct dev_pm_ops ufshcd_dev_pm_ops = { | ||
| 196 | .suspend = ufshcd_pltfrm_suspend, | ||
| 197 | .resume = ufshcd_pltfrm_resume, | ||
| 198 | }; | ||
| 199 | |||
| 200 | static struct platform_driver ufshcd_pltfrm_driver = { | ||
| 201 | .probe = ufshcd_pltfrm_probe, | ||
| 202 | .remove = ufshcd_pltfrm_remove, | ||
| 203 | .driver = { | ||
| 204 | .name = "ufshcd", | ||
| 205 | .owner = THIS_MODULE, | ||
| 206 | .pm = &ufshcd_dev_pm_ops, | ||
| 207 | .of_match_table = ufs_of_match, | ||
| 208 | }, | ||
| 209 | }; | ||
| 210 | |||
| 211 | module_platform_driver(ufshcd_pltfrm_driver); | ||
| 212 | |||
| 213 | MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>"); | ||
| 214 | MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>"); | ||
| 215 | MODULE_DESCRIPTION("UFS host controller Pltform bus based glue driver"); | ||
| 216 | MODULE_LICENSE("GPL"); | ||
| 217 | MODULE_VERSION(UFSHCD_DRIVER_VERSION); | ||
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 60fd40c4e4c2..c32a478df81b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c | |||
| @@ -478,7 +478,7 @@ static void ufshcd_compose_upiu(struct ufshcd_lrb *lrbp) | |||
| 478 | ucd_cmd_ptr->header.dword_2 = 0; | 478 | ucd_cmd_ptr->header.dword_2 = 0; |
| 479 | 479 | ||
| 480 | ucd_cmd_ptr->exp_data_transfer_len = | 480 | ucd_cmd_ptr->exp_data_transfer_len = |
| 481 | cpu_to_be32(lrbp->cmd->transfersize); | 481 | cpu_to_be32(lrbp->cmd->sdb.length); |
| 482 | 482 | ||
| 483 | memcpy(ucd_cmd_ptr->cdb, | 483 | memcpy(ucd_cmd_ptr->cdb, |
| 484 | lrbp->cmd->cmnd, | 484 | lrbp->cmd->cmnd, |
diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 787bd2c22bca..380387a47b1d 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c | |||
| @@ -526,13 +526,17 @@ static void atmel_spi_next_xfer_pio(struct spi_master *master, | |||
| 526 | } | 526 | } |
| 527 | 527 | ||
| 528 | if (xfer->tx_buf) | 528 | if (xfer->tx_buf) |
| 529 | spi_writel(as, TDR, *(u8 *)(xfer->tx_buf)); | 529 | if (xfer->bits_per_word > 8) |
| 530 | spi_writel(as, TDR, *(u16 *)(xfer->tx_buf)); | ||
| 531 | else | ||
| 532 | spi_writel(as, TDR, *(u8 *)(xfer->tx_buf)); | ||
| 530 | else | 533 | else |
| 531 | spi_writel(as, TDR, 0); | 534 | spi_writel(as, TDR, 0); |
| 532 | 535 | ||
| 533 | dev_dbg(master->dev.parent, | 536 | dev_dbg(master->dev.parent, |
| 534 | " start pio xfer %p: len %u tx %p rx %p\n", | 537 | " start pio xfer %p: len %u tx %p rx %p bitpw %d\n", |
| 535 | xfer, xfer->len, xfer->tx_buf, xfer->rx_buf); | 538 | xfer, xfer->len, xfer->tx_buf, xfer->rx_buf, |
| 539 | xfer->bits_per_word); | ||
| 536 | 540 | ||
| 537 | /* Enable relevant interrupts */ | 541 | /* Enable relevant interrupts */ |
| 538 | spi_writel(as, IER, SPI_BIT(RDRF) | SPI_BIT(OVRES)); | 542 | spi_writel(as, IER, SPI_BIT(RDRF) | SPI_BIT(OVRES)); |
| @@ -950,21 +954,39 @@ atmel_spi_pump_pio_data(struct atmel_spi *as, struct spi_transfer *xfer) | |||
| 950 | { | 954 | { |
| 951 | u8 *txp; | 955 | u8 *txp; |
| 952 | u8 *rxp; | 956 | u8 *rxp; |
| 957 | u16 *txp16; | ||
| 958 | u16 *rxp16; | ||
| 953 | unsigned long xfer_pos = xfer->len - as->current_remaining_bytes; | 959 | unsigned long xfer_pos = xfer->len - as->current_remaining_bytes; |
| 954 | 960 | ||
| 955 | if (xfer->rx_buf) { | 961 | if (xfer->rx_buf) { |
| 956 | rxp = ((u8 *)xfer->rx_buf) + xfer_pos; | 962 | if (xfer->bits_per_word > 8) { |
| 957 | *rxp = spi_readl(as, RDR); | 963 | rxp16 = (u16 *)(((u8 *)xfer->rx_buf) + xfer_pos); |
| 964 | *rxp16 = spi_readl(as, RDR); | ||
| 965 | } else { | ||
| 966 | rxp = ((u8 *)xfer->rx_buf) + xfer_pos; | ||
| 967 | *rxp = spi_readl(as, RDR); | ||
| 968 | } | ||
| 958 | } else { | 969 | } else { |
| 959 | spi_readl(as, RDR); | 970 | spi_readl(as, RDR); |
| 960 | } | 971 | } |
| 961 | 972 | if (xfer->bits_per_word > 8) { | |
| 962 | as->current_remaining_bytes--; | 973 | as->current_remaining_bytes -= 2; |
| 974 | if (as->current_remaining_bytes < 0) | ||
| 975 | as->current_remaining_bytes = 0; | ||
| 976 | } else { | ||
| 977 | as->current_remaining_bytes--; | ||
| 978 | } | ||
| 963 | 979 | ||
| 964 | if (as->current_remaining_bytes) { | 980 | if (as->current_remaining_bytes) { |
| 965 | if (xfer->tx_buf) { | 981 | if (xfer->tx_buf) { |
| 966 | txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1; | 982 | if (xfer->bits_per_word > 8) { |
| 967 | spi_writel(as, TDR, *txp); | 983 | txp16 = (u16 *)(((u8 *)xfer->tx_buf) |
| 984 | + xfer_pos + 2); | ||
| 985 | spi_writel(as, TDR, *txp16); | ||
| 986 | } else { | ||
| 987 | txp = ((u8 *)xfer->tx_buf) + xfer_pos + 1; | ||
| 988 | spi_writel(as, TDR, *txp); | ||
| 989 | } | ||
| 968 | } else { | 990 | } else { |
| 969 | spi_writel(as, TDR, 0); | 991 | spi_writel(as, TDR, 0); |
| 970 | } | 992 | } |
| @@ -1378,9 +1400,16 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) | |||
| 1378 | } | 1400 | } |
| 1379 | } | 1401 | } |
| 1380 | 1402 | ||
| 1403 | if (xfer->bits_per_word > 8) { | ||
| 1404 | if (xfer->len % 2) { | ||
| 1405 | dev_dbg(&spi->dev, "buffer len should be 16 bits aligned\n"); | ||
| 1406 | return -EINVAL; | ||
| 1407 | } | ||
| 1408 | } | ||
| 1409 | |||
| 1381 | /* FIXME implement these protocol options!! */ | 1410 | /* FIXME implement these protocol options!! */ |
| 1382 | if (xfer->speed_hz) { | 1411 | if (xfer->speed_hz < spi->max_speed_hz) { |
| 1383 | dev_dbg(&spi->dev, "no protocol options yet\n"); | 1412 | dev_dbg(&spi->dev, "can't change speed in transfer\n"); |
| 1384 | return -ENOPROTOOPT; | 1413 | return -ENOPROTOOPT; |
| 1385 | } | 1414 | } |
| 1386 | 1415 | ||
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 2e8f24a1fb95..50b13c9b1ab6 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c | |||
| @@ -784,7 +784,7 @@ static const struct of_device_id davinci_spi_of_match[] = { | |||
| 784 | }, | 784 | }, |
| 785 | { }, | 785 | { }, |
| 786 | }; | 786 | }; |
| 787 | MODULE_DEVICE_TABLE(of, davini_spi_of_match); | 787 | MODULE_DEVICE_TABLE(of, davinci_spi_of_match); |
| 788 | 788 | ||
| 789 | /** | 789 | /** |
| 790 | * spi_davinci_get_pdata - Get platform data from DTS binding | 790 | * spi_davinci_get_pdata - Get platform data from DTS binding |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 163fd802b7ac..32b7bb111eb6 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
| @@ -334,7 +334,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master) | |||
| 334 | spi->dev.parent = &master->dev; | 334 | spi->dev.parent = &master->dev; |
| 335 | spi->dev.bus = &spi_bus_type; | 335 | spi->dev.bus = &spi_bus_type; |
| 336 | spi->dev.release = spidev_release; | 336 | spi->dev.release = spidev_release; |
| 337 | spi->cs_gpio = -EINVAL; | 337 | spi->cs_gpio = -ENOENT; |
| 338 | device_initialize(&spi->dev); | 338 | device_initialize(&spi->dev); |
| 339 | return spi; | 339 | return spi; |
| 340 | } | 340 | } |
| @@ -1067,8 +1067,11 @@ static int of_spi_register_master(struct spi_master *master) | |||
| 1067 | nb = of_gpio_named_count(np, "cs-gpios"); | 1067 | nb = of_gpio_named_count(np, "cs-gpios"); |
| 1068 | master->num_chipselect = max(nb, (int)master->num_chipselect); | 1068 | master->num_chipselect = max(nb, (int)master->num_chipselect); |
| 1069 | 1069 | ||
| 1070 | if (nb < 1) | 1070 | /* Return error only for an incorrectly formed cs-gpios property */ |
| 1071 | if (nb == 0 || nb == -ENOENT) | ||
| 1071 | return 0; | 1072 | return 0; |
| 1073 | else if (nb < 0) | ||
| 1074 | return nb; | ||
| 1072 | 1075 | ||
| 1073 | cs = devm_kzalloc(&master->dev, | 1076 | cs = devm_kzalloc(&master->dev, |
| 1074 | sizeof(int) * master->num_chipselect, | 1077 | sizeof(int) * master->num_chipselect, |
| @@ -1079,7 +1082,7 @@ static int of_spi_register_master(struct spi_master *master) | |||
| 1079 | return -ENOMEM; | 1082 | return -ENOMEM; |
| 1080 | 1083 | ||
| 1081 | for (i = 0; i < master->num_chipselect; i++) | 1084 | for (i = 0; i < master->num_chipselect; i++) |
| 1082 | cs[i] = -EINVAL; | 1085 | cs[i] = -ENOENT; |
| 1083 | 1086 | ||
| 1084 | for (i = 0; i < nb; i++) | 1087 | for (i = 0; i < nb; i++) |
| 1085 | cs[i] = of_get_named_gpio(np, "cs-gpios", i); | 1088 | cs[i] = of_get_named_gpio(np, "cs-gpios", i); |
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 6953dc82850c..a4fdce74f883 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c | |||
| @@ -60,24 +60,22 @@ static void tty_audit_buf_put(struct tty_audit_buf *buf) | |||
| 60 | tty_audit_buf_free(buf); | 60 | tty_audit_buf_free(buf); |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | static void tty_audit_log(const char *description, struct task_struct *tsk, | 63 | static void tty_audit_log(const char *description, int major, int minor, |
| 64 | kuid_t loginuid, unsigned sessionid, int major, | 64 | unsigned char *data, size_t size) |
| 65 | int minor, unsigned char *data, size_t size) | ||
| 66 | { | 65 | { |
| 67 | struct audit_buffer *ab; | 66 | struct audit_buffer *ab; |
| 67 | struct task_struct *tsk = current; | ||
| 68 | uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); | ||
| 69 | uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); | ||
| 70 | u32 sessionid = audit_get_sessionid(tsk); | ||
| 68 | 71 | ||
| 69 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); | 72 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); |
| 70 | if (ab) { | 73 | if (ab) { |
| 71 | char name[sizeof(tsk->comm)]; | 74 | char name[sizeof(tsk->comm)]; |
| 72 | kuid_t uid = task_uid(tsk); | 75 | |
| 73 | 76 | audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" | |
| 74 | audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u " | 77 | " minor=%d comm=", description, tsk->pid, uid, |
| 75 | "major=%d minor=%d comm=", description, | 78 | loginuid, sessionid, major, minor); |
| 76 | tsk->pid, | ||
| 77 | from_kuid(&init_user_ns, uid), | ||
| 78 | from_kuid(&init_user_ns, loginuid), | ||
| 79 | sessionid, | ||
| 80 | major, minor); | ||
| 81 | get_task_comm(name, tsk); | 79 | get_task_comm(name, tsk); |
| 82 | audit_log_untrustedstring(ab, name); | 80 | audit_log_untrustedstring(ab, name); |
| 83 | audit_log_format(ab, " data="); | 81 | audit_log_format(ab, " data="); |
| @@ -90,11 +88,9 @@ static void tty_audit_log(const char *description, struct task_struct *tsk, | |||
| 90 | * tty_audit_buf_push - Push buffered data out | 88 | * tty_audit_buf_push - Push buffered data out |
| 91 | * | 89 | * |
| 92 | * Generate an audit message from the contents of @buf, which is owned by | 90 | * Generate an audit message from the contents of @buf, which is owned by |
| 93 | * @tsk with @loginuid. @buf->mutex must be locked. | 91 | * the current task. @buf->mutex must be locked. |
| 94 | */ | 92 | */ |
| 95 | static void tty_audit_buf_push(struct task_struct *tsk, kuid_t loginuid, | 93 | static void tty_audit_buf_push(struct tty_audit_buf *buf) |
| 96 | unsigned int sessionid, | ||
| 97 | struct tty_audit_buf *buf) | ||
| 98 | { | 94 | { |
| 99 | if (buf->valid == 0) | 95 | if (buf->valid == 0) |
| 100 | return; | 96 | return; |
| @@ -102,25 +98,11 @@ static void tty_audit_buf_push(struct task_struct *tsk, kuid_t loginuid, | |||
| 102 | buf->valid = 0; | 98 | buf->valid = 0; |
| 103 | return; | 99 | return; |
| 104 | } | 100 | } |
| 105 | tty_audit_log("tty", tsk, loginuid, sessionid, buf->major, buf->minor, | 101 | tty_audit_log("tty", buf->major, buf->minor, buf->data, buf->valid); |
| 106 | buf->data, buf->valid); | ||
| 107 | buf->valid = 0; | 102 | buf->valid = 0; |
| 108 | } | 103 | } |
| 109 | 104 | ||
| 110 | /** | 105 | /** |
| 111 | * tty_audit_buf_push_current - Push buffered data out | ||
| 112 | * | ||
| 113 | * Generate an audit message from the contents of @buf, which is owned by | ||
| 114 | * the current task. @buf->mutex must be locked. | ||
| 115 | */ | ||
| 116 | static void tty_audit_buf_push_current(struct tty_audit_buf *buf) | ||
| 117 | { | ||
| 118 | kuid_t auid = audit_get_loginuid(current); | ||
| 119 | unsigned int sessionid = audit_get_sessionid(current); | ||
| 120 | tty_audit_buf_push(current, auid, sessionid, buf); | ||
| 121 | } | ||
| 122 | |||
| 123 | /** | ||
| 124 | * tty_audit_exit - Handle a task exit | 106 | * tty_audit_exit - Handle a task exit |
| 125 | * | 107 | * |
| 126 | * Make sure all buffered data is written out and deallocate the buffer. | 108 | * Make sure all buffered data is written out and deallocate the buffer. |
| @@ -130,15 +112,13 @@ void tty_audit_exit(void) | |||
| 130 | { | 112 | { |
| 131 | struct tty_audit_buf *buf; | 113 | struct tty_audit_buf *buf; |
| 132 | 114 | ||
| 133 | spin_lock_irq(¤t->sighand->siglock); | ||
| 134 | buf = current->signal->tty_audit_buf; | 115 | buf = current->signal->tty_audit_buf; |
| 135 | current->signal->tty_audit_buf = NULL; | 116 | current->signal->tty_audit_buf = NULL; |
| 136 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 137 | if (!buf) | 117 | if (!buf) |
| 138 | return; | 118 | return; |
| 139 | 119 | ||
| 140 | mutex_lock(&buf->mutex); | 120 | mutex_lock(&buf->mutex); |
| 141 | tty_audit_buf_push_current(buf); | 121 | tty_audit_buf_push(buf); |
| 142 | mutex_unlock(&buf->mutex); | 122 | mutex_unlock(&buf->mutex); |
| 143 | 123 | ||
| 144 | tty_audit_buf_put(buf); | 124 | tty_audit_buf_put(buf); |
| @@ -151,9 +131,8 @@ void tty_audit_exit(void) | |||
| 151 | */ | 131 | */ |
| 152 | void tty_audit_fork(struct signal_struct *sig) | 132 | void tty_audit_fork(struct signal_struct *sig) |
| 153 | { | 133 | { |
| 154 | spin_lock_irq(¤t->sighand->siglock); | ||
| 155 | sig->audit_tty = current->signal->audit_tty; | 134 | sig->audit_tty = current->signal->audit_tty; |
| 156 | spin_unlock_irq(¤t->sighand->siglock); | 135 | sig->audit_tty_log_passwd = current->signal->audit_tty_log_passwd; |
| 157 | } | 136 | } |
| 158 | 137 | ||
| 159 | /** | 138 | /** |
| @@ -163,20 +142,21 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) | |||
| 163 | { | 142 | { |
| 164 | struct tty_audit_buf *buf; | 143 | struct tty_audit_buf *buf; |
| 165 | int major, minor, should_audit; | 144 | int major, minor, should_audit; |
| 145 | unsigned long flags; | ||
| 166 | 146 | ||
| 167 | spin_lock_irq(¤t->sighand->siglock); | 147 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
| 168 | should_audit = current->signal->audit_tty; | 148 | should_audit = current->signal->audit_tty; |
| 169 | buf = current->signal->tty_audit_buf; | 149 | buf = current->signal->tty_audit_buf; |
| 170 | if (buf) | 150 | if (buf) |
| 171 | atomic_inc(&buf->count); | 151 | atomic_inc(&buf->count); |
| 172 | spin_unlock_irq(¤t->sighand->siglock); | 152 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
| 173 | 153 | ||
| 174 | major = tty->driver->major; | 154 | major = tty->driver->major; |
| 175 | minor = tty->driver->minor_start + tty->index; | 155 | minor = tty->driver->minor_start + tty->index; |
| 176 | if (buf) { | 156 | if (buf) { |
| 177 | mutex_lock(&buf->mutex); | 157 | mutex_lock(&buf->mutex); |
| 178 | if (buf->major == major && buf->minor == minor) | 158 | if (buf->major == major && buf->minor == minor) |
| 179 | tty_audit_buf_push_current(buf); | 159 | tty_audit_buf_push(buf); |
| 180 | mutex_unlock(&buf->mutex); | 160 | mutex_unlock(&buf->mutex); |
| 181 | tty_audit_buf_put(buf); | 161 | tty_audit_buf_put(buf); |
| 182 | } | 162 | } |
| @@ -187,24 +167,20 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch) | |||
| 187 | 167 | ||
| 188 | auid = audit_get_loginuid(current); | 168 | auid = audit_get_loginuid(current); |
| 189 | sessionid = audit_get_sessionid(current); | 169 | sessionid = audit_get_sessionid(current); |
| 190 | tty_audit_log("ioctl=TIOCSTI", current, auid, sessionid, major, | 170 | tty_audit_log("ioctl=TIOCSTI", major, minor, &ch, 1); |
| 191 | minor, &ch, 1); | ||
| 192 | } | 171 | } |
| 193 | } | 172 | } |
| 194 | 173 | ||
| 195 | /** | 174 | /** |
| 196 | * tty_audit_push_task - Flush task's pending audit data | 175 | * tty_audit_push_current - Flush current's pending audit data |
| 197 | * @tsk: task pointer | ||
| 198 | * @loginuid: sender login uid | ||
| 199 | * @sessionid: sender session id | ||
| 200 | * | 176 | * |
| 201 | * Called with a ref on @tsk held. Try to lock sighand and get a | 177 | * Try to lock sighand and get a reference to the tty audit buffer if available. |
| 202 | * reference to the tty audit buffer if available. | ||
| 203 | * Flush the buffer or return an appropriate error code. | 178 | * Flush the buffer or return an appropriate error code. |
| 204 | */ | 179 | */ |
| 205 | int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid) | 180 | int tty_audit_push_current(void) |
| 206 | { | 181 | { |
| 207 | struct tty_audit_buf *buf = ERR_PTR(-EPERM); | 182 | struct tty_audit_buf *buf = ERR_PTR(-EPERM); |
| 183 | struct task_struct *tsk = current; | ||
| 208 | unsigned long flags; | 184 | unsigned long flags; |
| 209 | 185 | ||
| 210 | if (!lock_task_sighand(tsk, &flags)) | 186 | if (!lock_task_sighand(tsk, &flags)) |
| @@ -225,7 +201,7 @@ int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid) | |||
| 225 | return PTR_ERR(buf); | 201 | return PTR_ERR(buf); |
| 226 | 202 | ||
| 227 | mutex_lock(&buf->mutex); | 203 | mutex_lock(&buf->mutex); |
| 228 | tty_audit_buf_push(tsk, loginuid, sessionid, buf); | 204 | tty_audit_buf_push(buf); |
| 229 | mutex_unlock(&buf->mutex); | 205 | mutex_unlock(&buf->mutex); |
| 230 | 206 | ||
| 231 | tty_audit_buf_put(buf); | 207 | tty_audit_buf_put(buf); |
| @@ -243,10 +219,11 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, | |||
| 243 | unsigned icanon) | 219 | unsigned icanon) |
| 244 | { | 220 | { |
| 245 | struct tty_audit_buf *buf, *buf2; | 221 | struct tty_audit_buf *buf, *buf2; |
| 222 | unsigned long flags; | ||
| 246 | 223 | ||
| 247 | buf = NULL; | 224 | buf = NULL; |
| 248 | buf2 = NULL; | 225 | buf2 = NULL; |
| 249 | spin_lock_irq(¤t->sighand->siglock); | 226 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
| 250 | if (likely(!current->signal->audit_tty)) | 227 | if (likely(!current->signal->audit_tty)) |
| 251 | goto out; | 228 | goto out; |
| 252 | buf = current->signal->tty_audit_buf; | 229 | buf = current->signal->tty_audit_buf; |
| @@ -254,7 +231,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, | |||
| 254 | atomic_inc(&buf->count); | 231 | atomic_inc(&buf->count); |
| 255 | goto out; | 232 | goto out; |
| 256 | } | 233 | } |
| 257 | spin_unlock_irq(¤t->sighand->siglock); | 234 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
| 258 | 235 | ||
| 259 | buf2 = tty_audit_buf_alloc(tty->driver->major, | 236 | buf2 = tty_audit_buf_alloc(tty->driver->major, |
| 260 | tty->driver->minor_start + tty->index, | 237 | tty->driver->minor_start + tty->index, |
| @@ -264,7 +241,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, | |||
| 264 | return NULL; | 241 | return NULL; |
| 265 | } | 242 | } |
| 266 | 243 | ||
| 267 | spin_lock_irq(¤t->sighand->siglock); | 244 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
| 268 | if (!current->signal->audit_tty) | 245 | if (!current->signal->audit_tty) |
| 269 | goto out; | 246 | goto out; |
| 270 | buf = current->signal->tty_audit_buf; | 247 | buf = current->signal->tty_audit_buf; |
| @@ -276,7 +253,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty, | |||
| 276 | atomic_inc(&buf->count); | 253 | atomic_inc(&buf->count); |
| 277 | /* Fall through */ | 254 | /* Fall through */ |
| 278 | out: | 255 | out: |
| 279 | spin_unlock_irq(¤t->sighand->siglock); | 256 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
| 280 | if (buf2) | 257 | if (buf2) |
| 281 | tty_audit_buf_free(buf2); | 258 | tty_audit_buf_free(buf2); |
| 282 | return buf; | 259 | return buf; |
| @@ -292,10 +269,18 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, | |||
| 292 | { | 269 | { |
| 293 | struct tty_audit_buf *buf; | 270 | struct tty_audit_buf *buf; |
| 294 | int major, minor; | 271 | int major, minor; |
| 272 | int audit_log_tty_passwd; | ||
| 273 | unsigned long flags; | ||
| 295 | 274 | ||
| 296 | if (unlikely(size == 0)) | 275 | if (unlikely(size == 0)) |
| 297 | return; | 276 | return; |
| 298 | 277 | ||
| 278 | spin_lock_irqsave(¤t->sighand->siglock, flags); | ||
| 279 | audit_log_tty_passwd = current->signal->audit_tty_log_passwd; | ||
| 280 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
| 281 | if (!audit_log_tty_passwd && icanon && !L_ECHO(tty)) | ||
| 282 | return; | ||
| 283 | |||
| 299 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY | 284 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY |
| 300 | && tty->driver->subtype == PTY_TYPE_MASTER) | 285 | && tty->driver->subtype == PTY_TYPE_MASTER) |
| 301 | return; | 286 | return; |
| @@ -309,7 +294,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, | |||
| 309 | minor = tty->driver->minor_start + tty->index; | 294 | minor = tty->driver->minor_start + tty->index; |
| 310 | if (buf->major != major || buf->minor != minor | 295 | if (buf->major != major || buf->minor != minor |
| 311 | || buf->icanon != icanon) { | 296 | || buf->icanon != icanon) { |
| 312 | tty_audit_buf_push_current(buf); | 297 | tty_audit_buf_push(buf); |
| 313 | buf->major = major; | 298 | buf->major = major; |
| 314 | buf->minor = minor; | 299 | buf->minor = minor; |
| 315 | buf->icanon = icanon; | 300 | buf->icanon = icanon; |
| @@ -325,7 +310,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, | |||
| 325 | data += run; | 310 | data += run; |
| 326 | size -= run; | 311 | size -= run; |
| 327 | if (buf->valid == N_TTY_BUF_SIZE) | 312 | if (buf->valid == N_TTY_BUF_SIZE) |
| 328 | tty_audit_buf_push_current(buf); | 313 | tty_audit_buf_push(buf); |
| 329 | } while (size != 0); | 314 | } while (size != 0); |
| 330 | mutex_unlock(&buf->mutex); | 315 | mutex_unlock(&buf->mutex); |
| 331 | tty_audit_buf_put(buf); | 316 | tty_audit_buf_put(buf); |
| @@ -339,16 +324,17 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, | |||
| 339 | void tty_audit_push(struct tty_struct *tty) | 324 | void tty_audit_push(struct tty_struct *tty) |
| 340 | { | 325 | { |
| 341 | struct tty_audit_buf *buf; | 326 | struct tty_audit_buf *buf; |
| 327 | unsigned long flags; | ||
| 342 | 328 | ||
| 343 | spin_lock_irq(¤t->sighand->siglock); | 329 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
| 344 | if (likely(!current->signal->audit_tty)) { | 330 | if (likely(!current->signal->audit_tty)) { |
| 345 | spin_unlock_irq(¤t->sighand->siglock); | 331 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
| 346 | return; | 332 | return; |
| 347 | } | 333 | } |
| 348 | buf = current->signal->tty_audit_buf; | 334 | buf = current->signal->tty_audit_buf; |
| 349 | if (buf) | 335 | if (buf) |
| 350 | atomic_inc(&buf->count); | 336 | atomic_inc(&buf->count); |
| 351 | spin_unlock_irq(¤t->sighand->siglock); | 337 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
| 352 | 338 | ||
| 353 | if (buf) { | 339 | if (buf) { |
| 354 | int major, minor; | 340 | int major, minor; |
| @@ -357,7 +343,7 @@ void tty_audit_push(struct tty_struct *tty) | |||
| 357 | minor = tty->driver->minor_start + tty->index; | 343 | minor = tty->driver->minor_start + tty->index; |
| 358 | mutex_lock(&buf->mutex); | 344 | mutex_lock(&buf->mutex); |
| 359 | if (buf->major == major && buf->minor == minor) | 345 | if (buf->major == major && buf->minor == minor) |
| 360 | tty_audit_buf_push_current(buf); | 346 | tty_audit_buf_push(buf); |
| 361 | mutex_unlock(&buf->mutex); | 347 | mutex_unlock(&buf->mutex); |
| 362 | tty_audit_buf_put(buf); | 348 | tty_audit_buf_put(buf); |
| 363 | } | 349 | } |
diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c index bff0775e258c..5174ebac288d 100644 --- a/drivers/vhost/vringh.c +++ b/drivers/vhost/vringh.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Since these may be in userspace, we use (inline) accessors. | 4 | * Since these may be in userspace, we use (inline) accessors. |
| 5 | */ | 5 | */ |
| 6 | #include <linux/module.h> | ||
| 6 | #include <linux/vringh.h> | 7 | #include <linux/vringh.h> |
| 7 | #include <linux/virtio_ring.h> | 8 | #include <linux/virtio_ring.h> |
| 8 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| @@ -1005,3 +1006,5 @@ int vringh_need_notify_kern(struct vringh *vrh) | |||
| 1005 | return __vringh_need_notify(vrh, getu16_kern); | 1006 | return __vringh_need_notify(vrh, getu16_kern); |
| 1006 | } | 1007 | } |
| 1007 | EXPORT_SYMBOL(vringh_need_notify_kern); | 1008 | EXPORT_SYMBOL(vringh_need_notify_kern); |
| 1009 | |||
| 1010 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index dd4d9cb86243..f03bf501527f 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig | |||
| @@ -141,7 +141,7 @@ config XEN_GRANT_DEV_ALLOC | |||
| 141 | 141 | ||
| 142 | config SWIOTLB_XEN | 142 | config SWIOTLB_XEN |
| 143 | def_bool y | 143 | def_bool y |
| 144 | depends on PCI | 144 | depends on PCI && X86 |
| 145 | select SWIOTLB | 145 | select SWIOTLB |
| 146 | 146 | ||
| 147 | config XEN_TMEM | 147 | config XEN_TMEM |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index d8cc8127f19c..6a6bbe4ede92 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
| @@ -167,6 +167,8 @@ static void xen_irq_info_common_init(struct irq_info *info, | |||
| 167 | info->cpu = cpu; | 167 | info->cpu = cpu; |
| 168 | 168 | ||
| 169 | evtchn_to_irq[evtchn] = irq; | 169 | evtchn_to_irq[evtchn] = irq; |
| 170 | |||
| 171 | irq_clear_status_flags(irq, IRQ_NOREQUEST|IRQ_NOAUTOEN); | ||
| 170 | } | 172 | } |
| 171 | 173 | ||
| 172 | static void xen_irq_info_evtchn_init(unsigned irq, | 174 | static void xen_irq_info_evtchn_init(unsigned irq, |
| @@ -874,7 +876,6 @@ int bind_evtchn_to_irq(unsigned int evtchn) | |||
| 874 | struct irq_info *info = info_for_irq(irq); | 876 | struct irq_info *info = info_for_irq(irq); |
| 875 | WARN_ON(info == NULL || info->type != IRQT_EVTCHN); | 877 | WARN_ON(info == NULL || info->type != IRQT_EVTCHN); |
| 876 | } | 878 | } |
| 877 | irq_clear_status_flags(irq, IRQ_NOREQUEST|IRQ_NOAUTOEN); | ||
| 878 | 879 | ||
| 879 | out: | 880 | out: |
| 880 | mutex_unlock(&irq_mapping_update_lock); | 881 | mutex_unlock(&irq_mapping_update_lock); |
diff --git a/fs/namei.c b/fs/namei.c index 57ae9c8c66bf..85e40d1c0a8f 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -2740,7 +2740,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
| 2740 | if (error) | 2740 | if (error) |
| 2741 | return error; | 2741 | return error; |
| 2742 | 2742 | ||
| 2743 | audit_inode(name, dir, 0); | 2743 | audit_inode(name, dir, LOOKUP_PARENT); |
| 2744 | error = -EISDIR; | 2744 | error = -EISDIR; |
| 2745 | /* trailing slashes? */ | 2745 | /* trailing slashes? */ |
| 2746 | if (nd->last.name[nd->last.len]) | 2746 | if (nd->last.name[nd->last.len]) |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 61196592152e..63d17ee9eb48 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
| @@ -316,6 +316,7 @@ struct drm_ioctl_desc { | |||
| 316 | int flags; | 316 | int flags; |
| 317 | drm_ioctl_t *func; | 317 | drm_ioctl_t *func; |
| 318 | unsigned int cmd_drv; | 318 | unsigned int cmd_drv; |
| 319 | const char *name; | ||
| 319 | }; | 320 | }; |
| 320 | 321 | ||
| 321 | /** | 322 | /** |
| @@ -324,7 +325,7 @@ struct drm_ioctl_desc { | |||
| 324 | */ | 325 | */ |
| 325 | 326 | ||
| 326 | #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ | 327 | #define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \ |
| 327 | [DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl} | 328 | [DRM_IOCTL_NR(DRM_##ioctl)] = {.cmd = DRM_##ioctl, .func = _func, .flags = _flags, .cmd_drv = DRM_IOCTL_##ioctl, .name = #ioctl} |
| 328 | 329 | ||
| 329 | struct drm_magic_entry { | 330 | struct drm_magic_entry { |
| 330 | struct list_head head; | 331 | struct list_head head; |
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 8230b46fdd73..471f276ce8f7 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h | |||
| @@ -50,13 +50,14 @@ struct drm_fb_helper_surface_size { | |||
| 50 | 50 | ||
| 51 | /** | 51 | /** |
| 52 | * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library | 52 | * struct drm_fb_helper_funcs - driver callbacks for the fbdev emulation library |
| 53 | * @gamma_set: - Set the given gamma lut register on the given crtc. | 53 | * @gamma_set: Set the given gamma lut register on the given crtc. |
| 54 | * @gamma_get: - Read the given gamma lut register on the given crtc, used to | 54 | * @gamma_get: Read the given gamma lut register on the given crtc, used to |
| 55 | * save the current lut when force-restoring the fbdev for e.g. | 55 | * save the current lut when force-restoring the fbdev for e.g. |
| 56 | * kdbg. | 56 | * kdbg. |
| 57 | * @fb_probe: - Driver callback to allocate and initialize the fbdev info | 57 | * @fb_probe: Driver callback to allocate and initialize the fbdev info |
| 58 | * structure. Futhermore it also needs to allocate the drm | 58 | * structure. Futhermore it also needs to allocate the drm |
| 59 | * framebuffer used to back the fbdev. | 59 | * framebuffer used to back the fbdev. |
| 60 | * @initial_config: Setup an initial fbdev display configuration | ||
| 60 | * | 61 | * |
| 61 | * Driver callbacks used by the fbdev emulation helper library. | 62 | * Driver callbacks used by the fbdev emulation helper library. |
| 62 | */ | 63 | */ |
diff --git a/include/linux/audit.h b/include/linux/audit.h index 5a6d718adf34..b20b03852f21 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -84,8 +84,13 @@ extern int audit_classify_arch(int arch); | |||
| 84 | #define AUDIT_TYPE_CHILD_DELETE 3 /* a child being deleted */ | 84 | #define AUDIT_TYPE_CHILD_DELETE 3 /* a child being deleted */ |
| 85 | #define AUDIT_TYPE_CHILD_CREATE 4 /* a child being created */ | 85 | #define AUDIT_TYPE_CHILD_CREATE 4 /* a child being created */ |
| 86 | 86 | ||
| 87 | /* maximized args number that audit_socketcall can process */ | ||
| 88 | #define AUDITSC_ARGS 6 | ||
| 89 | |||
| 87 | struct filename; | 90 | struct filename; |
| 88 | 91 | ||
| 92 | extern void audit_log_session_info(struct audit_buffer *ab); | ||
| 93 | |||
| 89 | #ifdef CONFIG_AUDITSYSCALL | 94 | #ifdef CONFIG_AUDITSYSCALL |
| 90 | /* These are defined in auditsc.c */ | 95 | /* These are defined in auditsc.c */ |
| 91 | /* Public API */ | 96 | /* Public API */ |
| @@ -120,7 +125,7 @@ static inline void audit_syscall_entry(int arch, int major, unsigned long a0, | |||
| 120 | unsigned long a1, unsigned long a2, | 125 | unsigned long a1, unsigned long a2, |
| 121 | unsigned long a3) | 126 | unsigned long a3) |
| 122 | { | 127 | { |
| 123 | if (unlikely(!audit_dummy_context())) | 128 | if (unlikely(current->audit_context)) |
| 124 | __audit_syscall_entry(arch, major, a0, a1, a2, a3); | 129 | __audit_syscall_entry(arch, major, a0, a1, a2, a3); |
| 125 | } | 130 | } |
| 126 | static inline void audit_syscall_exit(void *pt_regs) | 131 | static inline void audit_syscall_exit(void *pt_regs) |
| @@ -185,12 +190,10 @@ static inline int audit_get_sessionid(struct task_struct *tsk) | |||
| 185 | return tsk->sessionid; | 190 | return tsk->sessionid; |
| 186 | } | 191 | } |
| 187 | 192 | ||
| 188 | extern void audit_log_task_context(struct audit_buffer *ab); | ||
| 189 | extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk); | ||
| 190 | extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); | 193 | extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); |
| 191 | extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); | 194 | extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); |
| 192 | extern int __audit_bprm(struct linux_binprm *bprm); | 195 | extern int __audit_bprm(struct linux_binprm *bprm); |
| 193 | extern void __audit_socketcall(int nargs, unsigned long *args); | 196 | extern int __audit_socketcall(int nargs, unsigned long *args); |
| 194 | extern int __audit_sockaddr(int len, void *addr); | 197 | extern int __audit_sockaddr(int len, void *addr); |
| 195 | extern void __audit_fd_pair(int fd1, int fd2); | 198 | extern void __audit_fd_pair(int fd1, int fd2); |
| 196 | extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr); | 199 | extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr); |
| @@ -224,10 +227,11 @@ static inline int audit_bprm(struct linux_binprm *bprm) | |||
| 224 | return __audit_bprm(bprm); | 227 | return __audit_bprm(bprm); |
| 225 | return 0; | 228 | return 0; |
| 226 | } | 229 | } |
| 227 | static inline void audit_socketcall(int nargs, unsigned long *args) | 230 | static inline int audit_socketcall(int nargs, unsigned long *args) |
| 228 | { | 231 | { |
| 229 | if (unlikely(!audit_dummy_context())) | 232 | if (unlikely(!audit_dummy_context())) |
| 230 | __audit_socketcall(nargs, args); | 233 | return __audit_socketcall(nargs, args); |
| 234 | return 0; | ||
| 231 | } | 235 | } |
| 232 | static inline int audit_sockaddr(int len, void *addr) | 236 | static inline int audit_sockaddr(int len, void *addr) |
| 233 | { | 237 | { |
| @@ -340,11 +344,6 @@ static inline int audit_get_sessionid(struct task_struct *tsk) | |||
| 340 | { | 344 | { |
| 341 | return -1; | 345 | return -1; |
| 342 | } | 346 | } |
| 343 | static inline void audit_log_task_context(struct audit_buffer *ab) | ||
| 344 | { } | ||
| 345 | static inline void audit_log_task_info(struct audit_buffer *ab, | ||
| 346 | struct task_struct *tsk) | ||
| 347 | { } | ||
| 348 | static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) | 347 | static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) |
| 349 | { } | 348 | { } |
| 350 | static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, | 349 | static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, |
| @@ -354,8 +353,10 @@ static inline int audit_bprm(struct linux_binprm *bprm) | |||
| 354 | { | 353 | { |
| 355 | return 0; | 354 | return 0; |
| 356 | } | 355 | } |
| 357 | static inline void audit_socketcall(int nargs, unsigned long *args) | 356 | static inline int audit_socketcall(int nargs, unsigned long *args) |
| 358 | { } | 357 | { |
| 358 | return 0; | ||
| 359 | } | ||
| 359 | static inline void audit_fd_pair(int fd1, int fd2) | 360 | static inline void audit_fd_pair(int fd1, int fd2) |
| 360 | { } | 361 | { } |
| 361 | static inline int audit_sockaddr(int len, void *addr) | 362 | static inline int audit_sockaddr(int len, void *addr) |
| @@ -390,6 +391,11 @@ static inline void audit_ptrace(struct task_struct *t) | |||
| 390 | #define audit_signals 0 | 391 | #define audit_signals 0 |
| 391 | #endif /* CONFIG_AUDITSYSCALL */ | 392 | #endif /* CONFIG_AUDITSYSCALL */ |
| 392 | 393 | ||
| 394 | static inline bool audit_loginuid_set(struct task_struct *tsk) | ||
| 395 | { | ||
| 396 | return uid_valid(audit_get_loginuid(tsk)); | ||
| 397 | } | ||
| 398 | |||
| 393 | #ifdef CONFIG_AUDIT | 399 | #ifdef CONFIG_AUDIT |
| 394 | /* These are defined in audit.c */ | 400 | /* These are defined in audit.c */ |
| 395 | /* Public API */ | 401 | /* Public API */ |
| @@ -429,14 +435,17 @@ static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) | |||
| 429 | { } | 435 | { } |
| 430 | #endif | 436 | #endif |
| 431 | 437 | ||
| 438 | extern int audit_log_task_context(struct audit_buffer *ab); | ||
| 439 | extern void audit_log_task_info(struct audit_buffer *ab, | ||
| 440 | struct task_struct *tsk); | ||
| 441 | |||
| 432 | extern int audit_update_lsm_rules(void); | 442 | extern int audit_update_lsm_rules(void); |
| 433 | 443 | ||
| 434 | /* Private API (for audit.c only) */ | 444 | /* Private API (for audit.c only) */ |
| 435 | extern int audit_filter_user(void); | 445 | extern int audit_filter_user(int type); |
| 436 | extern int audit_filter_type(int type); | 446 | extern int audit_filter_type(int type); |
| 437 | extern int audit_receive_filter(int type, int pid, int seq, | 447 | extern int audit_receive_filter(int type, int pid, int seq, |
| 438 | void *data, size_t datasz, kuid_t loginuid, | 448 | void *data, size_t datasz); |
| 439 | u32 sessionid, u32 sid); | ||
| 440 | extern int audit_enabled; | 449 | extern int audit_enabled; |
| 441 | #else /* CONFIG_AUDIT */ | 450 | #else /* CONFIG_AUDIT */ |
| 442 | static inline __printf(4, 5) | 451 | static inline __printf(4, 5) |
| @@ -476,6 +485,13 @@ static inline void audit_log_link_denied(const char *string, | |||
| 476 | { } | 485 | { } |
| 477 | static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) | 486 | static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) |
| 478 | { } | 487 | { } |
| 488 | static inline int audit_log_task_context(struct audit_buffer *ab) | ||
| 489 | { | ||
| 490 | return 0; | ||
| 491 | } | ||
| 492 | static inline void audit_log_task_info(struct audit_buffer *ab, | ||
| 493 | struct task_struct *tsk) | ||
| 494 | { } | ||
| 479 | #define audit_enabled 0 | 495 | #define audit_enabled 0 |
| 480 | #endif /* CONFIG_AUDIT */ | 496 | #endif /* CONFIG_AUDIT */ |
| 481 | static inline void audit_log_string(struct audit_buffer *ab, const char *buf) | 497 | static inline void audit_log_string(struct audit_buffer *ab, const char *buf) |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 3c86faa59798..8f0406230a0a 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #include <linux/completion.h> | 17 | #include <linux/completion.h> |
| 18 | #include <linux/hrtimer.h> | 18 | #include <linux/hrtimer.h> |
| 19 | 19 | ||
| 20 | #define CPUIDLE_STATE_MAX 8 | 20 | #define CPUIDLE_STATE_MAX 10 |
| 21 | #define CPUIDLE_NAME_LEN 16 | 21 | #define CPUIDLE_NAME_LEN 16 |
| 22 | #define CPUIDLE_DESC_LEN 32 | 22 | #define CPUIDLE_DESC_LEN 32 |
| 23 | 23 | ||
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index f83e17a40e8b..99d0fbcbaf79 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
| @@ -90,6 +90,8 @@ typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip, | |||
| 90 | * not set this, then the ftrace infrastructure will add recursion | 90 | * not set this, then the ftrace infrastructure will add recursion |
| 91 | * protection for the caller. | 91 | * protection for the caller. |
| 92 | * STUB - The ftrace_ops is just a place holder. | 92 | * STUB - The ftrace_ops is just a place holder. |
| 93 | * INITIALIZED - The ftrace_ops has already been initialized (first use time | ||
| 94 | * register_ftrace_function() is called, it will initialized the ops) | ||
| 93 | */ | 95 | */ |
| 94 | enum { | 96 | enum { |
| 95 | FTRACE_OPS_FL_ENABLED = 1 << 0, | 97 | FTRACE_OPS_FL_ENABLED = 1 << 0, |
| @@ -100,6 +102,7 @@ enum { | |||
| 100 | FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 5, | 102 | FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 5, |
| 101 | FTRACE_OPS_FL_RECURSION_SAFE = 1 << 6, | 103 | FTRACE_OPS_FL_RECURSION_SAFE = 1 << 6, |
| 102 | FTRACE_OPS_FL_STUB = 1 << 7, | 104 | FTRACE_OPS_FL_STUB = 1 << 7, |
| 105 | FTRACE_OPS_FL_INITIALIZED = 1 << 8, | ||
| 103 | }; | 106 | }; |
| 104 | 107 | ||
| 105 | struct ftrace_ops { | 108 | struct ftrace_ops { |
| @@ -110,6 +113,7 @@ struct ftrace_ops { | |||
| 110 | #ifdef CONFIG_DYNAMIC_FTRACE | 113 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 111 | struct ftrace_hash *notrace_hash; | 114 | struct ftrace_hash *notrace_hash; |
| 112 | struct ftrace_hash *filter_hash; | 115 | struct ftrace_hash *filter_hash; |
| 116 | struct mutex regex_lock; | ||
| 113 | #endif | 117 | #endif |
| 114 | }; | 118 | }; |
| 115 | 119 | ||
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 34e00fb49bec..4372658c73ae 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h | |||
| @@ -293,6 +293,7 @@ struct ftrace_event_file { | |||
| 293 | * caching and such. Which is mostly OK ;-) | 293 | * caching and such. Which is mostly OK ;-) |
| 294 | */ | 294 | */ |
| 295 | unsigned long flags; | 295 | unsigned long flags; |
| 296 | atomic_t sm_ref; /* soft-mode reference counter */ | ||
| 296 | }; | 297 | }; |
| 297 | 298 | ||
| 298 | #define __TRACE_EVENT_FLAGS(name, value) \ | 299 | #define __TRACE_EVENT_FLAGS(name, value) \ |
diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h index 67f46ad6920a..352eec9df1b8 100644 --- a/include/linux/mlx4/qp.h +++ b/include/linux/mlx4/qp.h | |||
| @@ -126,7 +126,7 @@ struct mlx4_rss_context { | |||
| 126 | 126 | ||
| 127 | struct mlx4_qp_path { | 127 | struct mlx4_qp_path { |
| 128 | u8 fl; | 128 | u8 fl; |
| 129 | u8 reserved1[1]; | 129 | u8 vlan_control; |
| 130 | u8 disable_pkey_check; | 130 | u8 disable_pkey_check; |
| 131 | u8 pkey_index; | 131 | u8 pkey_index; |
| 132 | u8 counter_index; | 132 | u8 counter_index; |
| @@ -141,11 +141,32 @@ struct mlx4_qp_path { | |||
| 141 | u8 sched_queue; | 141 | u8 sched_queue; |
| 142 | u8 vlan_index; | 142 | u8 vlan_index; |
| 143 | u8 feup; | 143 | u8 feup; |
| 144 | u8 reserved3; | 144 | u8 fvl_rx; |
| 145 | u8 reserved4[2]; | 145 | u8 reserved4[2]; |
| 146 | u8 dmac[6]; | 146 | u8 dmac[6]; |
| 147 | }; | 147 | }; |
| 148 | 148 | ||
| 149 | enum { /* fl */ | ||
| 150 | MLX4_FL_CV = 1 << 6, | ||
| 151 | MLX4_FL_ETH_HIDE_CQE_VLAN = 1 << 2 | ||
| 152 | }; | ||
| 153 | enum { /* vlan_control */ | ||
| 154 | MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED = 1 << 6, | ||
| 155 | MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED = 1 << 2, | ||
| 156 | MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED = 1 << 1, /* 802.1p priority tag */ | ||
| 157 | MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED = 1 << 0 | ||
| 158 | }; | ||
| 159 | |||
| 160 | enum { /* feup */ | ||
| 161 | MLX4_FEUP_FORCE_ETH_UP = 1 << 6, /* force Eth UP */ | ||
| 162 | MLX4_FSM_FORCE_ETH_SRC_MAC = 1 << 5, /* force Source MAC */ | ||
| 163 | MLX4_FVL_FORCE_ETH_VLAN = 1 << 3 /* force Eth vlan */ | ||
| 164 | }; | ||
| 165 | |||
| 166 | enum { /* fvl_rx */ | ||
| 167 | MLX4_FVL_RX_FORCE_ETH_VLAN = 1 << 0 /* enforce Eth rx vlan */ | ||
| 168 | }; | ||
| 169 | |||
| 149 | struct mlx4_qp_context { | 170 | struct mlx4_qp_context { |
| 150 | __be32 flags; | 171 | __be32 flags; |
| 151 | __be32 pd; | 172 | __be32 pd; |
| @@ -185,6 +206,10 @@ struct mlx4_qp_context { | |||
| 185 | u32 reserved5[10]; | 206 | u32 reserved5[10]; |
| 186 | }; | 207 | }; |
| 187 | 208 | ||
| 209 | enum { /* param3 */ | ||
| 210 | MLX4_STRIP_VLAN = 1 << 30 | ||
| 211 | }; | ||
| 212 | |||
| 188 | /* Which firmware version adds support for NEC (NoErrorCompletion) bit */ | 213 | /* Which firmware version adds support for NEC (NoErrorCompletion) bit */ |
| 189 | #define MLX4_FW_VER_WQE_CTRL_NEC mlx4_fw_ver(2, 2, 232) | 214 | #define MLX4_FW_VER_WQE_CTRL_NEC mlx4_fw_ver(2, 2, 232) |
| 190 | 215 | ||
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 2b85c521f737..c12916248469 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -2147,11 +2147,13 @@ | |||
| 2147 | #define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e | 2147 | #define PCI_DEVICE_ID_TIGON3_5705M_2 0x165e |
| 2148 | #define PCI_DEVICE_ID_NX2_57712 0x1662 | 2148 | #define PCI_DEVICE_ID_NX2_57712 0x1662 |
| 2149 | #define PCI_DEVICE_ID_NX2_57712E 0x1663 | 2149 | #define PCI_DEVICE_ID_NX2_57712E 0x1663 |
| 2150 | #define PCI_DEVICE_ID_NX2_57712_MF 0x1663 | ||
| 2150 | #define PCI_DEVICE_ID_TIGON3_5714 0x1668 | 2151 | #define PCI_DEVICE_ID_TIGON3_5714 0x1668 |
| 2151 | #define PCI_DEVICE_ID_TIGON3_5714S 0x1669 | 2152 | #define PCI_DEVICE_ID_TIGON3_5714S 0x1669 |
| 2152 | #define PCI_DEVICE_ID_TIGON3_5780 0x166a | 2153 | #define PCI_DEVICE_ID_TIGON3_5780 0x166a |
| 2153 | #define PCI_DEVICE_ID_TIGON3_5780S 0x166b | 2154 | #define PCI_DEVICE_ID_TIGON3_5780S 0x166b |
| 2154 | #define PCI_DEVICE_ID_TIGON3_5705F 0x166e | 2155 | #define PCI_DEVICE_ID_TIGON3_5705F 0x166e |
| 2156 | #define PCI_DEVICE_ID_NX2_57712_VF 0x166f | ||
| 2155 | #define PCI_DEVICE_ID_TIGON3_5754M 0x1672 | 2157 | #define PCI_DEVICE_ID_TIGON3_5754M 0x1672 |
| 2156 | #define PCI_DEVICE_ID_TIGON3_5755M 0x1673 | 2158 | #define PCI_DEVICE_ID_TIGON3_5755M 0x1673 |
| 2157 | #define PCI_DEVICE_ID_TIGON3_5756 0x1674 | 2159 | #define PCI_DEVICE_ID_TIGON3_5756 0x1674 |
| @@ -2177,13 +2179,15 @@ | |||
| 2177 | #define PCI_DEVICE_ID_TIGON3_5787 0x169b | 2179 | #define PCI_DEVICE_ID_TIGON3_5787 0x169b |
| 2178 | #define PCI_DEVICE_ID_TIGON3_5788 0x169c | 2180 | #define PCI_DEVICE_ID_TIGON3_5788 0x169c |
| 2179 | #define PCI_DEVICE_ID_TIGON3_5789 0x169d | 2181 | #define PCI_DEVICE_ID_TIGON3_5789 0x169d |
| 2182 | #define PCI_DEVICE_ID_NX2_57840_4_10 0x16a1 | ||
| 2183 | #define PCI_DEVICE_ID_NX2_57840_2_20 0x16a2 | ||
| 2184 | #define PCI_DEVICE_ID_NX2_57840_MF 0x16a4 | ||
| 2180 | #define PCI_DEVICE_ID_NX2_57800_MF 0x16a5 | 2185 | #define PCI_DEVICE_ID_NX2_57800_MF 0x16a5 |
| 2181 | #define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 | 2186 | #define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 |
| 2182 | #define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 | 2187 | #define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 |
| 2183 | #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 | 2188 | #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 |
| 2184 | #define PCI_DEVICE_ID_NX2_57800_VF 0x16a9 | 2189 | #define PCI_DEVICE_ID_NX2_57800_VF 0x16a9 |
| 2185 | #define PCI_DEVICE_ID_NX2_5706S 0x16aa | 2190 | #define PCI_DEVICE_ID_NX2_5706S 0x16aa |
| 2186 | #define PCI_DEVICE_ID_NX2_57840_MF 0x16a4 | ||
| 2187 | #define PCI_DEVICE_ID_NX2_5708S 0x16ac | 2191 | #define PCI_DEVICE_ID_NX2_5708S 0x16ac |
| 2188 | #define PCI_DEVICE_ID_NX2_57840_VF 0x16ad | 2192 | #define PCI_DEVICE_ID_NX2_57840_VF 0x16ad |
| 2189 | #define PCI_DEVICE_ID_NX2_57810_MF 0x16ae | 2193 | #define PCI_DEVICE_ID_NX2_57810_MF 0x16ae |
diff --git a/include/linux/sched.h b/include/linux/sched.h index caa8f4d0186b..178a8d909f14 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -593,6 +593,7 @@ struct signal_struct { | |||
| 593 | #endif | 593 | #endif |
| 594 | #ifdef CONFIG_AUDIT | 594 | #ifdef CONFIG_AUDIT |
| 595 | unsigned audit_tty; | 595 | unsigned audit_tty; |
| 596 | unsigned audit_tty_log_passwd; | ||
| 596 | struct tty_audit_buf *tty_audit_buf; | 597 | struct tty_audit_buf *tty_audit_buf; |
| 597 | #endif | 598 | #endif |
| 598 | #ifdef CONFIG_CGROUPS | 599 | #ifdef CONFIG_CGROUPS |
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 733eb5ee31c5..6ff26c8db7b9 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h | |||
| @@ -57,7 +57,7 @@ extern struct bus_type spi_bus_type; | |||
| 57 | * @modalias: Name of the driver to use with this device, or an alias | 57 | * @modalias: Name of the driver to use with this device, or an alias |
| 58 | * for that name. This appears in the sysfs "modalias" attribute | 58 | * for that name. This appears in the sysfs "modalias" attribute |
| 59 | * for driver coldplugging, and in uevents used for hotplugging | 59 | * for driver coldplugging, and in uevents used for hotplugging |
| 60 | * @cs_gpio: gpio number of the chipselect line (optional, -EINVAL when | 60 | * @cs_gpio: gpio number of the chipselect line (optional, -ENOENT when |
| 61 | * when not using a GPIO line) | 61 | * when not using a GPIO line) |
| 62 | * | 62 | * |
| 63 | * A @spi_device is used to interchange data between an SPI slave | 63 | * A @spi_device is used to interchange data between an SPI slave |
| @@ -266,7 +266,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) | |||
| 266 | * queue so the subsystem notifies the driver that it may relax the | 266 | * queue so the subsystem notifies the driver that it may relax the |
| 267 | * hardware by issuing this call | 267 | * hardware by issuing this call |
| 268 | * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS | 268 | * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS |
| 269 | * number. Any individual value may be -EINVAL for CS lines that | 269 | * number. Any individual value may be -ENOENT for CS lines that |
| 270 | * are not GPIOs (driven by the SPI controller itself). | 270 | * are not GPIOs (driven by the SPI controller itself). |
| 271 | * | 271 | * |
| 272 | * Each SPI master controller can communicate with one or more @spi_device | 272 | * Each SPI master controller can communicate with one or more @spi_device |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 7e92bd86a808..8780bd2a272a 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -575,8 +575,7 @@ extern void tty_audit_exit(void); | |||
| 575 | extern void tty_audit_fork(struct signal_struct *sig); | 575 | extern void tty_audit_fork(struct signal_struct *sig); |
| 576 | extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); | 576 | extern void tty_audit_tiocsti(struct tty_struct *tty, char ch); |
| 577 | extern void tty_audit_push(struct tty_struct *tty); | 577 | extern void tty_audit_push(struct tty_struct *tty); |
| 578 | extern int tty_audit_push_task(struct task_struct *tsk, | 578 | extern int tty_audit_push_current(void); |
| 579 | kuid_t loginuid, u32 sessionid); | ||
| 580 | #else | 579 | #else |
| 581 | static inline void tty_audit_add_data(struct tty_struct *tty, | 580 | static inline void tty_audit_add_data(struct tty_struct *tty, |
| 582 | unsigned char *data, size_t size, unsigned icanon) | 581 | unsigned char *data, size_t size, unsigned icanon) |
| @@ -594,8 +593,7 @@ static inline void tty_audit_fork(struct signal_struct *sig) | |||
| 594 | static inline void tty_audit_push(struct tty_struct *tty) | 593 | static inline void tty_audit_push(struct tty_struct *tty) |
| 595 | { | 594 | { |
| 596 | } | 595 | } |
| 597 | static inline int tty_audit_push_task(struct task_struct *tsk, | 596 | static inline int tty_audit_push_current(void) |
| 598 | kuid_t loginuid, u32 sessionid) | ||
| 599 | { | 597 | { |
| 600 | return 0; | 598 | return 0; |
| 601 | } | 599 | } |
diff --git a/include/net/sock.h b/include/net/sock.h index 5c97b0fc5623..66772cf8c3c5 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
| @@ -866,6 +866,18 @@ struct inet_hashinfo; | |||
| 866 | struct raw_hashinfo; | 866 | struct raw_hashinfo; |
| 867 | struct module; | 867 | struct module; |
| 868 | 868 | ||
| 869 | /* | ||
| 870 | * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes | ||
| 871 | * un-modified. Special care is taken when initializing object to zero. | ||
| 872 | */ | ||
| 873 | static inline void sk_prot_clear_nulls(struct sock *sk, int size) | ||
| 874 | { | ||
| 875 | if (offsetof(struct sock, sk_node.next) != 0) | ||
| 876 | memset(sk, 0, offsetof(struct sock, sk_node.next)); | ||
| 877 | memset(&sk->sk_node.pprev, 0, | ||
| 878 | size - offsetof(struct sock, sk_node.pprev)); | ||
| 879 | } | ||
| 880 | |||
| 869 | /* Networking protocol blocks we attach to sockets. | 881 | /* Networking protocol blocks we attach to sockets. |
| 870 | * socket layer -> transport layer interface | 882 | * socket layer -> transport layer interface |
| 871 | * transport -> network interface is defined by struct inet_proto | 883 | * transport -> network interface is defined by struct inet_proto |
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index ef937b56f9b5..e2c1e66d58ae 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h | |||
| @@ -118,7 +118,7 @@ struct ex_phy { | |||
| 118 | 118 | ||
| 119 | enum ex_phy_state phy_state; | 119 | enum ex_phy_state phy_state; |
| 120 | 120 | ||
| 121 | enum sas_dev_type attached_dev_type; | 121 | enum sas_device_type attached_dev_type; |
| 122 | enum sas_linkrate linkrate; | 122 | enum sas_linkrate linkrate; |
| 123 | 123 | ||
| 124 | u8 attached_sata_host:1; | 124 | u8 attached_sata_host:1; |
| @@ -195,7 +195,7 @@ enum { | |||
| 195 | 195 | ||
| 196 | struct domain_device { | 196 | struct domain_device { |
| 197 | spinlock_t done_lock; | 197 | spinlock_t done_lock; |
| 198 | enum sas_dev_type dev_type; | 198 | enum sas_device_type dev_type; |
| 199 | 199 | ||
| 200 | enum sas_linkrate linkrate; | 200 | enum sas_linkrate linkrate; |
| 201 | enum sas_linkrate min_linkrate; | 201 | enum sas_linkrate min_linkrate; |
diff --git a/include/scsi/osd_protocol.h b/include/scsi/osd_protocol.h index a6026da25f3e..25ac6283b9c7 100644 --- a/include/scsi/osd_protocol.h +++ b/include/scsi/osd_protocol.h | |||
| @@ -107,7 +107,7 @@ enum osd_attributes_mode { | |||
| 107 | * int exponent: 04; | 107 | * int exponent: 04; |
| 108 | * } | 108 | * } |
| 109 | */ | 109 | */ |
| 110 | typedef __be32 __bitwise osd_cdb_offset; | 110 | typedef __be32 osd_cdb_offset; |
| 111 | 111 | ||
| 112 | enum { | 112 | enum { |
| 113 | OSD_OFFSET_UNUSED = 0xFFFFFFFF, | 113 | OSD_OFFSET_UNUSED = 0xFFFFFFFF, |
diff --git a/include/scsi/sas.h b/include/scsi/sas.h index be3eb0bf1ac0..0d2607d12387 100644 --- a/include/scsi/sas.h +++ b/include/scsi/sas.h | |||
| @@ -90,16 +90,18 @@ enum sas_oob_mode { | |||
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | /* See sas_discover.c if you plan on changing these */ | 92 | /* See sas_discover.c if you plan on changing these */ |
| 93 | enum sas_dev_type { | 93 | enum sas_device_type { |
| 94 | NO_DEVICE = 0, /* protocol */ | 94 | /* these are SAS protocol defined (attached device type field) */ |
| 95 | SAS_END_DEV = 1, /* protocol */ | 95 | SAS_PHY_UNUSED = 0, |
| 96 | EDGE_DEV = 2, /* protocol */ | 96 | SAS_END_DEVICE = 1, |
| 97 | FANOUT_DEV = 3, /* protocol */ | 97 | SAS_EDGE_EXPANDER_DEVICE = 2, |
| 98 | SAS_HA = 4, | 98 | SAS_FANOUT_EXPANDER_DEVICE = 3, |
| 99 | SATA_DEV = 5, | 99 | /* these are internal to libsas */ |
| 100 | SATA_PM = 7, | 100 | SAS_HA = 4, |
| 101 | SATA_PM_PORT= 8, | 101 | SAS_SATA_DEV = 5, |
| 102 | SATA_PENDING = 9, | 102 | SAS_SATA_PM = 7, |
| 103 | SAS_SATA_PM_PORT = 8, | ||
| 104 | SAS_SATA_PENDING = 9, | ||
| 103 | }; | 105 | }; |
| 104 | 106 | ||
| 105 | enum sas_protocol { | 107 | enum sas_protocol { |
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h index ff71a5654684..00f41aeeecf5 100644 --- a/include/scsi/sas_ata.h +++ b/include/scsi/sas_ata.h | |||
| @@ -32,8 +32,8 @@ | |||
| 32 | 32 | ||
| 33 | static inline int dev_is_sata(struct domain_device *dev) | 33 | static inline int dev_is_sata(struct domain_device *dev) |
| 34 | { | 34 | { |
| 35 | return dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM || | 35 | return dev->dev_type == SAS_SATA_DEV || dev->dev_type == SAS_SATA_PM || |
| 36 | dev->dev_type == SATA_PM_PORT || dev->dev_type == SATA_PENDING; | 36 | dev->dev_type == SAS_SATA_PM_PORT || dev->dev_type == SAS_SATA_PENDING; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy); | 39 | int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy); |
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index a7f9cba275e9..cc645876d147 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
| @@ -394,10 +394,18 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | |||
| 394 | int data_direction, void *buffer, unsigned bufflen, | 394 | int data_direction, void *buffer, unsigned bufflen, |
| 395 | unsigned char *sense, int timeout, int retries, | 395 | unsigned char *sense, int timeout, int retries, |
| 396 | int flag, int *resid); | 396 | int flag, int *resid); |
| 397 | extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | 397 | extern int scsi_execute_req_flags(struct scsi_device *sdev, |
| 398 | int data_direction, void *buffer, unsigned bufflen, | 398 | const unsigned char *cmd, int data_direction, void *buffer, |
| 399 | struct scsi_sense_hdr *, int timeout, int retries, | 399 | unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout, |
| 400 | int *resid); | 400 | int retries, int *resid, int flags); |
| 401 | static inline int scsi_execute_req(struct scsi_device *sdev, | ||
| 402 | const unsigned char *cmd, int data_direction, void *buffer, | ||
| 403 | unsigned bufflen, struct scsi_sense_hdr *sshdr, int timeout, | ||
| 404 | int retries, int *resid) | ||
| 405 | { | ||
| 406 | return scsi_execute_req_flags(sdev, cmd, data_direction, buffer, | ||
| 407 | bufflen, sshdr, timeout, retries, resid, 0); | ||
| 408 | } | ||
| 401 | extern void sdev_disable_disk_events(struct scsi_device *sdev); | 409 | extern void sdev_disable_disk_events(struct scsi_device *sdev); |
| 402 | extern void sdev_enable_disk_events(struct scsi_device *sdev); | 410 | extern void sdev_enable_disk_events(struct scsi_device *sdev); |
| 403 | 411 | ||
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 4a58cca2ecc1..d0f1602985e7 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h | |||
| @@ -471,14 +471,10 @@ iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session *fnode_sess); | |||
| 471 | extern void iscsi_destroy_all_flashnode(struct Scsi_Host *shost); | 471 | extern void iscsi_destroy_all_flashnode(struct Scsi_Host *shost); |
| 472 | extern int iscsi_flashnode_bus_match(struct device *dev, | 472 | extern int iscsi_flashnode_bus_match(struct device *dev, |
| 473 | struct device_driver *drv); | 473 | struct device_driver *drv); |
| 474 | extern int iscsi_is_flashnode_conn_dev(struct device *dev, void *data); | ||
| 475 | |||
| 476 | extern struct device * | 474 | extern struct device * |
| 477 | iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data, | 475 | iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data, |
| 478 | int (*fn)(struct device *dev, void *data)); | 476 | int (*fn)(struct device *dev, void *data)); |
| 479 | |||
| 480 | extern struct device * | 477 | extern struct device * |
| 481 | iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess, | 478 | iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess); |
| 482 | void *data, | 479 | |
| 483 | int (*fn)(struct device *dev, void *data)); | ||
| 484 | #endif | 480 | #endif |
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 9b8e08879cfc..0bd71e2702e3 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h | |||
| @@ -10,13 +10,6 @@ struct scsi_transport_template; | |||
| 10 | struct sas_rphy; | 10 | struct sas_rphy; |
| 11 | struct request; | 11 | struct request; |
| 12 | 12 | ||
| 13 | enum sas_device_type { | ||
| 14 | SAS_PHY_UNUSED = 0, | ||
| 15 | SAS_END_DEVICE = 1, | ||
| 16 | SAS_EDGE_EXPANDER_DEVICE = 2, | ||
| 17 | SAS_FANOUT_EXPANDER_DEVICE = 3, | ||
| 18 | }; | ||
| 19 | |||
| 20 | static inline int sas_protocol_ata(enum sas_protocol proto) | 13 | static inline int sas_protocol_ata(enum sas_protocol proto) |
| 21 | { | 14 | { |
| 22 | return ((proto & SAS_PROTOCOL_SATA) || | 15 | return ((proto & SAS_PROTOCOL_SATA) || |
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 9f096f1c0907..75cef3fd97ad 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h | |||
| @@ -246,6 +246,7 @@ | |||
| 246 | #define AUDIT_OBJ_TYPE 21 | 246 | #define AUDIT_OBJ_TYPE 21 |
| 247 | #define AUDIT_OBJ_LEV_LOW 22 | 247 | #define AUDIT_OBJ_LEV_LOW 22 |
| 248 | #define AUDIT_OBJ_LEV_HIGH 23 | 248 | #define AUDIT_OBJ_LEV_HIGH 23 |
| 249 | #define AUDIT_LOGINUID_SET 24 | ||
| 249 | 250 | ||
| 250 | /* These are ONLY useful when checking | 251 | /* These are ONLY useful when checking |
| 251 | * at syscall exit time (AUDIT_AT_EXIT). */ | 252 | * at syscall exit time (AUDIT_AT_EXIT). */ |
| @@ -369,7 +370,8 @@ struct audit_status { | |||
| 369 | }; | 370 | }; |
| 370 | 371 | ||
| 371 | struct audit_tty_status { | 372 | struct audit_tty_status { |
| 372 | __u32 enabled; /* 1 = enabled, 0 = disabled */ | 373 | __u32 enabled; /* 1 = enabled, 0 = disabled */ |
| 374 | __u32 log_passwd; /* 1 = enabled, 0 = disabled */ | ||
| 373 | }; | 375 | }; |
| 374 | 376 | ||
| 375 | /* audit_rule_data supports filter rules with both integer and string | 377 | /* audit_rule_data supports filter rules with both integer and string |
diff --git a/kernel/audit.c b/kernel/audit.c index 0b084fa44b1f..21c7fa615bd3 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -49,6 +49,8 @@ | |||
| 49 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
| 50 | #include <linux/err.h> | 50 | #include <linux/err.h> |
| 51 | #include <linux/kthread.h> | 51 | #include <linux/kthread.h> |
| 52 | #include <linux/kernel.h> | ||
| 53 | #include <linux/syscalls.h> | ||
| 52 | 54 | ||
| 53 | #include <linux/audit.h> | 55 | #include <linux/audit.h> |
| 54 | 56 | ||
| @@ -265,7 +267,6 @@ void audit_log_lost(const char *message) | |||
| 265 | } | 267 | } |
| 266 | 268 | ||
| 267 | static int audit_log_config_change(char *function_name, int new, int old, | 269 | static int audit_log_config_change(char *function_name, int new, int old, |
| 268 | kuid_t loginuid, u32 sessionid, u32 sid, | ||
| 269 | int allow_changes) | 270 | int allow_changes) |
| 270 | { | 271 | { |
| 271 | struct audit_buffer *ab; | 272 | struct audit_buffer *ab; |
| @@ -274,29 +275,17 @@ static int audit_log_config_change(char *function_name, int new, int old, | |||
| 274 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 275 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
| 275 | if (unlikely(!ab)) | 276 | if (unlikely(!ab)) |
| 276 | return rc; | 277 | return rc; |
| 277 | audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, | 278 | audit_log_format(ab, "%s=%d old=%d", function_name, new, old); |
| 278 | old, from_kuid(&init_user_ns, loginuid), sessionid); | 279 | audit_log_session_info(ab); |
| 279 | if (sid) { | 280 | rc = audit_log_task_context(ab); |
| 280 | char *ctx = NULL; | 281 | if (rc) |
| 281 | u32 len; | 282 | allow_changes = 0; /* Something weird, deny request */ |
| 282 | |||
| 283 | rc = security_secid_to_secctx(sid, &ctx, &len); | ||
| 284 | if (rc) { | ||
| 285 | audit_log_format(ab, " sid=%u", sid); | ||
| 286 | allow_changes = 0; /* Something weird, deny request */ | ||
| 287 | } else { | ||
| 288 | audit_log_format(ab, " subj=%s", ctx); | ||
| 289 | security_release_secctx(ctx, len); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | audit_log_format(ab, " res=%d", allow_changes); | 283 | audit_log_format(ab, " res=%d", allow_changes); |
| 293 | audit_log_end(ab); | 284 | audit_log_end(ab); |
| 294 | return rc; | 285 | return rc; |
| 295 | } | 286 | } |
| 296 | 287 | ||
| 297 | static int audit_do_config_change(char *function_name, int *to_change, | 288 | static int audit_do_config_change(char *function_name, int *to_change, int new) |
| 298 | int new, kuid_t loginuid, u32 sessionid, | ||
| 299 | u32 sid) | ||
| 300 | { | 289 | { |
| 301 | int allow_changes, rc = 0, old = *to_change; | 290 | int allow_changes, rc = 0, old = *to_change; |
| 302 | 291 | ||
| @@ -307,8 +296,7 @@ static int audit_do_config_change(char *function_name, int *to_change, | |||
| 307 | allow_changes = 1; | 296 | allow_changes = 1; |
| 308 | 297 | ||
| 309 | if (audit_enabled != AUDIT_OFF) { | 298 | if (audit_enabled != AUDIT_OFF) { |
| 310 | rc = audit_log_config_change(function_name, new, old, loginuid, | 299 | rc = audit_log_config_change(function_name, new, old, allow_changes); |
| 311 | sessionid, sid, allow_changes); | ||
| 312 | if (rc) | 300 | if (rc) |
| 313 | allow_changes = 0; | 301 | allow_changes = 0; |
| 314 | } | 302 | } |
| @@ -322,44 +310,37 @@ static int audit_do_config_change(char *function_name, int *to_change, | |||
| 322 | return rc; | 310 | return rc; |
| 323 | } | 311 | } |
| 324 | 312 | ||
| 325 | static int audit_set_rate_limit(int limit, kuid_t loginuid, u32 sessionid, | 313 | static int audit_set_rate_limit(int limit) |
| 326 | u32 sid) | ||
| 327 | { | 314 | { |
| 328 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, | 315 | return audit_do_config_change("audit_rate_limit", &audit_rate_limit, limit); |
| 329 | limit, loginuid, sessionid, sid); | ||
| 330 | } | 316 | } |
| 331 | 317 | ||
| 332 | static int audit_set_backlog_limit(int limit, kuid_t loginuid, u32 sessionid, | 318 | static int audit_set_backlog_limit(int limit) |
| 333 | u32 sid) | ||
| 334 | { | 319 | { |
| 335 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, | 320 | return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, limit); |
| 336 | limit, loginuid, sessionid, sid); | ||
| 337 | } | 321 | } |
| 338 | 322 | ||
| 339 | static int audit_set_enabled(int state, kuid_t loginuid, u32 sessionid, u32 sid) | 323 | static int audit_set_enabled(int state) |
| 340 | { | 324 | { |
| 341 | int rc; | 325 | int rc; |
| 342 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) | 326 | if (state < AUDIT_OFF || state > AUDIT_LOCKED) |
| 343 | return -EINVAL; | 327 | return -EINVAL; |
| 344 | 328 | ||
| 345 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state, | 329 | rc = audit_do_config_change("audit_enabled", &audit_enabled, state); |
| 346 | loginuid, sessionid, sid); | ||
| 347 | |||
| 348 | if (!rc) | 330 | if (!rc) |
| 349 | audit_ever_enabled |= !!state; | 331 | audit_ever_enabled |= !!state; |
| 350 | 332 | ||
| 351 | return rc; | 333 | return rc; |
| 352 | } | 334 | } |
| 353 | 335 | ||
| 354 | static int audit_set_failure(int state, kuid_t loginuid, u32 sessionid, u32 sid) | 336 | static int audit_set_failure(int state) |
| 355 | { | 337 | { |
| 356 | if (state != AUDIT_FAIL_SILENT | 338 | if (state != AUDIT_FAIL_SILENT |
| 357 | && state != AUDIT_FAIL_PRINTK | 339 | && state != AUDIT_FAIL_PRINTK |
| 358 | && state != AUDIT_FAIL_PANIC) | 340 | && state != AUDIT_FAIL_PANIC) |
| 359 | return -EINVAL; | 341 | return -EINVAL; |
| 360 | 342 | ||
| 361 | return audit_do_config_change("audit_failure", &audit_failure, state, | 343 | return audit_do_config_change("audit_failure", &audit_failure, state); |
| 362 | loginuid, sessionid, sid); | ||
| 363 | } | 344 | } |
| 364 | 345 | ||
| 365 | /* | 346 | /* |
| @@ -417,34 +398,53 @@ static void kauditd_send_skb(struct sk_buff *skb) | |||
| 417 | consume_skb(skb); | 398 | consume_skb(skb); |
| 418 | } | 399 | } |
| 419 | 400 | ||
| 420 | static int kauditd_thread(void *dummy) | 401 | /* |
| 402 | * flush_hold_queue - empty the hold queue if auditd appears | ||
| 403 | * | ||
| 404 | * If auditd just started, drain the queue of messages already | ||
| 405 | * sent to syslog/printk. Remember loss here is ok. We already | ||
| 406 | * called audit_log_lost() if it didn't go out normally. so the | ||
| 407 | * race between the skb_dequeue and the next check for audit_pid | ||
| 408 | * doesn't matter. | ||
| 409 | * | ||
| 410 | * If you ever find kauditd to be too slow we can get a perf win | ||
| 411 | * by doing our own locking and keeping better track if there | ||
| 412 | * are messages in this queue. I don't see the need now, but | ||
| 413 | * in 5 years when I want to play with this again I'll see this | ||
| 414 | * note and still have no friggin idea what i'm thinking today. | ||
| 415 | */ | ||
| 416 | static void flush_hold_queue(void) | ||
| 421 | { | 417 | { |
| 422 | struct sk_buff *skb; | 418 | struct sk_buff *skb; |
| 423 | 419 | ||
| 420 | if (!audit_default || !audit_pid) | ||
| 421 | return; | ||
| 422 | |||
| 423 | skb = skb_dequeue(&audit_skb_hold_queue); | ||
| 424 | if (likely(!skb)) | ||
| 425 | return; | ||
| 426 | |||
| 427 | while (skb && audit_pid) { | ||
| 428 | kauditd_send_skb(skb); | ||
| 429 | skb = skb_dequeue(&audit_skb_hold_queue); | ||
| 430 | } | ||
| 431 | |||
| 432 | /* | ||
| 433 | * if auditd just disappeared but we | ||
| 434 | * dequeued an skb we need to drop ref | ||
| 435 | */ | ||
| 436 | if (skb) | ||
| 437 | consume_skb(skb); | ||
| 438 | } | ||
| 439 | |||
| 440 | static int kauditd_thread(void *dummy) | ||
| 441 | { | ||
| 424 | set_freezable(); | 442 | set_freezable(); |
| 425 | while (!kthread_should_stop()) { | 443 | while (!kthread_should_stop()) { |
| 426 | /* | 444 | struct sk_buff *skb; |
| 427 | * if auditd just started drain the queue of messages already | 445 | DECLARE_WAITQUEUE(wait, current); |
| 428 | * sent to syslog/printk. remember loss here is ok. we already | 446 | |
| 429 | * called audit_log_lost() if it didn't go out normally. so the | 447 | flush_hold_queue(); |
| 430 | * race between the skb_dequeue and the next check for audit_pid | ||
| 431 | * doesn't matter. | ||
| 432 | * | ||
| 433 | * if you ever find kauditd to be too slow we can get a perf win | ||
| 434 | * by doing our own locking and keeping better track if there | ||
| 435 | * are messages in this queue. I don't see the need now, but | ||
| 436 | * in 5 years when I want to play with this again I'll see this | ||
| 437 | * note and still have no friggin idea what i'm thinking today. | ||
| 438 | */ | ||
| 439 | if (audit_default && audit_pid) { | ||
| 440 | skb = skb_dequeue(&audit_skb_hold_queue); | ||
| 441 | if (unlikely(skb)) { | ||
| 442 | while (skb && audit_pid) { | ||
| 443 | kauditd_send_skb(skb); | ||
| 444 | skb = skb_dequeue(&audit_skb_hold_queue); | ||
| 445 | } | ||
| 446 | } | ||
| 447 | } | ||
| 448 | 448 | ||
| 449 | skb = skb_dequeue(&audit_skb_queue); | 449 | skb = skb_dequeue(&audit_skb_queue); |
| 450 | wake_up(&audit_backlog_wait); | 450 | wake_up(&audit_backlog_wait); |
| @@ -453,19 +453,18 @@ static int kauditd_thread(void *dummy) | |||
| 453 | kauditd_send_skb(skb); | 453 | kauditd_send_skb(skb); |
| 454 | else | 454 | else |
| 455 | audit_printk_skb(skb); | 455 | audit_printk_skb(skb); |
| 456 | } else { | 456 | continue; |
| 457 | DECLARE_WAITQUEUE(wait, current); | 457 | } |
| 458 | set_current_state(TASK_INTERRUPTIBLE); | 458 | set_current_state(TASK_INTERRUPTIBLE); |
| 459 | add_wait_queue(&kauditd_wait, &wait); | 459 | add_wait_queue(&kauditd_wait, &wait); |
| 460 | |||
| 461 | if (!skb_queue_len(&audit_skb_queue)) { | ||
| 462 | try_to_freeze(); | ||
| 463 | schedule(); | ||
| 464 | } | ||
| 465 | 460 | ||
| 466 | __set_current_state(TASK_RUNNING); | 461 | if (!skb_queue_len(&audit_skb_queue)) { |
| 467 | remove_wait_queue(&kauditd_wait, &wait); | 462 | try_to_freeze(); |
| 463 | schedule(); | ||
| 468 | } | 464 | } |
| 465 | |||
| 466 | __set_current_state(TASK_RUNNING); | ||
| 467 | remove_wait_queue(&kauditd_wait, &wait); | ||
| 469 | } | 468 | } |
| 470 | return 0; | 469 | return 0; |
| 471 | } | 470 | } |
| @@ -579,13 +578,14 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
| 579 | return -EPERM; | 578 | return -EPERM; |
| 580 | 579 | ||
| 581 | switch (msg_type) { | 580 | switch (msg_type) { |
| 582 | case AUDIT_GET: | ||
| 583 | case AUDIT_LIST: | 581 | case AUDIT_LIST: |
| 584 | case AUDIT_LIST_RULES: | ||
| 585 | case AUDIT_SET: | ||
| 586 | case AUDIT_ADD: | 582 | case AUDIT_ADD: |
| 587 | case AUDIT_ADD_RULE: | ||
| 588 | case AUDIT_DEL: | 583 | case AUDIT_DEL: |
| 584 | return -EOPNOTSUPP; | ||
| 585 | case AUDIT_GET: | ||
| 586 | case AUDIT_SET: | ||
| 587 | case AUDIT_LIST_RULES: | ||
| 588 | case AUDIT_ADD_RULE: | ||
| 589 | case AUDIT_DEL_RULE: | 589 | case AUDIT_DEL_RULE: |
| 590 | case AUDIT_SIGNAL_INFO: | 590 | case AUDIT_SIGNAL_INFO: |
| 591 | case AUDIT_TTY_GET: | 591 | case AUDIT_TTY_GET: |
| @@ -608,12 +608,10 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
| 608 | return err; | 608 | return err; |
| 609 | } | 609 | } |
| 610 | 610 | ||
| 611 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | 611 | static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) |
| 612 | kuid_t auid, u32 ses, u32 sid) | ||
| 613 | { | 612 | { |
| 614 | int rc = 0; | 613 | int rc = 0; |
| 615 | char *ctx = NULL; | 614 | uid_t uid = from_kuid(&init_user_ns, current_uid()); |
| 616 | u32 len; | ||
| 617 | 615 | ||
| 618 | if (!audit_enabled) { | 616 | if (!audit_enabled) { |
| 619 | *ab = NULL; | 617 | *ab = NULL; |
| @@ -623,33 +621,21 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | |||
| 623 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); | 621 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
| 624 | if (unlikely(!*ab)) | 622 | if (unlikely(!*ab)) |
| 625 | return rc; | 623 | return rc; |
| 626 | audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u", | 624 | audit_log_format(*ab, "pid=%d uid=%u", task_tgid_vnr(current), uid); |
| 627 | task_tgid_vnr(current), | 625 | audit_log_session_info(*ab); |
| 628 | from_kuid(&init_user_ns, current_uid()), | 626 | audit_log_task_context(*ab); |
| 629 | from_kuid(&init_user_ns, auid), ses); | ||
| 630 | if (sid) { | ||
| 631 | rc = security_secid_to_secctx(sid, &ctx, &len); | ||
| 632 | if (rc) | ||
| 633 | audit_log_format(*ab, " ssid=%u", sid); | ||
| 634 | else { | ||
| 635 | audit_log_format(*ab, " subj=%s", ctx); | ||
| 636 | security_release_secctx(ctx, len); | ||
| 637 | } | ||
| 638 | } | ||
| 639 | 627 | ||
| 640 | return rc; | 628 | return rc; |
| 641 | } | 629 | } |
| 642 | 630 | ||
| 643 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 631 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
| 644 | { | 632 | { |
| 645 | u32 seq, sid; | 633 | u32 seq; |
| 646 | void *data; | 634 | void *data; |
| 647 | struct audit_status *status_get, status_set; | 635 | struct audit_status *status_get, status_set; |
| 648 | int err; | 636 | int err; |
| 649 | struct audit_buffer *ab; | 637 | struct audit_buffer *ab; |
| 650 | u16 msg_type = nlh->nlmsg_type; | 638 | u16 msg_type = nlh->nlmsg_type; |
| 651 | kuid_t loginuid; /* loginuid of sender */ | ||
| 652 | u32 sessionid; | ||
| 653 | struct audit_sig_info *sig_data; | 639 | struct audit_sig_info *sig_data; |
| 654 | char *ctx = NULL; | 640 | char *ctx = NULL; |
| 655 | u32 len; | 641 | u32 len; |
| @@ -668,9 +654,6 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 668 | return err; | 654 | return err; |
| 669 | } | 655 | } |
| 670 | } | 656 | } |
| 671 | loginuid = audit_get_loginuid(current); | ||
| 672 | sessionid = audit_get_sessionid(current); | ||
| 673 | security_task_getsecid(current, &sid); | ||
| 674 | seq = nlh->nlmsg_seq; | 657 | seq = nlh->nlmsg_seq; |
| 675 | data = nlmsg_data(nlh); | 658 | data = nlmsg_data(nlh); |
| 676 | 659 | ||
| @@ -691,14 +674,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 691 | return -EINVAL; | 674 | return -EINVAL; |
| 692 | status_get = (struct audit_status *)data; | 675 | status_get = (struct audit_status *)data; |
| 693 | if (status_get->mask & AUDIT_STATUS_ENABLED) { | 676 | if (status_get->mask & AUDIT_STATUS_ENABLED) { |
| 694 | err = audit_set_enabled(status_get->enabled, | 677 | err = audit_set_enabled(status_get->enabled); |
| 695 | loginuid, sessionid, sid); | ||
| 696 | if (err < 0) | 678 | if (err < 0) |
| 697 | return err; | 679 | return err; |
| 698 | } | 680 | } |
| 699 | if (status_get->mask & AUDIT_STATUS_FAILURE) { | 681 | if (status_get->mask & AUDIT_STATUS_FAILURE) { |
| 700 | err = audit_set_failure(status_get->failure, | 682 | err = audit_set_failure(status_get->failure); |
| 701 | loginuid, sessionid, sid); | ||
| 702 | if (err < 0) | 683 | if (err < 0) |
| 703 | return err; | 684 | return err; |
| 704 | } | 685 | } |
| @@ -706,22 +687,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 706 | int new_pid = status_get->pid; | 687 | int new_pid = status_get->pid; |
| 707 | 688 | ||
| 708 | if (audit_enabled != AUDIT_OFF) | 689 | if (audit_enabled != AUDIT_OFF) |
| 709 | audit_log_config_change("audit_pid", new_pid, | 690 | audit_log_config_change("audit_pid", new_pid, audit_pid, 1); |
| 710 | audit_pid, loginuid, | ||
| 711 | sessionid, sid, 1); | ||
| 712 | |||
| 713 | audit_pid = new_pid; | 691 | audit_pid = new_pid; |
| 714 | audit_nlk_portid = NETLINK_CB(skb).portid; | 692 | audit_nlk_portid = NETLINK_CB(skb).portid; |
| 715 | } | 693 | } |
| 716 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) { | 694 | if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) { |
| 717 | err = audit_set_rate_limit(status_get->rate_limit, | 695 | err = audit_set_rate_limit(status_get->rate_limit); |
| 718 | loginuid, sessionid, sid); | ||
| 719 | if (err < 0) | 696 | if (err < 0) |
| 720 | return err; | 697 | return err; |
| 721 | } | 698 | } |
| 722 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) | 699 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) |
| 723 | err = audit_set_backlog_limit(status_get->backlog_limit, | 700 | err = audit_set_backlog_limit(status_get->backlog_limit); |
| 724 | loginuid, sessionid, sid); | ||
| 725 | break; | 701 | break; |
| 726 | case AUDIT_USER: | 702 | case AUDIT_USER: |
| 727 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: | 703 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: |
| @@ -729,25 +705,22 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 729 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) | 705 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) |
| 730 | return 0; | 706 | return 0; |
| 731 | 707 | ||
| 732 | err = audit_filter_user(); | 708 | err = audit_filter_user(msg_type); |
| 733 | if (err == 1) { | 709 | if (err == 1) { |
| 734 | err = 0; | 710 | err = 0; |
| 735 | if (msg_type == AUDIT_USER_TTY) { | 711 | if (msg_type == AUDIT_USER_TTY) { |
| 736 | err = tty_audit_push_task(current, loginuid, | 712 | err = tty_audit_push_current(); |
| 737 | sessionid); | ||
| 738 | if (err) | 713 | if (err) |
| 739 | break; | 714 | break; |
| 740 | } | 715 | } |
| 741 | audit_log_common_recv_msg(&ab, msg_type, | 716 | audit_log_common_recv_msg(&ab, msg_type); |
| 742 | loginuid, sessionid, sid); | ||
| 743 | |||
| 744 | if (msg_type != AUDIT_USER_TTY) | 717 | if (msg_type != AUDIT_USER_TTY) |
| 745 | audit_log_format(ab, " msg='%.1024s'", | 718 | audit_log_format(ab, " msg='%.1024s'", |
| 746 | (char *)data); | 719 | (char *)data); |
| 747 | else { | 720 | else { |
| 748 | int size; | 721 | int size; |
| 749 | 722 | ||
| 750 | audit_log_format(ab, " msg="); | 723 | audit_log_format(ab, " data="); |
| 751 | size = nlmsg_len(nlh); | 724 | size = nlmsg_len(nlh); |
| 752 | if (size > 0 && | 725 | if (size > 0 && |
| 753 | ((unsigned char *)data)[size - 1] == '\0') | 726 | ((unsigned char *)data)[size - 1] == '\0') |
| @@ -758,50 +731,24 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 758 | audit_log_end(ab); | 731 | audit_log_end(ab); |
| 759 | } | 732 | } |
| 760 | break; | 733 | break; |
| 761 | case AUDIT_ADD: | ||
| 762 | case AUDIT_DEL: | ||
| 763 | if (nlmsg_len(nlh) < sizeof(struct audit_rule)) | ||
| 764 | return -EINVAL; | ||
| 765 | if (audit_enabled == AUDIT_LOCKED) { | ||
| 766 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, | ||
| 767 | loginuid, sessionid, sid); | ||
| 768 | |||
| 769 | audit_log_format(ab, " audit_enabled=%d res=0", | ||
| 770 | audit_enabled); | ||
| 771 | audit_log_end(ab); | ||
| 772 | return -EPERM; | ||
| 773 | } | ||
| 774 | /* fallthrough */ | ||
| 775 | case AUDIT_LIST: | ||
| 776 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid, | ||
| 777 | seq, data, nlmsg_len(nlh), | ||
| 778 | loginuid, sessionid, sid); | ||
| 779 | break; | ||
| 780 | case AUDIT_ADD_RULE: | 734 | case AUDIT_ADD_RULE: |
| 781 | case AUDIT_DEL_RULE: | 735 | case AUDIT_DEL_RULE: |
| 782 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) | 736 | if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) |
| 783 | return -EINVAL; | 737 | return -EINVAL; |
| 784 | if (audit_enabled == AUDIT_LOCKED) { | 738 | if (audit_enabled == AUDIT_LOCKED) { |
| 785 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, | 739 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); |
| 786 | loginuid, sessionid, sid); | 740 | audit_log_format(ab, " audit_enabled=%d res=0", audit_enabled); |
| 787 | |||
| 788 | audit_log_format(ab, " audit_enabled=%d res=0", | ||
| 789 | audit_enabled); | ||
| 790 | audit_log_end(ab); | 741 | audit_log_end(ab); |
| 791 | return -EPERM; | 742 | return -EPERM; |
| 792 | } | 743 | } |
| 793 | /* fallthrough */ | 744 | /* fallthrough */ |
| 794 | case AUDIT_LIST_RULES: | 745 | case AUDIT_LIST_RULES: |
| 795 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid, | 746 | err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid, |
| 796 | seq, data, nlmsg_len(nlh), | 747 | seq, data, nlmsg_len(nlh)); |
| 797 | loginuid, sessionid, sid); | ||
| 798 | break; | 748 | break; |
| 799 | case AUDIT_TRIM: | 749 | case AUDIT_TRIM: |
| 800 | audit_trim_trees(); | 750 | audit_trim_trees(); |
| 801 | 751 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); | |
| 802 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, | ||
| 803 | loginuid, sessionid, sid); | ||
| 804 | |||
| 805 | audit_log_format(ab, " op=trim res=1"); | 752 | audit_log_format(ab, " op=trim res=1"); |
| 806 | audit_log_end(ab); | 753 | audit_log_end(ab); |
| 807 | break; | 754 | break; |
| @@ -831,8 +778,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 831 | /* OK, here comes... */ | 778 | /* OK, here comes... */ |
| 832 | err = audit_tag_tree(old, new); | 779 | err = audit_tag_tree(old, new); |
| 833 | 780 | ||
| 834 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, | 781 | audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); |
| 835 | loginuid, sessionid, sid); | ||
| 836 | 782 | ||
| 837 | audit_log_format(ab, " op=make_equiv old="); | 783 | audit_log_format(ab, " op=make_equiv old="); |
| 838 | audit_log_untrustedstring(ab, old); | 784 | audit_log_untrustedstring(ab, old); |
| @@ -871,27 +817,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 871 | struct audit_tty_status s; | 817 | struct audit_tty_status s; |
| 872 | struct task_struct *tsk = current; | 818 | struct task_struct *tsk = current; |
| 873 | 819 | ||
| 874 | spin_lock_irq(&tsk->sighand->siglock); | 820 | spin_lock(&tsk->sighand->siglock); |
| 875 | s.enabled = tsk->signal->audit_tty != 0; | 821 | s.enabled = tsk->signal->audit_tty != 0; |
| 876 | spin_unlock_irq(&tsk->sighand->siglock); | 822 | s.log_passwd = tsk->signal->audit_tty_log_passwd; |
| 823 | spin_unlock(&tsk->sighand->siglock); | ||
| 877 | 824 | ||
| 878 | audit_send_reply(NETLINK_CB(skb).portid, seq, | 825 | audit_send_reply(NETLINK_CB(skb).portid, seq, |
| 879 | AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); | 826 | AUDIT_TTY_GET, 0, 0, &s, sizeof(s)); |
| 880 | break; | 827 | break; |
| 881 | } | 828 | } |
| 882 | case AUDIT_TTY_SET: { | 829 | case AUDIT_TTY_SET: { |
| 883 | struct audit_tty_status *s; | 830 | struct audit_tty_status s; |
| 884 | struct task_struct *tsk = current; | 831 | struct task_struct *tsk = current; |
| 885 | 832 | ||
| 886 | if (nlh->nlmsg_len < sizeof(struct audit_tty_status)) | 833 | memset(&s, 0, sizeof(s)); |
| 887 | return -EINVAL; | 834 | /* guard against past and future API changes */ |
| 888 | s = data; | 835 | memcpy(&s, data, min(sizeof(s), (size_t)nlh->nlmsg_len)); |
| 889 | if (s->enabled != 0 && s->enabled != 1) | 836 | if ((s.enabled != 0 && s.enabled != 1) || |
| 837 | (s.log_passwd != 0 && s.log_passwd != 1)) | ||
| 890 | return -EINVAL; | 838 | return -EINVAL; |
| 891 | 839 | ||
| 892 | spin_lock_irq(&tsk->sighand->siglock); | 840 | spin_lock(&tsk->sighand->siglock); |
| 893 | tsk->signal->audit_tty = s->enabled != 0; | 841 | tsk->signal->audit_tty = s.enabled; |
| 894 | spin_unlock_irq(&tsk->sighand->siglock); | 842 | tsk->signal->audit_tty_log_passwd = s.log_passwd; |
| 843 | spin_unlock(&tsk->sighand->siglock); | ||
| 895 | break; | 844 | break; |
| 896 | } | 845 | } |
| 897 | default: | 846 | default: |
| @@ -1434,6 +1383,14 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix, | |||
| 1434 | kfree(pathname); | 1383 | kfree(pathname); |
| 1435 | } | 1384 | } |
| 1436 | 1385 | ||
| 1386 | void audit_log_session_info(struct audit_buffer *ab) | ||
| 1387 | { | ||
| 1388 | u32 sessionid = audit_get_sessionid(current); | ||
| 1389 | uid_t auid = from_kuid(&init_user_ns, audit_get_loginuid(current)); | ||
| 1390 | |||
| 1391 | audit_log_format(ab, " auid=%u ses=%u\n", auid, sessionid); | ||
| 1392 | } | ||
| 1393 | |||
| 1437 | void audit_log_key(struct audit_buffer *ab, char *key) | 1394 | void audit_log_key(struct audit_buffer *ab, char *key) |
| 1438 | { | 1395 | { |
| 1439 | audit_log_format(ab, " key="); | 1396 | audit_log_format(ab, " key="); |
| @@ -1443,6 +1400,224 @@ void audit_log_key(struct audit_buffer *ab, char *key) | |||
| 1443 | audit_log_format(ab, "(null)"); | 1400 | audit_log_format(ab, "(null)"); |
| 1444 | } | 1401 | } |
| 1445 | 1402 | ||
| 1403 | void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) | ||
| 1404 | { | ||
| 1405 | int i; | ||
| 1406 | |||
| 1407 | audit_log_format(ab, " %s=", prefix); | ||
| 1408 | CAP_FOR_EACH_U32(i) { | ||
| 1409 | audit_log_format(ab, "%08x", | ||
| 1410 | cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]); | ||
| 1411 | } | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) | ||
| 1415 | { | ||
| 1416 | kernel_cap_t *perm = &name->fcap.permitted; | ||
| 1417 | kernel_cap_t *inh = &name->fcap.inheritable; | ||
| 1418 | int log = 0; | ||
| 1419 | |||
| 1420 | if (!cap_isclear(*perm)) { | ||
| 1421 | audit_log_cap(ab, "cap_fp", perm); | ||
| 1422 | log = 1; | ||
| 1423 | } | ||
| 1424 | if (!cap_isclear(*inh)) { | ||
| 1425 | audit_log_cap(ab, "cap_fi", inh); | ||
| 1426 | log = 1; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | if (log) | ||
| 1430 | audit_log_format(ab, " cap_fe=%d cap_fver=%x", | ||
| 1431 | name->fcap.fE, name->fcap_ver); | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | static inline int audit_copy_fcaps(struct audit_names *name, | ||
| 1435 | const struct dentry *dentry) | ||
| 1436 | { | ||
| 1437 | struct cpu_vfs_cap_data caps; | ||
| 1438 | int rc; | ||
| 1439 | |||
| 1440 | if (!dentry) | ||
| 1441 | return 0; | ||
| 1442 | |||
| 1443 | rc = get_vfs_caps_from_disk(dentry, &caps); | ||
| 1444 | if (rc) | ||
| 1445 | return rc; | ||
| 1446 | |||
| 1447 | name->fcap.permitted = caps.permitted; | ||
| 1448 | name->fcap.inheritable = caps.inheritable; | ||
| 1449 | name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); | ||
| 1450 | name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> | ||
| 1451 | VFS_CAP_REVISION_SHIFT; | ||
| 1452 | |||
| 1453 | return 0; | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | /* Copy inode data into an audit_names. */ | ||
| 1457 | void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, | ||
| 1458 | const struct inode *inode) | ||
| 1459 | { | ||
| 1460 | name->ino = inode->i_ino; | ||
| 1461 | name->dev = inode->i_sb->s_dev; | ||
| 1462 | name->mode = inode->i_mode; | ||
| 1463 | name->uid = inode->i_uid; | ||
| 1464 | name->gid = inode->i_gid; | ||
| 1465 | name->rdev = inode->i_rdev; | ||
| 1466 | security_inode_getsecid(inode, &name->osid); | ||
| 1467 | audit_copy_fcaps(name, dentry); | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | /** | ||
| 1471 | * audit_log_name - produce AUDIT_PATH record from struct audit_names | ||
| 1472 | * @context: audit_context for the task | ||
| 1473 | * @n: audit_names structure with reportable details | ||
| 1474 | * @path: optional path to report instead of audit_names->name | ||
| 1475 | * @record_num: record number to report when handling a list of names | ||
| 1476 | * @call_panic: optional pointer to int that will be updated if secid fails | ||
| 1477 | */ | ||
| 1478 | void audit_log_name(struct audit_context *context, struct audit_names *n, | ||
| 1479 | struct path *path, int record_num, int *call_panic) | ||
| 1480 | { | ||
| 1481 | struct audit_buffer *ab; | ||
| 1482 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); | ||
| 1483 | if (!ab) | ||
| 1484 | return; | ||
| 1485 | |||
| 1486 | audit_log_format(ab, "item=%d", record_num); | ||
| 1487 | |||
| 1488 | if (path) | ||
| 1489 | audit_log_d_path(ab, " name=", path); | ||
| 1490 | else if (n->name) { | ||
| 1491 | switch (n->name_len) { | ||
| 1492 | case AUDIT_NAME_FULL: | ||
| 1493 | /* log the full path */ | ||
| 1494 | audit_log_format(ab, " name="); | ||
| 1495 | audit_log_untrustedstring(ab, n->name->name); | ||
| 1496 | break; | ||
| 1497 | case 0: | ||
| 1498 | /* name was specified as a relative path and the | ||
| 1499 | * directory component is the cwd */ | ||
| 1500 | audit_log_d_path(ab, " name=", &context->pwd); | ||
| 1501 | break; | ||
| 1502 | default: | ||
| 1503 | /* log the name's directory component */ | ||
| 1504 | audit_log_format(ab, " name="); | ||
| 1505 | audit_log_n_untrustedstring(ab, n->name->name, | ||
| 1506 | n->name_len); | ||
| 1507 | } | ||
| 1508 | } else | ||
| 1509 | audit_log_format(ab, " name=(null)"); | ||
| 1510 | |||
| 1511 | if (n->ino != (unsigned long)-1) { | ||
| 1512 | audit_log_format(ab, " inode=%lu" | ||
| 1513 | " dev=%02x:%02x mode=%#ho" | ||
| 1514 | " ouid=%u ogid=%u rdev=%02x:%02x", | ||
| 1515 | n->ino, | ||
| 1516 | MAJOR(n->dev), | ||
| 1517 | MINOR(n->dev), | ||
| 1518 | n->mode, | ||
| 1519 | from_kuid(&init_user_ns, n->uid), | ||
| 1520 | from_kgid(&init_user_ns, n->gid), | ||
| 1521 | MAJOR(n->rdev), | ||
| 1522 | MINOR(n->rdev)); | ||
| 1523 | } | ||
| 1524 | if (n->osid != 0) { | ||
| 1525 | char *ctx = NULL; | ||
| 1526 | u32 len; | ||
| 1527 | if (security_secid_to_secctx( | ||
| 1528 | n->osid, &ctx, &len)) { | ||
| 1529 | audit_log_format(ab, " osid=%u", n->osid); | ||
| 1530 | if (call_panic) | ||
| 1531 | *call_panic = 2; | ||
| 1532 | } else { | ||
| 1533 | audit_log_format(ab, " obj=%s", ctx); | ||
| 1534 | security_release_secctx(ctx, len); | ||
| 1535 | } | ||
| 1536 | } | ||
| 1537 | |||
| 1538 | audit_log_fcaps(ab, n); | ||
| 1539 | audit_log_end(ab); | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | int audit_log_task_context(struct audit_buffer *ab) | ||
| 1543 | { | ||
| 1544 | char *ctx = NULL; | ||
| 1545 | unsigned len; | ||
| 1546 | int error; | ||
| 1547 | u32 sid; | ||
| 1548 | |||
| 1549 | security_task_getsecid(current, &sid); | ||
| 1550 | if (!sid) | ||
| 1551 | return 0; | ||
| 1552 | |||
| 1553 | error = security_secid_to_secctx(sid, &ctx, &len); | ||
| 1554 | if (error) { | ||
| 1555 | if (error != -EINVAL) | ||
| 1556 | goto error_path; | ||
| 1557 | return 0; | ||
| 1558 | } | ||
| 1559 | |||
| 1560 | audit_log_format(ab, " subj=%s", ctx); | ||
| 1561 | security_release_secctx(ctx, len); | ||
| 1562 | return 0; | ||
| 1563 | |||
| 1564 | error_path: | ||
| 1565 | audit_panic("error in audit_log_task_context"); | ||
| 1566 | return error; | ||
| 1567 | } | ||
| 1568 | EXPORT_SYMBOL(audit_log_task_context); | ||
| 1569 | |||
| 1570 | void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) | ||
| 1571 | { | ||
| 1572 | const struct cred *cred; | ||
| 1573 | char name[sizeof(tsk->comm)]; | ||
| 1574 | struct mm_struct *mm = tsk->mm; | ||
| 1575 | char *tty; | ||
| 1576 | |||
| 1577 | if (!ab) | ||
| 1578 | return; | ||
| 1579 | |||
| 1580 | /* tsk == current */ | ||
| 1581 | cred = current_cred(); | ||
| 1582 | |||
| 1583 | spin_lock_irq(&tsk->sighand->siglock); | ||
| 1584 | if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) | ||
| 1585 | tty = tsk->signal->tty->name; | ||
| 1586 | else | ||
| 1587 | tty = "(none)"; | ||
| 1588 | spin_unlock_irq(&tsk->sighand->siglock); | ||
| 1589 | |||
| 1590 | audit_log_format(ab, | ||
| 1591 | " ppid=%ld pid=%d auid=%u uid=%u gid=%u" | ||
| 1592 | " euid=%u suid=%u fsuid=%u" | ||
| 1593 | " egid=%u sgid=%u fsgid=%u ses=%u tty=%s", | ||
| 1594 | sys_getppid(), | ||
| 1595 | tsk->pid, | ||
| 1596 | from_kuid(&init_user_ns, audit_get_loginuid(tsk)), | ||
| 1597 | from_kuid(&init_user_ns, cred->uid), | ||
| 1598 | from_kgid(&init_user_ns, cred->gid), | ||
| 1599 | from_kuid(&init_user_ns, cred->euid), | ||
| 1600 | from_kuid(&init_user_ns, cred->suid), | ||
| 1601 | from_kuid(&init_user_ns, cred->fsuid), | ||
| 1602 | from_kgid(&init_user_ns, cred->egid), | ||
| 1603 | from_kgid(&init_user_ns, cred->sgid), | ||
| 1604 | from_kgid(&init_user_ns, cred->fsgid), | ||
| 1605 | audit_get_sessionid(tsk), tty); | ||
| 1606 | |||
| 1607 | get_task_comm(name, tsk); | ||
| 1608 | audit_log_format(ab, " comm="); | ||
| 1609 | audit_log_untrustedstring(ab, name); | ||
| 1610 | |||
| 1611 | if (mm) { | ||
| 1612 | down_read(&mm->mmap_sem); | ||
| 1613 | if (mm->exe_file) | ||
| 1614 | audit_log_d_path(ab, " exe=", &mm->exe_file->f_path); | ||
| 1615 | up_read(&mm->mmap_sem); | ||
| 1616 | } | ||
| 1617 | audit_log_task_context(ab); | ||
| 1618 | } | ||
| 1619 | EXPORT_SYMBOL(audit_log_task_info); | ||
| 1620 | |||
| 1446 | /** | 1621 | /** |
| 1447 | * audit_log_link_denied - report a link restriction denial | 1622 | * audit_log_link_denied - report a link restriction denial |
| 1448 | * @operation: specific link opreation | 1623 | * @operation: specific link opreation |
| @@ -1451,19 +1626,28 @@ void audit_log_key(struct audit_buffer *ab, char *key) | |||
| 1451 | void audit_log_link_denied(const char *operation, struct path *link) | 1626 | void audit_log_link_denied(const char *operation, struct path *link) |
| 1452 | { | 1627 | { |
| 1453 | struct audit_buffer *ab; | 1628 | struct audit_buffer *ab; |
| 1629 | struct audit_names *name; | ||
| 1630 | |||
| 1631 | name = kzalloc(sizeof(*name), GFP_NOFS); | ||
| 1632 | if (!name) | ||
| 1633 | return; | ||
| 1454 | 1634 | ||
| 1635 | /* Generate AUDIT_ANOM_LINK with subject, operation, outcome. */ | ||
| 1455 | ab = audit_log_start(current->audit_context, GFP_KERNEL, | 1636 | ab = audit_log_start(current->audit_context, GFP_KERNEL, |
| 1456 | AUDIT_ANOM_LINK); | 1637 | AUDIT_ANOM_LINK); |
| 1457 | if (!ab) | 1638 | if (!ab) |
| 1458 | return; | 1639 | goto out; |
| 1459 | audit_log_format(ab, "op=%s action=denied", operation); | 1640 | audit_log_format(ab, "op=%s", operation); |
| 1460 | audit_log_format(ab, " pid=%d comm=", current->pid); | 1641 | audit_log_task_info(ab, current); |
| 1461 | audit_log_untrustedstring(ab, current->comm); | 1642 | audit_log_format(ab, " res=0"); |
| 1462 | audit_log_d_path(ab, " path=", link); | ||
| 1463 | audit_log_format(ab, " dev="); | ||
| 1464 | audit_log_untrustedstring(ab, link->dentry->d_inode->i_sb->s_id); | ||
| 1465 | audit_log_format(ab, " ino=%lu", link->dentry->d_inode->i_ino); | ||
| 1466 | audit_log_end(ab); | 1643 | audit_log_end(ab); |
| 1644 | |||
| 1645 | /* Generate AUDIT_PATH record with object. */ | ||
| 1646 | name->type = AUDIT_TYPE_NORMAL; | ||
| 1647 | audit_copy_inode(name, link->dentry, link->dentry->d_inode); | ||
| 1648 | audit_log_name(current->audit_context, name, link, 0, NULL); | ||
| 1649 | out: | ||
| 1650 | kfree(name); | ||
| 1467 | } | 1651 | } |
| 1468 | 1652 | ||
| 1469 | /** | 1653 | /** |
diff --git a/kernel/audit.h b/kernel/audit.h index 11468d99dad0..1c95131ef760 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
| 23 | #include <linux/audit.h> | 23 | #include <linux/audit.h> |
| 24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
| 25 | #include <uapi/linux/mqueue.h> | ||
| 25 | 26 | ||
| 26 | /* 0 = no checking | 27 | /* 0 = no checking |
| 27 | 1 = put_count checking | 28 | 1 = put_count checking |
| @@ -29,6 +30,11 @@ | |||
| 29 | */ | 30 | */ |
| 30 | #define AUDIT_DEBUG 0 | 31 | #define AUDIT_DEBUG 0 |
| 31 | 32 | ||
| 33 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context | ||
| 34 | * for saving names from getname(). If we get more names we will allocate | ||
| 35 | * a name dynamically and also add those to the list anchored by names_list. */ | ||
| 36 | #define AUDIT_NAMES 5 | ||
| 37 | |||
| 32 | /* At task start time, the audit_state is set in the audit_context using | 38 | /* At task start time, the audit_state is set in the audit_context using |
| 33 | a per-task filter. At syscall entry, the audit_state is augmented by | 39 | a per-task filter. At syscall entry, the audit_state is augmented by |
| 34 | the syscall filter. */ | 40 | the syscall filter. */ |
| @@ -59,8 +65,158 @@ struct audit_entry { | |||
| 59 | struct audit_krule rule; | 65 | struct audit_krule rule; |
| 60 | }; | 66 | }; |
| 61 | 67 | ||
| 68 | struct audit_cap_data { | ||
| 69 | kernel_cap_t permitted; | ||
| 70 | kernel_cap_t inheritable; | ||
| 71 | union { | ||
| 72 | unsigned int fE; /* effective bit of file cap */ | ||
| 73 | kernel_cap_t effective; /* effective set of process */ | ||
| 74 | }; | ||
| 75 | }; | ||
| 76 | |||
| 77 | /* When fs/namei.c:getname() is called, we store the pointer in name and | ||
| 78 | * we don't let putname() free it (instead we free all of the saved | ||
| 79 | * pointers at syscall exit time). | ||
| 80 | * | ||
| 81 | * Further, in fs/namei.c:path_lookup() we store the inode and device. | ||
| 82 | */ | ||
| 83 | struct audit_names { | ||
| 84 | struct list_head list; /* audit_context->names_list */ | ||
| 85 | |||
| 86 | struct filename *name; | ||
| 87 | int name_len; /* number of chars to log */ | ||
| 88 | bool name_put; /* call __putname()? */ | ||
| 89 | |||
| 90 | unsigned long ino; | ||
| 91 | dev_t dev; | ||
| 92 | umode_t mode; | ||
| 93 | kuid_t uid; | ||
| 94 | kgid_t gid; | ||
| 95 | dev_t rdev; | ||
| 96 | u32 osid; | ||
| 97 | struct audit_cap_data fcap; | ||
| 98 | unsigned int fcap_ver; | ||
| 99 | unsigned char type; /* record type */ | ||
| 100 | /* | ||
| 101 | * This was an allocated audit_names and not from the array of | ||
| 102 | * names allocated in the task audit context. Thus this name | ||
| 103 | * should be freed on syscall exit. | ||
| 104 | */ | ||
| 105 | bool should_free; | ||
| 106 | }; | ||
| 107 | |||
| 108 | /* The per-task audit context. */ | ||
| 109 | struct audit_context { | ||
| 110 | int dummy; /* must be the first element */ | ||
| 111 | int in_syscall; /* 1 if task is in a syscall */ | ||
| 112 | enum audit_state state, current_state; | ||
| 113 | unsigned int serial; /* serial number for record */ | ||
| 114 | int major; /* syscall number */ | ||
| 115 | struct timespec ctime; /* time of syscall entry */ | ||
| 116 | unsigned long argv[4]; /* syscall arguments */ | ||
| 117 | long return_code;/* syscall return code */ | ||
| 118 | u64 prio; | ||
| 119 | int return_valid; /* return code is valid */ | ||
| 120 | /* | ||
| 121 | * The names_list is the list of all audit_names collected during this | ||
| 122 | * syscall. The first AUDIT_NAMES entries in the names_list will | ||
| 123 | * actually be from the preallocated_names array for performance | ||
| 124 | * reasons. Except during allocation they should never be referenced | ||
| 125 | * through the preallocated_names array and should only be found/used | ||
| 126 | * by running the names_list. | ||
| 127 | */ | ||
| 128 | struct audit_names preallocated_names[AUDIT_NAMES]; | ||
| 129 | int name_count; /* total records in names_list */ | ||
| 130 | struct list_head names_list; /* struct audit_names->list anchor */ | ||
| 131 | char *filterkey; /* key for rule that triggered record */ | ||
| 132 | struct path pwd; | ||
| 133 | struct audit_aux_data *aux; | ||
| 134 | struct audit_aux_data *aux_pids; | ||
| 135 | struct sockaddr_storage *sockaddr; | ||
| 136 | size_t sockaddr_len; | ||
| 137 | /* Save things to print about task_struct */ | ||
| 138 | pid_t pid, ppid; | ||
| 139 | kuid_t uid, euid, suid, fsuid; | ||
| 140 | kgid_t gid, egid, sgid, fsgid; | ||
| 141 | unsigned long personality; | ||
| 142 | int arch; | ||
| 143 | |||
| 144 | pid_t target_pid; | ||
| 145 | kuid_t target_auid; | ||
| 146 | kuid_t target_uid; | ||
| 147 | unsigned int target_sessionid; | ||
| 148 | u32 target_sid; | ||
| 149 | char target_comm[TASK_COMM_LEN]; | ||
| 150 | |||
| 151 | struct audit_tree_refs *trees, *first_trees; | ||
| 152 | struct list_head killed_trees; | ||
| 153 | int tree_count; | ||
| 154 | |||
| 155 | int type; | ||
| 156 | union { | ||
| 157 | struct { | ||
| 158 | int nargs; | ||
| 159 | long args[6]; | ||
| 160 | } socketcall; | ||
| 161 | struct { | ||
| 162 | kuid_t uid; | ||
| 163 | kgid_t gid; | ||
| 164 | umode_t mode; | ||
| 165 | u32 osid; | ||
| 166 | int has_perm; | ||
| 167 | uid_t perm_uid; | ||
| 168 | gid_t perm_gid; | ||
| 169 | umode_t perm_mode; | ||
| 170 | unsigned long qbytes; | ||
| 171 | } ipc; | ||
| 172 | struct { | ||
| 173 | mqd_t mqdes; | ||
| 174 | struct mq_attr mqstat; | ||
| 175 | } mq_getsetattr; | ||
| 176 | struct { | ||
| 177 | mqd_t mqdes; | ||
| 178 | int sigev_signo; | ||
| 179 | } mq_notify; | ||
| 180 | struct { | ||
| 181 | mqd_t mqdes; | ||
| 182 | size_t msg_len; | ||
| 183 | unsigned int msg_prio; | ||
| 184 | struct timespec abs_timeout; | ||
| 185 | } mq_sendrecv; | ||
| 186 | struct { | ||
| 187 | int oflag; | ||
| 188 | umode_t mode; | ||
| 189 | struct mq_attr attr; | ||
| 190 | } mq_open; | ||
| 191 | struct { | ||
| 192 | pid_t pid; | ||
| 193 | struct audit_cap_data cap; | ||
| 194 | } capset; | ||
| 195 | struct { | ||
| 196 | int fd; | ||
| 197 | int flags; | ||
| 198 | } mmap; | ||
| 199 | }; | ||
| 200 | int fds[2]; | ||
| 201 | |||
| 202 | #if AUDIT_DEBUG | ||
| 203 | int put_count; | ||
| 204 | int ino_count; | ||
| 205 | #endif | ||
| 206 | }; | ||
| 207 | |||
| 62 | extern int audit_ever_enabled; | 208 | extern int audit_ever_enabled; |
| 63 | 209 | ||
| 210 | extern void audit_copy_inode(struct audit_names *name, | ||
| 211 | const struct dentry *dentry, | ||
| 212 | const struct inode *inode); | ||
| 213 | extern void audit_log_cap(struct audit_buffer *ab, char *prefix, | ||
| 214 | kernel_cap_t *cap); | ||
| 215 | extern void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name); | ||
| 216 | extern void audit_log_name(struct audit_context *context, | ||
| 217 | struct audit_names *n, struct path *path, | ||
| 218 | int record_num, int *call_panic); | ||
| 219 | |||
| 64 | extern int audit_pid; | 220 | extern int audit_pid; |
| 65 | 221 | ||
| 66 | #define AUDIT_INODE_BUCKETS 32 | 222 | #define AUDIT_INODE_BUCKETS 32 |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 267436826c3b..83a2970295d1 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -310,121 +310,83 @@ static u32 audit_to_op(u32 op) | |||
| 310 | return n; | 310 | return n; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | 313 | /* check if an audit field is valid */ | |
| 314 | /* Translate struct audit_rule to kernel's rule respresentation. | 314 | static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) |
| 315 | * Exists for backward compatibility with userspace. */ | ||
| 316 | static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) | ||
| 317 | { | 315 | { |
| 318 | struct audit_entry *entry; | 316 | switch(f->type) { |
| 319 | int err = 0; | 317 | case AUDIT_MSGTYPE: |
| 320 | int i; | 318 | if (entry->rule.listnr != AUDIT_FILTER_TYPE && |
| 321 | 319 | entry->rule.listnr != AUDIT_FILTER_USER) | |
| 322 | entry = audit_to_entry_common(rule); | 320 | return -EINVAL; |
| 323 | if (IS_ERR(entry)) | 321 | break; |
| 324 | goto exit_nofree; | 322 | }; |
| 325 | |||
| 326 | for (i = 0; i < rule->field_count; i++) { | ||
| 327 | struct audit_field *f = &entry->rule.fields[i]; | ||
| 328 | u32 n; | ||
| 329 | |||
| 330 | n = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS); | ||
| 331 | |||
| 332 | /* Support for legacy operators where | ||
| 333 | * AUDIT_NEGATE bit signifies != and otherwise assumes == */ | ||
| 334 | if (n & AUDIT_NEGATE) | ||
| 335 | f->op = Audit_not_equal; | ||
| 336 | else if (!n) | ||
| 337 | f->op = Audit_equal; | ||
| 338 | else | ||
| 339 | f->op = audit_to_op(n); | ||
| 340 | |||
| 341 | entry->rule.vers_ops = (n & AUDIT_OPERATORS) ? 2 : 1; | ||
| 342 | |||
| 343 | f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS); | ||
| 344 | f->val = rule->values[i]; | ||
| 345 | f->uid = INVALID_UID; | ||
| 346 | f->gid = INVALID_GID; | ||
| 347 | |||
| 348 | err = -EINVAL; | ||
| 349 | if (f->op == Audit_bad) | ||
| 350 | goto exit_free; | ||
| 351 | |||
| 352 | switch(f->type) { | ||
| 353 | default: | ||
| 354 | goto exit_free; | ||
| 355 | case AUDIT_UID: | ||
| 356 | case AUDIT_EUID: | ||
| 357 | case AUDIT_SUID: | ||
| 358 | case AUDIT_FSUID: | ||
| 359 | case AUDIT_LOGINUID: | ||
| 360 | /* bit ops not implemented for uid comparisons */ | ||
| 361 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 362 | goto exit_free; | ||
| 363 | |||
| 364 | f->uid = make_kuid(current_user_ns(), f->val); | ||
| 365 | if (!uid_valid(f->uid)) | ||
| 366 | goto exit_free; | ||
| 367 | break; | ||
| 368 | case AUDIT_GID: | ||
| 369 | case AUDIT_EGID: | ||
| 370 | case AUDIT_SGID: | ||
| 371 | case AUDIT_FSGID: | ||
| 372 | /* bit ops not implemented for gid comparisons */ | ||
| 373 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 374 | goto exit_free; | ||
| 375 | |||
| 376 | f->gid = make_kgid(current_user_ns(), f->val); | ||
| 377 | if (!gid_valid(f->gid)) | ||
| 378 | goto exit_free; | ||
| 379 | break; | ||
| 380 | case AUDIT_PID: | ||
| 381 | case AUDIT_PERS: | ||
| 382 | case AUDIT_MSGTYPE: | ||
| 383 | case AUDIT_PPID: | ||
| 384 | case AUDIT_DEVMAJOR: | ||
| 385 | case AUDIT_DEVMINOR: | ||
| 386 | case AUDIT_EXIT: | ||
| 387 | case AUDIT_SUCCESS: | ||
| 388 | /* bit ops are only useful on syscall args */ | ||
| 389 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 390 | goto exit_free; | ||
| 391 | break; | ||
| 392 | case AUDIT_ARG0: | ||
| 393 | case AUDIT_ARG1: | ||
| 394 | case AUDIT_ARG2: | ||
| 395 | case AUDIT_ARG3: | ||
| 396 | break; | ||
| 397 | /* arch is only allowed to be = or != */ | ||
| 398 | case AUDIT_ARCH: | ||
| 399 | if (f->op != Audit_not_equal && f->op != Audit_equal) | ||
| 400 | goto exit_free; | ||
| 401 | entry->rule.arch_f = f; | ||
| 402 | break; | ||
| 403 | case AUDIT_PERM: | ||
| 404 | if (f->val & ~15) | ||
| 405 | goto exit_free; | ||
| 406 | break; | ||
| 407 | case AUDIT_FILETYPE: | ||
| 408 | if (f->val & ~S_IFMT) | ||
| 409 | goto exit_free; | ||
| 410 | break; | ||
| 411 | case AUDIT_INODE: | ||
| 412 | err = audit_to_inode(&entry->rule, f); | ||
| 413 | if (err) | ||
| 414 | goto exit_free; | ||
| 415 | break; | ||
| 416 | } | ||
| 417 | } | ||
| 418 | |||
| 419 | if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal) | ||
| 420 | entry->rule.inode_f = NULL; | ||
| 421 | |||
| 422 | exit_nofree: | ||
| 423 | return entry; | ||
| 424 | 323 | ||
| 425 | exit_free: | 324 | switch(f->type) { |
| 426 | audit_free_rule(entry); | 325 | default: |
| 427 | return ERR_PTR(err); | 326 | return -EINVAL; |
| 327 | case AUDIT_UID: | ||
| 328 | case AUDIT_EUID: | ||
| 329 | case AUDIT_SUID: | ||
| 330 | case AUDIT_FSUID: | ||
| 331 | case AUDIT_LOGINUID: | ||
| 332 | case AUDIT_OBJ_UID: | ||
| 333 | case AUDIT_GID: | ||
| 334 | case AUDIT_EGID: | ||
| 335 | case AUDIT_SGID: | ||
| 336 | case AUDIT_FSGID: | ||
| 337 | case AUDIT_OBJ_GID: | ||
| 338 | case AUDIT_PID: | ||
| 339 | case AUDIT_PERS: | ||
| 340 | case AUDIT_MSGTYPE: | ||
| 341 | case AUDIT_PPID: | ||
| 342 | case AUDIT_DEVMAJOR: | ||
| 343 | case AUDIT_DEVMINOR: | ||
| 344 | case AUDIT_EXIT: | ||
| 345 | case AUDIT_SUCCESS: | ||
| 346 | /* bit ops are only useful on syscall args */ | ||
| 347 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 348 | return -EINVAL; | ||
| 349 | break; | ||
| 350 | case AUDIT_ARG0: | ||
| 351 | case AUDIT_ARG1: | ||
| 352 | case AUDIT_ARG2: | ||
| 353 | case AUDIT_ARG3: | ||
| 354 | case AUDIT_SUBJ_USER: | ||
| 355 | case AUDIT_SUBJ_ROLE: | ||
| 356 | case AUDIT_SUBJ_TYPE: | ||
| 357 | case AUDIT_SUBJ_SEN: | ||
| 358 | case AUDIT_SUBJ_CLR: | ||
| 359 | case AUDIT_OBJ_USER: | ||
| 360 | case AUDIT_OBJ_ROLE: | ||
| 361 | case AUDIT_OBJ_TYPE: | ||
| 362 | case AUDIT_OBJ_LEV_LOW: | ||
| 363 | case AUDIT_OBJ_LEV_HIGH: | ||
| 364 | case AUDIT_WATCH: | ||
| 365 | case AUDIT_DIR: | ||
| 366 | case AUDIT_FILTERKEY: | ||
| 367 | break; | ||
| 368 | case AUDIT_LOGINUID_SET: | ||
| 369 | if ((f->val != 0) && (f->val != 1)) | ||
| 370 | return -EINVAL; | ||
| 371 | /* FALL THROUGH */ | ||
| 372 | case AUDIT_ARCH: | ||
| 373 | if (f->op != Audit_not_equal && f->op != Audit_equal) | ||
| 374 | return -EINVAL; | ||
| 375 | break; | ||
| 376 | case AUDIT_PERM: | ||
| 377 | if (f->val & ~15) | ||
| 378 | return -EINVAL; | ||
| 379 | break; | ||
| 380 | case AUDIT_FILETYPE: | ||
| 381 | if (f->val & ~S_IFMT) | ||
| 382 | return -EINVAL; | ||
| 383 | break; | ||
| 384 | case AUDIT_FIELD_COMPARE: | ||
| 385 | if (f->val > AUDIT_MAX_FIELD_COMPARE) | ||
| 386 | return -EINVAL; | ||
| 387 | break; | ||
| 388 | }; | ||
| 389 | return 0; | ||
| 428 | } | 390 | } |
| 429 | 391 | ||
| 430 | /* Translate struct audit_rule_data to kernel's rule respresentation. */ | 392 | /* Translate struct audit_rule_data to kernel's rule respresentation. */ |
| @@ -459,17 +421,25 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 459 | f->gid = INVALID_GID; | 421 | f->gid = INVALID_GID; |
| 460 | f->lsm_str = NULL; | 422 | f->lsm_str = NULL; |
| 461 | f->lsm_rule = NULL; | 423 | f->lsm_rule = NULL; |
| 462 | switch(f->type) { | 424 | |
| 425 | /* Support legacy tests for a valid loginuid */ | ||
| 426 | if ((f->type == AUDIT_LOGINUID) && (f->val == 4294967295)) { | ||
| 427 | f->type = AUDIT_LOGINUID_SET; | ||
| 428 | f->val = 0; | ||
| 429 | } | ||
| 430 | |||
| 431 | err = audit_field_valid(entry, f); | ||
| 432 | if (err) | ||
| 433 | goto exit_free; | ||
| 434 | |||
| 435 | err = -EINVAL; | ||
| 436 | switch (f->type) { | ||
| 437 | case AUDIT_LOGINUID: | ||
| 463 | case AUDIT_UID: | 438 | case AUDIT_UID: |
| 464 | case AUDIT_EUID: | 439 | case AUDIT_EUID: |
| 465 | case AUDIT_SUID: | 440 | case AUDIT_SUID: |
| 466 | case AUDIT_FSUID: | 441 | case AUDIT_FSUID: |
| 467 | case AUDIT_LOGINUID: | ||
| 468 | case AUDIT_OBJ_UID: | 442 | case AUDIT_OBJ_UID: |
| 469 | /* bit ops not implemented for uid comparisons */ | ||
| 470 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 471 | goto exit_free; | ||
| 472 | |||
| 473 | f->uid = make_kuid(current_user_ns(), f->val); | 443 | f->uid = make_kuid(current_user_ns(), f->val); |
| 474 | if (!uid_valid(f->uid)) | 444 | if (!uid_valid(f->uid)) |
| 475 | goto exit_free; | 445 | goto exit_free; |
| @@ -479,27 +449,10 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 479 | case AUDIT_SGID: | 449 | case AUDIT_SGID: |
| 480 | case AUDIT_FSGID: | 450 | case AUDIT_FSGID: |
| 481 | case AUDIT_OBJ_GID: | 451 | case AUDIT_OBJ_GID: |
| 482 | /* bit ops not implemented for gid comparisons */ | ||
| 483 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | ||
| 484 | goto exit_free; | ||
| 485 | |||
| 486 | f->gid = make_kgid(current_user_ns(), f->val); | 452 | f->gid = make_kgid(current_user_ns(), f->val); |
| 487 | if (!gid_valid(f->gid)) | 453 | if (!gid_valid(f->gid)) |
| 488 | goto exit_free; | 454 | goto exit_free; |
| 489 | break; | 455 | break; |
| 490 | case AUDIT_PID: | ||
| 491 | case AUDIT_PERS: | ||
| 492 | case AUDIT_MSGTYPE: | ||
| 493 | case AUDIT_PPID: | ||
| 494 | case AUDIT_DEVMAJOR: | ||
| 495 | case AUDIT_DEVMINOR: | ||
| 496 | case AUDIT_EXIT: | ||
| 497 | case AUDIT_SUCCESS: | ||
| 498 | case AUDIT_ARG0: | ||
| 499 | case AUDIT_ARG1: | ||
| 500 | case AUDIT_ARG2: | ||
| 501 | case AUDIT_ARG3: | ||
| 502 | break; | ||
| 503 | case AUDIT_ARCH: | 456 | case AUDIT_ARCH: |
| 504 | entry->rule.arch_f = f; | 457 | entry->rule.arch_f = f; |
| 505 | break; | 458 | break; |
| @@ -570,20 +523,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 570 | entry->rule.buflen += f->val; | 523 | entry->rule.buflen += f->val; |
| 571 | entry->rule.filterkey = str; | 524 | entry->rule.filterkey = str; |
| 572 | break; | 525 | break; |
| 573 | case AUDIT_PERM: | ||
| 574 | if (f->val & ~15) | ||
| 575 | goto exit_free; | ||
| 576 | break; | ||
| 577 | case AUDIT_FILETYPE: | ||
| 578 | if (f->val & ~S_IFMT) | ||
| 579 | goto exit_free; | ||
| 580 | break; | ||
| 581 | case AUDIT_FIELD_COMPARE: | ||
| 582 | if (f->val > AUDIT_MAX_FIELD_COMPARE) | ||
| 583 | goto exit_free; | ||
| 584 | break; | ||
| 585 | default: | ||
| 586 | goto exit_free; | ||
| 587 | } | 526 | } |
| 588 | } | 527 | } |
| 589 | 528 | ||
| @@ -613,36 +552,6 @@ static inline size_t audit_pack_string(void **bufp, const char *str) | |||
| 613 | return len; | 552 | return len; |
| 614 | } | 553 | } |
| 615 | 554 | ||
| 616 | /* Translate kernel rule respresentation to struct audit_rule. | ||
| 617 | * Exists for backward compatibility with userspace. */ | ||
| 618 | static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule) | ||
| 619 | { | ||
| 620 | struct audit_rule *rule; | ||
| 621 | int i; | ||
| 622 | |||
| 623 | rule = kzalloc(sizeof(*rule), GFP_KERNEL); | ||
| 624 | if (unlikely(!rule)) | ||
| 625 | return NULL; | ||
| 626 | |||
| 627 | rule->flags = krule->flags | krule->listnr; | ||
| 628 | rule->action = krule->action; | ||
| 629 | rule->field_count = krule->field_count; | ||
| 630 | for (i = 0; i < rule->field_count; i++) { | ||
| 631 | rule->values[i] = krule->fields[i].val; | ||
| 632 | rule->fields[i] = krule->fields[i].type; | ||
| 633 | |||
| 634 | if (krule->vers_ops == 1) { | ||
| 635 | if (krule->fields[i].op == Audit_not_equal) | ||
| 636 | rule->fields[i] |= AUDIT_NEGATE; | ||
| 637 | } else { | ||
| 638 | rule->fields[i] |= audit_ops[krule->fields[i].op]; | ||
| 639 | } | ||
| 640 | } | ||
| 641 | for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i]; | ||
| 642 | |||
| 643 | return rule; | ||
| 644 | } | ||
| 645 | |||
| 646 | /* Translate kernel rule respresentation to struct audit_rule_data. */ | 555 | /* Translate kernel rule respresentation to struct audit_rule_data. */ |
| 647 | static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) | 556 | static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) |
| 648 | { | 557 | { |
| @@ -1055,35 +964,6 @@ out: | |||
| 1055 | return ret; | 964 | return ret; |
| 1056 | } | 965 | } |
| 1057 | 966 | ||
| 1058 | /* List rules using struct audit_rule. Exists for backward | ||
| 1059 | * compatibility with userspace. */ | ||
| 1060 | static void audit_list(int pid, int seq, struct sk_buff_head *q) | ||
| 1061 | { | ||
| 1062 | struct sk_buff *skb; | ||
| 1063 | struct audit_krule *r; | ||
| 1064 | int i; | ||
| 1065 | |||
| 1066 | /* This is a blocking read, so use audit_filter_mutex instead of rcu | ||
| 1067 | * iterator to sync with list writers. */ | ||
| 1068 | for (i=0; i<AUDIT_NR_FILTERS; i++) { | ||
| 1069 | list_for_each_entry(r, &audit_rules_list[i], list) { | ||
| 1070 | struct audit_rule *rule; | ||
| 1071 | |||
| 1072 | rule = audit_krule_to_rule(r); | ||
| 1073 | if (unlikely(!rule)) | ||
| 1074 | break; | ||
| 1075 | skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1, | ||
| 1076 | rule, sizeof(*rule)); | ||
| 1077 | if (skb) | ||
| 1078 | skb_queue_tail(q, skb); | ||
| 1079 | kfree(rule); | ||
| 1080 | } | ||
| 1081 | } | ||
| 1082 | skb = audit_make_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0); | ||
| 1083 | if (skb) | ||
| 1084 | skb_queue_tail(q, skb); | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | /* List rules using struct audit_rule_data. */ | 967 | /* List rules using struct audit_rule_data. */ |
| 1088 | static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) | 968 | static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) |
| 1089 | { | 969 | { |
| @@ -1113,11 +993,11 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) | |||
| 1113 | } | 993 | } |
| 1114 | 994 | ||
| 1115 | /* Log rule additions and removals */ | 995 | /* Log rule additions and removals */ |
| 1116 | static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid, | 996 | static void audit_log_rule_change(char *action, struct audit_krule *rule, int res) |
| 1117 | char *action, struct audit_krule *rule, | ||
| 1118 | int res) | ||
| 1119 | { | 997 | { |
| 1120 | struct audit_buffer *ab; | 998 | struct audit_buffer *ab; |
| 999 | uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current)); | ||
| 1000 | u32 sessionid = audit_get_sessionid(current); | ||
| 1121 | 1001 | ||
| 1122 | if (!audit_enabled) | 1002 | if (!audit_enabled) |
| 1123 | return; | 1003 | return; |
| @@ -1125,18 +1005,8 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid, | |||
| 1125 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 1005 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
| 1126 | if (!ab) | 1006 | if (!ab) |
| 1127 | return; | 1007 | return; |
| 1128 | audit_log_format(ab, "auid=%u ses=%u", | 1008 | audit_log_format(ab, "auid=%u ses=%u" ,loginuid, sessionid); |
| 1129 | from_kuid(&init_user_ns, loginuid), sessionid); | 1009 | audit_log_task_context(ab); |
| 1130 | if (sid) { | ||
| 1131 | char *ctx = NULL; | ||
| 1132 | u32 len; | ||
| 1133 | if (security_secid_to_secctx(sid, &ctx, &len)) | ||
| 1134 | audit_log_format(ab, " ssid=%u", sid); | ||
| 1135 | else { | ||
| 1136 | audit_log_format(ab, " subj=%s", ctx); | ||
| 1137 | security_release_secctx(ctx, len); | ||
| 1138 | } | ||
| 1139 | } | ||
| 1140 | audit_log_format(ab, " op="); | 1010 | audit_log_format(ab, " op="); |
| 1141 | audit_log_string(ab, action); | 1011 | audit_log_string(ab, action); |
| 1142 | audit_log_key(ab, rule->filterkey); | 1012 | audit_log_key(ab, rule->filterkey); |
| @@ -1155,8 +1025,7 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid, | |||
| 1155 | * @sessionid: sessionid for netlink audit message | 1025 | * @sessionid: sessionid for netlink audit message |
| 1156 | * @sid: SE Linux Security ID of sender | 1026 | * @sid: SE Linux Security ID of sender |
| 1157 | */ | 1027 | */ |
| 1158 | int audit_receive_filter(int type, int pid, int seq, void *data, | 1028 | int audit_receive_filter(int type, int pid, int seq, void *data, size_t datasz) |
| 1159 | size_t datasz, kuid_t loginuid, u32 sessionid, u32 sid) | ||
| 1160 | { | 1029 | { |
| 1161 | struct task_struct *tsk; | 1030 | struct task_struct *tsk; |
| 1162 | struct audit_netlink_list *dest; | 1031 | struct audit_netlink_list *dest; |
| @@ -1164,7 +1033,6 @@ int audit_receive_filter(int type, int pid, int seq, void *data, | |||
| 1164 | struct audit_entry *entry; | 1033 | struct audit_entry *entry; |
| 1165 | 1034 | ||
| 1166 | switch (type) { | 1035 | switch (type) { |
| 1167 | case AUDIT_LIST: | ||
| 1168 | case AUDIT_LIST_RULES: | 1036 | case AUDIT_LIST_RULES: |
| 1169 | /* We can't just spew out the rules here because we might fill | 1037 | /* We can't just spew out the rules here because we might fill |
| 1170 | * the available socket buffer space and deadlock waiting for | 1038 | * the available socket buffer space and deadlock waiting for |
| @@ -1179,10 +1047,7 @@ int audit_receive_filter(int type, int pid, int seq, void *data, | |||
| 1179 | skb_queue_head_init(&dest->q); | 1047 | skb_queue_head_init(&dest->q); |
| 1180 | 1048 | ||
| 1181 | mutex_lock(&audit_filter_mutex); | 1049 | mutex_lock(&audit_filter_mutex); |
| 1182 | if (type == AUDIT_LIST) | 1050 | audit_list_rules(pid, seq, &dest->q); |
| 1183 | audit_list(pid, seq, &dest->q); | ||
| 1184 | else | ||
| 1185 | audit_list_rules(pid, seq, &dest->q); | ||
| 1186 | mutex_unlock(&audit_filter_mutex); | 1051 | mutex_unlock(&audit_filter_mutex); |
| 1187 | 1052 | ||
| 1188 | tsk = kthread_run(audit_send_list, dest, "audit_send_list"); | 1053 | tsk = kthread_run(audit_send_list, dest, "audit_send_list"); |
| @@ -1192,35 +1057,23 @@ int audit_receive_filter(int type, int pid, int seq, void *data, | |||
| 1192 | err = PTR_ERR(tsk); | 1057 | err = PTR_ERR(tsk); |
| 1193 | } | 1058 | } |
| 1194 | break; | 1059 | break; |
| 1195 | case AUDIT_ADD: | ||
| 1196 | case AUDIT_ADD_RULE: | 1060 | case AUDIT_ADD_RULE: |
| 1197 | if (type == AUDIT_ADD) | 1061 | entry = audit_data_to_entry(data, datasz); |
| 1198 | entry = audit_rule_to_entry(data); | ||
| 1199 | else | ||
| 1200 | entry = audit_data_to_entry(data, datasz); | ||
| 1201 | if (IS_ERR(entry)) | 1062 | if (IS_ERR(entry)) |
| 1202 | return PTR_ERR(entry); | 1063 | return PTR_ERR(entry); |
| 1203 | 1064 | ||
| 1204 | err = audit_add_rule(entry); | 1065 | err = audit_add_rule(entry); |
| 1205 | audit_log_rule_change(loginuid, sessionid, sid, "add rule", | 1066 | audit_log_rule_change("add rule", &entry->rule, !err); |
| 1206 | &entry->rule, !err); | ||
| 1207 | |||
| 1208 | if (err) | 1067 | if (err) |
| 1209 | audit_free_rule(entry); | 1068 | audit_free_rule(entry); |
| 1210 | break; | 1069 | break; |
| 1211 | case AUDIT_DEL: | ||
| 1212 | case AUDIT_DEL_RULE: | 1070 | case AUDIT_DEL_RULE: |
| 1213 | if (type == AUDIT_DEL) | 1071 | entry = audit_data_to_entry(data, datasz); |
| 1214 | entry = audit_rule_to_entry(data); | ||
| 1215 | else | ||
| 1216 | entry = audit_data_to_entry(data, datasz); | ||
| 1217 | if (IS_ERR(entry)) | 1072 | if (IS_ERR(entry)) |
| 1218 | return PTR_ERR(entry); | 1073 | return PTR_ERR(entry); |
| 1219 | 1074 | ||
| 1220 | err = audit_del_rule(entry); | 1075 | err = audit_del_rule(entry); |
| 1221 | audit_log_rule_change(loginuid, sessionid, sid, "remove rule", | 1076 | audit_log_rule_change("remove rule", &entry->rule, !err); |
| 1222 | &entry->rule, !err); | ||
| 1223 | |||
| 1224 | audit_free_rule(entry); | 1077 | audit_free_rule(entry); |
| 1225 | break; | 1078 | break; |
| 1226 | default: | 1079 | default: |
| @@ -1358,7 +1211,7 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen) | |||
| 1358 | return strncmp(p, dname, dlen); | 1211 | return strncmp(p, dname, dlen); |
| 1359 | } | 1212 | } |
| 1360 | 1213 | ||
| 1361 | static int audit_filter_user_rules(struct audit_krule *rule, | 1214 | static int audit_filter_user_rules(struct audit_krule *rule, int type, |
| 1362 | enum audit_state *state) | 1215 | enum audit_state *state) |
| 1363 | { | 1216 | { |
| 1364 | int i; | 1217 | int i; |
| @@ -1382,6 +1235,13 @@ static int audit_filter_user_rules(struct audit_krule *rule, | |||
| 1382 | result = audit_uid_comparator(audit_get_loginuid(current), | 1235 | result = audit_uid_comparator(audit_get_loginuid(current), |
| 1383 | f->op, f->uid); | 1236 | f->op, f->uid); |
| 1384 | break; | 1237 | break; |
| 1238 | case AUDIT_LOGINUID_SET: | ||
| 1239 | result = audit_comparator(audit_loginuid_set(current), | ||
| 1240 | f->op, f->val); | ||
| 1241 | break; | ||
| 1242 | case AUDIT_MSGTYPE: | ||
| 1243 | result = audit_comparator(type, f->op, f->val); | ||
| 1244 | break; | ||
| 1385 | case AUDIT_SUBJ_USER: | 1245 | case AUDIT_SUBJ_USER: |
| 1386 | case AUDIT_SUBJ_ROLE: | 1246 | case AUDIT_SUBJ_ROLE: |
| 1387 | case AUDIT_SUBJ_TYPE: | 1247 | case AUDIT_SUBJ_TYPE: |
| @@ -1408,7 +1268,7 @@ static int audit_filter_user_rules(struct audit_krule *rule, | |||
| 1408 | return 1; | 1268 | return 1; |
| 1409 | } | 1269 | } |
| 1410 | 1270 | ||
| 1411 | int audit_filter_user(void) | 1271 | int audit_filter_user(int type) |
| 1412 | { | 1272 | { |
| 1413 | enum audit_state state = AUDIT_DISABLED; | 1273 | enum audit_state state = AUDIT_DISABLED; |
| 1414 | struct audit_entry *e; | 1274 | struct audit_entry *e; |
| @@ -1416,7 +1276,7 @@ int audit_filter_user(void) | |||
| 1416 | 1276 | ||
| 1417 | rcu_read_lock(); | 1277 | rcu_read_lock(); |
| 1418 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { | 1278 | list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { |
| 1419 | if (audit_filter_user_rules(&e->rule, &state)) { | 1279 | if (audit_filter_user_rules(&e->rule, type, &state)) { |
| 1420 | if (state == AUDIT_DISABLED) | 1280 | if (state == AUDIT_DISABLED) |
| 1421 | ret = 0; | 1281 | ret = 0; |
| 1422 | break; | 1282 | break; |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index c68229411a7c..3c8a601324a2 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -76,11 +76,6 @@ | |||
| 76 | #define AUDITSC_SUCCESS 1 | 76 | #define AUDITSC_SUCCESS 1 |
| 77 | #define AUDITSC_FAILURE 2 | 77 | #define AUDITSC_FAILURE 2 |
| 78 | 78 | ||
| 79 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context | ||
| 80 | * for saving names from getname(). If we get more names we will allocate | ||
| 81 | * a name dynamically and also add those to the list anchored by names_list. */ | ||
| 82 | #define AUDIT_NAMES 5 | ||
| 83 | |||
| 84 | /* no execve audit message should be longer than this (userspace limits) */ | 79 | /* no execve audit message should be longer than this (userspace limits) */ |
| 85 | #define MAX_EXECVE_AUDIT_LEN 7500 | 80 | #define MAX_EXECVE_AUDIT_LEN 7500 |
| 86 | 81 | ||
| @@ -90,44 +85,6 @@ int audit_n_rules; | |||
| 90 | /* determines whether we collect data for signals sent */ | 85 | /* determines whether we collect data for signals sent */ |
| 91 | int audit_signals; | 86 | int audit_signals; |
| 92 | 87 | ||
| 93 | struct audit_cap_data { | ||
| 94 | kernel_cap_t permitted; | ||
| 95 | kernel_cap_t inheritable; | ||
| 96 | union { | ||
| 97 | unsigned int fE; /* effective bit of a file capability */ | ||
| 98 | kernel_cap_t effective; /* effective set of a process */ | ||
| 99 | }; | ||
| 100 | }; | ||
| 101 | |||
| 102 | /* When fs/namei.c:getname() is called, we store the pointer in name and | ||
| 103 | * we don't let putname() free it (instead we free all of the saved | ||
| 104 | * pointers at syscall exit time). | ||
| 105 | * | ||
| 106 | * Further, in fs/namei.c:path_lookup() we store the inode and device. | ||
| 107 | */ | ||
| 108 | struct audit_names { | ||
| 109 | struct list_head list; /* audit_context->names_list */ | ||
| 110 | struct filename *name; | ||
| 111 | unsigned long ino; | ||
| 112 | dev_t dev; | ||
| 113 | umode_t mode; | ||
| 114 | kuid_t uid; | ||
| 115 | kgid_t gid; | ||
| 116 | dev_t rdev; | ||
| 117 | u32 osid; | ||
| 118 | struct audit_cap_data fcap; | ||
| 119 | unsigned int fcap_ver; | ||
| 120 | int name_len; /* number of name's characters to log */ | ||
| 121 | unsigned char type; /* record type */ | ||
| 122 | bool name_put; /* call __putname() for this name */ | ||
| 123 | /* | ||
| 124 | * This was an allocated audit_names and not from the array of | ||
| 125 | * names allocated in the task audit context. Thus this name | ||
| 126 | * should be freed on syscall exit | ||
| 127 | */ | ||
| 128 | bool should_free; | ||
| 129 | }; | ||
| 130 | |||
| 131 | struct audit_aux_data { | 88 | struct audit_aux_data { |
| 132 | struct audit_aux_data *next; | 89 | struct audit_aux_data *next; |
| 133 | int type; | 90 | int type; |
| @@ -175,106 +132,6 @@ struct audit_tree_refs { | |||
| 175 | struct audit_chunk *c[31]; | 132 | struct audit_chunk *c[31]; |
| 176 | }; | 133 | }; |
| 177 | 134 | ||
| 178 | /* The per-task audit context. */ | ||
| 179 | struct audit_context { | ||
| 180 | int dummy; /* must be the first element */ | ||
| 181 | int in_syscall; /* 1 if task is in a syscall */ | ||
| 182 | enum audit_state state, current_state; | ||
| 183 | unsigned int serial; /* serial number for record */ | ||
| 184 | int major; /* syscall number */ | ||
| 185 | struct timespec ctime; /* time of syscall entry */ | ||
| 186 | unsigned long argv[4]; /* syscall arguments */ | ||
| 187 | long return_code;/* syscall return code */ | ||
| 188 | u64 prio; | ||
| 189 | int return_valid; /* return code is valid */ | ||
| 190 | /* | ||
| 191 | * The names_list is the list of all audit_names collected during this | ||
| 192 | * syscall. The first AUDIT_NAMES entries in the names_list will | ||
| 193 | * actually be from the preallocated_names array for performance | ||
| 194 | * reasons. Except during allocation they should never be referenced | ||
| 195 | * through the preallocated_names array and should only be found/used | ||
| 196 | * by running the names_list. | ||
| 197 | */ | ||
| 198 | struct audit_names preallocated_names[AUDIT_NAMES]; | ||
| 199 | int name_count; /* total records in names_list */ | ||
| 200 | struct list_head names_list; /* anchor for struct audit_names->list */ | ||
| 201 | char * filterkey; /* key for rule that triggered record */ | ||
| 202 | struct path pwd; | ||
| 203 | struct audit_aux_data *aux; | ||
| 204 | struct audit_aux_data *aux_pids; | ||
| 205 | struct sockaddr_storage *sockaddr; | ||
| 206 | size_t sockaddr_len; | ||
| 207 | /* Save things to print about task_struct */ | ||
| 208 | pid_t pid, ppid; | ||
| 209 | kuid_t uid, euid, suid, fsuid; | ||
| 210 | kgid_t gid, egid, sgid, fsgid; | ||
| 211 | unsigned long personality; | ||
| 212 | int arch; | ||
| 213 | |||
| 214 | pid_t target_pid; | ||
| 215 | kuid_t target_auid; | ||
| 216 | kuid_t target_uid; | ||
| 217 | unsigned int target_sessionid; | ||
| 218 | u32 target_sid; | ||
| 219 | char target_comm[TASK_COMM_LEN]; | ||
| 220 | |||
| 221 | struct audit_tree_refs *trees, *first_trees; | ||
| 222 | struct list_head killed_trees; | ||
| 223 | int tree_count; | ||
| 224 | |||
| 225 | int type; | ||
| 226 | union { | ||
| 227 | struct { | ||
| 228 | int nargs; | ||
| 229 | long args[6]; | ||
| 230 | } socketcall; | ||
| 231 | struct { | ||
| 232 | kuid_t uid; | ||
| 233 | kgid_t gid; | ||
| 234 | umode_t mode; | ||
| 235 | u32 osid; | ||
| 236 | int has_perm; | ||
| 237 | uid_t perm_uid; | ||
| 238 | gid_t perm_gid; | ||
| 239 | umode_t perm_mode; | ||
| 240 | unsigned long qbytes; | ||
| 241 | } ipc; | ||
| 242 | struct { | ||
| 243 | mqd_t mqdes; | ||
| 244 | struct mq_attr mqstat; | ||
| 245 | } mq_getsetattr; | ||
| 246 | struct { | ||
| 247 | mqd_t mqdes; | ||
| 248 | int sigev_signo; | ||
| 249 | } mq_notify; | ||
| 250 | struct { | ||
| 251 | mqd_t mqdes; | ||
| 252 | size_t msg_len; | ||
| 253 | unsigned int msg_prio; | ||
| 254 | struct timespec abs_timeout; | ||
| 255 | } mq_sendrecv; | ||
| 256 | struct { | ||
| 257 | int oflag; | ||
| 258 | umode_t mode; | ||
| 259 | struct mq_attr attr; | ||
| 260 | } mq_open; | ||
| 261 | struct { | ||
| 262 | pid_t pid; | ||
| 263 | struct audit_cap_data cap; | ||
| 264 | } capset; | ||
| 265 | struct { | ||
| 266 | int fd; | ||
| 267 | int flags; | ||
| 268 | } mmap; | ||
| 269 | }; | ||
| 270 | int fds[2]; | ||
| 271 | |||
| 272 | #if AUDIT_DEBUG | ||
| 273 | int put_count; | ||
| 274 | int ino_count; | ||
| 275 | #endif | ||
| 276 | }; | ||
| 277 | |||
| 278 | static inline int open_arg(int flags, int mask) | 135 | static inline int open_arg(int flags, int mask) |
| 279 | { | 136 | { |
| 280 | int n = ACC_MODE(flags); | 137 | int n = ACC_MODE(flags); |
| @@ -633,9 +490,23 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 633 | break; | 490 | break; |
| 634 | case AUDIT_GID: | 491 | case AUDIT_GID: |
| 635 | result = audit_gid_comparator(cred->gid, f->op, f->gid); | 492 | result = audit_gid_comparator(cred->gid, f->op, f->gid); |
| 493 | if (f->op == Audit_equal) { | ||
| 494 | if (!result) | ||
| 495 | result = in_group_p(f->gid); | ||
| 496 | } else if (f->op == Audit_not_equal) { | ||
| 497 | if (result) | ||
| 498 | result = !in_group_p(f->gid); | ||
| 499 | } | ||
| 636 | break; | 500 | break; |
| 637 | case AUDIT_EGID: | 501 | case AUDIT_EGID: |
| 638 | result = audit_gid_comparator(cred->egid, f->op, f->gid); | 502 | result = audit_gid_comparator(cred->egid, f->op, f->gid); |
| 503 | if (f->op == Audit_equal) { | ||
| 504 | if (!result) | ||
| 505 | result = in_egroup_p(f->gid); | ||
| 506 | } else if (f->op == Audit_not_equal) { | ||
| 507 | if (result) | ||
| 508 | result = !in_egroup_p(f->gid); | ||
| 509 | } | ||
| 639 | break; | 510 | break; |
| 640 | case AUDIT_SGID: | 511 | case AUDIT_SGID: |
| 641 | result = audit_gid_comparator(cred->sgid, f->op, f->gid); | 512 | result = audit_gid_comparator(cred->sgid, f->op, f->gid); |
| @@ -742,6 +613,9 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 742 | if (ctx) | 613 | if (ctx) |
| 743 | result = audit_uid_comparator(tsk->loginuid, f->op, f->uid); | 614 | result = audit_uid_comparator(tsk->loginuid, f->op, f->uid); |
| 744 | break; | 615 | break; |
| 616 | case AUDIT_LOGINUID_SET: | ||
| 617 | result = audit_comparator(audit_loginuid_set(tsk), f->op, f->val); | ||
| 618 | break; | ||
| 745 | case AUDIT_SUBJ_USER: | 619 | case AUDIT_SUBJ_USER: |
| 746 | case AUDIT_SUBJ_ROLE: | 620 | case AUDIT_SUBJ_ROLE: |
| 747 | case AUDIT_SUBJ_TYPE: | 621 | case AUDIT_SUBJ_TYPE: |
| @@ -987,6 +861,8 @@ static inline void audit_free_names(struct audit_context *context) | |||
| 987 | 861 | ||
| 988 | #if AUDIT_DEBUG == 2 | 862 | #if AUDIT_DEBUG == 2 |
| 989 | if (context->put_count + context->ino_count != context->name_count) { | 863 | if (context->put_count + context->ino_count != context->name_count) { |
| 864 | int i = 0; | ||
| 865 | |||
| 990 | printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" | 866 | printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" |
| 991 | " name_count=%d put_count=%d" | 867 | " name_count=%d put_count=%d" |
| 992 | " ino_count=%d [NOT freeing]\n", | 868 | " ino_count=%d [NOT freeing]\n", |
| @@ -995,7 +871,7 @@ static inline void audit_free_names(struct audit_context *context) | |||
| 995 | context->name_count, context->put_count, | 871 | context->name_count, context->put_count, |
| 996 | context->ino_count); | 872 | context->ino_count); |
| 997 | list_for_each_entry(n, &context->names_list, list) { | 873 | list_for_each_entry(n, &context->names_list, list) { |
| 998 | printk(KERN_ERR "names[%d] = %p = %s\n", i, | 874 | printk(KERN_ERR "names[%d] = %p = %s\n", i++, |
| 999 | n->name, n->name->name ?: "(null)"); | 875 | n->name, n->name->name ?: "(null)"); |
| 1000 | } | 876 | } |
| 1001 | dump_stack(); | 877 | dump_stack(); |
| @@ -1010,7 +886,7 @@ static inline void audit_free_names(struct audit_context *context) | |||
| 1010 | list_for_each_entry_safe(n, next, &context->names_list, list) { | 886 | list_for_each_entry_safe(n, next, &context->names_list, list) { |
| 1011 | list_del(&n->list); | 887 | list_del(&n->list); |
| 1012 | if (n->name && n->name_put) | 888 | if (n->name && n->name_put) |
| 1013 | __putname(n->name); | 889 | final_putname(n->name); |
| 1014 | if (n->should_free) | 890 | if (n->should_free) |
| 1015 | kfree(n); | 891 | kfree(n); |
| 1016 | } | 892 | } |
| @@ -1093,88 +969,6 @@ static inline void audit_free_context(struct audit_context *context) | |||
| 1093 | kfree(context); | 969 | kfree(context); |
| 1094 | } | 970 | } |
| 1095 | 971 | ||
| 1096 | void audit_log_task_context(struct audit_buffer *ab) | ||
| 1097 | { | ||
| 1098 | char *ctx = NULL; | ||
| 1099 | unsigned len; | ||
| 1100 | int error; | ||
| 1101 | u32 sid; | ||
| 1102 | |||
| 1103 | security_task_getsecid(current, &sid); | ||
| 1104 | if (!sid) | ||
| 1105 | return; | ||
| 1106 | |||
| 1107 | error = security_secid_to_secctx(sid, &ctx, &len); | ||
| 1108 | if (error) { | ||
| 1109 | if (error != -EINVAL) | ||
| 1110 | goto error_path; | ||
| 1111 | return; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | audit_log_format(ab, " subj=%s", ctx); | ||
| 1115 | security_release_secctx(ctx, len); | ||
| 1116 | return; | ||
| 1117 | |||
| 1118 | error_path: | ||
| 1119 | audit_panic("error in audit_log_task_context"); | ||
| 1120 | return; | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | EXPORT_SYMBOL(audit_log_task_context); | ||
| 1124 | |||
| 1125 | void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) | ||
| 1126 | { | ||
| 1127 | const struct cred *cred; | ||
| 1128 | char name[sizeof(tsk->comm)]; | ||
| 1129 | struct mm_struct *mm = tsk->mm; | ||
| 1130 | char *tty; | ||
| 1131 | |||
| 1132 | if (!ab) | ||
| 1133 | return; | ||
| 1134 | |||
| 1135 | /* tsk == current */ | ||
| 1136 | cred = current_cred(); | ||
| 1137 | |||
| 1138 | spin_lock_irq(&tsk->sighand->siglock); | ||
| 1139 | if (tsk->signal && tsk->signal->tty) | ||
| 1140 | tty = tsk->signal->tty->name; | ||
| 1141 | else | ||
| 1142 | tty = "(none)"; | ||
| 1143 | spin_unlock_irq(&tsk->sighand->siglock); | ||
| 1144 | |||
| 1145 | |||
| 1146 | audit_log_format(ab, | ||
| 1147 | " ppid=%ld pid=%d auid=%u uid=%u gid=%u" | ||
| 1148 | " euid=%u suid=%u fsuid=%u" | ||
| 1149 | " egid=%u sgid=%u fsgid=%u ses=%u tty=%s", | ||
| 1150 | sys_getppid(), | ||
| 1151 | tsk->pid, | ||
| 1152 | from_kuid(&init_user_ns, tsk->loginuid), | ||
| 1153 | from_kuid(&init_user_ns, cred->uid), | ||
| 1154 | from_kgid(&init_user_ns, cred->gid), | ||
| 1155 | from_kuid(&init_user_ns, cred->euid), | ||
| 1156 | from_kuid(&init_user_ns, cred->suid), | ||
| 1157 | from_kuid(&init_user_ns, cred->fsuid), | ||
| 1158 | from_kgid(&init_user_ns, cred->egid), | ||
| 1159 | from_kgid(&init_user_ns, cred->sgid), | ||
| 1160 | from_kgid(&init_user_ns, cred->fsgid), | ||
| 1161 | tsk->sessionid, tty); | ||
| 1162 | |||
| 1163 | get_task_comm(name, tsk); | ||
| 1164 | audit_log_format(ab, " comm="); | ||
| 1165 | audit_log_untrustedstring(ab, name); | ||
| 1166 | |||
| 1167 | if (mm) { | ||
| 1168 | down_read(&mm->mmap_sem); | ||
| 1169 | if (mm->exe_file) | ||
| 1170 | audit_log_d_path(ab, " exe=", &mm->exe_file->f_path); | ||
| 1171 | up_read(&mm->mmap_sem); | ||
| 1172 | } | ||
| 1173 | audit_log_task_context(ab); | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | EXPORT_SYMBOL(audit_log_task_info); | ||
| 1177 | |||
| 1178 | static int audit_log_pid_context(struct audit_context *context, pid_t pid, | 972 | static int audit_log_pid_context(struct audit_context *context, pid_t pid, |
| 1179 | kuid_t auid, kuid_t uid, unsigned int sessionid, | 973 | kuid_t auid, kuid_t uid, unsigned int sessionid, |
| 1180 | u32 sid, char *comm) | 974 | u32 sid, char *comm) |
| @@ -1191,12 +985,14 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid, | |||
| 1191 | audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, | 985 | audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, |
| 1192 | from_kuid(&init_user_ns, auid), | 986 | from_kuid(&init_user_ns, auid), |
| 1193 | from_kuid(&init_user_ns, uid), sessionid); | 987 | from_kuid(&init_user_ns, uid), sessionid); |
| 1194 | if (security_secid_to_secctx(sid, &ctx, &len)) { | 988 | if (sid) { |
| 1195 | audit_log_format(ab, " obj=(none)"); | 989 | if (security_secid_to_secctx(sid, &ctx, &len)) { |
| 1196 | rc = 1; | 990 | audit_log_format(ab, " obj=(none)"); |
| 1197 | } else { | 991 | rc = 1; |
| 1198 | audit_log_format(ab, " obj=%s", ctx); | 992 | } else { |
| 1199 | security_release_secctx(ctx, len); | 993 | audit_log_format(ab, " obj=%s", ctx); |
| 994 | security_release_secctx(ctx, len); | ||
| 995 | } | ||
| 1200 | } | 996 | } |
| 1201 | audit_log_format(ab, " ocomm="); | 997 | audit_log_format(ab, " ocomm="); |
| 1202 | audit_log_untrustedstring(ab, comm); | 998 | audit_log_untrustedstring(ab, comm); |
| @@ -1390,35 +1186,6 @@ static void audit_log_execve_info(struct audit_context *context, | |||
| 1390 | kfree(buf); | 1186 | kfree(buf); |
| 1391 | } | 1187 | } |
| 1392 | 1188 | ||
| 1393 | static void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) | ||
| 1394 | { | ||
| 1395 | int i; | ||
| 1396 | |||
| 1397 | audit_log_format(ab, " %s=", prefix); | ||
| 1398 | CAP_FOR_EACH_U32(i) { | ||
| 1399 | audit_log_format(ab, "%08x", cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]); | ||
| 1400 | } | ||
| 1401 | } | ||
| 1402 | |||
| 1403 | static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) | ||
| 1404 | { | ||
| 1405 | kernel_cap_t *perm = &name->fcap.permitted; | ||
| 1406 | kernel_cap_t *inh = &name->fcap.inheritable; | ||
| 1407 | int log = 0; | ||
| 1408 | |||
| 1409 | if (!cap_isclear(*perm)) { | ||
| 1410 | audit_log_cap(ab, "cap_fp", perm); | ||
| 1411 | log = 1; | ||
| 1412 | } | ||
| 1413 | if (!cap_isclear(*inh)) { | ||
| 1414 | audit_log_cap(ab, "cap_fi", inh); | ||
| 1415 | log = 1; | ||
| 1416 | } | ||
| 1417 | |||
| 1418 | if (log) | ||
| 1419 | audit_log_format(ab, " cap_fe=%d cap_fver=%x", name->fcap.fE, name->fcap_ver); | ||
| 1420 | } | ||
| 1421 | |||
| 1422 | static void show_special(struct audit_context *context, int *call_panic) | 1189 | static void show_special(struct audit_context *context, int *call_panic) |
| 1423 | { | 1190 | { |
| 1424 | struct audit_buffer *ab; | 1191 | struct audit_buffer *ab; |
| @@ -1516,68 +1283,6 @@ static void show_special(struct audit_context *context, int *call_panic) | |||
| 1516 | audit_log_end(ab); | 1283 | audit_log_end(ab); |
| 1517 | } | 1284 | } |
| 1518 | 1285 | ||
| 1519 | static void audit_log_name(struct audit_context *context, struct audit_names *n, | ||
| 1520 | int record_num, int *call_panic) | ||
| 1521 | { | ||
| 1522 | struct audit_buffer *ab; | ||
| 1523 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); | ||
| 1524 | if (!ab) | ||
| 1525 | return; /* audit_panic has been called */ | ||
| 1526 | |||
| 1527 | audit_log_format(ab, "item=%d", record_num); | ||
| 1528 | |||
| 1529 | if (n->name) { | ||
| 1530 | switch (n->name_len) { | ||
| 1531 | case AUDIT_NAME_FULL: | ||
| 1532 | /* log the full path */ | ||
| 1533 | audit_log_format(ab, " name="); | ||
| 1534 | audit_log_untrustedstring(ab, n->name->name); | ||
| 1535 | break; | ||
| 1536 | case 0: | ||
| 1537 | /* name was specified as a relative path and the | ||
| 1538 | * directory component is the cwd */ | ||
| 1539 | audit_log_d_path(ab, " name=", &context->pwd); | ||
| 1540 | break; | ||
| 1541 | default: | ||
| 1542 | /* log the name's directory component */ | ||
| 1543 | audit_log_format(ab, " name="); | ||
| 1544 | audit_log_n_untrustedstring(ab, n->name->name, | ||
| 1545 | n->name_len); | ||
| 1546 | } | ||
| 1547 | } else | ||
| 1548 | audit_log_format(ab, " name=(null)"); | ||
| 1549 | |||
| 1550 | if (n->ino != (unsigned long)-1) { | ||
| 1551 | audit_log_format(ab, " inode=%lu" | ||
| 1552 | " dev=%02x:%02x mode=%#ho" | ||
| 1553 | " ouid=%u ogid=%u rdev=%02x:%02x", | ||
| 1554 | n->ino, | ||
| 1555 | MAJOR(n->dev), | ||
| 1556 | MINOR(n->dev), | ||
| 1557 | n->mode, | ||
| 1558 | from_kuid(&init_user_ns, n->uid), | ||
| 1559 | from_kgid(&init_user_ns, n->gid), | ||
| 1560 | MAJOR(n->rdev), | ||
| 1561 | MINOR(n->rdev)); | ||
| 1562 | } | ||
| 1563 | if (n->osid != 0) { | ||
| 1564 | char *ctx = NULL; | ||
| 1565 | u32 len; | ||
| 1566 | if (security_secid_to_secctx( | ||
| 1567 | n->osid, &ctx, &len)) { | ||
| 1568 | audit_log_format(ab, " osid=%u", n->osid); | ||
| 1569 | *call_panic = 2; | ||
| 1570 | } else { | ||
| 1571 | audit_log_format(ab, " obj=%s", ctx); | ||
| 1572 | security_release_secctx(ctx, len); | ||
| 1573 | } | ||
| 1574 | } | ||
| 1575 | |||
| 1576 | audit_log_fcaps(ab, n); | ||
| 1577 | |||
| 1578 | audit_log_end(ab); | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) | 1286 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) |
| 1582 | { | 1287 | { |
| 1583 | int i, call_panic = 0; | 1288 | int i, call_panic = 0; |
| @@ -1695,7 +1400,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1695 | 1400 | ||
| 1696 | i = 0; | 1401 | i = 0; |
| 1697 | list_for_each_entry(n, &context->names_list, list) | 1402 | list_for_each_entry(n, &context->names_list, list) |
| 1698 | audit_log_name(context, n, i++, &call_panic); | 1403 | audit_log_name(context, n, NULL, i++, &call_panic); |
| 1699 | 1404 | ||
| 1700 | /* Send end of event record to help user space know we are finished */ | 1405 | /* Send end of event record to help user space know we are finished */ |
| 1701 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); | 1406 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); |
| @@ -2030,18 +1735,18 @@ void audit_putname(struct filename *name) | |||
| 2030 | BUG_ON(!context); | 1735 | BUG_ON(!context); |
| 2031 | if (!context->in_syscall) { | 1736 | if (!context->in_syscall) { |
| 2032 | #if AUDIT_DEBUG == 2 | 1737 | #if AUDIT_DEBUG == 2 |
| 2033 | printk(KERN_ERR "%s:%d(:%d): __putname(%p)\n", | 1738 | printk(KERN_ERR "%s:%d(:%d): final_putname(%p)\n", |
| 2034 | __FILE__, __LINE__, context->serial, name); | 1739 | __FILE__, __LINE__, context->serial, name); |
| 2035 | if (context->name_count) { | 1740 | if (context->name_count) { |
| 2036 | struct audit_names *n; | 1741 | struct audit_names *n; |
| 2037 | int i; | 1742 | int i = 0; |
| 2038 | 1743 | ||
| 2039 | list_for_each_entry(n, &context->names_list, list) | 1744 | list_for_each_entry(n, &context->names_list, list) |
| 2040 | printk(KERN_ERR "name[%d] = %p = %s\n", i, | 1745 | printk(KERN_ERR "name[%d] = %p = %s\n", i++, |
| 2041 | n->name, n->name->name ?: "(null)"); | 1746 | n->name, n->name->name ?: "(null)"); |
| 2042 | } | 1747 | } |
| 2043 | #endif | 1748 | #endif |
| 2044 | __putname(name); | 1749 | final_putname(name); |
| 2045 | } | 1750 | } |
| 2046 | #if AUDIT_DEBUG | 1751 | #if AUDIT_DEBUG |
| 2047 | else { | 1752 | else { |
| @@ -2060,41 +1765,6 @@ void audit_putname(struct filename *name) | |||
| 2060 | #endif | 1765 | #endif |
| 2061 | } | 1766 | } |
| 2062 | 1767 | ||
| 2063 | static inline int audit_copy_fcaps(struct audit_names *name, const struct dentry *dentry) | ||
| 2064 | { | ||
| 2065 | struct cpu_vfs_cap_data caps; | ||
| 2066 | int rc; | ||
| 2067 | |||
| 2068 | if (!dentry) | ||
| 2069 | return 0; | ||
| 2070 | |||
| 2071 | rc = get_vfs_caps_from_disk(dentry, &caps); | ||
| 2072 | if (rc) | ||
| 2073 | return rc; | ||
| 2074 | |||
| 2075 | name->fcap.permitted = caps.permitted; | ||
| 2076 | name->fcap.inheritable = caps.inheritable; | ||
| 2077 | name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); | ||
| 2078 | name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; | ||
| 2079 | |||
| 2080 | return 0; | ||
| 2081 | } | ||
| 2082 | |||
| 2083 | |||
| 2084 | /* Copy inode data into an audit_names. */ | ||
| 2085 | static void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, | ||
| 2086 | const struct inode *inode) | ||
| 2087 | { | ||
| 2088 | name->ino = inode->i_ino; | ||
| 2089 | name->dev = inode->i_sb->s_dev; | ||
| 2090 | name->mode = inode->i_mode; | ||
| 2091 | name->uid = inode->i_uid; | ||
| 2092 | name->gid = inode->i_gid; | ||
| 2093 | name->rdev = inode->i_rdev; | ||
| 2094 | security_inode_getsecid(inode, &name->osid); | ||
| 2095 | audit_copy_fcaps(name, dentry); | ||
| 2096 | } | ||
| 2097 | |||
| 2098 | /** | 1768 | /** |
| 2099 | * __audit_inode - store the inode and device from a lookup | 1769 | * __audit_inode - store the inode and device from a lookup |
| 2100 | * @name: name being audited | 1770 | * @name: name being audited |
| @@ -2303,7 +1973,7 @@ int audit_set_loginuid(kuid_t loginuid) | |||
| 2303 | unsigned int sessionid; | 1973 | unsigned int sessionid; |
| 2304 | 1974 | ||
| 2305 | #ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE | 1975 | #ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE |
| 2306 | if (uid_valid(task->loginuid)) | 1976 | if (audit_loginuid_set(task)) |
| 2307 | return -EPERM; | 1977 | return -EPERM; |
| 2308 | #else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ | 1978 | #else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ |
| 2309 | if (!capable(CAP_AUDIT_CONTROL)) | 1979 | if (!capable(CAP_AUDIT_CONTROL)) |
| @@ -2471,17 +2141,20 @@ int __audit_bprm(struct linux_binprm *bprm) | |||
| 2471 | 2141 | ||
| 2472 | /** | 2142 | /** |
| 2473 | * audit_socketcall - record audit data for sys_socketcall | 2143 | * audit_socketcall - record audit data for sys_socketcall |
| 2474 | * @nargs: number of args | 2144 | * @nargs: number of args, which should not be more than AUDITSC_ARGS. |
| 2475 | * @args: args array | 2145 | * @args: args array |
| 2476 | * | 2146 | * |
| 2477 | */ | 2147 | */ |
| 2478 | void __audit_socketcall(int nargs, unsigned long *args) | 2148 | int __audit_socketcall(int nargs, unsigned long *args) |
| 2479 | { | 2149 | { |
| 2480 | struct audit_context *context = current->audit_context; | 2150 | struct audit_context *context = current->audit_context; |
| 2481 | 2151 | ||
| 2152 | if (nargs <= 0 || nargs > AUDITSC_ARGS || !args) | ||
| 2153 | return -EINVAL; | ||
| 2482 | context->type = AUDIT_SOCKETCALL; | 2154 | context->type = AUDIT_SOCKETCALL; |
| 2483 | context->socketcall.nargs = nargs; | 2155 | context->socketcall.nargs = nargs; |
| 2484 | memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long)); | 2156 | memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long)); |
| 2157 | return 0; | ||
| 2485 | } | 2158 | } |
| 2486 | 2159 | ||
| 2487 | /** | 2160 | /** |
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 5e9efd4b83a4..015f85aaca08 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
| @@ -71,6 +71,7 @@ config TRACE_CLOCK | |||
| 71 | config RING_BUFFER | 71 | config RING_BUFFER |
| 72 | bool | 72 | bool |
| 73 | select TRACE_CLOCK | 73 | select TRACE_CLOCK |
| 74 | select IRQ_WORK | ||
| 74 | 75 | ||
| 75 | config FTRACE_NMI_ENTER | 76 | config FTRACE_NMI_ENTER |
| 76 | bool | 77 | bool |
| @@ -107,7 +108,6 @@ config TRACING | |||
| 107 | select BINARY_PRINTF | 108 | select BINARY_PRINTF |
| 108 | select EVENT_TRACING | 109 | select EVENT_TRACING |
| 109 | select TRACE_CLOCK | 110 | select TRACE_CLOCK |
| 110 | select IRQ_WORK | ||
| 111 | 111 | ||
| 112 | config GENERIC_TRACER | 112 | config GENERIC_TRACER |
| 113 | bool | 113 | bool |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 8a5c017bb50c..b549b0f5b977 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -64,6 +64,13 @@ | |||
| 64 | 64 | ||
| 65 | #define FL_GLOBAL_CONTROL_MASK (FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_CONTROL) | 65 | #define FL_GLOBAL_CONTROL_MASK (FTRACE_OPS_FL_GLOBAL | FTRACE_OPS_FL_CONTROL) |
| 66 | 66 | ||
| 67 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 68 | #define INIT_REGEX_LOCK(opsname) \ | ||
| 69 | .regex_lock = __MUTEX_INITIALIZER(opsname.regex_lock), | ||
| 70 | #else | ||
| 71 | #define INIT_REGEX_LOCK(opsname) | ||
| 72 | #endif | ||
| 73 | |||
| 67 | static struct ftrace_ops ftrace_list_end __read_mostly = { | 74 | static struct ftrace_ops ftrace_list_end __read_mostly = { |
| 68 | .func = ftrace_stub, | 75 | .func = ftrace_stub, |
| 69 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB, | 76 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB, |
| @@ -131,6 +138,16 @@ static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip); | |||
| 131 | while (likely(op = rcu_dereference_raw((op)->next)) && \ | 138 | while (likely(op = rcu_dereference_raw((op)->next)) && \ |
| 132 | unlikely((op) != &ftrace_list_end)) | 139 | unlikely((op) != &ftrace_list_end)) |
| 133 | 140 | ||
| 141 | static inline void ftrace_ops_init(struct ftrace_ops *ops) | ||
| 142 | { | ||
| 143 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 144 | if (!(ops->flags & FTRACE_OPS_FL_INITIALIZED)) { | ||
| 145 | mutex_init(&ops->regex_lock); | ||
| 146 | ops->flags |= FTRACE_OPS_FL_INITIALIZED; | ||
| 147 | } | ||
| 148 | #endif | ||
| 149 | } | ||
| 150 | |||
| 134 | /** | 151 | /** |
| 135 | * ftrace_nr_registered_ops - return number of ops registered | 152 | * ftrace_nr_registered_ops - return number of ops registered |
| 136 | * | 153 | * |
| @@ -907,7 +924,8 @@ static void unregister_ftrace_profiler(void) | |||
| 907 | #else | 924 | #else |
| 908 | static struct ftrace_ops ftrace_profile_ops __read_mostly = { | 925 | static struct ftrace_ops ftrace_profile_ops __read_mostly = { |
| 909 | .func = function_profile_call, | 926 | .func = function_profile_call, |
| 910 | .flags = FTRACE_OPS_FL_RECURSION_SAFE, | 927 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, |
| 928 | INIT_REGEX_LOCK(ftrace_profile_ops) | ||
| 911 | }; | 929 | }; |
| 912 | 930 | ||
| 913 | static int register_ftrace_profiler(void) | 931 | static int register_ftrace_profiler(void) |
| @@ -1103,11 +1121,10 @@ static struct ftrace_ops global_ops = { | |||
| 1103 | .func = ftrace_stub, | 1121 | .func = ftrace_stub, |
| 1104 | .notrace_hash = EMPTY_HASH, | 1122 | .notrace_hash = EMPTY_HASH, |
| 1105 | .filter_hash = EMPTY_HASH, | 1123 | .filter_hash = EMPTY_HASH, |
| 1106 | .flags = FTRACE_OPS_FL_RECURSION_SAFE, | 1124 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, |
| 1125 | INIT_REGEX_LOCK(global_ops) | ||
| 1107 | }; | 1126 | }; |
| 1108 | 1127 | ||
| 1109 | static DEFINE_MUTEX(ftrace_regex_lock); | ||
| 1110 | |||
| 1111 | struct ftrace_page { | 1128 | struct ftrace_page { |
| 1112 | struct ftrace_page *next; | 1129 | struct ftrace_page *next; |
| 1113 | struct dyn_ftrace *records; | 1130 | struct dyn_ftrace *records; |
| @@ -1247,6 +1264,7 @@ static void free_ftrace_hash_rcu(struct ftrace_hash *hash) | |||
| 1247 | 1264 | ||
| 1248 | void ftrace_free_filter(struct ftrace_ops *ops) | 1265 | void ftrace_free_filter(struct ftrace_ops *ops) |
| 1249 | { | 1266 | { |
| 1267 | ftrace_ops_init(ops); | ||
| 1250 | free_ftrace_hash(ops->filter_hash); | 1268 | free_ftrace_hash(ops->filter_hash); |
| 1251 | free_ftrace_hash(ops->notrace_hash); | 1269 | free_ftrace_hash(ops->notrace_hash); |
| 1252 | } | 1270 | } |
| @@ -2441,7 +2459,7 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 2441 | !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) || | 2459 | !ftrace_lookup_ip(ops->notrace_hash, rec->ip)) || |
| 2442 | 2460 | ||
| 2443 | ((iter->flags & FTRACE_ITER_ENABLED) && | 2461 | ((iter->flags & FTRACE_ITER_ENABLED) && |
| 2444 | !(rec->flags & ~FTRACE_FL_MASK))) { | 2462 | !(rec->flags & FTRACE_FL_ENABLED))) { |
| 2445 | 2463 | ||
| 2446 | rec = NULL; | 2464 | rec = NULL; |
| 2447 | goto retry; | 2465 | goto retry; |
| @@ -2624,6 +2642,8 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
| 2624 | struct ftrace_hash *hash; | 2642 | struct ftrace_hash *hash; |
| 2625 | int ret = 0; | 2643 | int ret = 0; |
| 2626 | 2644 | ||
| 2645 | ftrace_ops_init(ops); | ||
| 2646 | |||
| 2627 | if (unlikely(ftrace_disabled)) | 2647 | if (unlikely(ftrace_disabled)) |
| 2628 | return -ENODEV; | 2648 | return -ENODEV; |
| 2629 | 2649 | ||
| @@ -2636,28 +2656,26 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
| 2636 | return -ENOMEM; | 2656 | return -ENOMEM; |
| 2637 | } | 2657 | } |
| 2638 | 2658 | ||
| 2659 | iter->ops = ops; | ||
| 2660 | iter->flags = flag; | ||
| 2661 | |||
| 2662 | mutex_lock(&ops->regex_lock); | ||
| 2663 | |||
| 2639 | if (flag & FTRACE_ITER_NOTRACE) | 2664 | if (flag & FTRACE_ITER_NOTRACE) |
| 2640 | hash = ops->notrace_hash; | 2665 | hash = ops->notrace_hash; |
| 2641 | else | 2666 | else |
| 2642 | hash = ops->filter_hash; | 2667 | hash = ops->filter_hash; |
| 2643 | 2668 | ||
| 2644 | iter->ops = ops; | ||
| 2645 | iter->flags = flag; | ||
| 2646 | |||
| 2647 | if (file->f_mode & FMODE_WRITE) { | 2669 | if (file->f_mode & FMODE_WRITE) { |
| 2648 | mutex_lock(&ftrace_lock); | ||
| 2649 | iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash); | 2670 | iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash); |
| 2650 | mutex_unlock(&ftrace_lock); | ||
| 2651 | |||
| 2652 | if (!iter->hash) { | 2671 | if (!iter->hash) { |
| 2653 | trace_parser_put(&iter->parser); | 2672 | trace_parser_put(&iter->parser); |
| 2654 | kfree(iter); | 2673 | kfree(iter); |
| 2655 | return -ENOMEM; | 2674 | ret = -ENOMEM; |
| 2675 | goto out_unlock; | ||
| 2656 | } | 2676 | } |
| 2657 | } | 2677 | } |
| 2658 | 2678 | ||
| 2659 | mutex_lock(&ftrace_regex_lock); | ||
| 2660 | |||
| 2661 | if ((file->f_mode & FMODE_WRITE) && | 2679 | if ((file->f_mode & FMODE_WRITE) && |
| 2662 | (file->f_flags & O_TRUNC)) | 2680 | (file->f_flags & O_TRUNC)) |
| 2663 | ftrace_filter_reset(iter->hash); | 2681 | ftrace_filter_reset(iter->hash); |
| @@ -2677,7 +2695,9 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag, | |||
| 2677 | } | 2695 | } |
| 2678 | } else | 2696 | } else |
| 2679 | file->private_data = iter; | 2697 | file->private_data = iter; |
| 2680 | mutex_unlock(&ftrace_regex_lock); | 2698 | |
| 2699 | out_unlock: | ||
| 2700 | mutex_unlock(&ops->regex_lock); | ||
| 2681 | 2701 | ||
| 2682 | return ret; | 2702 | return ret; |
| 2683 | } | 2703 | } |
| @@ -2910,6 +2930,8 @@ static void function_trace_probe_call(unsigned long ip, unsigned long parent_ip, | |||
| 2910 | static struct ftrace_ops trace_probe_ops __read_mostly = | 2930 | static struct ftrace_ops trace_probe_ops __read_mostly = |
| 2911 | { | 2931 | { |
| 2912 | .func = function_trace_probe_call, | 2932 | .func = function_trace_probe_call, |
| 2933 | .flags = FTRACE_OPS_FL_INITIALIZED, | ||
| 2934 | INIT_REGEX_LOCK(trace_probe_ops) | ||
| 2913 | }; | 2935 | }; |
| 2914 | 2936 | ||
| 2915 | static int ftrace_probe_registered; | 2937 | static int ftrace_probe_registered; |
| @@ -2919,8 +2941,12 @@ static void __enable_ftrace_function_probe(void) | |||
| 2919 | int ret; | 2941 | int ret; |
| 2920 | int i; | 2942 | int i; |
| 2921 | 2943 | ||
| 2922 | if (ftrace_probe_registered) | 2944 | if (ftrace_probe_registered) { |
| 2945 | /* still need to update the function call sites */ | ||
| 2946 | if (ftrace_enabled) | ||
| 2947 | ftrace_run_update_code(FTRACE_UPDATE_CALLS); | ||
| 2923 | return; | 2948 | return; |
| 2949 | } | ||
| 2924 | 2950 | ||
| 2925 | for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { | 2951 | for (i = 0; i < FTRACE_FUNC_HASHSIZE; i++) { |
| 2926 | struct hlist_head *hhd = &ftrace_func_hash[i]; | 2952 | struct hlist_head *hhd = &ftrace_func_hash[i]; |
| @@ -2990,19 +3016,21 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
| 2990 | if (WARN_ON(not)) | 3016 | if (WARN_ON(not)) |
| 2991 | return -EINVAL; | 3017 | return -EINVAL; |
| 2992 | 3018 | ||
| 2993 | mutex_lock(&ftrace_lock); | 3019 | mutex_lock(&trace_probe_ops.regex_lock); |
| 2994 | 3020 | ||
| 2995 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); | 3021 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); |
| 2996 | if (!hash) { | 3022 | if (!hash) { |
| 2997 | count = -ENOMEM; | 3023 | count = -ENOMEM; |
| 2998 | goto out_unlock; | 3024 | goto out; |
| 2999 | } | 3025 | } |
| 3000 | 3026 | ||
| 3001 | if (unlikely(ftrace_disabled)) { | 3027 | if (unlikely(ftrace_disabled)) { |
| 3002 | count = -ENODEV; | 3028 | count = -ENODEV; |
| 3003 | goto out_unlock; | 3029 | goto out; |
| 3004 | } | 3030 | } |
| 3005 | 3031 | ||
| 3032 | mutex_lock(&ftrace_lock); | ||
| 3033 | |||
| 3006 | do_for_each_ftrace_rec(pg, rec) { | 3034 | do_for_each_ftrace_rec(pg, rec) { |
| 3007 | 3035 | ||
| 3008 | if (!ftrace_match_record(rec, NULL, search, len, type)) | 3036 | if (!ftrace_match_record(rec, NULL, search, len, type)) |
| @@ -3056,6 +3084,8 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
| 3056 | 3084 | ||
| 3057 | out_unlock: | 3085 | out_unlock: |
| 3058 | mutex_unlock(&ftrace_lock); | 3086 | mutex_unlock(&ftrace_lock); |
| 3087 | out: | ||
| 3088 | mutex_unlock(&trace_probe_ops.regex_lock); | ||
| 3059 | free_ftrace_hash(hash); | 3089 | free_ftrace_hash(hash); |
| 3060 | 3090 | ||
| 3061 | return count; | 3091 | return count; |
| @@ -3095,7 +3125,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
| 3095 | return; | 3125 | return; |
| 3096 | } | 3126 | } |
| 3097 | 3127 | ||
| 3098 | mutex_lock(&ftrace_lock); | 3128 | mutex_lock(&trace_probe_ops.regex_lock); |
| 3099 | 3129 | ||
| 3100 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); | 3130 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); |
| 3101 | if (!hash) | 3131 | if (!hash) |
| @@ -3133,6 +3163,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
| 3133 | list_add(&entry->free_list, &free_list); | 3163 | list_add(&entry->free_list, &free_list); |
| 3134 | } | 3164 | } |
| 3135 | } | 3165 | } |
| 3166 | mutex_lock(&ftrace_lock); | ||
| 3136 | __disable_ftrace_function_probe(); | 3167 | __disable_ftrace_function_probe(); |
| 3137 | /* | 3168 | /* |
| 3138 | * Remove after the disable is called. Otherwise, if the last | 3169 | * Remove after the disable is called. Otherwise, if the last |
| @@ -3144,9 +3175,10 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, | |||
| 3144 | list_del(&entry->free_list); | 3175 | list_del(&entry->free_list); |
| 3145 | ftrace_free_entry(entry); | 3176 | ftrace_free_entry(entry); |
| 3146 | } | 3177 | } |
| 3178 | mutex_unlock(&ftrace_lock); | ||
| 3147 | 3179 | ||
| 3148 | out_unlock: | 3180 | out_unlock: |
| 3149 | mutex_unlock(&ftrace_lock); | 3181 | mutex_unlock(&trace_probe_ops.regex_lock); |
| 3150 | free_ftrace_hash(hash); | 3182 | free_ftrace_hash(hash); |
| 3151 | } | 3183 | } |
| 3152 | 3184 | ||
| @@ -3256,18 +3288,17 @@ ftrace_regex_write(struct file *file, const char __user *ubuf, | |||
| 3256 | if (!cnt) | 3288 | if (!cnt) |
| 3257 | return 0; | 3289 | return 0; |
| 3258 | 3290 | ||
| 3259 | mutex_lock(&ftrace_regex_lock); | ||
| 3260 | |||
| 3261 | ret = -ENODEV; | ||
| 3262 | if (unlikely(ftrace_disabled)) | ||
| 3263 | goto out_unlock; | ||
| 3264 | |||
| 3265 | if (file->f_mode & FMODE_READ) { | 3291 | if (file->f_mode & FMODE_READ) { |
| 3266 | struct seq_file *m = file->private_data; | 3292 | struct seq_file *m = file->private_data; |
| 3267 | iter = m->private; | 3293 | iter = m->private; |
| 3268 | } else | 3294 | } else |
| 3269 | iter = file->private_data; | 3295 | iter = file->private_data; |
| 3270 | 3296 | ||
| 3297 | if (unlikely(ftrace_disabled)) | ||
| 3298 | return -ENODEV; | ||
| 3299 | |||
| 3300 | /* iter->hash is a local copy, so we don't need regex_lock */ | ||
| 3301 | |||
| 3271 | parser = &iter->parser; | 3302 | parser = &iter->parser; |
| 3272 | read = trace_get_user(parser, ubuf, cnt, ppos); | 3303 | read = trace_get_user(parser, ubuf, cnt, ppos); |
| 3273 | 3304 | ||
| @@ -3276,14 +3307,12 @@ ftrace_regex_write(struct file *file, const char __user *ubuf, | |||
| 3276 | ret = ftrace_process_regex(iter->hash, parser->buffer, | 3307 | ret = ftrace_process_regex(iter->hash, parser->buffer, |
| 3277 | parser->idx, enable); | 3308 | parser->idx, enable); |
| 3278 | trace_parser_clear(parser); | 3309 | trace_parser_clear(parser); |
| 3279 | if (ret) | 3310 | if (ret < 0) |
| 3280 | goto out_unlock; | 3311 | goto out; |
| 3281 | } | 3312 | } |
| 3282 | 3313 | ||
| 3283 | ret = read; | 3314 | ret = read; |
| 3284 | out_unlock: | 3315 | out: |
| 3285 | mutex_unlock(&ftrace_regex_lock); | ||
| 3286 | |||
| 3287 | return ret; | 3316 | return ret; |
| 3288 | } | 3317 | } |
| 3289 | 3318 | ||
| @@ -3335,16 +3364,19 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, | |||
| 3335 | if (unlikely(ftrace_disabled)) | 3364 | if (unlikely(ftrace_disabled)) |
| 3336 | return -ENODEV; | 3365 | return -ENODEV; |
| 3337 | 3366 | ||
| 3367 | mutex_lock(&ops->regex_lock); | ||
| 3368 | |||
| 3338 | if (enable) | 3369 | if (enable) |
| 3339 | orig_hash = &ops->filter_hash; | 3370 | orig_hash = &ops->filter_hash; |
| 3340 | else | 3371 | else |
| 3341 | orig_hash = &ops->notrace_hash; | 3372 | orig_hash = &ops->notrace_hash; |
| 3342 | 3373 | ||
| 3343 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); | 3374 | hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, *orig_hash); |
| 3344 | if (!hash) | 3375 | if (!hash) { |
| 3345 | return -ENOMEM; | 3376 | ret = -ENOMEM; |
| 3377 | goto out_regex_unlock; | ||
| 3378 | } | ||
| 3346 | 3379 | ||
| 3347 | mutex_lock(&ftrace_regex_lock); | ||
| 3348 | if (reset) | 3380 | if (reset) |
| 3349 | ftrace_filter_reset(hash); | 3381 | ftrace_filter_reset(hash); |
| 3350 | if (buf && !ftrace_match_records(hash, buf, len)) { | 3382 | if (buf && !ftrace_match_records(hash, buf, len)) { |
| @@ -3366,7 +3398,7 @@ ftrace_set_hash(struct ftrace_ops *ops, unsigned char *buf, int len, | |||
| 3366 | mutex_unlock(&ftrace_lock); | 3398 | mutex_unlock(&ftrace_lock); |
| 3367 | 3399 | ||
| 3368 | out_regex_unlock: | 3400 | out_regex_unlock: |
| 3369 | mutex_unlock(&ftrace_regex_lock); | 3401 | mutex_unlock(&ops->regex_lock); |
| 3370 | 3402 | ||
| 3371 | free_ftrace_hash(hash); | 3403 | free_ftrace_hash(hash); |
| 3372 | return ret; | 3404 | return ret; |
| @@ -3392,6 +3424,7 @@ ftrace_set_addr(struct ftrace_ops *ops, unsigned long ip, int remove, | |||
| 3392 | int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip, | 3424 | int ftrace_set_filter_ip(struct ftrace_ops *ops, unsigned long ip, |
| 3393 | int remove, int reset) | 3425 | int remove, int reset) |
| 3394 | { | 3426 | { |
| 3427 | ftrace_ops_init(ops); | ||
| 3395 | return ftrace_set_addr(ops, ip, remove, reset, 1); | 3428 | return ftrace_set_addr(ops, ip, remove, reset, 1); |
| 3396 | } | 3429 | } |
| 3397 | EXPORT_SYMBOL_GPL(ftrace_set_filter_ip); | 3430 | EXPORT_SYMBOL_GPL(ftrace_set_filter_ip); |
| @@ -3416,6 +3449,7 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len, | |||
| 3416 | int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf, | 3449 | int ftrace_set_filter(struct ftrace_ops *ops, unsigned char *buf, |
| 3417 | int len, int reset) | 3450 | int len, int reset) |
| 3418 | { | 3451 | { |
| 3452 | ftrace_ops_init(ops); | ||
| 3419 | return ftrace_set_regex(ops, buf, len, reset, 1); | 3453 | return ftrace_set_regex(ops, buf, len, reset, 1); |
| 3420 | } | 3454 | } |
| 3421 | EXPORT_SYMBOL_GPL(ftrace_set_filter); | 3455 | EXPORT_SYMBOL_GPL(ftrace_set_filter); |
| @@ -3434,6 +3468,7 @@ EXPORT_SYMBOL_GPL(ftrace_set_filter); | |||
| 3434 | int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf, | 3468 | int ftrace_set_notrace(struct ftrace_ops *ops, unsigned char *buf, |
| 3435 | int len, int reset) | 3469 | int len, int reset) |
| 3436 | { | 3470 | { |
| 3471 | ftrace_ops_init(ops); | ||
| 3437 | return ftrace_set_regex(ops, buf, len, reset, 0); | 3472 | return ftrace_set_regex(ops, buf, len, reset, 0); |
| 3438 | } | 3473 | } |
| 3439 | EXPORT_SYMBOL_GPL(ftrace_set_notrace); | 3474 | EXPORT_SYMBOL_GPL(ftrace_set_notrace); |
| @@ -3524,6 +3559,8 @@ ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable) | |||
| 3524 | { | 3559 | { |
| 3525 | char *func; | 3560 | char *func; |
| 3526 | 3561 | ||
| 3562 | ftrace_ops_init(ops); | ||
| 3563 | |||
| 3527 | while (buf) { | 3564 | while (buf) { |
| 3528 | func = strsep(&buf, ","); | 3565 | func = strsep(&buf, ","); |
| 3529 | ftrace_set_regex(ops, func, strlen(func), 0, enable); | 3566 | ftrace_set_regex(ops, func, strlen(func), 0, enable); |
| @@ -3551,10 +3588,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file) | |||
| 3551 | int filter_hash; | 3588 | int filter_hash; |
| 3552 | int ret; | 3589 | int ret; |
| 3553 | 3590 | ||
| 3554 | mutex_lock(&ftrace_regex_lock); | ||
| 3555 | if (file->f_mode & FMODE_READ) { | 3591 | if (file->f_mode & FMODE_READ) { |
| 3556 | iter = m->private; | 3592 | iter = m->private; |
| 3557 | |||
| 3558 | seq_release(inode, file); | 3593 | seq_release(inode, file); |
| 3559 | } else | 3594 | } else |
| 3560 | iter = file->private_data; | 3595 | iter = file->private_data; |
| @@ -3567,6 +3602,8 @@ int ftrace_regex_release(struct inode *inode, struct file *file) | |||
| 3567 | 3602 | ||
| 3568 | trace_parser_put(parser); | 3603 | trace_parser_put(parser); |
| 3569 | 3604 | ||
| 3605 | mutex_lock(&iter->ops->regex_lock); | ||
| 3606 | |||
| 3570 | if (file->f_mode & FMODE_WRITE) { | 3607 | if (file->f_mode & FMODE_WRITE) { |
| 3571 | filter_hash = !!(iter->flags & FTRACE_ITER_FILTER); | 3608 | filter_hash = !!(iter->flags & FTRACE_ITER_FILTER); |
| 3572 | 3609 | ||
| @@ -3584,10 +3621,11 @@ int ftrace_regex_release(struct inode *inode, struct file *file) | |||
| 3584 | 3621 | ||
| 3585 | mutex_unlock(&ftrace_lock); | 3622 | mutex_unlock(&ftrace_lock); |
| 3586 | } | 3623 | } |
| 3624 | |||
| 3625 | mutex_unlock(&iter->ops->regex_lock); | ||
| 3587 | free_ftrace_hash(iter->hash); | 3626 | free_ftrace_hash(iter->hash); |
| 3588 | kfree(iter); | 3627 | kfree(iter); |
| 3589 | 3628 | ||
| 3590 | mutex_unlock(&ftrace_regex_lock); | ||
| 3591 | return 0; | 3629 | return 0; |
| 3592 | } | 3630 | } |
| 3593 | 3631 | ||
| @@ -4126,7 +4164,8 @@ void __init ftrace_init(void) | |||
| 4126 | 4164 | ||
| 4127 | static struct ftrace_ops global_ops = { | 4165 | static struct ftrace_ops global_ops = { |
| 4128 | .func = ftrace_stub, | 4166 | .func = ftrace_stub, |
| 4129 | .flags = FTRACE_OPS_FL_RECURSION_SAFE, | 4167 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, |
| 4168 | INIT_REGEX_LOCK(global_ops) | ||
| 4130 | }; | 4169 | }; |
| 4131 | 4170 | ||
| 4132 | static int __init ftrace_nodyn_init(void) | 4171 | static int __init ftrace_nodyn_init(void) |
| @@ -4180,8 +4219,9 @@ ftrace_ops_control_func(unsigned long ip, unsigned long parent_ip, | |||
| 4180 | } | 4219 | } |
| 4181 | 4220 | ||
| 4182 | static struct ftrace_ops control_ops = { | 4221 | static struct ftrace_ops control_ops = { |
| 4183 | .func = ftrace_ops_control_func, | 4222 | .func = ftrace_ops_control_func, |
| 4184 | .flags = FTRACE_OPS_FL_RECURSION_SAFE, | 4223 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, |
| 4224 | INIT_REGEX_LOCK(control_ops) | ||
| 4185 | }; | 4225 | }; |
| 4186 | 4226 | ||
| 4187 | static inline void | 4227 | static inline void |
| @@ -4539,6 +4579,8 @@ int register_ftrace_function(struct ftrace_ops *ops) | |||
| 4539 | { | 4579 | { |
| 4540 | int ret = -1; | 4580 | int ret = -1; |
| 4541 | 4581 | ||
| 4582 | ftrace_ops_init(ops); | ||
| 4583 | |||
| 4542 | mutex_lock(&ftrace_lock); | 4584 | mutex_lock(&ftrace_lock); |
| 4543 | 4585 | ||
| 4544 | ret = __register_ftrace_function(ops); | 4586 | ret = __register_ftrace_function(ops); |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 53582e982e51..7a0cf68027cc 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
| @@ -251,7 +251,8 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file, | |||
| 251 | switch (enable) { | 251 | switch (enable) { |
| 252 | case 0: | 252 | case 0: |
| 253 | /* | 253 | /* |
| 254 | * When soft_disable is set and enable is cleared, we want | 254 | * When soft_disable is set and enable is cleared, the sm_ref |
| 255 | * reference counter is decremented. If it reaches 0, we want | ||
| 255 | * to clear the SOFT_DISABLED flag but leave the event in the | 256 | * to clear the SOFT_DISABLED flag but leave the event in the |
| 256 | * state that it was. That is, if the event was enabled and | 257 | * state that it was. That is, if the event was enabled and |
| 257 | * SOFT_DISABLED isn't set, then do nothing. But if SOFT_DISABLED | 258 | * SOFT_DISABLED isn't set, then do nothing. But if SOFT_DISABLED |
| @@ -263,6 +264,8 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file, | |||
| 263 | * "soft enable"s (clearing the SOFT_DISABLED bit) wont work. | 264 | * "soft enable"s (clearing the SOFT_DISABLED bit) wont work. |
| 264 | */ | 265 | */ |
| 265 | if (soft_disable) { | 266 | if (soft_disable) { |
| 267 | if (atomic_dec_return(&file->sm_ref) > 0) | ||
| 268 | break; | ||
| 266 | disable = file->flags & FTRACE_EVENT_FL_SOFT_DISABLED; | 269 | disable = file->flags & FTRACE_EVENT_FL_SOFT_DISABLED; |
| 267 | clear_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags); | 270 | clear_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags); |
| 268 | } else | 271 | } else |
| @@ -291,8 +294,11 @@ static int __ftrace_event_enable_disable(struct ftrace_event_file *file, | |||
| 291 | */ | 294 | */ |
| 292 | if (!soft_disable) | 295 | if (!soft_disable) |
| 293 | clear_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags); | 296 | clear_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &file->flags); |
| 294 | else | 297 | else { |
| 298 | if (atomic_inc_return(&file->sm_ref) > 1) | ||
| 299 | break; | ||
| 295 | set_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags); | 300 | set_bit(FTRACE_EVENT_FL_SOFT_MODE_BIT, &file->flags); |
| 301 | } | ||
| 296 | 302 | ||
| 297 | if (!(file->flags & FTRACE_EVENT_FL_ENABLED)) { | 303 | if (!(file->flags & FTRACE_EVENT_FL_ENABLED)) { |
| 298 | 304 | ||
| @@ -623,6 +629,8 @@ event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, | |||
| 623 | if (file->flags & FTRACE_EVENT_FL_ENABLED) { | 629 | if (file->flags & FTRACE_EVENT_FL_ENABLED) { |
| 624 | if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED) | 630 | if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED) |
| 625 | buf = "0*\n"; | 631 | buf = "0*\n"; |
| 632 | else if (file->flags & FTRACE_EVENT_FL_SOFT_MODE) | ||
| 633 | buf = "1*\n"; | ||
| 626 | else | 634 | else |
| 627 | buf = "1\n"; | 635 | buf = "1\n"; |
| 628 | } else | 636 | } else |
| @@ -1521,6 +1529,24 @@ __register_event(struct ftrace_event_call *call, struct module *mod) | |||
| 1521 | return 0; | 1529 | return 0; |
| 1522 | } | 1530 | } |
| 1523 | 1531 | ||
| 1532 | static struct ftrace_event_file * | ||
| 1533 | trace_create_new_event(struct ftrace_event_call *call, | ||
| 1534 | struct trace_array *tr) | ||
| 1535 | { | ||
| 1536 | struct ftrace_event_file *file; | ||
| 1537 | |||
| 1538 | file = kmem_cache_alloc(file_cachep, GFP_TRACE); | ||
| 1539 | if (!file) | ||
| 1540 | return NULL; | ||
| 1541 | |||
| 1542 | file->event_call = call; | ||
| 1543 | file->tr = tr; | ||
| 1544 | atomic_set(&file->sm_ref, 0); | ||
| 1545 | list_add(&file->list, &tr->events); | ||
| 1546 | |||
| 1547 | return file; | ||
| 1548 | } | ||
| 1549 | |||
| 1524 | /* Add an event to a trace directory */ | 1550 | /* Add an event to a trace directory */ |
| 1525 | static int | 1551 | static int |
| 1526 | __trace_add_new_event(struct ftrace_event_call *call, | 1552 | __trace_add_new_event(struct ftrace_event_call *call, |
| @@ -1532,14 +1558,10 @@ __trace_add_new_event(struct ftrace_event_call *call, | |||
| 1532 | { | 1558 | { |
| 1533 | struct ftrace_event_file *file; | 1559 | struct ftrace_event_file *file; |
| 1534 | 1560 | ||
| 1535 | file = kmem_cache_alloc(file_cachep, GFP_TRACE); | 1561 | file = trace_create_new_event(call, tr); |
| 1536 | if (!file) | 1562 | if (!file) |
| 1537 | return -ENOMEM; | 1563 | return -ENOMEM; |
| 1538 | 1564 | ||
| 1539 | file->event_call = call; | ||
| 1540 | file->tr = tr; | ||
| 1541 | list_add(&file->list, &tr->events); | ||
| 1542 | |||
| 1543 | return event_create_dir(tr->event_dir, file, id, enable, filter, format); | 1565 | return event_create_dir(tr->event_dir, file, id, enable, filter, format); |
| 1544 | } | 1566 | } |
| 1545 | 1567 | ||
| @@ -1554,14 +1576,10 @@ __trace_early_add_new_event(struct ftrace_event_call *call, | |||
| 1554 | { | 1576 | { |
| 1555 | struct ftrace_event_file *file; | 1577 | struct ftrace_event_file *file; |
| 1556 | 1578 | ||
| 1557 | file = kmem_cache_alloc(file_cachep, GFP_TRACE); | 1579 | file = trace_create_new_event(call, tr); |
| 1558 | if (!file) | 1580 | if (!file) |
| 1559 | return -ENOMEM; | 1581 | return -ENOMEM; |
| 1560 | 1582 | ||
| 1561 | file->event_call = call; | ||
| 1562 | file->tr = tr; | ||
| 1563 | list_add(&file->list, &tr->events); | ||
| 1564 | |||
| 1565 | return 0; | 1583 | return 0; |
| 1566 | } | 1584 | } |
| 1567 | 1585 | ||
| @@ -2061,8 +2079,18 @@ event_enable_func(struct ftrace_hash *hash, | |||
| 2061 | if (ret < 0) | 2079 | if (ret < 0) |
| 2062 | goto out_put; | 2080 | goto out_put; |
| 2063 | ret = register_ftrace_function_probe(glob, ops, data); | 2081 | ret = register_ftrace_function_probe(glob, ops, data); |
| 2064 | if (!ret) | 2082 | /* |
| 2083 | * The above returns on success the # of functions enabled, | ||
| 2084 | * but if it didn't find any functions it returns zero. | ||
| 2085 | * Consider no functions a failure too. | ||
| 2086 | */ | ||
| 2087 | if (!ret) { | ||
| 2088 | ret = -ENOENT; | ||
| 2089 | goto out_disable; | ||
| 2090 | } else if (ret < 0) | ||
| 2065 | goto out_disable; | 2091 | goto out_disable; |
| 2092 | /* Just return zero, not the number of enabled functions */ | ||
| 2093 | ret = 0; | ||
| 2066 | out: | 2094 | out: |
| 2067 | mutex_unlock(&event_mutex); | 2095 | mutex_unlock(&event_mutex); |
| 2068 | return ret; | 2096 | return ret; |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 1865d5f76538..636d45fe69b3 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | /** | 27 | /** |
| 28 | * Kprobe event core functions | 28 | * Kprobe event core functions |
| 29 | */ | 29 | */ |
| 30 | |||
| 31 | struct trace_probe { | 30 | struct trace_probe { |
| 32 | struct list_head list; | 31 | struct list_head list; |
| 33 | struct kretprobe rp; /* Use rp.kp for kprobe use */ | 32 | struct kretprobe rp; /* Use rp.kp for kprobe use */ |
| @@ -36,6 +35,7 @@ struct trace_probe { | |||
| 36 | const char *symbol; /* symbol name */ | 35 | const char *symbol; /* symbol name */ |
| 37 | struct ftrace_event_class class; | 36 | struct ftrace_event_class class; |
| 38 | struct ftrace_event_call call; | 37 | struct ftrace_event_call call; |
| 38 | struct ftrace_event_file **files; | ||
| 39 | ssize_t size; /* trace entry size */ | 39 | ssize_t size; /* trace entry size */ |
| 40 | unsigned int nr_args; | 40 | unsigned int nr_args; |
| 41 | struct probe_arg args[]; | 41 | struct probe_arg args[]; |
| @@ -46,7 +46,7 @@ struct trace_probe { | |||
| 46 | (sizeof(struct probe_arg) * (n))) | 46 | (sizeof(struct probe_arg) * (n))) |
| 47 | 47 | ||
| 48 | 48 | ||
| 49 | static __kprobes int trace_probe_is_return(struct trace_probe *tp) | 49 | static __kprobes bool trace_probe_is_return(struct trace_probe *tp) |
| 50 | { | 50 | { |
| 51 | return tp->rp.handler != NULL; | 51 | return tp->rp.handler != NULL; |
| 52 | } | 52 | } |
| @@ -183,12 +183,57 @@ static struct trace_probe *find_trace_probe(const char *event, | |||
| 183 | return NULL; | 183 | return NULL; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | /* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ | 186 | static int trace_probe_nr_files(struct trace_probe *tp) |
| 187 | static int enable_trace_probe(struct trace_probe *tp, int flag) | 187 | { |
| 188 | struct ftrace_event_file **file = tp->files; | ||
| 189 | int ret = 0; | ||
| 190 | |||
| 191 | if (file) | ||
| 192 | while (*(file++)) | ||
| 193 | ret++; | ||
| 194 | |||
| 195 | return ret; | ||
| 196 | } | ||
| 197 | |||
| 198 | static DEFINE_MUTEX(probe_enable_lock); | ||
| 199 | |||
| 200 | /* | ||
| 201 | * Enable trace_probe | ||
| 202 | * if the file is NULL, enable "perf" handler, or enable "trace" handler. | ||
| 203 | */ | ||
| 204 | static int | ||
| 205 | enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | ||
| 188 | { | 206 | { |
| 189 | int ret = 0; | 207 | int ret = 0; |
| 190 | 208 | ||
| 191 | tp->flags |= flag; | 209 | mutex_lock(&probe_enable_lock); |
| 210 | |||
| 211 | if (file) { | ||
| 212 | struct ftrace_event_file **new, **old = tp->files; | ||
| 213 | int n = trace_probe_nr_files(tp); | ||
| 214 | |||
| 215 | /* 1 is for new one and 1 is for stopper */ | ||
| 216 | new = kzalloc((n + 2) * sizeof(struct ftrace_event_file *), | ||
| 217 | GFP_KERNEL); | ||
| 218 | if (!new) { | ||
| 219 | ret = -ENOMEM; | ||
| 220 | goto out_unlock; | ||
| 221 | } | ||
| 222 | memcpy(new, old, n * sizeof(struct ftrace_event_file *)); | ||
| 223 | new[n] = file; | ||
| 224 | /* The last one keeps a NULL */ | ||
| 225 | |||
| 226 | rcu_assign_pointer(tp->files, new); | ||
| 227 | tp->flags |= TP_FLAG_TRACE; | ||
| 228 | |||
| 229 | if (old) { | ||
| 230 | /* Make sure the probe is done with old files */ | ||
| 231 | synchronize_sched(); | ||
| 232 | kfree(old); | ||
| 233 | } | ||
| 234 | } else | ||
| 235 | tp->flags |= TP_FLAG_PROFILE; | ||
| 236 | |||
| 192 | if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) && | 237 | if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) && |
| 193 | !trace_probe_has_gone(tp)) { | 238 | !trace_probe_has_gone(tp)) { |
| 194 | if (trace_probe_is_return(tp)) | 239 | if (trace_probe_is_return(tp)) |
| @@ -197,19 +242,83 @@ static int enable_trace_probe(struct trace_probe *tp, int flag) | |||
| 197 | ret = enable_kprobe(&tp->rp.kp); | 242 | ret = enable_kprobe(&tp->rp.kp); |
| 198 | } | 243 | } |
| 199 | 244 | ||
| 245 | out_unlock: | ||
| 246 | mutex_unlock(&probe_enable_lock); | ||
| 247 | |||
| 200 | return ret; | 248 | return ret; |
| 201 | } | 249 | } |
| 202 | 250 | ||
| 203 | /* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ | 251 | static int |
| 204 | static void disable_trace_probe(struct trace_probe *tp, int flag) | 252 | trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file) |
| 253 | { | ||
| 254 | int i; | ||
| 255 | |||
| 256 | if (tp->files) { | ||
| 257 | for (i = 0; tp->files[i]; i++) | ||
| 258 | if (tp->files[i] == file) | ||
| 259 | return i; | ||
| 260 | } | ||
| 261 | |||
| 262 | return -1; | ||
| 263 | } | ||
| 264 | |||
| 265 | /* | ||
| 266 | * Disable trace_probe | ||
| 267 | * if the file is NULL, disable "perf" handler, or disable "trace" handler. | ||
| 268 | */ | ||
| 269 | static int | ||
| 270 | disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file) | ||
| 205 | { | 271 | { |
| 206 | tp->flags &= ~flag; | 272 | int ret = 0; |
| 273 | |||
| 274 | mutex_lock(&probe_enable_lock); | ||
| 275 | |||
| 276 | if (file) { | ||
| 277 | struct ftrace_event_file **new, **old = tp->files; | ||
| 278 | int n = trace_probe_nr_files(tp); | ||
| 279 | int i, j; | ||
| 280 | |||
| 281 | if (n == 0 || trace_probe_file_index(tp, file) < 0) { | ||
| 282 | ret = -EINVAL; | ||
| 283 | goto out_unlock; | ||
| 284 | } | ||
| 285 | |||
| 286 | if (n == 1) { /* Remove the last file */ | ||
| 287 | tp->flags &= ~TP_FLAG_TRACE; | ||
| 288 | new = NULL; | ||
| 289 | } else { | ||
| 290 | new = kzalloc(n * sizeof(struct ftrace_event_file *), | ||
| 291 | GFP_KERNEL); | ||
| 292 | if (!new) { | ||
| 293 | ret = -ENOMEM; | ||
| 294 | goto out_unlock; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* This copy & check loop copies the NULL stopper too */ | ||
| 298 | for (i = 0, j = 0; j < n && i < n + 1; i++) | ||
| 299 | if (old[i] != file) | ||
| 300 | new[j++] = old[i]; | ||
| 301 | } | ||
| 302 | |||
| 303 | rcu_assign_pointer(tp->files, new); | ||
| 304 | |||
| 305 | /* Make sure the probe is done with old files */ | ||
| 306 | synchronize_sched(); | ||
| 307 | kfree(old); | ||
| 308 | } else | ||
| 309 | tp->flags &= ~TP_FLAG_PROFILE; | ||
| 310 | |||
| 207 | if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) { | 311 | if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) { |
| 208 | if (trace_probe_is_return(tp)) | 312 | if (trace_probe_is_return(tp)) |
| 209 | disable_kretprobe(&tp->rp); | 313 | disable_kretprobe(&tp->rp); |
| 210 | else | 314 | else |
| 211 | disable_kprobe(&tp->rp.kp); | 315 | disable_kprobe(&tp->rp.kp); |
| 212 | } | 316 | } |
| 317 | |||
| 318 | out_unlock: | ||
| 319 | mutex_unlock(&probe_enable_lock); | ||
| 320 | |||
| 321 | return ret; | ||
| 213 | } | 322 | } |
| 214 | 323 | ||
| 215 | /* Internal register function - just handle k*probes and flags */ | 324 | /* Internal register function - just handle k*probes and flags */ |
| @@ -723,9 +832,10 @@ static __kprobes void store_trace_args(int ent_size, struct trace_probe *tp, | |||
| 723 | } | 832 | } |
| 724 | 833 | ||
| 725 | /* Kprobe handler */ | 834 | /* Kprobe handler */ |
| 726 | static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | 835 | static __kprobes void |
| 836 | __kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs, | ||
| 837 | struct ftrace_event_file *ftrace_file) | ||
| 727 | { | 838 | { |
| 728 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | ||
| 729 | struct kprobe_trace_entry_head *entry; | 839 | struct kprobe_trace_entry_head *entry; |
| 730 | struct ring_buffer_event *event; | 840 | struct ring_buffer_event *event; |
| 731 | struct ring_buffer *buffer; | 841 | struct ring_buffer *buffer; |
| @@ -733,7 +843,10 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
| 733 | unsigned long irq_flags; | 843 | unsigned long irq_flags; |
| 734 | struct ftrace_event_call *call = &tp->call; | 844 | struct ftrace_event_call *call = &tp->call; |
| 735 | 845 | ||
| 736 | tp->nhit++; | 846 | WARN_ON(call != ftrace_file->event_call); |
| 847 | |||
| 848 | if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) | ||
| 849 | return; | ||
| 737 | 850 | ||
| 738 | local_save_flags(irq_flags); | 851 | local_save_flags(irq_flags); |
| 739 | pc = preempt_count(); | 852 | pc = preempt_count(); |
| @@ -741,13 +854,14 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
| 741 | dsize = __get_data_size(tp, regs); | 854 | dsize = __get_data_size(tp, regs); |
| 742 | size = sizeof(*entry) + tp->size + dsize; | 855 | size = sizeof(*entry) + tp->size + dsize; |
| 743 | 856 | ||
| 744 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, | 857 | event = trace_event_buffer_lock_reserve(&buffer, ftrace_file, |
| 745 | size, irq_flags, pc); | 858 | call->event.type, |
| 859 | size, irq_flags, pc); | ||
| 746 | if (!event) | 860 | if (!event) |
| 747 | return; | 861 | return; |
| 748 | 862 | ||
| 749 | entry = ring_buffer_event_data(event); | 863 | entry = ring_buffer_event_data(event); |
| 750 | entry->ip = (unsigned long)kp->addr; | 864 | entry->ip = (unsigned long)tp->rp.kp.addr; |
| 751 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); | 865 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
| 752 | 866 | ||
| 753 | if (!filter_current_check_discard(buffer, call, entry, event)) | 867 | if (!filter_current_check_discard(buffer, call, entry, event)) |
| @@ -755,11 +869,24 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) | |||
| 755 | irq_flags, pc, regs); | 869 | irq_flags, pc, regs); |
| 756 | } | 870 | } |
| 757 | 871 | ||
| 872 | static __kprobes void | ||
| 873 | kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs) | ||
| 874 | { | ||
| 875 | struct ftrace_event_file **file = tp->files; | ||
| 876 | |||
| 877 | /* Note: preempt is already disabled around the kprobe handler */ | ||
| 878 | while (*file) { | ||
| 879 | __kprobe_trace_func(tp, regs, *file); | ||
| 880 | file++; | ||
| 881 | } | ||
| 882 | } | ||
| 883 | |||
| 758 | /* Kretprobe handler */ | 884 | /* Kretprobe handler */ |
| 759 | static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | 885 | static __kprobes void |
| 760 | struct pt_regs *regs) | 886 | __kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, |
| 887 | struct pt_regs *regs, | ||
| 888 | struct ftrace_event_file *ftrace_file) | ||
| 761 | { | 889 | { |
| 762 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | ||
| 763 | struct kretprobe_trace_entry_head *entry; | 890 | struct kretprobe_trace_entry_head *entry; |
| 764 | struct ring_buffer_event *event; | 891 | struct ring_buffer_event *event; |
| 765 | struct ring_buffer *buffer; | 892 | struct ring_buffer *buffer; |
| @@ -767,14 +894,20 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 767 | unsigned long irq_flags; | 894 | unsigned long irq_flags; |
| 768 | struct ftrace_event_call *call = &tp->call; | 895 | struct ftrace_event_call *call = &tp->call; |
| 769 | 896 | ||
| 897 | WARN_ON(call != ftrace_file->event_call); | ||
| 898 | |||
| 899 | if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags)) | ||
| 900 | return; | ||
| 901 | |||
| 770 | local_save_flags(irq_flags); | 902 | local_save_flags(irq_flags); |
| 771 | pc = preempt_count(); | 903 | pc = preempt_count(); |
| 772 | 904 | ||
| 773 | dsize = __get_data_size(tp, regs); | 905 | dsize = __get_data_size(tp, regs); |
| 774 | size = sizeof(*entry) + tp->size + dsize; | 906 | size = sizeof(*entry) + tp->size + dsize; |
| 775 | 907 | ||
| 776 | event = trace_current_buffer_lock_reserve(&buffer, call->event.type, | 908 | event = trace_event_buffer_lock_reserve(&buffer, ftrace_file, |
| 777 | size, irq_flags, pc); | 909 | call->event.type, |
| 910 | size, irq_flags, pc); | ||
| 778 | if (!event) | 911 | if (!event) |
| 779 | return; | 912 | return; |
| 780 | 913 | ||
| @@ -788,6 +921,19 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, | |||
| 788 | irq_flags, pc, regs); | 921 | irq_flags, pc, regs); |
| 789 | } | 922 | } |
| 790 | 923 | ||
| 924 | static __kprobes void | ||
| 925 | kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, | ||
| 926 | struct pt_regs *regs) | ||
| 927 | { | ||
| 928 | struct ftrace_event_file **file = tp->files; | ||
| 929 | |||
| 930 | /* Note: preempt is already disabled around the kprobe handler */ | ||
| 931 | while (*file) { | ||
| 932 | __kretprobe_trace_func(tp, ri, regs, *file); | ||
| 933 | file++; | ||
| 934 | } | ||
| 935 | } | ||
| 936 | |||
| 791 | /* Event entry printers */ | 937 | /* Event entry printers */ |
| 792 | enum print_line_t | 938 | enum print_line_t |
| 793 | print_kprobe_event(struct trace_iterator *iter, int flags, | 939 | print_kprobe_event(struct trace_iterator *iter, int flags, |
| @@ -975,10 +1121,9 @@ static int set_print_fmt(struct trace_probe *tp) | |||
| 975 | #ifdef CONFIG_PERF_EVENTS | 1121 | #ifdef CONFIG_PERF_EVENTS |
| 976 | 1122 | ||
| 977 | /* Kprobe profile handler */ | 1123 | /* Kprobe profile handler */ |
| 978 | static __kprobes void kprobe_perf_func(struct kprobe *kp, | 1124 | static __kprobes void |
| 979 | struct pt_regs *regs) | 1125 | kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs) |
| 980 | { | 1126 | { |
| 981 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | ||
| 982 | struct ftrace_event_call *call = &tp->call; | 1127 | struct ftrace_event_call *call = &tp->call; |
| 983 | struct kprobe_trace_entry_head *entry; | 1128 | struct kprobe_trace_entry_head *entry; |
| 984 | struct hlist_head *head; | 1129 | struct hlist_head *head; |
| @@ -997,7 +1142,7 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
| 997 | if (!entry) | 1142 | if (!entry) |
| 998 | return; | 1143 | return; |
| 999 | 1144 | ||
| 1000 | entry->ip = (unsigned long)kp->addr; | 1145 | entry->ip = (unsigned long)tp->rp.kp.addr; |
| 1001 | memset(&entry[1], 0, dsize); | 1146 | memset(&entry[1], 0, dsize); |
| 1002 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); | 1147 | store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize); |
| 1003 | 1148 | ||
| @@ -1007,10 +1152,10 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
| 1007 | } | 1152 | } |
| 1008 | 1153 | ||
| 1009 | /* Kretprobe profile handler */ | 1154 | /* Kretprobe profile handler */ |
| 1010 | static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | 1155 | static __kprobes void |
| 1011 | struct pt_regs *regs) | 1156 | kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri, |
| 1157 | struct pt_regs *regs) | ||
| 1012 | { | 1158 | { |
| 1013 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | ||
| 1014 | struct ftrace_event_call *call = &tp->call; | 1159 | struct ftrace_event_call *call = &tp->call; |
| 1015 | struct kretprobe_trace_entry_head *entry; | 1160 | struct kretprobe_trace_entry_head *entry; |
| 1016 | struct hlist_head *head; | 1161 | struct hlist_head *head; |
| @@ -1044,20 +1189,19 @@ int kprobe_register(struct ftrace_event_call *event, | |||
| 1044 | enum trace_reg type, void *data) | 1189 | enum trace_reg type, void *data) |
| 1045 | { | 1190 | { |
| 1046 | struct trace_probe *tp = (struct trace_probe *)event->data; | 1191 | struct trace_probe *tp = (struct trace_probe *)event->data; |
| 1192 | struct ftrace_event_file *file = data; | ||
| 1047 | 1193 | ||
| 1048 | switch (type) { | 1194 | switch (type) { |
| 1049 | case TRACE_REG_REGISTER: | 1195 | case TRACE_REG_REGISTER: |
| 1050 | return enable_trace_probe(tp, TP_FLAG_TRACE); | 1196 | return enable_trace_probe(tp, file); |
| 1051 | case TRACE_REG_UNREGISTER: | 1197 | case TRACE_REG_UNREGISTER: |
| 1052 | disable_trace_probe(tp, TP_FLAG_TRACE); | 1198 | return disable_trace_probe(tp, file); |
| 1053 | return 0; | ||
| 1054 | 1199 | ||
| 1055 | #ifdef CONFIG_PERF_EVENTS | 1200 | #ifdef CONFIG_PERF_EVENTS |
| 1056 | case TRACE_REG_PERF_REGISTER: | 1201 | case TRACE_REG_PERF_REGISTER: |
| 1057 | return enable_trace_probe(tp, TP_FLAG_PROFILE); | 1202 | return enable_trace_probe(tp, NULL); |
| 1058 | case TRACE_REG_PERF_UNREGISTER: | 1203 | case TRACE_REG_PERF_UNREGISTER: |
| 1059 | disable_trace_probe(tp, TP_FLAG_PROFILE); | 1204 | return disable_trace_probe(tp, NULL); |
| 1060 | return 0; | ||
| 1061 | case TRACE_REG_PERF_OPEN: | 1205 | case TRACE_REG_PERF_OPEN: |
| 1062 | case TRACE_REG_PERF_CLOSE: | 1206 | case TRACE_REG_PERF_CLOSE: |
| 1063 | case TRACE_REG_PERF_ADD: | 1207 | case TRACE_REG_PERF_ADD: |
| @@ -1073,11 +1217,13 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) | |||
| 1073 | { | 1217 | { |
| 1074 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | 1218 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
| 1075 | 1219 | ||
| 1220 | tp->nhit++; | ||
| 1221 | |||
| 1076 | if (tp->flags & TP_FLAG_TRACE) | 1222 | if (tp->flags & TP_FLAG_TRACE) |
| 1077 | kprobe_trace_func(kp, regs); | 1223 | kprobe_trace_func(tp, regs); |
| 1078 | #ifdef CONFIG_PERF_EVENTS | 1224 | #ifdef CONFIG_PERF_EVENTS |
| 1079 | if (tp->flags & TP_FLAG_PROFILE) | 1225 | if (tp->flags & TP_FLAG_PROFILE) |
| 1080 | kprobe_perf_func(kp, regs); | 1226 | kprobe_perf_func(tp, regs); |
| 1081 | #endif | 1227 | #endif |
| 1082 | return 0; /* We don't tweek kernel, so just return 0 */ | 1228 | return 0; /* We don't tweek kernel, so just return 0 */ |
| 1083 | } | 1229 | } |
| @@ -1087,11 +1233,13 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) | |||
| 1087 | { | 1233 | { |
| 1088 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | 1234 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); |
| 1089 | 1235 | ||
| 1236 | tp->nhit++; | ||
| 1237 | |||
| 1090 | if (tp->flags & TP_FLAG_TRACE) | 1238 | if (tp->flags & TP_FLAG_TRACE) |
| 1091 | kretprobe_trace_func(ri, regs); | 1239 | kretprobe_trace_func(tp, ri, regs); |
| 1092 | #ifdef CONFIG_PERF_EVENTS | 1240 | #ifdef CONFIG_PERF_EVENTS |
| 1093 | if (tp->flags & TP_FLAG_PROFILE) | 1241 | if (tp->flags & TP_FLAG_PROFILE) |
| 1094 | kretprobe_perf_func(ri, regs); | 1242 | kretprobe_perf_func(tp, ri, regs); |
| 1095 | #endif | 1243 | #endif |
| 1096 | return 0; /* We don't tweek kernel, so just return 0 */ | 1244 | return 0; /* We don't tweek kernel, so just return 0 */ |
| 1097 | } | 1245 | } |
| @@ -1189,11 +1337,24 @@ static __used int kprobe_trace_selftest_target(int a1, int a2, int a3, | |||
| 1189 | return a1 + a2 + a3 + a4 + a5 + a6; | 1337 | return a1 + a2 + a3 + a4 + a5 + a6; |
| 1190 | } | 1338 | } |
| 1191 | 1339 | ||
| 1340 | static struct ftrace_event_file * | ||
| 1341 | find_trace_probe_file(struct trace_probe *tp, struct trace_array *tr) | ||
| 1342 | { | ||
| 1343 | struct ftrace_event_file *file; | ||
| 1344 | |||
| 1345 | list_for_each_entry(file, &tr->events, list) | ||
| 1346 | if (file->event_call == &tp->call) | ||
| 1347 | return file; | ||
| 1348 | |||
| 1349 | return NULL; | ||
| 1350 | } | ||
| 1351 | |||
| 1192 | static __init int kprobe_trace_self_tests_init(void) | 1352 | static __init int kprobe_trace_self_tests_init(void) |
| 1193 | { | 1353 | { |
| 1194 | int ret, warn = 0; | 1354 | int ret, warn = 0; |
| 1195 | int (*target)(int, int, int, int, int, int); | 1355 | int (*target)(int, int, int, int, int, int); |
| 1196 | struct trace_probe *tp; | 1356 | struct trace_probe *tp; |
| 1357 | struct ftrace_event_file *file; | ||
| 1197 | 1358 | ||
| 1198 | target = kprobe_trace_selftest_target; | 1359 | target = kprobe_trace_selftest_target; |
| 1199 | 1360 | ||
| @@ -1203,31 +1364,43 @@ static __init int kprobe_trace_self_tests_init(void) | |||
| 1203 | "$stack $stack0 +0($stack)", | 1364 | "$stack $stack0 +0($stack)", |
| 1204 | create_trace_probe); | 1365 | create_trace_probe); |
| 1205 | if (WARN_ON_ONCE(ret)) { | 1366 | if (WARN_ON_ONCE(ret)) { |
| 1206 | pr_warning("error on probing function entry.\n"); | 1367 | pr_warn("error on probing function entry.\n"); |
| 1207 | warn++; | 1368 | warn++; |
| 1208 | } else { | 1369 | } else { |
| 1209 | /* Enable trace point */ | 1370 | /* Enable trace point */ |
| 1210 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); | 1371 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); |
| 1211 | if (WARN_ON_ONCE(tp == NULL)) { | 1372 | if (WARN_ON_ONCE(tp == NULL)) { |
| 1212 | pr_warning("error on getting new probe.\n"); | 1373 | pr_warn("error on getting new probe.\n"); |
| 1213 | warn++; | 1374 | warn++; |
| 1214 | } else | 1375 | } else { |
| 1215 | enable_trace_probe(tp, TP_FLAG_TRACE); | 1376 | file = find_trace_probe_file(tp, top_trace_array()); |
| 1377 | if (WARN_ON_ONCE(file == NULL)) { | ||
| 1378 | pr_warn("error on getting probe file.\n"); | ||
| 1379 | warn++; | ||
| 1380 | } else | ||
| 1381 | enable_trace_probe(tp, file); | ||
| 1382 | } | ||
| 1216 | } | 1383 | } |
| 1217 | 1384 | ||
| 1218 | ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " | 1385 | ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " |
| 1219 | "$retval", create_trace_probe); | 1386 | "$retval", create_trace_probe); |
| 1220 | if (WARN_ON_ONCE(ret)) { | 1387 | if (WARN_ON_ONCE(ret)) { |
| 1221 | pr_warning("error on probing function return.\n"); | 1388 | pr_warn("error on probing function return.\n"); |
| 1222 | warn++; | 1389 | warn++; |
| 1223 | } else { | 1390 | } else { |
| 1224 | /* Enable trace point */ | 1391 | /* Enable trace point */ |
| 1225 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); | 1392 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); |
| 1226 | if (WARN_ON_ONCE(tp == NULL)) { | 1393 | if (WARN_ON_ONCE(tp == NULL)) { |
| 1227 | pr_warning("error on getting new probe.\n"); | 1394 | pr_warn("error on getting 2nd new probe.\n"); |
| 1228 | warn++; | 1395 | warn++; |
| 1229 | } else | 1396 | } else { |
| 1230 | enable_trace_probe(tp, TP_FLAG_TRACE); | 1397 | file = find_trace_probe_file(tp, top_trace_array()); |
| 1398 | if (WARN_ON_ONCE(file == NULL)) { | ||
| 1399 | pr_warn("error on getting probe file.\n"); | ||
| 1400 | warn++; | ||
| 1401 | } else | ||
| 1402 | enable_trace_probe(tp, file); | ||
| 1403 | } | ||
| 1231 | } | 1404 | } |
| 1232 | 1405 | ||
| 1233 | if (warn) | 1406 | if (warn) |
| @@ -1238,27 +1411,39 @@ static __init int kprobe_trace_self_tests_init(void) | |||
| 1238 | /* Disable trace points before removing it */ | 1411 | /* Disable trace points before removing it */ |
| 1239 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); | 1412 | tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); |
| 1240 | if (WARN_ON_ONCE(tp == NULL)) { | 1413 | if (WARN_ON_ONCE(tp == NULL)) { |
| 1241 | pr_warning("error on getting test probe.\n"); | 1414 | pr_warn("error on getting test probe.\n"); |
| 1242 | warn++; | 1415 | warn++; |
| 1243 | } else | 1416 | } else { |
| 1244 | disable_trace_probe(tp, TP_FLAG_TRACE); | 1417 | file = find_trace_probe_file(tp, top_trace_array()); |
| 1418 | if (WARN_ON_ONCE(file == NULL)) { | ||
| 1419 | pr_warn("error on getting probe file.\n"); | ||
| 1420 | warn++; | ||
| 1421 | } else | ||
| 1422 | disable_trace_probe(tp, file); | ||
| 1423 | } | ||
| 1245 | 1424 | ||
| 1246 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); | 1425 | tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); |
| 1247 | if (WARN_ON_ONCE(tp == NULL)) { | 1426 | if (WARN_ON_ONCE(tp == NULL)) { |
| 1248 | pr_warning("error on getting 2nd test probe.\n"); | 1427 | pr_warn("error on getting 2nd test probe.\n"); |
| 1249 | warn++; | 1428 | warn++; |
| 1250 | } else | 1429 | } else { |
| 1251 | disable_trace_probe(tp, TP_FLAG_TRACE); | 1430 | file = find_trace_probe_file(tp, top_trace_array()); |
| 1431 | if (WARN_ON_ONCE(file == NULL)) { | ||
| 1432 | pr_warn("error on getting probe file.\n"); | ||
| 1433 | warn++; | ||
| 1434 | } else | ||
| 1435 | disable_trace_probe(tp, file); | ||
| 1436 | } | ||
| 1252 | 1437 | ||
| 1253 | ret = traceprobe_command("-:testprobe", create_trace_probe); | 1438 | ret = traceprobe_command("-:testprobe", create_trace_probe); |
| 1254 | if (WARN_ON_ONCE(ret)) { | 1439 | if (WARN_ON_ONCE(ret)) { |
| 1255 | pr_warning("error on deleting a probe.\n"); | 1440 | pr_warn("error on deleting a probe.\n"); |
| 1256 | warn++; | 1441 | warn++; |
| 1257 | } | 1442 | } |
| 1258 | 1443 | ||
| 1259 | ret = traceprobe_command("-:testprobe2", create_trace_probe); | 1444 | ret = traceprobe_command("-:testprobe2", create_trace_probe); |
| 1260 | if (WARN_ON_ONCE(ret)) { | 1445 | if (WARN_ON_ONCE(ret)) { |
| 1261 | pr_warning("error on deleting a probe.\n"); | 1446 | pr_warn("error on deleting a probe.\n"); |
| 1262 | warn++; | 1447 | warn++; |
| 1263 | } | 1448 | } |
| 1264 | 1449 | ||
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 8e15d966d9b0..239992021b1d 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
| @@ -837,6 +837,19 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | |||
| 837 | 837 | ||
| 838 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); | 838 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); |
| 839 | if (dat_entry) { | 839 | if (dat_entry) { |
| 840 | /* If the ARP request is destined for a local client the local | ||
| 841 | * client will answer itself. DAT would only generate a | ||
| 842 | * duplicate packet. | ||
| 843 | * | ||
| 844 | * Moreover, if the soft-interface is enslaved into a bridge, an | ||
| 845 | * additional DAT answer may trigger kernel warnings about | ||
| 846 | * a packet coming from the wrong port. | ||
| 847 | */ | ||
| 848 | if (batadv_is_my_client(bat_priv, dat_entry->mac_addr)) { | ||
| 849 | ret = true; | ||
| 850 | goto out; | ||
| 851 | } | ||
| 852 | |||
| 840 | skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, | 853 | skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, |
| 841 | bat_priv->soft_iface, ip_dst, hw_src, | 854 | bat_priv->soft_iface, ip_dst, hw_src, |
| 842 | dat_entry->mac_addr, hw_src); | 855 | dat_entry->mac_addr, hw_src); |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 3e30a0f1b908..1240f07ad31d 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
| @@ -163,14 +163,22 @@ void batadv_mesh_free(struct net_device *soft_iface) | |||
| 163 | batadv_vis_quit(bat_priv); | 163 | batadv_vis_quit(bat_priv); |
| 164 | 164 | ||
| 165 | batadv_gw_node_purge(bat_priv); | 165 | batadv_gw_node_purge(bat_priv); |
| 166 | batadv_originator_free(bat_priv); | ||
| 167 | batadv_nc_free(bat_priv); | 166 | batadv_nc_free(bat_priv); |
| 167 | batadv_dat_free(bat_priv); | ||
| 168 | batadv_bla_free(bat_priv); | ||
| 168 | 169 | ||
| 170 | /* Free the TT and the originator tables only after having terminated | ||
| 171 | * all the other depending components which may use these structures for | ||
| 172 | * their purposes. | ||
| 173 | */ | ||
| 169 | batadv_tt_free(bat_priv); | 174 | batadv_tt_free(bat_priv); |
| 170 | 175 | ||
| 171 | batadv_bla_free(bat_priv); | 176 | /* Since the originator table clean up routine is accessing the TT |
| 172 | 177 | * tables as well, it has to be invoked after the TT tables have been | |
| 173 | batadv_dat_free(bat_priv); | 178 | * freed and marked as empty. This ensures that no cleanup RCU callbacks |
| 179 | * accessing the TT data are scheduled for later execution. | ||
| 180 | */ | ||
| 181 | batadv_originator_free(bat_priv); | ||
| 174 | 182 | ||
| 175 | free_percpu(bat_priv->bat_counters); | 183 | free_percpu(bat_priv->bat_counters); |
| 176 | 184 | ||
| @@ -475,7 +483,7 @@ static int batadv_param_set_ra(const char *val, const struct kernel_param *kp) | |||
| 475 | char *algo_name = (char *)val; | 483 | char *algo_name = (char *)val; |
| 476 | size_t name_len = strlen(algo_name); | 484 | size_t name_len = strlen(algo_name); |
| 477 | 485 | ||
| 478 | if (algo_name[name_len - 1] == '\n') | 486 | if (name_len > 0 && algo_name[name_len - 1] == '\n') |
| 479 | algo_name[name_len - 1] = '\0'; | 487 | algo_name[name_len - 1] = '\0'; |
| 480 | 488 | ||
| 481 | bat_algo_ops = batadv_algo_get(algo_name); | 489 | bat_algo_ops = batadv_algo_get(algo_name); |
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index f7c54305a918..e84629ece9b7 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c | |||
| @@ -1514,6 +1514,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
| 1514 | struct ethhdr *ethhdr, ethhdr_tmp; | 1514 | struct ethhdr *ethhdr, ethhdr_tmp; |
| 1515 | uint8_t *orig_dest, ttl, ttvn; | 1515 | uint8_t *orig_dest, ttl, ttvn; |
| 1516 | unsigned int coding_len; | 1516 | unsigned int coding_len; |
| 1517 | int err; | ||
| 1517 | 1518 | ||
| 1518 | /* Save headers temporarily */ | 1519 | /* Save headers temporarily */ |
| 1519 | memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp)); | 1520 | memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp)); |
| @@ -1568,8 +1569,11 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
| 1568 | coding_len); | 1569 | coding_len); |
| 1569 | 1570 | ||
| 1570 | /* Resize decoded skb if decoded with larger packet */ | 1571 | /* Resize decoded skb if decoded with larger packet */ |
| 1571 | if (nc_packet->skb->len > coding_len + h_size) | 1572 | if (nc_packet->skb->len > coding_len + h_size) { |
| 1572 | pskb_trim_rcsum(skb, coding_len + h_size); | 1573 | err = pskb_trim_rcsum(skb, coding_len + h_size); |
| 1574 | if (err) | ||
| 1575 | return NULL; | ||
| 1576 | } | ||
| 1573 | 1577 | ||
| 1574 | /* Create decoded unicast packet */ | 1578 | /* Create decoded unicast packet */ |
| 1575 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 1579 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
diff --git a/net/core/sock.c b/net/core/sock.c index d4f4cea726e7..6ba327da79e1 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -1217,18 +1217,6 @@ static void sock_copy(struct sock *nsk, const struct sock *osk) | |||
| 1217 | #endif | 1217 | #endif |
| 1218 | } | 1218 | } |
| 1219 | 1219 | ||
| 1220 | /* | ||
| 1221 | * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes | ||
| 1222 | * un-modified. Special care is taken when initializing object to zero. | ||
| 1223 | */ | ||
| 1224 | static inline void sk_prot_clear_nulls(struct sock *sk, int size) | ||
| 1225 | { | ||
| 1226 | if (offsetof(struct sock, sk_node.next) != 0) | ||
| 1227 | memset(sk, 0, offsetof(struct sock, sk_node.next)); | ||
| 1228 | memset(&sk->sk_node.pprev, 0, | ||
| 1229 | size - offsetof(struct sock, sk_node.pprev)); | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | void sk_prot_clear_portaddr_nulls(struct sock *sk, int size) | 1220 | void sk_prot_clear_portaddr_nulls(struct sock *sk, int size) |
| 1233 | { | 1221 | { |
| 1234 | unsigned long nulls1, nulls2; | 1222 | unsigned long nulls1, nulls2; |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 147abf5275aa..4bcabf3ab4ca 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -84,7 +84,7 @@ int sysctl_ip_default_ttl __read_mostly = IPDEFTTL; | |||
| 84 | EXPORT_SYMBOL(sysctl_ip_default_ttl); | 84 | EXPORT_SYMBOL(sysctl_ip_default_ttl); |
| 85 | 85 | ||
| 86 | /* Generate a checksum for an outgoing IP datagram. */ | 86 | /* Generate a checksum for an outgoing IP datagram. */ |
| 87 | __inline__ void ip_send_check(struct iphdr *iph) | 87 | void ip_send_check(struct iphdr *iph) |
| 88 | { | 88 | { |
| 89 | iph->check = 0; | 89 | iph->check = 0; |
| 90 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); | 90 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index d3ddd8400354..ecd60733e5e2 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
| @@ -1081,6 +1081,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev, | |||
| 1081 | } | 1081 | } |
| 1082 | if (t == NULL) | 1082 | if (t == NULL) |
| 1083 | t = netdev_priv(dev); | 1083 | t = netdev_priv(dev); |
| 1084 | memset(&p, 0, sizeof(p)); | ||
| 1084 | ip6gre_tnl_parm_to_user(&p, &t->parms); | 1085 | ip6gre_tnl_parm_to_user(&p, &t->parms); |
| 1085 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) | 1086 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) |
| 1086 | err = -EFAULT; | 1087 | err = -EFAULT; |
| @@ -1128,6 +1129,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev, | |||
| 1128 | if (t) { | 1129 | if (t) { |
| 1129 | err = 0; | 1130 | err = 0; |
| 1130 | 1131 | ||
| 1132 | memset(&p, 0, sizeof(p)); | ||
| 1131 | ip6gre_tnl_parm_to_user(&p, &t->parms); | 1133 | ip6gre_tnl_parm_to_user(&p, &t->parms); |
| 1132 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) | 1134 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) |
| 1133 | err = -EFAULT; | 1135 | err = -EFAULT; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 71167069b394..0a17ed9eaf39 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -1890,6 +1890,17 @@ void tcp6_proc_exit(struct net *net) | |||
| 1890 | } | 1890 | } |
| 1891 | #endif | 1891 | #endif |
| 1892 | 1892 | ||
| 1893 | static void tcp_v6_clear_sk(struct sock *sk, int size) | ||
| 1894 | { | ||
| 1895 | struct inet_sock *inet = inet_sk(sk); | ||
| 1896 | |||
| 1897 | /* we do not want to clear pinet6 field, because of RCU lookups */ | ||
| 1898 | sk_prot_clear_nulls(sk, offsetof(struct inet_sock, pinet6)); | ||
| 1899 | |||
| 1900 | size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6); | ||
| 1901 | memset(&inet->pinet6 + 1, 0, size); | ||
| 1902 | } | ||
| 1903 | |||
| 1893 | struct proto tcpv6_prot = { | 1904 | struct proto tcpv6_prot = { |
| 1894 | .name = "TCPv6", | 1905 | .name = "TCPv6", |
| 1895 | .owner = THIS_MODULE, | 1906 | .owner = THIS_MODULE, |
| @@ -1933,6 +1944,7 @@ struct proto tcpv6_prot = { | |||
| 1933 | #ifdef CONFIG_MEMCG_KMEM | 1944 | #ifdef CONFIG_MEMCG_KMEM |
| 1934 | .proto_cgroup = tcp_proto_cgroup, | 1945 | .proto_cgroup = tcp_proto_cgroup, |
| 1935 | #endif | 1946 | #endif |
| 1947 | .clear_sk = tcp_v6_clear_sk, | ||
| 1936 | }; | 1948 | }; |
| 1937 | 1949 | ||
| 1938 | static const struct inet6_protocol tcpv6_protocol = { | 1950 | static const struct inet6_protocol tcpv6_protocol = { |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d4defdd44937..42923b14dfa6 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -1432,6 +1432,17 @@ void udp6_proc_exit(struct net *net) { | |||
| 1432 | } | 1432 | } |
| 1433 | #endif /* CONFIG_PROC_FS */ | 1433 | #endif /* CONFIG_PROC_FS */ |
| 1434 | 1434 | ||
| 1435 | void udp_v6_clear_sk(struct sock *sk, int size) | ||
| 1436 | { | ||
| 1437 | struct inet_sock *inet = inet_sk(sk); | ||
| 1438 | |||
| 1439 | /* we do not want to clear pinet6 field, because of RCU lookups */ | ||
| 1440 | sk_prot_clear_portaddr_nulls(sk, offsetof(struct inet_sock, pinet6)); | ||
| 1441 | |||
| 1442 | size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6); | ||
| 1443 | memset(&inet->pinet6 + 1, 0, size); | ||
| 1444 | } | ||
| 1445 | |||
| 1435 | /* ------------------------------------------------------------------------ */ | 1446 | /* ------------------------------------------------------------------------ */ |
| 1436 | 1447 | ||
| 1437 | struct proto udpv6_prot = { | 1448 | struct proto udpv6_prot = { |
| @@ -1462,7 +1473,7 @@ struct proto udpv6_prot = { | |||
| 1462 | .compat_setsockopt = compat_udpv6_setsockopt, | 1473 | .compat_setsockopt = compat_udpv6_setsockopt, |
| 1463 | .compat_getsockopt = compat_udpv6_getsockopt, | 1474 | .compat_getsockopt = compat_udpv6_getsockopt, |
| 1464 | #endif | 1475 | #endif |
| 1465 | .clear_sk = sk_prot_clear_portaddr_nulls, | 1476 | .clear_sk = udp_v6_clear_sk, |
| 1466 | }; | 1477 | }; |
| 1467 | 1478 | ||
| 1468 | static struct inet_protosw udpv6_protosw = { | 1479 | static struct inet_protosw udpv6_protosw = { |
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h index d7571046bfc4..4691ed50a928 100644 --- a/net/ipv6/udp_impl.h +++ b/net/ipv6/udp_impl.h | |||
| @@ -31,6 +31,8 @@ extern int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
| 31 | extern int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb); | 31 | extern int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb); |
| 32 | extern void udpv6_destroy_sock(struct sock *sk); | 32 | extern void udpv6_destroy_sock(struct sock *sk); |
| 33 | 33 | ||
| 34 | extern void udp_v6_clear_sk(struct sock *sk, int size); | ||
| 35 | |||
| 34 | #ifdef CONFIG_PROC_FS | 36 | #ifdef CONFIG_PROC_FS |
| 35 | extern int udp6_seq_show(struct seq_file *seq, void *v); | 37 | extern int udp6_seq_show(struct seq_file *seq, void *v); |
| 36 | #endif | 38 | #endif |
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 1d08e21d9f69..dfcc4be46898 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
| @@ -56,7 +56,7 @@ struct proto udplitev6_prot = { | |||
| 56 | .compat_setsockopt = compat_udpv6_setsockopt, | 56 | .compat_setsockopt = compat_udpv6_setsockopt, |
| 57 | .compat_getsockopt = compat_udpv6_getsockopt, | 57 | .compat_getsockopt = compat_udpv6_getsockopt, |
| 58 | #endif | 58 | #endif |
| 59 | .clear_sk = sk_prot_clear_portaddr_nulls, | 59 | .clear_sk = udp_v6_clear_sk, |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
| 62 | static struct inet_protosw udplite6_protosw = { | 62 | static struct inet_protosw udplite6_protosw = { |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 4ef7bdb65440..23ed03d786c8 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
| @@ -103,8 +103,10 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
| 103 | dev_hold(dev); | 103 | dev_hold(dev); |
| 104 | 104 | ||
| 105 | xdst->u.rt6.rt6i_idev = in6_dev_get(dev); | 105 | xdst->u.rt6.rt6i_idev = in6_dev_get(dev); |
| 106 | if (!xdst->u.rt6.rt6i_idev) | 106 | if (!xdst->u.rt6.rt6i_idev) { |
| 107 | dev_put(dev); | ||
| 107 | return -ENODEV; | 108 | return -ENODEV; |
| 109 | } | ||
| 108 | 110 | ||
| 109 | rt6_transfer_peer(&xdst->u.rt6, rt); | 111 | rt6_transfer_peer(&xdst->u.rt6, rt); |
| 110 | 112 | ||
diff --git a/net/socket.c b/net/socket.c index b416093997da..6b94633ca61d 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -2412,7 +2412,7 @@ static const unsigned char nargs[21] = { | |||
| 2412 | 2412 | ||
| 2413 | SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) | 2413 | SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) |
| 2414 | { | 2414 | { |
| 2415 | unsigned long a[6]; | 2415 | unsigned long a[AUDITSC_ARGS]; |
| 2416 | unsigned long a0, a1; | 2416 | unsigned long a0, a1; |
| 2417 | int err; | 2417 | int err; |
| 2418 | unsigned int len; | 2418 | unsigned int len; |
| @@ -2428,7 +2428,9 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) | |||
| 2428 | if (copy_from_user(a, args, len)) | 2428 | if (copy_from_user(a, args, len)) |
| 2429 | return -EFAULT; | 2429 | return -EFAULT; |
| 2430 | 2430 | ||
| 2431 | audit_socketcall(nargs[call] / sizeof(unsigned long), a); | 2431 | err = audit_socketcall(nargs[call] / sizeof(unsigned long), a); |
| 2432 | if (err) | ||
| 2433 | return err; | ||
| 2432 | 2434 | ||
| 2433 | a0 = a[0]; | 2435 | a0 = a[0]; |
| 2434 | a1 = a[1]; | 2436 | a1 = a[1]; |
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 321e066a0753..9e9d34871195 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c | |||
| @@ -46,6 +46,7 @@ unsigned int skip_c0; | |||
| 46 | unsigned int skip_c1; | 46 | unsigned int skip_c1; |
| 47 | unsigned int do_nhm_cstates; | 47 | unsigned int do_nhm_cstates; |
| 48 | unsigned int do_snb_cstates; | 48 | unsigned int do_snb_cstates; |
| 49 | unsigned int do_c8_c9_c10; | ||
| 49 | unsigned int has_aperf; | 50 | unsigned int has_aperf; |
| 50 | unsigned int has_epb; | 51 | unsigned int has_epb; |
| 51 | unsigned int units = 1000000000; /* Ghz etc */ | 52 | unsigned int units = 1000000000; /* Ghz etc */ |
| @@ -120,6 +121,9 @@ struct pkg_data { | |||
| 120 | unsigned long long pc3; | 121 | unsigned long long pc3; |
| 121 | unsigned long long pc6; | 122 | unsigned long long pc6; |
| 122 | unsigned long long pc7; | 123 | unsigned long long pc7; |
| 124 | unsigned long long pc8; | ||
| 125 | unsigned long long pc9; | ||
| 126 | unsigned long long pc10; | ||
| 123 | unsigned int package_id; | 127 | unsigned int package_id; |
| 124 | unsigned int energy_pkg; /* MSR_PKG_ENERGY_STATUS */ | 128 | unsigned int energy_pkg; /* MSR_PKG_ENERGY_STATUS */ |
| 125 | unsigned int energy_dram; /* MSR_DRAM_ENERGY_STATUS */ | 129 | unsigned int energy_dram; /* MSR_DRAM_ENERGY_STATUS */ |
| @@ -282,6 +286,11 @@ void print_header(void) | |||
| 282 | outp += sprintf(outp, " %%pc6"); | 286 | outp += sprintf(outp, " %%pc6"); |
| 283 | if (do_snb_cstates) | 287 | if (do_snb_cstates) |
| 284 | outp += sprintf(outp, " %%pc7"); | 288 | outp += sprintf(outp, " %%pc7"); |
| 289 | if (do_c8_c9_c10) { | ||
| 290 | outp += sprintf(outp, " %%pc8"); | ||
| 291 | outp += sprintf(outp, " %%pc9"); | ||
| 292 | outp += sprintf(outp, " %%pc10"); | ||
| 293 | } | ||
| 285 | 294 | ||
| 286 | if (do_rapl & RAPL_PKG) | 295 | if (do_rapl & RAPL_PKG) |
| 287 | outp += sprintf(outp, " Pkg_W"); | 296 | outp += sprintf(outp, " Pkg_W"); |
| @@ -336,6 +345,9 @@ int dump_counters(struct thread_data *t, struct core_data *c, | |||
| 336 | fprintf(stderr, "pc3: %016llX\n", p->pc3); | 345 | fprintf(stderr, "pc3: %016llX\n", p->pc3); |
| 337 | fprintf(stderr, "pc6: %016llX\n", p->pc6); | 346 | fprintf(stderr, "pc6: %016llX\n", p->pc6); |
| 338 | fprintf(stderr, "pc7: %016llX\n", p->pc7); | 347 | fprintf(stderr, "pc7: %016llX\n", p->pc7); |
| 348 | fprintf(stderr, "pc8: %016llX\n", p->pc8); | ||
| 349 | fprintf(stderr, "pc9: %016llX\n", p->pc9); | ||
| 350 | fprintf(stderr, "pc10: %016llX\n", p->pc10); | ||
| 339 | fprintf(stderr, "Joules PKG: %0X\n", p->energy_pkg); | 351 | fprintf(stderr, "Joules PKG: %0X\n", p->energy_pkg); |
| 340 | fprintf(stderr, "Joules COR: %0X\n", p->energy_cores); | 352 | fprintf(stderr, "Joules COR: %0X\n", p->energy_cores); |
| 341 | fprintf(stderr, "Joules GFX: %0X\n", p->energy_gfx); | 353 | fprintf(stderr, "Joules GFX: %0X\n", p->energy_gfx); |
| @@ -493,6 +505,11 @@ int format_counters(struct thread_data *t, struct core_data *c, | |||
| 493 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc); | 505 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc6/t->tsc); |
| 494 | if (do_snb_cstates) | 506 | if (do_snb_cstates) |
| 495 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); | 507 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc7/t->tsc); |
| 508 | if (do_c8_c9_c10) { | ||
| 509 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc8/t->tsc); | ||
| 510 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc9/t->tsc); | ||
| 511 | outp += sprintf(outp, " %6.2f", 100.0 * p->pc10/t->tsc); | ||
| 512 | } | ||
| 496 | 513 | ||
| 497 | /* | 514 | /* |
| 498 | * If measurement interval exceeds minimum RAPL Joule Counter range, | 515 | * If measurement interval exceeds minimum RAPL Joule Counter range, |
| @@ -569,6 +586,9 @@ delta_package(struct pkg_data *new, struct pkg_data *old) | |||
| 569 | old->pc3 = new->pc3 - old->pc3; | 586 | old->pc3 = new->pc3 - old->pc3; |
| 570 | old->pc6 = new->pc6 - old->pc6; | 587 | old->pc6 = new->pc6 - old->pc6; |
| 571 | old->pc7 = new->pc7 - old->pc7; | 588 | old->pc7 = new->pc7 - old->pc7; |
| 589 | old->pc8 = new->pc8 - old->pc8; | ||
| 590 | old->pc9 = new->pc9 - old->pc9; | ||
| 591 | old->pc10 = new->pc10 - old->pc10; | ||
| 572 | old->pkg_temp_c = new->pkg_temp_c; | 592 | old->pkg_temp_c = new->pkg_temp_c; |
| 573 | 593 | ||
| 574 | DELTA_WRAP32(new->energy_pkg, old->energy_pkg); | 594 | DELTA_WRAP32(new->energy_pkg, old->energy_pkg); |
| @@ -702,6 +722,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data | |||
| 702 | p->pc3 = 0; | 722 | p->pc3 = 0; |
| 703 | p->pc6 = 0; | 723 | p->pc6 = 0; |
| 704 | p->pc7 = 0; | 724 | p->pc7 = 0; |
| 725 | p->pc8 = 0; | ||
| 726 | p->pc9 = 0; | ||
| 727 | p->pc10 = 0; | ||
| 705 | 728 | ||
| 706 | p->energy_pkg = 0; | 729 | p->energy_pkg = 0; |
| 707 | p->energy_dram = 0; | 730 | p->energy_dram = 0; |
| @@ -740,6 +763,9 @@ int sum_counters(struct thread_data *t, struct core_data *c, | |||
| 740 | average.packages.pc3 += p->pc3; | 763 | average.packages.pc3 += p->pc3; |
| 741 | average.packages.pc6 += p->pc6; | 764 | average.packages.pc6 += p->pc6; |
| 742 | average.packages.pc7 += p->pc7; | 765 | average.packages.pc7 += p->pc7; |
| 766 | average.packages.pc8 += p->pc8; | ||
| 767 | average.packages.pc9 += p->pc9; | ||
| 768 | average.packages.pc10 += p->pc10; | ||
| 743 | 769 | ||
| 744 | average.packages.energy_pkg += p->energy_pkg; | 770 | average.packages.energy_pkg += p->energy_pkg; |
| 745 | average.packages.energy_dram += p->energy_dram; | 771 | average.packages.energy_dram += p->energy_dram; |
| @@ -781,6 +807,10 @@ void compute_average(struct thread_data *t, struct core_data *c, | |||
| 781 | average.packages.pc3 /= topo.num_packages; | 807 | average.packages.pc3 /= topo.num_packages; |
| 782 | average.packages.pc6 /= topo.num_packages; | 808 | average.packages.pc6 /= topo.num_packages; |
| 783 | average.packages.pc7 /= topo.num_packages; | 809 | average.packages.pc7 /= topo.num_packages; |
| 810 | |||
| 811 | average.packages.pc8 /= topo.num_packages; | ||
| 812 | average.packages.pc9 /= topo.num_packages; | ||
| 813 | average.packages.pc10 /= topo.num_packages; | ||
| 784 | } | 814 | } |
| 785 | 815 | ||
| 786 | static unsigned long long rdtsc(void) | 816 | static unsigned long long rdtsc(void) |
| @@ -880,6 +910,14 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) | |||
| 880 | if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7)) | 910 | if (get_msr(cpu, MSR_PKG_C7_RESIDENCY, &p->pc7)) |
| 881 | return -12; | 911 | return -12; |
| 882 | } | 912 | } |
| 913 | if (do_c8_c9_c10) { | ||
| 914 | if (get_msr(cpu, MSR_PKG_C8_RESIDENCY, &p->pc8)) | ||
| 915 | return -13; | ||
| 916 | if (get_msr(cpu, MSR_PKG_C9_RESIDENCY, &p->pc9)) | ||
| 917 | return -13; | ||
| 918 | if (get_msr(cpu, MSR_PKG_C10_RESIDENCY, &p->pc10)) | ||
| 919 | return -13; | ||
| 920 | } | ||
| 883 | if (do_rapl & RAPL_PKG) { | 921 | if (do_rapl & RAPL_PKG) { |
| 884 | if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr)) | 922 | if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr)) |
| 885 | return -13; | 923 | return -13; |
| @@ -1762,6 +1800,19 @@ int is_snb(unsigned int family, unsigned int model) | |||
| 1762 | return 0; | 1800 | return 0; |
| 1763 | } | 1801 | } |
| 1764 | 1802 | ||
| 1803 | int has_c8_c9_c10(unsigned int family, unsigned int model) | ||
| 1804 | { | ||
| 1805 | if (!genuine_intel) | ||
| 1806 | return 0; | ||
| 1807 | |||
| 1808 | switch (model) { | ||
| 1809 | case 0x45: | ||
| 1810 | return 1; | ||
| 1811 | } | ||
| 1812 | return 0; | ||
| 1813 | } | ||
| 1814 | |||
| 1815 | |||
| 1765 | double discover_bclk(unsigned int family, unsigned int model) | 1816 | double discover_bclk(unsigned int family, unsigned int model) |
| 1766 | { | 1817 | { |
| 1767 | if (is_snb(family, model)) | 1818 | if (is_snb(family, model)) |
| @@ -1918,6 +1969,7 @@ void check_cpuid() | |||
| 1918 | do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */ | 1969 | do_nhm_cstates = genuine_intel; /* all Intel w/ non-stop TSC have NHM counters */ |
| 1919 | do_smi = do_nhm_cstates; | 1970 | do_smi = do_nhm_cstates; |
| 1920 | do_snb_cstates = is_snb(family, model); | 1971 | do_snb_cstates = is_snb(family, model); |
| 1972 | do_c8_c9_c10 = has_c8_c9_c10(family, model); | ||
| 1921 | bclk = discover_bclk(family, model); | 1973 | bclk = discover_bclk(family, model); |
| 1922 | 1974 | ||
| 1923 | do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); | 1975 | do_nehalem_turbo_ratio_limit = has_nehalem_turbo_ratio_limit(family, model); |
| @@ -2279,7 +2331,7 @@ int main(int argc, char **argv) | |||
| 2279 | cmdline(argc, argv); | 2331 | cmdline(argc, argv); |
| 2280 | 2332 | ||
| 2281 | if (verbose) | 2333 | if (verbose) |
| 2282 | fprintf(stderr, "turbostat v3.3 March 15, 2013" | 2334 | fprintf(stderr, "turbostat v3.4 April 17, 2013" |
| 2283 | " - Len Brown <lenb@kernel.org>\n"); | 2335 | " - Len Brown <lenb@kernel.org>\n"); |
| 2284 | 2336 | ||
| 2285 | turbostat_init(); | 2337 | turbostat_init(); |
