diff options
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 116 |
1 files changed, 80 insertions, 36 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 52568588039f..df9a12c8b373 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -1096,6 +1096,7 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res, | |||
1096 | res->bus = cfgtew->u.cfgte->res_addr.bus; | 1096 | res->bus = cfgtew->u.cfgte->res_addr.bus; |
1097 | res->target = cfgtew->u.cfgte->res_addr.target; | 1097 | res->target = cfgtew->u.cfgte->res_addr.target; |
1098 | res->lun = cfgtew->u.cfgte->res_addr.lun; | 1098 | res->lun = cfgtew->u.cfgte->res_addr.lun; |
1099 | res->lun_wwn = get_unaligned_be64(cfgtew->u.cfgte->lun_wwn); | ||
1099 | } | 1100 | } |
1100 | 1101 | ||
1101 | ipr_update_ata_class(res, proto); | 1102 | ipr_update_ata_class(res, proto); |
@@ -1142,7 +1143,7 @@ static char *ipr_format_res_path(u8 *res_path, char *buffer, int len) | |||
1142 | int i; | 1143 | int i; |
1143 | char *p = buffer; | 1144 | char *p = buffer; |
1144 | 1145 | ||
1145 | res_path[0] = '\0'; | 1146 | *p = '\0'; |
1146 | p += snprintf(p, buffer + len - p, "%02X", res_path[0]); | 1147 | p += snprintf(p, buffer + len - p, "%02X", res_path[0]); |
1147 | for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++) | 1148 | for (i = 1; res_path[i] != 0xff && ((i * 3) < len); i++) |
1148 | p += snprintf(p, buffer + len - p, "-%02X", res_path[i]); | 1149 | p += snprintf(p, buffer + len - p, "-%02X", res_path[i]); |
@@ -1670,7 +1671,7 @@ static void ipr_log_enhanced_array_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1670 | 1671 | ||
1671 | array_entry = error->array_member; | 1672 | array_entry = error->array_member; |
1672 | num_entries = min_t(u32, be32_to_cpu(error->num_entries), | 1673 | num_entries = min_t(u32, be32_to_cpu(error->num_entries), |
1673 | sizeof(error->array_member)); | 1674 | ARRAY_SIZE(error->array_member)); |
1674 | 1675 | ||
1675 | for (i = 0; i < num_entries; i++, array_entry++) { | 1676 | for (i = 0; i < num_entries; i++, array_entry++) { |
1676 | if (!memcmp(array_entry->vpd.vpd.sn, zero_sn, IPR_SERIAL_NUM_LEN)) | 1677 | if (!memcmp(array_entry->vpd.vpd.sn, zero_sn, IPR_SERIAL_NUM_LEN)) |
@@ -2151,8 +2152,8 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg, | |||
2151 | ipr_err_separator; | 2152 | ipr_err_separator; |
2152 | 2153 | ||
2153 | array_entry = error->array_member; | 2154 | array_entry = error->array_member; |
2154 | num_entries = min_t(u32, be32_to_cpu(error->num_entries), | 2155 | num_entries = min_t(u32, error->num_entries, |
2155 | sizeof(error->array_member)); | 2156 | ARRAY_SIZE(error->array_member)); |
2156 | 2157 | ||
2157 | for (i = 0; i < num_entries; i++, array_entry++) { | 2158 | for (i = 0; i < num_entries; i++, array_entry++) { |
2158 | 2159 | ||
@@ -2166,10 +2167,10 @@ static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg, | |||
2166 | 2167 | ||
2167 | ipr_err("Array Member %d:\n", i); | 2168 | ipr_err("Array Member %d:\n", i); |
2168 | ipr_log_ext_vpd(&array_entry->vpd); | 2169 | ipr_log_ext_vpd(&array_entry->vpd); |
2169 | ipr_err("Current Location: %s", | 2170 | ipr_err("Current Location: %s\n", |
2170 | ipr_format_res_path(array_entry->res_path, buffer, | 2171 | ipr_format_res_path(array_entry->res_path, buffer, |
2171 | sizeof(buffer))); | 2172 | sizeof(buffer))); |
2172 | ipr_err("Expected Location: %s", | 2173 | ipr_err("Expected Location: %s\n", |
2173 | ipr_format_res_path(array_entry->expected_res_path, | 2174 | ipr_format_res_path(array_entry->expected_res_path, |
2174 | buffer, sizeof(buffer))); | 2175 | buffer, sizeof(buffer))); |
2175 | 2176 | ||
@@ -4089,6 +4090,7 @@ static int ipr_change_queue_type(struct scsi_device *sdev, int tag_type) | |||
4089 | /** | 4090 | /** |
4090 | * ipr_show_adapter_handle - Show the adapter's resource handle for this device | 4091 | * ipr_show_adapter_handle - Show the adapter's resource handle for this device |
4091 | * @dev: device struct | 4092 | * @dev: device struct |
4093 | * @attr: device attribute structure | ||
4092 | * @buf: buffer | 4094 | * @buf: buffer |
4093 | * | 4095 | * |
4094 | * Return value: | 4096 | * Return value: |
@@ -4122,6 +4124,7 @@ static struct device_attribute ipr_adapter_handle_attr = { | |||
4122 | * ipr_show_resource_path - Show the resource path or the resource address for | 4124 | * ipr_show_resource_path - Show the resource path or the resource address for |
4123 | * this device. | 4125 | * this device. |
4124 | * @dev: device struct | 4126 | * @dev: device struct |
4127 | * @attr: device attribute structure | ||
4125 | * @buf: buffer | 4128 | * @buf: buffer |
4126 | * | 4129 | * |
4127 | * Return value: | 4130 | * Return value: |
@@ -4159,8 +4162,45 @@ static struct device_attribute ipr_resource_path_attr = { | |||
4159 | }; | 4162 | }; |
4160 | 4163 | ||
4161 | /** | 4164 | /** |
4165 | * ipr_show_device_id - Show the device_id for this device. | ||
4166 | * @dev: device struct | ||
4167 | * @attr: device attribute structure | ||
4168 | * @buf: buffer | ||
4169 | * | ||
4170 | * Return value: | ||
4171 | * number of bytes printed to buffer | ||
4172 | **/ | ||
4173 | static ssize_t ipr_show_device_id(struct device *dev, struct device_attribute *attr, char *buf) | ||
4174 | { | ||
4175 | struct scsi_device *sdev = to_scsi_device(dev); | ||
4176 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata; | ||
4177 | struct ipr_resource_entry *res; | ||
4178 | unsigned long lock_flags = 0; | ||
4179 | ssize_t len = -ENXIO; | ||
4180 | |||
4181 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
4182 | res = (struct ipr_resource_entry *)sdev->hostdata; | ||
4183 | if (res && ioa_cfg->sis64) | ||
4184 | len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->dev_id); | ||
4185 | else if (res) | ||
4186 | len = snprintf(buf, PAGE_SIZE, "0x%llx\n", res->lun_wwn); | ||
4187 | |||
4188 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
4189 | return len; | ||
4190 | } | ||
4191 | |||
4192 | static struct device_attribute ipr_device_id_attr = { | ||
4193 | .attr = { | ||
4194 | .name = "device_id", | ||
4195 | .mode = S_IRUGO, | ||
4196 | }, | ||
4197 | .show = ipr_show_device_id | ||
4198 | }; | ||
4199 | |||
4200 | /** | ||
4162 | * ipr_show_resource_type - Show the resource type for this device. | 4201 | * ipr_show_resource_type - Show the resource type for this device. |
4163 | * @dev: device struct | 4202 | * @dev: device struct |
4203 | * @attr: device attribute structure | ||
4164 | * @buf: buffer | 4204 | * @buf: buffer |
4165 | * | 4205 | * |
4166 | * Return value: | 4206 | * Return value: |
@@ -4195,6 +4235,7 @@ static struct device_attribute ipr_resource_type_attr = { | |||
4195 | static struct device_attribute *ipr_dev_attrs[] = { | 4235 | static struct device_attribute *ipr_dev_attrs[] = { |
4196 | &ipr_adapter_handle_attr, | 4236 | &ipr_adapter_handle_attr, |
4197 | &ipr_resource_path_attr, | 4237 | &ipr_resource_path_attr, |
4238 | &ipr_device_id_attr, | ||
4198 | &ipr_resource_type_attr, | 4239 | &ipr_resource_type_attr, |
4199 | NULL, | 4240 | NULL, |
4200 | }; | 4241 | }; |
@@ -4898,39 +4939,15 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd) | |||
4898 | /** | 4939 | /** |
4899 | * ipr_handle_other_interrupt - Handle "other" interrupts | 4940 | * ipr_handle_other_interrupt - Handle "other" interrupts |
4900 | * @ioa_cfg: ioa config struct | 4941 | * @ioa_cfg: ioa config struct |
4942 | * @int_reg: interrupt register | ||
4901 | * | 4943 | * |
4902 | * Return value: | 4944 | * Return value: |
4903 | * IRQ_NONE / IRQ_HANDLED | 4945 | * IRQ_NONE / IRQ_HANDLED |
4904 | **/ | 4946 | **/ |
4905 | static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg) | 4947 | static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, |
4948 | volatile u32 int_reg) | ||
4906 | { | 4949 | { |
4907 | irqreturn_t rc = IRQ_HANDLED; | 4950 | irqreturn_t rc = IRQ_HANDLED; |
4908 | volatile u32 int_reg, int_mask_reg; | ||
4909 | |||
4910 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); | ||
4911 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; | ||
4912 | |||
4913 | /* If an interrupt on the adapter did not occur, ignore it. | ||
4914 | * Or in the case of SIS 64, check for a stage change interrupt. | ||
4915 | */ | ||
4916 | if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) { | ||
4917 | if (ioa_cfg->sis64) { | ||
4918 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); | ||
4919 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
4920 | if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { | ||
4921 | |||
4922 | /* clear stage change */ | ||
4923 | writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); | ||
4924 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
4925 | list_del(&ioa_cfg->reset_cmd->queue); | ||
4926 | del_timer(&ioa_cfg->reset_cmd->timer); | ||
4927 | ipr_reset_ioa_job(ioa_cfg->reset_cmd); | ||
4928 | return IRQ_HANDLED; | ||
4929 | } | ||
4930 | } | ||
4931 | |||
4932 | return IRQ_NONE; | ||
4933 | } | ||
4934 | 4951 | ||
4935 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { | 4952 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { |
4936 | /* Mask the interrupt */ | 4953 | /* Mask the interrupt */ |
@@ -4991,7 +5008,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
4991 | { | 5008 | { |
4992 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; | 5009 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; |
4993 | unsigned long lock_flags = 0; | 5010 | unsigned long lock_flags = 0; |
4994 | volatile u32 int_reg; | 5011 | volatile u32 int_reg, int_mask_reg; |
4995 | u32 ioasc; | 5012 | u32 ioasc; |
4996 | u16 cmd_index; | 5013 | u16 cmd_index; |
4997 | int num_hrrq = 0; | 5014 | int num_hrrq = 0; |
@@ -5006,6 +5023,33 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
5006 | return IRQ_NONE; | 5023 | return IRQ_NONE; |
5007 | } | 5024 | } |
5008 | 5025 | ||
5026 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); | ||
5027 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; | ||
5028 | |||
5029 | /* If an interrupt on the adapter did not occur, ignore it. | ||
5030 | * Or in the case of SIS 64, check for a stage change interrupt. | ||
5031 | */ | ||
5032 | if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) { | ||
5033 | if (ioa_cfg->sis64) { | ||
5034 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); | ||
5035 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
5036 | if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { | ||
5037 | |||
5038 | /* clear stage change */ | ||
5039 | writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); | ||
5040 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
5041 | list_del(&ioa_cfg->reset_cmd->queue); | ||
5042 | del_timer(&ioa_cfg->reset_cmd->timer); | ||
5043 | ipr_reset_ioa_job(ioa_cfg->reset_cmd); | ||
5044 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
5045 | return IRQ_HANDLED; | ||
5046 | } | ||
5047 | } | ||
5048 | |||
5049 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
5050 | return IRQ_NONE; | ||
5051 | } | ||
5052 | |||
5009 | while (1) { | 5053 | while (1) { |
5010 | ipr_cmd = NULL; | 5054 | ipr_cmd = NULL; |
5011 | 5055 | ||
@@ -5045,7 +5089,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
5045 | /* Clear the PCI interrupt */ | 5089 | /* Clear the PCI interrupt */ |
5046 | do { | 5090 | do { |
5047 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); | 5091 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); |
5048 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); | 5092 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; |
5049 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && | 5093 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && |
5050 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); | 5094 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); |
5051 | 5095 | ||
@@ -5060,7 +5104,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
5060 | } | 5104 | } |
5061 | 5105 | ||
5062 | if (unlikely(rc == IRQ_NONE)) | 5106 | if (unlikely(rc == IRQ_NONE)) |
5063 | rc = ipr_handle_other_interrupt(ioa_cfg); | 5107 | rc = ipr_handle_other_interrupt(ioa_cfg, int_reg); |
5064 | 5108 | ||
5065 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 5109 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
5066 | return rc; | 5110 | return rc; |