diff options
Diffstat (limited to 'drivers/scsi')
39 files changed, 1953 insertions, 1296 deletions
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 471d08791766..1a8c9b53fafa 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
| @@ -172,6 +172,7 @@ scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o | |||
| 172 | scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o | 172 | scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o |
| 173 | scsi_mod-y += scsi_trace.o scsi_logging.o | 173 | scsi_mod-y += scsi_trace.o scsi_logging.o |
| 174 | scsi_mod-$(CONFIG_PM) += scsi_pm.o | 174 | scsi_mod-$(CONFIG_PM) += scsi_pm.o |
| 175 | scsi_mod-$(CONFIG_SCSI_DH) += scsi_dh.o | ||
| 175 | 176 | ||
| 176 | hv_storvsc-y := storvsc_drv.o | 177 | hv_storvsc-y := storvsc_drv.o |
| 177 | 178 | ||
diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index edb43fda9f36..c831e30411fa 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c | |||
| @@ -983,7 +983,7 @@ static int asd_process_ctrl_a_user(struct asd_ha_struct *asd_ha, | |||
| 983 | { | 983 | { |
| 984 | int err, i; | 984 | int err, i; |
| 985 | u32 offs, size; | 985 | u32 offs, size; |
| 986 | struct asd_ll_el *el; | 986 | struct asd_ll_el *el = NULL; |
| 987 | struct asd_ctrla_phy_settings *ps; | 987 | struct asd_ctrla_phy_settings *ps; |
| 988 | struct asd_ctrla_phy_settings dflt_ps; | 988 | struct asd_ctrla_phy_settings dflt_ps; |
| 989 | 989 | ||
| @@ -1004,6 +1004,7 @@ static int asd_process_ctrl_a_user(struct asd_ha_struct *asd_ha, | |||
| 1004 | 1004 | ||
| 1005 | size = sizeof(struct asd_ctrla_phy_settings); | 1005 | size = sizeof(struct asd_ctrla_phy_settings); |
| 1006 | ps = &dflt_ps; | 1006 | ps = &dflt_ps; |
| 1007 | goto out_process; | ||
| 1007 | } | 1008 | } |
| 1008 | 1009 | ||
| 1009 | if (size == 0) | 1010 | if (size == 0) |
| @@ -1028,7 +1029,7 @@ static int asd_process_ctrl_a_user(struct asd_ha_struct *asd_ha, | |||
| 1028 | ASD_DPRINTK("couldn't find ctrla phy settings struct\n"); | 1029 | ASD_DPRINTK("couldn't find ctrla phy settings struct\n"); |
| 1029 | goto out2; | 1030 | goto out2; |
| 1030 | } | 1031 | } |
| 1031 | 1032 | out_process: | |
| 1032 | err = asd_process_ctrla_phy_settings(asd_ha, ps); | 1033 | err = asd_process_ctrla_phy_settings(asd_ha, ps); |
| 1033 | if (err) { | 1034 | if (err) { |
| 1034 | ASD_DPRINTK("couldn't process ctrla phy settings\n"); | 1035 | ASD_DPRINTK("couldn't process ctrla phy settings\n"); |
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 315d6d6dcfc8..98f7e8cca52d 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c | |||
| @@ -3665,19 +3665,19 @@ bfa_cb_sfp_state_query(struct bfa_sfp_s *sfp) | |||
| 3665 | if (sfp->state_query_cbfn) | 3665 | if (sfp->state_query_cbfn) |
| 3666 | sfp->state_query_cbfn(sfp->state_query_cbarg, | 3666 | sfp->state_query_cbfn(sfp->state_query_cbarg, |
| 3667 | sfp->status); | 3667 | sfp->status); |
| 3668 | sfp->media = NULL; | 3668 | sfp->media = NULL; |
| 3669 | } | 3669 | } |
| 3670 | 3670 | ||
| 3671 | if (sfp->portspeed) { | 3671 | if (sfp->portspeed) { |
| 3672 | sfp->status = bfa_sfp_speed_valid(sfp, sfp->portspeed); | 3672 | sfp->status = bfa_sfp_speed_valid(sfp, sfp->portspeed); |
| 3673 | if (sfp->state_query_cbfn) | 3673 | if (sfp->state_query_cbfn) |
| 3674 | sfp->state_query_cbfn(sfp->state_query_cbarg, | 3674 | sfp->state_query_cbfn(sfp->state_query_cbarg, |
| 3675 | sfp->status); | 3675 | sfp->status); |
| 3676 | sfp->portspeed = BFA_PORT_SPEED_UNKNOWN; | 3676 | sfp->portspeed = BFA_PORT_SPEED_UNKNOWN; |
| 3677 | } | 3677 | } |
| 3678 | 3678 | ||
| 3679 | sfp->state_query_lock = 0; | 3679 | sfp->state_query_lock = 0; |
| 3680 | sfp->state_query_cbfn = NULL; | 3680 | sfp->state_query_cbfn = NULL; |
| 3681 | } | 3681 | } |
| 3682 | 3682 | ||
| 3683 | /* | 3683 | /* |
| @@ -3878,7 +3878,7 @@ bfa_sfp_show_comp(struct bfa_sfp_s *sfp, struct bfi_mbmsg_s *msg) | |||
| 3878 | bfa_trc(sfp, sfp->data_valid); | 3878 | bfa_trc(sfp, sfp->data_valid); |
| 3879 | if (sfp->data_valid) { | 3879 | if (sfp->data_valid) { |
| 3880 | u32 size = sizeof(struct sfp_mem_s); | 3880 | u32 size = sizeof(struct sfp_mem_s); |
| 3881 | u8 *des = (u8 *) &(sfp->sfpmem); | 3881 | u8 *des = (u8 *)(sfp->sfpmem); |
| 3882 | memcpy(des, sfp->dbuf_kva, size); | 3882 | memcpy(des, sfp->dbuf_kva, size); |
| 3883 | } | 3883 | } |
| 3884 | /* | 3884 | /* |
diff --git a/drivers/scsi/device_handler/Kconfig b/drivers/scsi/device_handler/Kconfig index 69abd0ad48e2..e5647d59224f 100644 --- a/drivers/scsi/device_handler/Kconfig +++ b/drivers/scsi/device_handler/Kconfig | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | menuconfig SCSI_DH | 5 | menuconfig SCSI_DH |
| 6 | tristate "SCSI Device Handlers" | 6 | bool "SCSI Device Handlers" |
| 7 | depends on SCSI | 7 | depends on SCSI |
| 8 | default n | 8 | default n |
| 9 | help | 9 | help |
diff --git a/drivers/scsi/device_handler/Makefile b/drivers/scsi/device_handler/Makefile index e1d2ea083e15..09866c50fbb4 100644 --- a/drivers/scsi/device_handler/Makefile +++ b/drivers/scsi/device_handler/Makefile | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | # | 1 | # |
| 2 | # SCSI Device Handler | 2 | # SCSI Device Handler |
| 3 | # | 3 | # |
| 4 | obj-$(CONFIG_SCSI_DH) += scsi_dh.o | ||
| 5 | obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o | 4 | obj-$(CONFIG_SCSI_DH_RDAC) += scsi_dh_rdac.o |
| 6 | obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o | 5 | obj-$(CONFIG_SCSI_DH_HP_SW) += scsi_dh_hp_sw.o |
| 7 | obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o | 6 | obj-$(CONFIG_SCSI_DH_EMC) += scsi_dh_emc.o |
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c deleted file mode 100644 index 1efebc9eedfb..000000000000 --- a/drivers/scsi/device_handler/scsi_dh.c +++ /dev/null | |||
| @@ -1,621 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * SCSI device handler infrastruture. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify it | ||
| 5 | * under the terms of the GNU General Public License as published by the | ||
| 6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 7 | * option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, but | ||
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along | ||
| 15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 16 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 17 | * | ||
| 18 | * Copyright IBM Corporation, 2007 | ||
| 19 | * Authors: | ||
| 20 | * Chandra Seetharaman <sekharan@us.ibm.com> | ||
| 21 | * Mike Anderson <andmike@linux.vnet.ibm.com> | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <scsi/scsi_dh.h> | ||
| 27 | #include "../scsi_priv.h" | ||
| 28 | |||
| 29 | static DEFINE_SPINLOCK(list_lock); | ||
| 30 | static LIST_HEAD(scsi_dh_list); | ||
| 31 | |||
| 32 | static struct scsi_device_handler *get_device_handler(const char *name) | ||
| 33 | { | ||
| 34 | struct scsi_device_handler *tmp, *found = NULL; | ||
| 35 | |||
| 36 | spin_lock(&list_lock); | ||
| 37 | list_for_each_entry(tmp, &scsi_dh_list, list) { | ||
| 38 | if (!strncmp(tmp->name, name, strlen(tmp->name))) { | ||
| 39 | found = tmp; | ||
| 40 | break; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | spin_unlock(&list_lock); | ||
| 44 | return found; | ||
| 45 | } | ||
| 46 | |||
| 47 | /* | ||
| 48 | * device_handler_match_function - Match a device handler to a device | ||
| 49 | * @sdev - SCSI device to be tested | ||
| 50 | * | ||
| 51 | * Tests @sdev against the match function of all registered device_handler. | ||
| 52 | * Returns the found device handler or NULL if not found. | ||
| 53 | */ | ||
| 54 | static struct scsi_device_handler * | ||
| 55 | device_handler_match_function(struct scsi_device *sdev) | ||
| 56 | { | ||
| 57 | struct scsi_device_handler *tmp_dh, *found_dh = NULL; | ||
| 58 | |||
| 59 | spin_lock(&list_lock); | ||
| 60 | list_for_each_entry(tmp_dh, &scsi_dh_list, list) { | ||
| 61 | if (tmp_dh->match && tmp_dh->match(sdev)) { | ||
| 62 | found_dh = tmp_dh; | ||
| 63 | break; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | spin_unlock(&list_lock); | ||
| 67 | return found_dh; | ||
| 68 | } | ||
| 69 | |||
| 70 | /* | ||
| 71 | * device_handler_match - Attach a device handler to a device | ||
| 72 | * @scsi_dh - The device handler to match against or NULL | ||
| 73 | * @sdev - SCSI device to be tested against @scsi_dh | ||
| 74 | * | ||
| 75 | * Tests @sdev against the device handler @scsi_dh or against | ||
| 76 | * all registered device_handler if @scsi_dh == NULL. | ||
| 77 | * Returns the found device handler or NULL if not found. | ||
| 78 | */ | ||
| 79 | static struct scsi_device_handler * | ||
| 80 | device_handler_match(struct scsi_device_handler *scsi_dh, | ||
| 81 | struct scsi_device *sdev) | ||
| 82 | { | ||
| 83 | struct scsi_device_handler *found_dh; | ||
| 84 | |||
| 85 | found_dh = device_handler_match_function(sdev); | ||
| 86 | |||
| 87 | if (scsi_dh && found_dh != scsi_dh) | ||
| 88 | found_dh = NULL; | ||
| 89 | |||
| 90 | return found_dh; | ||
| 91 | } | ||
| 92 | |||
| 93 | /* | ||
| 94 | * scsi_dh_handler_attach - Attach a device handler to a device | ||
| 95 | * @sdev - SCSI device the device handler should attach to | ||
| 96 | * @scsi_dh - The device handler to attach | ||
| 97 | */ | ||
| 98 | static int scsi_dh_handler_attach(struct scsi_device *sdev, | ||
| 99 | struct scsi_device_handler *scsi_dh) | ||
| 100 | { | ||
| 101 | struct scsi_dh_data *d; | ||
| 102 | |||
| 103 | if (sdev->scsi_dh_data) { | ||
| 104 | if (sdev->scsi_dh_data->scsi_dh != scsi_dh) | ||
| 105 | return -EBUSY; | ||
| 106 | |||
| 107 | kref_get(&sdev->scsi_dh_data->kref); | ||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | if (!try_module_get(scsi_dh->module)) | ||
| 112 | return -EINVAL; | ||
| 113 | |||
| 114 | d = scsi_dh->attach(sdev); | ||
| 115 | if (IS_ERR(d)) { | ||
| 116 | sdev_printk(KERN_ERR, sdev, "%s: Attach failed (%ld)\n", | ||
| 117 | scsi_dh->name, PTR_ERR(d)); | ||
| 118 | module_put(scsi_dh->module); | ||
| 119 | return PTR_ERR(d); | ||
| 120 | } | ||
| 121 | |||
| 122 | d->scsi_dh = scsi_dh; | ||
| 123 | kref_init(&d->kref); | ||
| 124 | d->sdev = sdev; | ||
| 125 | |||
| 126 | spin_lock_irq(sdev->request_queue->queue_lock); | ||
| 127 | sdev->scsi_dh_data = d; | ||
| 128 | spin_unlock_irq(sdev->request_queue->queue_lock); | ||
| 129 | return 0; | ||
| 130 | } | ||
| 131 | |||
| 132 | static void __detach_handler (struct kref *kref) | ||
| 133 | { | ||
| 134 | struct scsi_dh_data *scsi_dh_data = | ||
| 135 | container_of(kref, struct scsi_dh_data, kref); | ||
| 136 | struct scsi_device_handler *scsi_dh = scsi_dh_data->scsi_dh; | ||
| 137 | struct scsi_device *sdev = scsi_dh_data->sdev; | ||
| 138 | |||
| 139 | scsi_dh->detach(sdev); | ||
| 140 | |||
| 141 | spin_lock_irq(sdev->request_queue->queue_lock); | ||
| 142 | sdev->scsi_dh_data = NULL; | ||
| 143 | spin_unlock_irq(sdev->request_queue->queue_lock); | ||
| 144 | |||
| 145 | sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", scsi_dh->name); | ||
| 146 | module_put(scsi_dh->module); | ||
| 147 | } | ||
| 148 | |||
| 149 | /* | ||
| 150 | * scsi_dh_handler_detach - Detach a device handler from a device | ||
| 151 | * @sdev - SCSI device the device handler should be detached from | ||
| 152 | * @scsi_dh - Device handler to be detached | ||
| 153 | * | ||
| 154 | * Detach from a device handler. If a device handler is specified, | ||
| 155 | * only detach if the currently attached handler matches @scsi_dh. | ||
| 156 | */ | ||
| 157 | static void scsi_dh_handler_detach(struct scsi_device *sdev, | ||
| 158 | struct scsi_device_handler *scsi_dh) | ||
| 159 | { | ||
| 160 | if (!sdev->scsi_dh_data) | ||
| 161 | return; | ||
| 162 | |||
| 163 | if (scsi_dh && scsi_dh != sdev->scsi_dh_data->scsi_dh) | ||
| 164 | return; | ||
| 165 | |||
| 166 | if (!scsi_dh) | ||
| 167 | scsi_dh = sdev->scsi_dh_data->scsi_dh; | ||
| 168 | |||
| 169 | if (scsi_dh) | ||
| 170 | kref_put(&sdev->scsi_dh_data->kref, __detach_handler); | ||
| 171 | } | ||
| 172 | |||
| 173 | /* | ||
| 174 | * Functions for sysfs attribute 'dh_state' | ||
| 175 | */ | ||
| 176 | static ssize_t | ||
| 177 | store_dh_state(struct device *dev, struct device_attribute *attr, | ||
| 178 | const char *buf, size_t count) | ||
| 179 | { | ||
| 180 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 181 | struct scsi_device_handler *scsi_dh; | ||
| 182 | int err = -EINVAL; | ||
| 183 | |||
| 184 | if (sdev->sdev_state == SDEV_CANCEL || | ||
| 185 | sdev->sdev_state == SDEV_DEL) | ||
| 186 | return -ENODEV; | ||
| 187 | |||
| 188 | if (!sdev->scsi_dh_data) { | ||
| 189 | /* | ||
| 190 | * Attach to a device handler | ||
| 191 | */ | ||
| 192 | if (!(scsi_dh = get_device_handler(buf))) | ||
| 193 | return err; | ||
| 194 | err = scsi_dh_handler_attach(sdev, scsi_dh); | ||
| 195 | } else { | ||
| 196 | scsi_dh = sdev->scsi_dh_data->scsi_dh; | ||
| 197 | if (!strncmp(buf, "detach", 6)) { | ||
| 198 | /* | ||
| 199 | * Detach from a device handler | ||
| 200 | */ | ||
| 201 | scsi_dh_handler_detach(sdev, scsi_dh); | ||
| 202 | err = 0; | ||
| 203 | } else if (!strncmp(buf, "activate", 8)) { | ||
| 204 | /* | ||
| 205 | * Activate a device handler | ||
| 206 | */ | ||
| 207 | if (scsi_dh->activate) | ||
| 208 | err = scsi_dh->activate(sdev, NULL, NULL); | ||
| 209 | else | ||
| 210 | err = 0; | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | return err<0?err:count; | ||
| 215 | } | ||
| 216 | |||
| 217 | static ssize_t | ||
| 218 | show_dh_state(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 219 | { | ||
| 220 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 221 | |||
| 222 | if (!sdev->scsi_dh_data) | ||
| 223 | return snprintf(buf, 20, "detached\n"); | ||
| 224 | |||
| 225 | return snprintf(buf, 20, "%s\n", sdev->scsi_dh_data->scsi_dh->name); | ||
| 226 | } | ||
| 227 | |||
| 228 | static struct device_attribute scsi_dh_state_attr = | ||
| 229 | __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state, | ||
| 230 | store_dh_state); | ||
| 231 | |||
| 232 | /* | ||
| 233 | * scsi_dh_sysfs_attr_add - Callback for scsi_init_dh | ||
| 234 | */ | ||
| 235 | static int scsi_dh_sysfs_attr_add(struct device *dev, void *data) | ||
| 236 | { | ||
| 237 | struct scsi_device *sdev; | ||
| 238 | int err; | ||
| 239 | |||
| 240 | if (!scsi_is_sdev_device(dev)) | ||
| 241 | return 0; | ||
| 242 | |||
| 243 | sdev = to_scsi_device(dev); | ||
| 244 | |||
| 245 | err = device_create_file(&sdev->sdev_gendev, | ||
| 246 | &scsi_dh_state_attr); | ||
| 247 | |||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | |||
| 251 | /* | ||
| 252 | * scsi_dh_sysfs_attr_remove - Callback for scsi_exit_dh | ||
| 253 | */ | ||
| 254 | static int scsi_dh_sysfs_attr_remove(struct device *dev, void *data) | ||
| 255 | { | ||
| 256 | struct scsi_device *sdev; | ||
| 257 | |||
| 258 | if (!scsi_is_sdev_device(dev)) | ||
| 259 | return 0; | ||
| 260 | |||
| 261 | sdev = to_scsi_device(dev); | ||
| 262 | |||
| 263 | device_remove_file(&sdev->sdev_gendev, | ||
| 264 | &scsi_dh_state_attr); | ||
| 265 | |||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | /* | ||
| 270 | * scsi_dh_notifier - notifier chain callback | ||
| 271 | */ | ||
| 272 | static int scsi_dh_notifier(struct notifier_block *nb, | ||
| 273 | unsigned long action, void *data) | ||
| 274 | { | ||
| 275 | struct device *dev = data; | ||
| 276 | struct scsi_device *sdev; | ||
| 277 | int err = 0; | ||
| 278 | struct scsi_device_handler *devinfo = NULL; | ||
| 279 | |||
| 280 | if (!scsi_is_sdev_device(dev)) | ||
| 281 | return 0; | ||
| 282 | |||
| 283 | sdev = to_scsi_device(dev); | ||
| 284 | |||
| 285 | if (action == BUS_NOTIFY_ADD_DEVICE) { | ||
| 286 | err = device_create_file(dev, &scsi_dh_state_attr); | ||
| 287 | /* don't care about err */ | ||
| 288 | devinfo = device_handler_match(NULL, sdev); | ||
| 289 | if (devinfo) | ||
| 290 | err = scsi_dh_handler_attach(sdev, devinfo); | ||
| 291 | } else if (action == BUS_NOTIFY_DEL_DEVICE) { | ||
| 292 | device_remove_file(dev, &scsi_dh_state_attr); | ||
| 293 | scsi_dh_handler_detach(sdev, NULL); | ||
| 294 | } | ||
| 295 | return err; | ||
| 296 | } | ||
| 297 | |||
| 298 | /* | ||
| 299 | * scsi_dh_notifier_add - Callback for scsi_register_device_handler | ||
| 300 | */ | ||
| 301 | static int scsi_dh_notifier_add(struct device *dev, void *data) | ||
| 302 | { | ||
| 303 | struct scsi_device_handler *scsi_dh = data; | ||
| 304 | struct scsi_device *sdev; | ||
| 305 | |||
| 306 | if (!scsi_is_sdev_device(dev)) | ||
| 307 | return 0; | ||
| 308 | |||
| 309 | if (!get_device(dev)) | ||
| 310 | return 0; | ||
| 311 | |||
| 312 | sdev = to_scsi_device(dev); | ||
| 313 | |||
| 314 | if (device_handler_match(scsi_dh, sdev)) | ||
| 315 | scsi_dh_handler_attach(sdev, scsi_dh); | ||
| 316 | |||
| 317 | put_device(dev); | ||
| 318 | |||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | |||
| 322 | /* | ||
| 323 | * scsi_dh_notifier_remove - Callback for scsi_unregister_device_handler | ||
| 324 | */ | ||
| 325 | static int scsi_dh_notifier_remove(struct device *dev, void *data) | ||
| 326 | { | ||
| 327 | struct scsi_device_handler *scsi_dh = data; | ||
| 328 | struct scsi_device *sdev; | ||
| 329 | |||
| 330 | if (!scsi_is_sdev_device(dev)) | ||
| 331 | return 0; | ||
| 332 | |||
| 333 | if (!get_device(dev)) | ||
| 334 | return 0; | ||
| 335 | |||
| 336 | sdev = to_scsi_device(dev); | ||
| 337 | |||
| 338 | scsi_dh_handler_detach(sdev, scsi_dh); | ||
| 339 | |||
| 340 | put_device(dev); | ||
| 341 | |||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | |||
| 345 | /* | ||
| 346 | * scsi_register_device_handler - register a device handler personality | ||
| 347 | * module. | ||
| 348 | * @scsi_dh - device handler to be registered. | ||
| 349 | * | ||
| 350 | * Returns 0 on success, -EBUSY if handler already registered. | ||
| 351 | */ | ||
| 352 | int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) | ||
| 353 | { | ||
| 354 | |||
| 355 | if (get_device_handler(scsi_dh->name)) | ||
| 356 | return -EBUSY; | ||
| 357 | |||
| 358 | if (!scsi_dh->attach || !scsi_dh->detach) | ||
| 359 | return -EINVAL; | ||
| 360 | |||
| 361 | spin_lock(&list_lock); | ||
| 362 | list_add(&scsi_dh->list, &scsi_dh_list); | ||
| 363 | spin_unlock(&list_lock); | ||
| 364 | |||
| 365 | bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add); | ||
| 366 | printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name); | ||
| 367 | |||
| 368 | return SCSI_DH_OK; | ||
| 369 | } | ||
| 370 | EXPORT_SYMBOL_GPL(scsi_register_device_handler); | ||
| 371 | |||
| 372 | /* | ||
| 373 | * scsi_unregister_device_handler - register a device handler personality | ||
| 374 | * module. | ||
| 375 | * @scsi_dh - device handler to be unregistered. | ||
| 376 | * | ||
| 377 | * Returns 0 on success, -ENODEV if handler not registered. | ||
| 378 | */ | ||
| 379 | int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) | ||
| 380 | { | ||
| 381 | |||
| 382 | if (!get_device_handler(scsi_dh->name)) | ||
| 383 | return -ENODEV; | ||
| 384 | |||
| 385 | bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, | ||
| 386 | scsi_dh_notifier_remove); | ||
| 387 | |||
| 388 | spin_lock(&list_lock); | ||
| 389 | list_del(&scsi_dh->list); | ||
| 390 | spin_unlock(&list_lock); | ||
| 391 | printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name); | ||
| 392 | |||
| 393 | return SCSI_DH_OK; | ||
| 394 | } | ||
| 395 | EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); | ||
| 396 | |||
| 397 | /* | ||
| 398 | * scsi_dh_activate - activate the path associated with the scsi_device | ||
| 399 | * corresponding to the given request queue. | ||
| 400 | * Returns immediately without waiting for activation to be completed. | ||
| 401 | * @q - Request queue that is associated with the scsi_device to be | ||
| 402 | * activated. | ||
| 403 | * @fn - Function to be called upon completion of the activation. | ||
| 404 | * Function fn is called with data (below) and the error code. | ||
| 405 | * Function fn may be called from the same calling context. So, | ||
| 406 | * do not hold the lock in the caller which may be needed in fn. | ||
| 407 | * @data - data passed to the function fn upon completion. | ||
| 408 | * | ||
| 409 | */ | ||
| 410 | int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) | ||
| 411 | { | ||
| 412 | int err = 0; | ||
| 413 | unsigned long flags; | ||
| 414 | struct scsi_device *sdev; | ||
| 415 | struct scsi_device_handler *scsi_dh = NULL; | ||
| 416 | struct device *dev = NULL; | ||
| 417 | |||
| 418 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 419 | sdev = q->queuedata; | ||
| 420 | if (!sdev) { | ||
| 421 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 422 | err = SCSI_DH_NOSYS; | ||
| 423 | if (fn) | ||
| 424 | fn(data, err); | ||
| 425 | return err; | ||
| 426 | } | ||
| 427 | |||
| 428 | if (sdev->scsi_dh_data) | ||
| 429 | scsi_dh = sdev->scsi_dh_data->scsi_dh; | ||
| 430 | dev = get_device(&sdev->sdev_gendev); | ||
| 431 | if (!scsi_dh || !dev || | ||
| 432 | sdev->sdev_state == SDEV_CANCEL || | ||
| 433 | sdev->sdev_state == SDEV_DEL) | ||
| 434 | err = SCSI_DH_NOSYS; | ||
| 435 | if (sdev->sdev_state == SDEV_OFFLINE) | ||
| 436 | err = SCSI_DH_DEV_OFFLINED; | ||
| 437 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 438 | |||
| 439 | if (err) { | ||
| 440 | if (fn) | ||
| 441 | fn(data, err); | ||
| 442 | goto out; | ||
| 443 | } | ||
| 444 | |||
| 445 | if (scsi_dh->activate) | ||
| 446 | err = scsi_dh->activate(sdev, fn, data); | ||
| 447 | out: | ||
| 448 | put_device(dev); | ||
| 449 | return err; | ||
| 450 | } | ||
| 451 | EXPORT_SYMBOL_GPL(scsi_dh_activate); | ||
| 452 | |||
| 453 | /* | ||
| 454 | * scsi_dh_set_params - set the parameters for the device as per the | ||
| 455 | * string specified in params. | ||
| 456 | * @q - Request queue that is associated with the scsi_device for | ||
| 457 | * which the parameters to be set. | ||
| 458 | * @params - parameters in the following format | ||
| 459 | * "no_of_params\0param1\0param2\0param3\0...\0" | ||
| 460 | * for example, string for 2 parameters with value 10 and 21 | ||
| 461 | * is specified as "2\010\021\0". | ||
| 462 | */ | ||
| 463 | int scsi_dh_set_params(struct request_queue *q, const char *params) | ||
| 464 | { | ||
| 465 | int err = -SCSI_DH_NOSYS; | ||
| 466 | unsigned long flags; | ||
| 467 | struct scsi_device *sdev; | ||
| 468 | struct scsi_device_handler *scsi_dh = NULL; | ||
| 469 | |||
| 470 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 471 | sdev = q->queuedata; | ||
| 472 | if (sdev && sdev->scsi_dh_data) | ||
| 473 | scsi_dh = sdev->scsi_dh_data->scsi_dh; | ||
| 474 | if (scsi_dh && scsi_dh->set_params && get_device(&sdev->sdev_gendev)) | ||
| 475 | err = 0; | ||
| 476 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 477 | |||
| 478 | if (err) | ||
| 479 | return err; | ||
| 480 | err = scsi_dh->set_params(sdev, params); | ||
| 481 | put_device(&sdev->sdev_gendev); | ||
| 482 | return err; | ||
| 483 | } | ||
| 484 | EXPORT_SYMBOL_GPL(scsi_dh_set_params); | ||
| 485 | |||
| 486 | /* | ||
| 487 | * scsi_dh_handler_exist - Return TRUE(1) if a device handler exists for | ||
| 488 | * the given name. FALSE(0) otherwise. | ||
| 489 | * @name - name of the device handler. | ||
| 490 | */ | ||
| 491 | int scsi_dh_handler_exist(const char *name) | ||
| 492 | { | ||
| 493 | return (get_device_handler(name) != NULL); | ||
| 494 | } | ||
| 495 | EXPORT_SYMBOL_GPL(scsi_dh_handler_exist); | ||
| 496 | |||
| 497 | /* | ||
| 498 | * scsi_dh_attach - Attach device handler | ||
| 499 | * @q - Request queue that is associated with the scsi_device | ||
| 500 | * the handler should be attached to | ||
| 501 | * @name - name of the handler to attach | ||
| 502 | */ | ||
| 503 | int scsi_dh_attach(struct request_queue *q, const char *name) | ||
| 504 | { | ||
| 505 | unsigned long flags; | ||
| 506 | struct scsi_device *sdev; | ||
| 507 | struct scsi_device_handler *scsi_dh; | ||
| 508 | int err = 0; | ||
| 509 | |||
| 510 | scsi_dh = get_device_handler(name); | ||
| 511 | if (!scsi_dh) | ||
| 512 | return -EINVAL; | ||
| 513 | |||
| 514 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 515 | sdev = q->queuedata; | ||
| 516 | if (!sdev || !get_device(&sdev->sdev_gendev)) | ||
| 517 | err = -ENODEV; | ||
| 518 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 519 | |||
| 520 | if (!err) { | ||
| 521 | err = scsi_dh_handler_attach(sdev, scsi_dh); | ||
| 522 | put_device(&sdev->sdev_gendev); | ||
| 523 | } | ||
| 524 | return err; | ||
| 525 | } | ||
| 526 | EXPORT_SYMBOL_GPL(scsi_dh_attach); | ||
| 527 | |||
| 528 | /* | ||
| 529 | * scsi_dh_detach - Detach device handler | ||
| 530 | * @q - Request queue that is associated with the scsi_device | ||
| 531 | * the handler should be detached from | ||
| 532 | * | ||
| 533 | * This function will detach the device handler only | ||
| 534 | * if the sdev is not part of the internal list, ie | ||
| 535 | * if it has been attached manually. | ||
| 536 | */ | ||
| 537 | void scsi_dh_detach(struct request_queue *q) | ||
| 538 | { | ||
| 539 | unsigned long flags; | ||
| 540 | struct scsi_device *sdev; | ||
| 541 | struct scsi_device_handler *scsi_dh = NULL; | ||
| 542 | |||
| 543 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 544 | sdev = q->queuedata; | ||
| 545 | if (!sdev || !get_device(&sdev->sdev_gendev)) | ||
| 546 | sdev = NULL; | ||
| 547 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 548 | |||
| 549 | if (!sdev) | ||
| 550 | return; | ||
| 551 | |||
| 552 | if (sdev->scsi_dh_data) { | ||
| 553 | scsi_dh = sdev->scsi_dh_data->scsi_dh; | ||
| 554 | scsi_dh_handler_detach(sdev, scsi_dh); | ||
| 555 | } | ||
| 556 | put_device(&sdev->sdev_gendev); | ||
| 557 | } | ||
| 558 | EXPORT_SYMBOL_GPL(scsi_dh_detach); | ||
| 559 | |||
| 560 | /* | ||
| 561 | * scsi_dh_attached_handler_name - Get attached device handler's name | ||
| 562 | * @q - Request queue that is associated with the scsi_device | ||
| 563 | * that may have a device handler attached | ||
| 564 | * @gfp - the GFP mask used in the kmalloc() call when allocating memory | ||
| 565 | * | ||
| 566 | * Returns name of attached handler, NULL if no handler is attached. | ||
| 567 | * Caller must take care to free the returned string. | ||
| 568 | */ | ||
| 569 | const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) | ||
| 570 | { | ||
| 571 | unsigned long flags; | ||
| 572 | struct scsi_device *sdev; | ||
| 573 | const char *handler_name = NULL; | ||
| 574 | |||
| 575 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 576 | sdev = q->queuedata; | ||
| 577 | if (!sdev || !get_device(&sdev->sdev_gendev)) | ||
| 578 | sdev = NULL; | ||
| 579 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 580 | |||
| 581 | if (!sdev) | ||
| 582 | return NULL; | ||
| 583 | |||
| 584 | if (sdev->scsi_dh_data) | ||
| 585 | handler_name = kstrdup(sdev->scsi_dh_data->scsi_dh->name, gfp); | ||
| 586 | |||
| 587 | put_device(&sdev->sdev_gendev); | ||
| 588 | return handler_name; | ||
| 589 | } | ||
| 590 | EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name); | ||
| 591 | |||
| 592 | static struct notifier_block scsi_dh_nb = { | ||
| 593 | .notifier_call = scsi_dh_notifier | ||
| 594 | }; | ||
| 595 | |||
| 596 | static int __init scsi_dh_init(void) | ||
| 597 | { | ||
| 598 | int r; | ||
| 599 | |||
| 600 | r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb); | ||
| 601 | |||
| 602 | if (!r) | ||
| 603 | bus_for_each_dev(&scsi_bus_type, NULL, NULL, | ||
| 604 | scsi_dh_sysfs_attr_add); | ||
| 605 | |||
| 606 | return r; | ||
| 607 | } | ||
| 608 | |||
| 609 | static void __exit scsi_dh_exit(void) | ||
| 610 | { | ||
| 611 | bus_for_each_dev(&scsi_bus_type, NULL, NULL, | ||
| 612 | scsi_dh_sysfs_attr_remove); | ||
| 613 | bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb); | ||
| 614 | } | ||
| 615 | |||
| 616 | module_init(scsi_dh_init); | ||
| 617 | module_exit(scsi_dh_exit); | ||
| 618 | |||
| 619 | MODULE_DESCRIPTION("SCSI device handler"); | ||
| 620 | MODULE_AUTHOR("Chandra Seetharaman <sekharan@us.ibm.com>"); | ||
| 621 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 854b568b9931..cc2773b5de68 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c | |||
| @@ -62,7 +62,6 @@ | |||
| 62 | #define ALUA_OPTIMIZE_STPG 1 | 62 | #define ALUA_OPTIMIZE_STPG 1 |
| 63 | 63 | ||
| 64 | struct alua_dh_data { | 64 | struct alua_dh_data { |
| 65 | struct scsi_dh_data dh_data; | ||
| 66 | int group_id; | 65 | int group_id; |
| 67 | int rel_port; | 66 | int rel_port; |
| 68 | int tpgs; | 67 | int tpgs; |
| @@ -86,11 +85,6 @@ struct alua_dh_data { | |||
| 86 | static char print_alua_state(int); | 85 | static char print_alua_state(int); |
| 87 | static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *); | 86 | static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *); |
| 88 | 87 | ||
| 89 | static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev) | ||
| 90 | { | ||
| 91 | return container_of(sdev->scsi_dh_data, struct alua_dh_data, dh_data); | ||
| 92 | } | ||
| 93 | |||
| 94 | static int realloc_buffer(struct alua_dh_data *h, unsigned len) | 88 | static int realloc_buffer(struct alua_dh_data *h, unsigned len) |
| 95 | { | 89 | { |
| 96 | if (h->buff && h->buff != h->inq) | 90 | if (h->buff && h->buff != h->inq) |
| @@ -708,7 +702,7 @@ out: | |||
| 708 | */ | 702 | */ |
| 709 | static int alua_set_params(struct scsi_device *sdev, const char *params) | 703 | static int alua_set_params(struct scsi_device *sdev, const char *params) |
| 710 | { | 704 | { |
| 711 | struct alua_dh_data *h = get_alua_data(sdev); | 705 | struct alua_dh_data *h = sdev->handler_data; |
| 712 | unsigned int optimize = 0, argc; | 706 | unsigned int optimize = 0, argc; |
| 713 | const char *p = params; | 707 | const char *p = params; |
| 714 | int result = SCSI_DH_OK; | 708 | int result = SCSI_DH_OK; |
| @@ -746,7 +740,7 @@ MODULE_PARM_DESC(optimize_stpg, "Allow use of a non-optimized path, rather than | |||
| 746 | static int alua_activate(struct scsi_device *sdev, | 740 | static int alua_activate(struct scsi_device *sdev, |
| 747 | activate_complete fn, void *data) | 741 | activate_complete fn, void *data) |
| 748 | { | 742 | { |
| 749 | struct alua_dh_data *h = get_alua_data(sdev); | 743 | struct alua_dh_data *h = sdev->handler_data; |
| 750 | int err = SCSI_DH_OK; | 744 | int err = SCSI_DH_OK; |
| 751 | int stpg = 0; | 745 | int stpg = 0; |
| 752 | 746 | ||
| @@ -804,7 +798,7 @@ out: | |||
| 804 | */ | 798 | */ |
| 805 | static int alua_prep_fn(struct scsi_device *sdev, struct request *req) | 799 | static int alua_prep_fn(struct scsi_device *sdev, struct request *req) |
| 806 | { | 800 | { |
| 807 | struct alua_dh_data *h = get_alua_data(sdev); | 801 | struct alua_dh_data *h = sdev->handler_data; |
| 808 | int ret = BLKPREP_OK; | 802 | int ret = BLKPREP_OK; |
| 809 | 803 | ||
| 810 | if (h->state == TPGS_STATE_TRANSITIONING) | 804 | if (h->state == TPGS_STATE_TRANSITIONING) |
| @@ -819,23 +813,18 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req) | |||
| 819 | 813 | ||
| 820 | } | 814 | } |
| 821 | 815 | ||
| 822 | static bool alua_match(struct scsi_device *sdev) | ||
| 823 | { | ||
| 824 | return (scsi_device_tpgs(sdev) != 0); | ||
| 825 | } | ||
| 826 | |||
| 827 | /* | 816 | /* |
| 828 | * alua_bus_attach - Attach device handler | 817 | * alua_bus_attach - Attach device handler |
| 829 | * @sdev: device to be attached to | 818 | * @sdev: device to be attached to |
| 830 | */ | 819 | */ |
| 831 | static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev) | 820 | static int alua_bus_attach(struct scsi_device *sdev) |
| 832 | { | 821 | { |
| 833 | struct alua_dh_data *h; | 822 | struct alua_dh_data *h; |
| 834 | int err; | 823 | int err; |
| 835 | 824 | ||
| 836 | h = kzalloc(sizeof(*h) , GFP_KERNEL); | 825 | h = kzalloc(sizeof(*h) , GFP_KERNEL); |
| 837 | if (!h) | 826 | if (!h) |
| 838 | return ERR_PTR(-ENOMEM); | 827 | return -ENOMEM; |
| 839 | h->tpgs = TPGS_MODE_UNINITIALIZED; | 828 | h->tpgs = TPGS_MODE_UNINITIALIZED; |
| 840 | h->state = TPGS_STATE_OPTIMIZED; | 829 | h->state = TPGS_STATE_OPTIMIZED; |
| 841 | h->group_id = -1; | 830 | h->group_id = -1; |
| @@ -848,11 +837,11 @@ static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev) | |||
| 848 | if (err != SCSI_DH_OK && err != SCSI_DH_DEV_OFFLINED) | 837 | if (err != SCSI_DH_OK && err != SCSI_DH_DEV_OFFLINED) |
| 849 | goto failed; | 838 | goto failed; |
| 850 | 839 | ||
| 851 | sdev_printk(KERN_NOTICE, sdev, "%s: Attached\n", ALUA_DH_NAME); | 840 | sdev->handler_data = h; |
| 852 | return &h->dh_data; | 841 | return 0; |
| 853 | failed: | 842 | failed: |
| 854 | kfree(h); | 843 | kfree(h); |
| 855 | return ERR_PTR(-EINVAL); | 844 | return -EINVAL; |
| 856 | } | 845 | } |
| 857 | 846 | ||
| 858 | /* | 847 | /* |
| @@ -861,10 +850,11 @@ failed: | |||
| 861 | */ | 850 | */ |
| 862 | static void alua_bus_detach(struct scsi_device *sdev) | 851 | static void alua_bus_detach(struct scsi_device *sdev) |
| 863 | { | 852 | { |
| 864 | struct alua_dh_data *h = get_alua_data(sdev); | 853 | struct alua_dh_data *h = sdev->handler_data; |
| 865 | 854 | ||
| 866 | if (h->buff && h->inq != h->buff) | 855 | if (h->buff && h->inq != h->buff) |
| 867 | kfree(h->buff); | 856 | kfree(h->buff); |
| 857 | sdev->handler_data = NULL; | ||
| 868 | kfree(h); | 858 | kfree(h); |
| 869 | } | 859 | } |
| 870 | 860 | ||
| @@ -877,7 +867,6 @@ static struct scsi_device_handler alua_dh = { | |||
| 877 | .check_sense = alua_check_sense, | 867 | .check_sense = alua_check_sense, |
| 878 | .activate = alua_activate, | 868 | .activate = alua_activate, |
| 879 | .set_params = alua_set_params, | 869 | .set_params = alua_set_params, |
| 880 | .match = alua_match, | ||
| 881 | }; | 870 | }; |
| 882 | 871 | ||
| 883 | static int __init alua_init(void) | 872 | static int __init alua_init(void) |
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index 6ed1caadbc6a..e6fb97cb12f4 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c | |||
| @@ -72,7 +72,6 @@ static const char * lun_state[] = | |||
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | struct clariion_dh_data { | 74 | struct clariion_dh_data { |
| 75 | struct scsi_dh_data dh_data; | ||
| 76 | /* | 75 | /* |
| 77 | * Flags: | 76 | * Flags: |
| 78 | * CLARIION_SHORT_TRESPASS | 77 | * CLARIION_SHORT_TRESPASS |
| @@ -114,13 +113,6 @@ struct clariion_dh_data { | |||
| 114 | int current_sp; | 113 | int current_sp; |
| 115 | }; | 114 | }; |
| 116 | 115 | ||
| 117 | static inline struct clariion_dh_data | ||
| 118 | *get_clariion_data(struct scsi_device *sdev) | ||
| 119 | { | ||
| 120 | return container_of(sdev->scsi_dh_data, struct clariion_dh_data, | ||
| 121 | dh_data); | ||
| 122 | } | ||
| 123 | |||
| 124 | /* | 116 | /* |
| 125 | * Parse MODE_SELECT cmd reply. | 117 | * Parse MODE_SELECT cmd reply. |
| 126 | */ | 118 | */ |
| @@ -450,7 +442,7 @@ static int clariion_check_sense(struct scsi_device *sdev, | |||
| 450 | 442 | ||
| 451 | static int clariion_prep_fn(struct scsi_device *sdev, struct request *req) | 443 | static int clariion_prep_fn(struct scsi_device *sdev, struct request *req) |
| 452 | { | 444 | { |
| 453 | struct clariion_dh_data *h = get_clariion_data(sdev); | 445 | struct clariion_dh_data *h = sdev->handler_data; |
| 454 | int ret = BLKPREP_OK; | 446 | int ret = BLKPREP_OK; |
| 455 | 447 | ||
| 456 | if (h->lun_state != CLARIION_LUN_OWNED) { | 448 | if (h->lun_state != CLARIION_LUN_OWNED) { |
| @@ -533,7 +525,7 @@ retry: | |||
| 533 | static int clariion_activate(struct scsi_device *sdev, | 525 | static int clariion_activate(struct scsi_device *sdev, |
| 534 | activate_complete fn, void *data) | 526 | activate_complete fn, void *data) |
| 535 | { | 527 | { |
| 536 | struct clariion_dh_data *csdev = get_clariion_data(sdev); | 528 | struct clariion_dh_data *csdev = sdev->handler_data; |
| 537 | int result; | 529 | int result; |
| 538 | 530 | ||
| 539 | result = clariion_send_inquiry(sdev, csdev); | 531 | result = clariion_send_inquiry(sdev, csdev); |
| @@ -574,7 +566,7 @@ done: | |||
| 574 | */ | 566 | */ |
| 575 | static int clariion_set_params(struct scsi_device *sdev, const char *params) | 567 | static int clariion_set_params(struct scsi_device *sdev, const char *params) |
| 576 | { | 568 | { |
| 577 | struct clariion_dh_data *csdev = get_clariion_data(sdev); | 569 | struct clariion_dh_data *csdev = sdev->handler_data; |
| 578 | unsigned int hr = 0, st = 0, argc; | 570 | unsigned int hr = 0, st = 0, argc; |
| 579 | const char *p = params; | 571 | const char *p = params; |
| 580 | int result = SCSI_DH_OK; | 572 | int result = SCSI_DH_OK; |
| @@ -622,42 +614,14 @@ done: | |||
| 622 | return result; | 614 | return result; |
| 623 | } | 615 | } |
| 624 | 616 | ||
| 625 | static const struct { | 617 | static int clariion_bus_attach(struct scsi_device *sdev) |
| 626 | char *vendor; | ||
| 627 | char *model; | ||
| 628 | } clariion_dev_list[] = { | ||
| 629 | {"DGC", "RAID"}, | ||
| 630 | {"DGC", "DISK"}, | ||
| 631 | {"DGC", "VRAID"}, | ||
| 632 | {NULL, NULL}, | ||
| 633 | }; | ||
| 634 | |||
| 635 | static bool clariion_match(struct scsi_device *sdev) | ||
| 636 | { | ||
| 637 | int i; | ||
| 638 | |||
| 639 | if (scsi_device_tpgs(sdev)) | ||
| 640 | return false; | ||
| 641 | |||
| 642 | for (i = 0; clariion_dev_list[i].vendor; i++) { | ||
| 643 | if (!strncmp(sdev->vendor, clariion_dev_list[i].vendor, | ||
| 644 | strlen(clariion_dev_list[i].vendor)) && | ||
| 645 | !strncmp(sdev->model, clariion_dev_list[i].model, | ||
| 646 | strlen(clariion_dev_list[i].model))) { | ||
| 647 | return true; | ||
| 648 | } | ||
| 649 | } | ||
| 650 | return false; | ||
| 651 | } | ||
| 652 | |||
| 653 | static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev) | ||
| 654 | { | 618 | { |
| 655 | struct clariion_dh_data *h; | 619 | struct clariion_dh_data *h; |
| 656 | int err; | 620 | int err; |
| 657 | 621 | ||
| 658 | h = kzalloc(sizeof(*h) , GFP_KERNEL); | 622 | h = kzalloc(sizeof(*h) , GFP_KERNEL); |
| 659 | if (!h) | 623 | if (!h) |
| 660 | return ERR_PTR(-ENOMEM); | 624 | return -ENOMEM; |
| 661 | h->lun_state = CLARIION_LUN_UNINITIALIZED; | 625 | h->lun_state = CLARIION_LUN_UNINITIALIZED; |
| 662 | h->default_sp = CLARIION_UNBOUND_LU; | 626 | h->default_sp = CLARIION_UNBOUND_LU; |
| 663 | h->current_sp = CLARIION_UNBOUND_LU; | 627 | h->current_sp = CLARIION_UNBOUND_LU; |
| @@ -675,18 +639,19 @@ static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev) | |||
| 675 | CLARIION_NAME, h->current_sp + 'A', | 639 | CLARIION_NAME, h->current_sp + 'A', |
| 676 | h->port, lun_state[h->lun_state], | 640 | h->port, lun_state[h->lun_state], |
| 677 | h->default_sp + 'A'); | 641 | h->default_sp + 'A'); |
| 678 | return &h->dh_data; | 642 | |
| 643 | sdev->handler_data = h; | ||
| 644 | return 0; | ||
| 679 | 645 | ||
| 680 | failed: | 646 | failed: |
| 681 | kfree(h); | 647 | kfree(h); |
| 682 | return ERR_PTR(-EINVAL); | 648 | return -EINVAL; |
| 683 | } | 649 | } |
| 684 | 650 | ||
| 685 | static void clariion_bus_detach(struct scsi_device *sdev) | 651 | static void clariion_bus_detach(struct scsi_device *sdev) |
| 686 | { | 652 | { |
| 687 | struct clariion_dh_data *h = get_clariion_data(sdev); | 653 | kfree(sdev->handler_data); |
| 688 | 654 | sdev->handler_data = NULL; | |
| 689 | kfree(h); | ||
| 690 | } | 655 | } |
| 691 | 656 | ||
| 692 | static struct scsi_device_handler clariion_dh = { | 657 | static struct scsi_device_handler clariion_dh = { |
| @@ -698,7 +663,6 @@ static struct scsi_device_handler clariion_dh = { | |||
| 698 | .activate = clariion_activate, | 663 | .activate = clariion_activate, |
| 699 | .prep_fn = clariion_prep_fn, | 664 | .prep_fn = clariion_prep_fn, |
| 700 | .set_params = clariion_set_params, | 665 | .set_params = clariion_set_params, |
| 701 | .match = clariion_match, | ||
| 702 | }; | 666 | }; |
| 703 | 667 | ||
| 704 | static int __init clariion_init(void) | 668 | static int __init clariion_init(void) |
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index 485d99544a15..9406d5f4a3d3 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c | |||
| @@ -38,7 +38,6 @@ | |||
| 38 | #define HP_SW_PATH_PASSIVE 1 | 38 | #define HP_SW_PATH_PASSIVE 1 |
| 39 | 39 | ||
| 40 | struct hp_sw_dh_data { | 40 | struct hp_sw_dh_data { |
| 41 | struct scsi_dh_data dh_data; | ||
| 42 | unsigned char sense[SCSI_SENSE_BUFFERSIZE]; | 41 | unsigned char sense[SCSI_SENSE_BUFFERSIZE]; |
| 43 | int path_state; | 42 | int path_state; |
| 44 | int retries; | 43 | int retries; |
| @@ -50,11 +49,6 @@ struct hp_sw_dh_data { | |||
| 50 | 49 | ||
| 51 | static int hp_sw_start_stop(struct hp_sw_dh_data *); | 50 | static int hp_sw_start_stop(struct hp_sw_dh_data *); |
| 52 | 51 | ||
| 53 | static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev) | ||
| 54 | { | ||
| 55 | return container_of(sdev->scsi_dh_data, struct hp_sw_dh_data, dh_data); | ||
| 56 | } | ||
| 57 | |||
| 58 | /* | 52 | /* |
| 59 | * tur_done - Handle TEST UNIT READY return status | 53 | * tur_done - Handle TEST UNIT READY return status |
| 60 | * @sdev: sdev the command has been sent to | 54 | * @sdev: sdev the command has been sent to |
| @@ -267,7 +261,7 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h) | |||
| 267 | 261 | ||
| 268 | static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req) | 262 | static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req) |
| 269 | { | 263 | { |
| 270 | struct hp_sw_dh_data *h = get_hp_sw_data(sdev); | 264 | struct hp_sw_dh_data *h = sdev->handler_data; |
| 271 | int ret = BLKPREP_OK; | 265 | int ret = BLKPREP_OK; |
| 272 | 266 | ||
| 273 | if (h->path_state != HP_SW_PATH_ACTIVE) { | 267 | if (h->path_state != HP_SW_PATH_ACTIVE) { |
| @@ -292,7 +286,7 @@ static int hp_sw_activate(struct scsi_device *sdev, | |||
| 292 | activate_complete fn, void *data) | 286 | activate_complete fn, void *data) |
| 293 | { | 287 | { |
| 294 | int ret = SCSI_DH_OK; | 288 | int ret = SCSI_DH_OK; |
| 295 | struct hp_sw_dh_data *h = get_hp_sw_data(sdev); | 289 | struct hp_sw_dh_data *h = sdev->handler_data; |
| 296 | 290 | ||
| 297 | ret = hp_sw_tur(sdev, h); | 291 | ret = hp_sw_tur(sdev, h); |
| 298 | 292 | ||
| @@ -311,43 +305,14 @@ static int hp_sw_activate(struct scsi_device *sdev, | |||
| 311 | return 0; | 305 | return 0; |
| 312 | } | 306 | } |
| 313 | 307 | ||
| 314 | static const struct { | 308 | static int hp_sw_bus_attach(struct scsi_device *sdev) |
| 315 | char *vendor; | ||
| 316 | char *model; | ||
| 317 | } hp_sw_dh_data_list[] = { | ||
| 318 | {"COMPAQ", "MSA1000 VOLUME"}, | ||
| 319 | {"COMPAQ", "HSV110"}, | ||
| 320 | {"HP", "HSV100"}, | ||
| 321 | {"DEC", "HSG80"}, | ||
| 322 | {NULL, NULL}, | ||
| 323 | }; | ||
| 324 | |||
| 325 | static bool hp_sw_match(struct scsi_device *sdev) | ||
| 326 | { | ||
| 327 | int i; | ||
| 328 | |||
| 329 | if (scsi_device_tpgs(sdev)) | ||
| 330 | return false; | ||
| 331 | |||
| 332 | for (i = 0; hp_sw_dh_data_list[i].vendor; i++) { | ||
| 333 | if (!strncmp(sdev->vendor, hp_sw_dh_data_list[i].vendor, | ||
| 334 | strlen(hp_sw_dh_data_list[i].vendor)) && | ||
| 335 | !strncmp(sdev->model, hp_sw_dh_data_list[i].model, | ||
| 336 | strlen(hp_sw_dh_data_list[i].model))) { | ||
| 337 | return true; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | return false; | ||
| 341 | } | ||
| 342 | |||
| 343 | static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev) | ||
| 344 | { | 309 | { |
| 345 | struct hp_sw_dh_data *h; | 310 | struct hp_sw_dh_data *h; |
| 346 | int ret; | 311 | int ret; |
| 347 | 312 | ||
| 348 | h = kzalloc(sizeof(*h), GFP_KERNEL); | 313 | h = kzalloc(sizeof(*h), GFP_KERNEL); |
| 349 | if (!h) | 314 | if (!h) |
| 350 | return ERR_PTR(-ENOMEM); | 315 | return -ENOMEM; |
| 351 | h->path_state = HP_SW_PATH_UNINITIALIZED; | 316 | h->path_state = HP_SW_PATH_UNINITIALIZED; |
| 352 | h->retries = HP_SW_RETRIES; | 317 | h->retries = HP_SW_RETRIES; |
| 353 | h->sdev = sdev; | 318 | h->sdev = sdev; |
| @@ -359,17 +324,18 @@ static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev) | |||
| 359 | sdev_printk(KERN_INFO, sdev, "%s: attached to %s path\n", | 324 | sdev_printk(KERN_INFO, sdev, "%s: attached to %s path\n", |
| 360 | HP_SW_NAME, h->path_state == HP_SW_PATH_ACTIVE? | 325 | HP_SW_NAME, h->path_state == HP_SW_PATH_ACTIVE? |
| 361 | "active":"passive"); | 326 | "active":"passive"); |
| 362 | return &h->dh_data; | 327 | |
| 328 | sdev->handler_data = h; | ||
| 329 | return 0; | ||
| 363 | failed: | 330 | failed: |
| 364 | kfree(h); | 331 | kfree(h); |
| 365 | return ERR_PTR(-EINVAL); | 332 | return -EINVAL; |
| 366 | } | 333 | } |
| 367 | 334 | ||
| 368 | static void hp_sw_bus_detach( struct scsi_device *sdev ) | 335 | static void hp_sw_bus_detach( struct scsi_device *sdev ) |
| 369 | { | 336 | { |
| 370 | struct hp_sw_dh_data *h = get_hp_sw_data(sdev); | 337 | kfree(sdev->handler_data); |
| 371 | 338 | sdev->handler_data = NULL; | |
| 372 | kfree(h); | ||
| 373 | } | 339 | } |
| 374 | 340 | ||
| 375 | static struct scsi_device_handler hp_sw_dh = { | 341 | static struct scsi_device_handler hp_sw_dh = { |
| @@ -379,7 +345,6 @@ static struct scsi_device_handler hp_sw_dh = { | |||
| 379 | .detach = hp_sw_bus_detach, | 345 | .detach = hp_sw_bus_detach, |
| 380 | .activate = hp_sw_activate, | 346 | .activate = hp_sw_activate, |
| 381 | .prep_fn = hp_sw_prep_fn, | 347 | .prep_fn = hp_sw_prep_fn, |
| 382 | .match = hp_sw_match, | ||
| 383 | }; | 348 | }; |
| 384 | 349 | ||
| 385 | static int __init hp_sw_init(void) | 350 | static int __init hp_sw_init(void) |
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index b46ace3d4bf0..361358134315 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |||
| @@ -181,7 +181,6 @@ struct c2_inquiry { | |||
| 181 | }; | 181 | }; |
| 182 | 182 | ||
| 183 | struct rdac_dh_data { | 183 | struct rdac_dh_data { |
| 184 | struct scsi_dh_data dh_data; | ||
| 185 | struct rdac_controller *ctlr; | 184 | struct rdac_controller *ctlr; |
| 186 | #define UNINITIALIZED_LUN (1 << 8) | 185 | #define UNINITIALIZED_LUN (1 << 8) |
| 187 | unsigned lun; | 186 | unsigned lun; |
| @@ -260,11 +259,6 @@ do { \ | |||
| 260 | sdev_printk(KERN_INFO, sdev, RDAC_NAME ": " f "\n", ## arg); \ | 259 | sdev_printk(KERN_INFO, sdev, RDAC_NAME ": " f "\n", ## arg); \ |
| 261 | } while (0); | 260 | } while (0); |
| 262 | 261 | ||
| 263 | static inline struct rdac_dh_data *get_rdac_data(struct scsi_device *sdev) | ||
| 264 | { | ||
| 265 | return container_of(sdev->scsi_dh_data, struct rdac_dh_data, dh_data); | ||
| 266 | } | ||
| 267 | |||
| 268 | static struct request *get_rdac_req(struct scsi_device *sdev, | 262 | static struct request *get_rdac_req(struct scsi_device *sdev, |
| 269 | void *buffer, unsigned buflen, int rw) | 263 | void *buffer, unsigned buflen, int rw) |
| 270 | { | 264 | { |
| @@ -544,7 +538,7 @@ static int mode_select_handle_sense(struct scsi_device *sdev, | |||
| 544 | { | 538 | { |
| 545 | struct scsi_sense_hdr sense_hdr; | 539 | struct scsi_sense_hdr sense_hdr; |
| 546 | int err = SCSI_DH_IO, ret; | 540 | int err = SCSI_DH_IO, ret; |
| 547 | struct rdac_dh_data *h = get_rdac_data(sdev); | 541 | struct rdac_dh_data *h = sdev->handler_data; |
| 548 | 542 | ||
| 549 | ret = scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, &sense_hdr); | 543 | ret = scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, &sense_hdr); |
| 550 | if (!ret) | 544 | if (!ret) |
| @@ -589,7 +583,7 @@ static void send_mode_select(struct work_struct *work) | |||
| 589 | container_of(work, struct rdac_controller, ms_work); | 583 | container_of(work, struct rdac_controller, ms_work); |
| 590 | struct request *rq; | 584 | struct request *rq; |
| 591 | struct scsi_device *sdev = ctlr->ms_sdev; | 585 | struct scsi_device *sdev = ctlr->ms_sdev; |
| 592 | struct rdac_dh_data *h = get_rdac_data(sdev); | 586 | struct rdac_dh_data *h = sdev->handler_data; |
| 593 | struct request_queue *q = sdev->request_queue; | 587 | struct request_queue *q = sdev->request_queue; |
| 594 | int err, retry_cnt = RDAC_RETRY_COUNT; | 588 | int err, retry_cnt = RDAC_RETRY_COUNT; |
| 595 | struct rdac_queue_data *tmp, *qdata; | 589 | struct rdac_queue_data *tmp, *qdata; |
| @@ -648,7 +642,7 @@ static int queue_mode_select(struct scsi_device *sdev, | |||
| 648 | if (!qdata) | 642 | if (!qdata) |
| 649 | return SCSI_DH_RETRY; | 643 | return SCSI_DH_RETRY; |
| 650 | 644 | ||
| 651 | qdata->h = get_rdac_data(sdev); | 645 | qdata->h = sdev->handler_data; |
| 652 | qdata->callback_fn = fn; | 646 | qdata->callback_fn = fn; |
| 653 | qdata->callback_data = data; | 647 | qdata->callback_data = data; |
| 654 | 648 | ||
| @@ -667,7 +661,7 @@ static int queue_mode_select(struct scsi_device *sdev, | |||
| 667 | static int rdac_activate(struct scsi_device *sdev, | 661 | static int rdac_activate(struct scsi_device *sdev, |
| 668 | activate_complete fn, void *data) | 662 | activate_complete fn, void *data) |
| 669 | { | 663 | { |
| 670 | struct rdac_dh_data *h = get_rdac_data(sdev); | 664 | struct rdac_dh_data *h = sdev->handler_data; |
| 671 | int err = SCSI_DH_OK; | 665 | int err = SCSI_DH_OK; |
| 672 | int act = 0; | 666 | int act = 0; |
| 673 | 667 | ||
| @@ -702,7 +696,7 @@ done: | |||
| 702 | 696 | ||
| 703 | static int rdac_prep_fn(struct scsi_device *sdev, struct request *req) | 697 | static int rdac_prep_fn(struct scsi_device *sdev, struct request *req) |
| 704 | { | 698 | { |
| 705 | struct rdac_dh_data *h = get_rdac_data(sdev); | 699 | struct rdac_dh_data *h = sdev->handler_data; |
| 706 | int ret = BLKPREP_OK; | 700 | int ret = BLKPREP_OK; |
| 707 | 701 | ||
| 708 | if (h->state != RDAC_STATE_ACTIVE) { | 702 | if (h->state != RDAC_STATE_ACTIVE) { |
| @@ -716,7 +710,7 @@ static int rdac_prep_fn(struct scsi_device *sdev, struct request *req) | |||
| 716 | static int rdac_check_sense(struct scsi_device *sdev, | 710 | static int rdac_check_sense(struct scsi_device *sdev, |
| 717 | struct scsi_sense_hdr *sense_hdr) | 711 | struct scsi_sense_hdr *sense_hdr) |
| 718 | { | 712 | { |
| 719 | struct rdac_dh_data *h = get_rdac_data(sdev); | 713 | struct rdac_dh_data *h = sdev->handler_data; |
| 720 | 714 | ||
| 721 | RDAC_LOG(RDAC_LOG_SENSE, sdev, "array %s, ctlr %d, " | 715 | RDAC_LOG(RDAC_LOG_SENSE, sdev, "array %s, ctlr %d, " |
| 722 | "I/O returned with sense %02x/%02x/%02x", | 716 | "I/O returned with sense %02x/%02x/%02x", |
| @@ -778,56 +772,7 @@ static int rdac_check_sense(struct scsi_device *sdev, | |||
| 778 | return SCSI_RETURN_NOT_HANDLED; | 772 | return SCSI_RETURN_NOT_HANDLED; |
| 779 | } | 773 | } |
| 780 | 774 | ||
| 781 | static const struct { | 775 | static int rdac_bus_attach(struct scsi_device *sdev) |
| 782 | char *vendor; | ||
| 783 | char *model; | ||
| 784 | } rdac_dev_list[] = { | ||
| 785 | {"IBM", "1722"}, | ||
| 786 | {"IBM", "1724"}, | ||
| 787 | {"IBM", "1726"}, | ||
| 788 | {"IBM", "1742"}, | ||
| 789 | {"IBM", "1745"}, | ||
| 790 | {"IBM", "1746"}, | ||
| 791 | {"IBM", "1813"}, | ||
| 792 | {"IBM", "1814"}, | ||
| 793 | {"IBM", "1815"}, | ||
| 794 | {"IBM", "1818"}, | ||
| 795 | {"IBM", "3526"}, | ||
| 796 | {"SGI", "TP9"}, | ||
| 797 | {"SGI", "IS"}, | ||
| 798 | {"STK", "OPENstorage D280"}, | ||
| 799 | {"STK", "FLEXLINE 380"}, | ||
| 800 | {"SUN", "CSM"}, | ||
| 801 | {"SUN", "LCSM100"}, | ||
| 802 | {"SUN", "STK6580_6780"}, | ||
| 803 | {"SUN", "SUN_6180"}, | ||
| 804 | {"SUN", "ArrayStorage"}, | ||
| 805 | {"DELL", "MD3"}, | ||
| 806 | {"NETAPP", "INF-01-00"}, | ||
| 807 | {"LSI", "INF-01-00"}, | ||
| 808 | {"ENGENIO", "INF-01-00"}, | ||
| 809 | {NULL, NULL}, | ||
| 810 | }; | ||
| 811 | |||
| 812 | static bool rdac_match(struct scsi_device *sdev) | ||
| 813 | { | ||
| 814 | int i; | ||
| 815 | |||
| 816 | if (scsi_device_tpgs(sdev)) | ||
| 817 | return false; | ||
| 818 | |||
| 819 | for (i = 0; rdac_dev_list[i].vendor; i++) { | ||
| 820 | if (!strncmp(sdev->vendor, rdac_dev_list[i].vendor, | ||
| 821 | strlen(rdac_dev_list[i].vendor)) && | ||
| 822 | !strncmp(sdev->model, rdac_dev_list[i].model, | ||
| 823 | strlen(rdac_dev_list[i].model))) { | ||
| 824 | return true; | ||
| 825 | } | ||
| 826 | } | ||
| 827 | return false; | ||
| 828 | } | ||
| 829 | |||
| 830 | static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev) | ||
| 831 | { | 776 | { |
| 832 | struct rdac_dh_data *h; | 777 | struct rdac_dh_data *h; |
| 833 | int err; | 778 | int err; |
| @@ -836,7 +781,7 @@ static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev) | |||
| 836 | 781 | ||
| 837 | h = kzalloc(sizeof(*h) , GFP_KERNEL); | 782 | h = kzalloc(sizeof(*h) , GFP_KERNEL); |
| 838 | if (!h) | 783 | if (!h) |
| 839 | return ERR_PTR(-ENOMEM); | 784 | return -ENOMEM; |
| 840 | h->lun = UNINITIALIZED_LUN; | 785 | h->lun = UNINITIALIZED_LUN; |
| 841 | h->state = RDAC_STATE_ACTIVE; | 786 | h->state = RDAC_STATE_ACTIVE; |
| 842 | 787 | ||
| @@ -861,7 +806,8 @@ static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev) | |||
| 861 | RDAC_NAME, h->lun, mode[(int)h->mode], | 806 | RDAC_NAME, h->lun, mode[(int)h->mode], |
| 862 | lun_state[(int)h->lun_state]); | 807 | lun_state[(int)h->lun_state]); |
| 863 | 808 | ||
| 864 | return &h->dh_data; | 809 | sdev->handler_data = h; |
| 810 | return 0; | ||
| 865 | 811 | ||
| 866 | clean_ctlr: | 812 | clean_ctlr: |
| 867 | spin_lock(&list_lock); | 813 | spin_lock(&list_lock); |
| @@ -870,12 +816,12 @@ clean_ctlr: | |||
| 870 | 816 | ||
| 871 | failed: | 817 | failed: |
| 872 | kfree(h); | 818 | kfree(h); |
| 873 | return ERR_PTR(-EINVAL); | 819 | return -EINVAL; |
| 874 | } | 820 | } |
| 875 | 821 | ||
| 876 | static void rdac_bus_detach( struct scsi_device *sdev ) | 822 | static void rdac_bus_detach( struct scsi_device *sdev ) |
| 877 | { | 823 | { |
| 878 | struct rdac_dh_data *h = get_rdac_data(sdev); | 824 | struct rdac_dh_data *h = sdev->handler_data; |
| 879 | 825 | ||
| 880 | if (h->ctlr && h->ctlr->ms_queued) | 826 | if (h->ctlr && h->ctlr->ms_queued) |
| 881 | flush_workqueue(kmpath_rdacd); | 827 | flush_workqueue(kmpath_rdacd); |
| @@ -884,6 +830,7 @@ static void rdac_bus_detach( struct scsi_device *sdev ) | |||
| 884 | if (h->ctlr) | 830 | if (h->ctlr) |
| 885 | kref_put(&h->ctlr->kref, release_controller); | 831 | kref_put(&h->ctlr->kref, release_controller); |
| 886 | spin_unlock(&list_lock); | 832 | spin_unlock(&list_lock); |
| 833 | sdev->handler_data = NULL; | ||
| 887 | kfree(h); | 834 | kfree(h); |
| 888 | } | 835 | } |
| 889 | 836 | ||
| @@ -895,7 +842,6 @@ static struct scsi_device_handler rdac_dh = { | |||
| 895 | .attach = rdac_bus_attach, | 842 | .attach = rdac_bus_attach, |
| 896 | .detach = rdac_bus_detach, | 843 | .detach = rdac_bus_detach, |
| 897 | .activate = rdac_activate, | 844 | .activate = rdac_activate, |
| 898 | .match = rdac_match, | ||
| 899 | }; | 845 | }; |
| 900 | 846 | ||
| 901 | static int __init rdac_init(void) | 847 | static int __init rdac_init(void) |
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index ec193a8357d7..d3eb80c46bbe 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
| @@ -364,7 +364,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe, | |||
| 364 | * on the ethertype for the given device | 364 | * on the ethertype for the given device |
| 365 | */ | 365 | */ |
| 366 | fcoe->fcoe_packet_type.func = fcoe_rcv; | 366 | fcoe->fcoe_packet_type.func = fcoe_rcv; |
| 367 | fcoe->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE); | 367 | fcoe->fcoe_packet_type.type = htons(ETH_P_FCOE); |
| 368 | fcoe->fcoe_packet_type.dev = netdev; | 368 | fcoe->fcoe_packet_type.dev = netdev; |
| 369 | dev_add_pack(&fcoe->fcoe_packet_type); | 369 | dev_add_pack(&fcoe->fcoe_packet_type); |
| 370 | 370 | ||
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 341191952155..b62836ddbbee 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
| @@ -4555,7 +4555,7 @@ static ssize_t ipr_store_raw_mode(struct device *dev, | |||
| 4555 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | 4555 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); |
| 4556 | res = (struct ipr_resource_entry *)sdev->hostdata; | 4556 | res = (struct ipr_resource_entry *)sdev->hostdata; |
| 4557 | if (res) { | 4557 | if (res) { |
| 4558 | if (ioa_cfg->sis64 && ipr_is_af_dasd_device(res)) { | 4558 | if (ipr_is_af_dasd_device(res)) { |
| 4559 | res->raw_mode = simple_strtoul(buf, NULL, 10); | 4559 | res->raw_mode = simple_strtoul(buf, NULL, 10); |
| 4560 | len = strlen(buf); | 4560 | len = strlen(buf); |
| 4561 | if (res->sdev) | 4561 | if (res->sdev) |
| @@ -6383,9 +6383,13 @@ static int ipr_queuecommand(struct Scsi_Host *shost, | |||
| 6383 | (!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE)) { | 6383 | (!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE)) { |
| 6384 | ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD; | 6384 | ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD; |
| 6385 | } | 6385 | } |
| 6386 | if (res->raw_mode && ipr_is_af_dasd_device(res)) | 6386 | if (res->raw_mode && ipr_is_af_dasd_device(res)) { |
| 6387 | ioarcb->cmd_pkt.request_type = IPR_RQTYPE_PIPE; | 6387 | ioarcb->cmd_pkt.request_type = IPR_RQTYPE_PIPE; |
| 6388 | 6388 | ||
| 6389 | if (scsi_cmd->underflow == 0) | ||
| 6390 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_ULEN_CHK; | ||
| 6391 | } | ||
| 6392 | |||
| 6389 | if (ioa_cfg->sis64) | 6393 | if (ioa_cfg->sis64) |
| 6390 | rc = ipr_build_ioadl64(ioa_cfg, ipr_cmd); | 6394 | rc = ipr_build_ioadl64(ioa_cfg, ipr_cmd); |
| 6391 | else | 6395 | else |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 98d9bb6ff725..33c74d3436c9 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
| @@ -853,12 +853,9 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
| 853 | SAM_STAT_CHECK_CONDITION; | 853 | SAM_STAT_CHECK_CONDITION; |
| 854 | scsi_build_sense_buffer(1, sc->sense_buffer, | 854 | scsi_build_sense_buffer(1, sc->sense_buffer, |
| 855 | ILLEGAL_REQUEST, 0x10, ascq); | 855 | ILLEGAL_REQUEST, 0x10, ascq); |
| 856 | sc->sense_buffer[7] = 0xc; /* Additional sense length */ | 856 | scsi_set_sense_information(sc->sense_buffer, |
| 857 | sc->sense_buffer[8] = 0; /* Information desc type */ | 857 | SCSI_SENSE_BUFFERSIZE, |
| 858 | sc->sense_buffer[9] = 0xa; /* Additional desc length */ | 858 | sector); |
| 859 | sc->sense_buffer[10] = 0x80; /* Validity bit */ | ||
| 860 | |||
| 861 | put_unaligned_be64(sector, &sc->sense_buffer[12]); | ||
| 862 | goto out; | 859 | goto out; |
| 863 | } | 860 | } |
| 864 | } | 861 | } |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index eb627724417e..4abb93a83e0f 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
| @@ -2284,7 +2284,7 @@ lpfc_mbx_cmpl_rdp_page_a2(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) | |||
| 2284 | (struct lpfc_rdp_context *)(mbox->context2); | 2284 | (struct lpfc_rdp_context *)(mbox->context2); |
| 2285 | 2285 | ||
| 2286 | if (bf_get(lpfc_mqe_status, &mbox->u.mqe)) | 2286 | if (bf_get(lpfc_mqe_status, &mbox->u.mqe)) |
| 2287 | goto error; | 2287 | goto error_mbuf_free; |
| 2288 | 2288 | ||
| 2289 | lpfc_sli_bemem_bcopy(mp->virt, &rdp_context->page_a2, | 2289 | lpfc_sli_bemem_bcopy(mp->virt, &rdp_context->page_a2, |
| 2290 | DMP_SFF_PAGE_A2_SIZE); | 2290 | DMP_SFF_PAGE_A2_SIZE); |
| @@ -2299,13 +2299,14 @@ lpfc_mbx_cmpl_rdp_page_a2(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox) | |||
| 2299 | mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_link_stat; | 2299 | mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_link_stat; |
| 2300 | mbox->context2 = (struct lpfc_rdp_context *) rdp_context; | 2300 | mbox->context2 = (struct lpfc_rdp_context *) rdp_context; |
| 2301 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) == MBX_NOT_FINISHED) | 2301 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) == MBX_NOT_FINISHED) |
| 2302 | goto error; | 2302 | goto error_cmd_free; |
| 2303 | 2303 | ||
| 2304 | return; | 2304 | return; |
| 2305 | 2305 | ||
| 2306 | error: | 2306 | error_mbuf_free: |
| 2307 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 2307 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
| 2308 | kfree(mp); | 2308 | kfree(mp); |
| 2309 | error_cmd_free: | ||
| 2309 | lpfc_sli4_mbox_cmd_free(phba, mbox); | 2310 | lpfc_sli4_mbox_cmd_free(phba, mbox); |
| 2310 | rdp_context->cmpl(phba, rdp_context, FAILURE); | 2311 | rdp_context->cmpl(phba, rdp_context, FAILURE); |
| 2311 | } | 2312 | } |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 6dec7cff316f..c167911221e9 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
| @@ -112,9 +112,12 @@ _scsih_set_fwfault_debug(const char *val, struct kernel_param *kp) | |||
| 112 | if (ret) | 112 | if (ret) |
| 113 | return ret; | 113 | return ret; |
| 114 | 114 | ||
| 115 | /* global ioc spinlock to protect controller list on list operations */ | ||
| 115 | printk(KERN_INFO "setting fwfault_debug(%d)\n", mpt2sas_fwfault_debug); | 116 | printk(KERN_INFO "setting fwfault_debug(%d)\n", mpt2sas_fwfault_debug); |
| 117 | spin_lock(&gioc_lock); | ||
| 116 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) | 118 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) |
| 117 | ioc->fwfault_debug = mpt2sas_fwfault_debug; | 119 | ioc->fwfault_debug = mpt2sas_fwfault_debug; |
| 120 | spin_unlock(&gioc_lock); | ||
| 118 | return 0; | 121 | return 0; |
| 119 | } | 122 | } |
| 120 | 123 | ||
| @@ -4437,6 +4440,8 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | |||
| 4437 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, | 4440 | dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, |
| 4438 | __func__)); | 4441 | __func__)); |
| 4439 | 4442 | ||
| 4443 | /* synchronizing freeing resource with pci_access_mutex lock */ | ||
| 4444 | mutex_lock(&ioc->pci_access_mutex); | ||
| 4440 | if (ioc->chip_phys && ioc->chip) { | 4445 | if (ioc->chip_phys && ioc->chip) { |
| 4441 | _base_mask_interrupts(ioc); | 4446 | _base_mask_interrupts(ioc); |
| 4442 | ioc->shost_recovery = 1; | 4447 | ioc->shost_recovery = 1; |
| @@ -4456,6 +4461,7 @@ mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc) | |||
| 4456 | pci_disable_pcie_error_reporting(pdev); | 4461 | pci_disable_pcie_error_reporting(pdev); |
| 4457 | pci_disable_device(pdev); | 4462 | pci_disable_device(pdev); |
| 4458 | } | 4463 | } |
| 4464 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 4459 | return; | 4465 | return; |
| 4460 | } | 4466 | } |
| 4461 | 4467 | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index caff8d10cca4..97ea360c6920 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
| @@ -238,6 +238,7 @@ | |||
| 238 | * @flags: MPT_TARGET_FLAGS_XXX flags | 238 | * @flags: MPT_TARGET_FLAGS_XXX flags |
| 239 | * @deleted: target flaged for deletion | 239 | * @deleted: target flaged for deletion |
| 240 | * @tm_busy: target is busy with TM request. | 240 | * @tm_busy: target is busy with TM request. |
| 241 | * @sdev: The sas_device associated with this target | ||
| 241 | */ | 242 | */ |
| 242 | struct MPT2SAS_TARGET { | 243 | struct MPT2SAS_TARGET { |
| 243 | struct scsi_target *starget; | 244 | struct scsi_target *starget; |
| @@ -248,6 +249,7 @@ struct MPT2SAS_TARGET { | |||
| 248 | u32 flags; | 249 | u32 flags; |
| 249 | u8 deleted; | 250 | u8 deleted; |
| 250 | u8 tm_busy; | 251 | u8 tm_busy; |
| 252 | struct _sas_device *sdev; | ||
| 251 | }; | 253 | }; |
| 252 | 254 | ||
| 253 | 255 | ||
| @@ -376,8 +378,24 @@ struct _sas_device { | |||
| 376 | u8 phy; | 378 | u8 phy; |
| 377 | u8 responding; | 379 | u8 responding; |
| 378 | u8 pfa_led_on; | 380 | u8 pfa_led_on; |
| 381 | struct kref refcount; | ||
| 379 | }; | 382 | }; |
| 380 | 383 | ||
| 384 | static inline void sas_device_get(struct _sas_device *s) | ||
| 385 | { | ||
| 386 | kref_get(&s->refcount); | ||
| 387 | } | ||
| 388 | |||
| 389 | static inline void sas_device_free(struct kref *r) | ||
| 390 | { | ||
| 391 | kfree(container_of(r, struct _sas_device, refcount)); | ||
| 392 | } | ||
| 393 | |||
| 394 | static inline void sas_device_put(struct _sas_device *s) | ||
| 395 | { | ||
| 396 | kref_put(&s->refcount, sas_device_free); | ||
| 397 | } | ||
| 398 | |||
| 381 | /** | 399 | /** |
| 382 | * struct _raid_device - raid volume link list | 400 | * struct _raid_device - raid volume link list |
| 383 | * @list: sas device list | 401 | * @list: sas device list |
| @@ -799,6 +817,12 @@ typedef void (*MPT2SAS_FLUSH_RUNNING_CMDS)(struct MPT2SAS_ADAPTER *ioc); | |||
| 799 | * @delayed_tr_list: target reset link list | 817 | * @delayed_tr_list: target reset link list |
| 800 | * @delayed_tr_volume_list: volume target reset link list | 818 | * @delayed_tr_volume_list: volume target reset link list |
| 801 | * @@temp_sensors_count: flag to carry the number of temperature sensors | 819 | * @@temp_sensors_count: flag to carry the number of temperature sensors |
| 820 | * @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and | ||
| 821 | * pci resource handling. PCI resource freeing will lead to free | ||
| 822 | * vital hardware/memory resource, which might be in use by cli/sysfs | ||
| 823 | * path functions resulting in Null pointer reference followed by kernel | ||
| 824 | * crash. To avoid the above race condition we use mutex syncrhonization | ||
| 825 | * which ensures the syncrhonization between cli/sysfs_show path | ||
| 802 | */ | 826 | */ |
| 803 | struct MPT2SAS_ADAPTER { | 827 | struct MPT2SAS_ADAPTER { |
| 804 | struct list_head list; | 828 | struct list_head list; |
| @@ -1015,6 +1039,7 @@ struct MPT2SAS_ADAPTER { | |||
| 1015 | u8 mfg_pg10_hide_flag; | 1039 | u8 mfg_pg10_hide_flag; |
| 1016 | u8 hide_drives; | 1040 | u8 hide_drives; |
| 1017 | 1041 | ||
| 1042 | struct mutex pci_access_mutex; | ||
| 1018 | }; | 1043 | }; |
| 1019 | 1044 | ||
| 1020 | typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | 1045 | typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
| @@ -1023,6 +1048,17 @@ typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | |||
| 1023 | 1048 | ||
| 1024 | /* base shared API */ | 1049 | /* base shared API */ |
| 1025 | extern struct list_head mpt2sas_ioc_list; | 1050 | extern struct list_head mpt2sas_ioc_list; |
| 1051 | /* spinlock on list operations over IOCs | ||
| 1052 | * Case: when multiple warpdrive cards(IOCs) are in use | ||
| 1053 | * Each IOC will added to the ioc list stucture on initialization. | ||
| 1054 | * Watchdog threads run at regular intervals to check IOC for any | ||
| 1055 | * fault conditions which will trigger the dead_ioc thread to | ||
| 1056 | * deallocate pci resource, resulting deleting the IOC netry from list, | ||
| 1057 | * this deletion need to protected by spinlock to enusre that | ||
| 1058 | * ioc removal is syncrhonized, if not synchronized it might lead to | ||
| 1059 | * list_del corruption as the ioc list is traversed in cli path | ||
| 1060 | */ | ||
| 1061 | extern spinlock_t gioc_lock; | ||
| 1026 | void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc); | 1062 | void mpt2sas_base_start_watchdog(struct MPT2SAS_ADAPTER *ioc); |
| 1027 | void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc); | 1063 | void mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc); |
| 1028 | 1064 | ||
| @@ -1095,11 +1131,12 @@ struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER * | |||
| 1095 | u16 handle); | 1131 | u16 handle); |
| 1096 | struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER | 1132 | struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER |
| 1097 | *ioc, u64 sas_address); | 1133 | *ioc, u64 sas_address); |
| 1098 | struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address( | 1134 | struct _sas_device *mpt2sas_get_sdev_by_addr( |
| 1135 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); | ||
| 1136 | struct _sas_device *__mpt2sas_get_sdev_by_addr( | ||
| 1099 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); | 1137 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); |
| 1100 | 1138 | ||
| 1101 | void mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc); | 1139 | void mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc); |
| 1102 | |||
| 1103 | void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); | 1140 | void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); |
| 1104 | 1141 | ||
| 1105 | /* config shared API */ | 1142 | /* config shared API */ |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index 4e509604b571..3694b63bd993 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c | |||
| @@ -427,13 +427,16 @@ static int | |||
| 427 | _ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp) | 427 | _ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp) |
| 428 | { | 428 | { |
| 429 | struct MPT2SAS_ADAPTER *ioc; | 429 | struct MPT2SAS_ADAPTER *ioc; |
| 430 | 430 | /* global ioc lock to protect controller on list operations */ | |
| 431 | spin_lock(&gioc_lock); | ||
| 431 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { | 432 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { |
| 432 | if (ioc->id != ioc_number) | 433 | if (ioc->id != ioc_number) |
| 433 | continue; | 434 | continue; |
| 435 | spin_unlock(&gioc_lock); | ||
| 434 | *iocpp = ioc; | 436 | *iocpp = ioc; |
| 435 | return ioc_number; | 437 | return ioc_number; |
| 436 | } | 438 | } |
| 439 | spin_unlock(&gioc_lock); | ||
| 437 | *iocpp = NULL; | 440 | *iocpp = NULL; |
| 438 | return -1; | 441 | return -1; |
| 439 | } | 442 | } |
| @@ -522,10 +525,15 @@ _ctl_poll(struct file *filep, poll_table *wait) | |||
| 522 | 525 | ||
| 523 | poll_wait(filep, &ctl_poll_wait, wait); | 526 | poll_wait(filep, &ctl_poll_wait, wait); |
| 524 | 527 | ||
| 528 | /* global ioc lock to protect controller on list operations */ | ||
| 529 | spin_lock(&gioc_lock); | ||
| 525 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { | 530 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) { |
| 526 | if (ioc->aen_event_read_flag) | 531 | if (ioc->aen_event_read_flag) { |
| 532 | spin_unlock(&gioc_lock); | ||
| 527 | return POLLIN | POLLRDNORM; | 533 | return POLLIN | POLLRDNORM; |
| 534 | } | ||
| 528 | } | 535 | } |
| 536 | spin_unlock(&gioc_lock); | ||
| 529 | return 0; | 537 | return 0; |
| 530 | } | 538 | } |
| 531 | 539 | ||
| @@ -2168,16 +2176,23 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, | |||
| 2168 | 2176 | ||
| 2169 | if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc) | 2177 | if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc) |
| 2170 | return -ENODEV; | 2178 | return -ENODEV; |
| 2179 | /* pci_access_mutex lock acquired by ioctl path */ | ||
| 2180 | mutex_lock(&ioc->pci_access_mutex); | ||
| 2171 | if (ioc->shost_recovery || ioc->pci_error_recovery || | 2181 | if (ioc->shost_recovery || ioc->pci_error_recovery || |
| 2172 | ioc->is_driver_loading) | 2182 | ioc->is_driver_loading || ioc->remove_host) { |
| 2173 | return -EAGAIN; | 2183 | ret = -EAGAIN; |
| 2184 | goto out_unlock_pciaccess; | ||
| 2185 | } | ||
| 2174 | 2186 | ||
| 2175 | state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING; | 2187 | state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING; |
| 2176 | if (state == NON_BLOCKING) { | 2188 | if (state == NON_BLOCKING) { |
| 2177 | if (!mutex_trylock(&ioc->ctl_cmds.mutex)) | 2189 | if (!mutex_trylock(&ioc->ctl_cmds.mutex)) { |
| 2178 | return -EAGAIN; | 2190 | ret = -EAGAIN; |
| 2191 | goto out_unlock_pciaccess; | ||
| 2192 | } | ||
| 2179 | } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) { | 2193 | } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) { |
| 2180 | return -ERESTARTSYS; | 2194 | ret = -ERESTARTSYS; |
| 2195 | goto out_unlock_pciaccess; | ||
| 2181 | } | 2196 | } |
| 2182 | 2197 | ||
| 2183 | switch (cmd) { | 2198 | switch (cmd) { |
| @@ -2258,6 +2273,8 @@ _ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, | |||
| 2258 | } | 2273 | } |
| 2259 | 2274 | ||
| 2260 | mutex_unlock(&ioc->ctl_cmds.mutex); | 2275 | mutex_unlock(&ioc->ctl_cmds.mutex); |
| 2276 | out_unlock_pciaccess: | ||
| 2277 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2261 | return ret; | 2278 | return ret; |
| 2262 | } | 2279 | } |
| 2263 | 2280 | ||
| @@ -2711,6 +2728,12 @@ _ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr, | |||
| 2711 | "warpdrive\n", ioc->name, __func__); | 2728 | "warpdrive\n", ioc->name, __func__); |
| 2712 | goto out; | 2729 | goto out; |
| 2713 | } | 2730 | } |
| 2731 | /* pci_access_mutex lock acquired by sysfs show path */ | ||
| 2732 | mutex_lock(&ioc->pci_access_mutex); | ||
| 2733 | if (ioc->pci_error_recovery || ioc->remove_host) { | ||
| 2734 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2735 | return 0; | ||
| 2736 | } | ||
| 2714 | 2737 | ||
| 2715 | /* allocate upto GPIOVal 36 entries */ | 2738 | /* allocate upto GPIOVal 36 entries */ |
| 2716 | sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36); | 2739 | sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36); |
| @@ -2749,6 +2772,7 @@ _ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr, | |||
| 2749 | 2772 | ||
| 2750 | out: | 2773 | out: |
| 2751 | kfree(io_unit_pg3); | 2774 | kfree(io_unit_pg3); |
| 2775 | mutex_unlock(&ioc->pci_access_mutex); | ||
| 2752 | return rc; | 2776 | return rc; |
| 2753 | } | 2777 | } |
| 2754 | static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL); | 2778 | static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 3f26147bbc64..0ad09b2bff9c 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
| @@ -79,7 +79,8 @@ static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time); | |||
| 79 | 79 | ||
| 80 | /* global parameters */ | 80 | /* global parameters */ |
| 81 | LIST_HEAD(mpt2sas_ioc_list); | 81 | LIST_HEAD(mpt2sas_ioc_list); |
| 82 | 82 | /* global ioc lock for list operations */ | |
| 83 | DEFINE_SPINLOCK(gioc_lock); | ||
| 83 | /* local parameters */ | 84 | /* local parameters */ |
| 84 | static u8 scsi_io_cb_idx = -1; | 85 | static u8 scsi_io_cb_idx = -1; |
| 85 | static u8 tm_cb_idx = -1; | 86 | static u8 tm_cb_idx = -1; |
| @@ -176,9 +177,37 @@ struct fw_event_work { | |||
| 176 | u8 VP_ID; | 177 | u8 VP_ID; |
| 177 | u8 ignore; | 178 | u8 ignore; |
| 178 | u16 event; | 179 | u16 event; |
| 180 | struct kref refcount; | ||
| 179 | char event_data[0] __aligned(4); | 181 | char event_data[0] __aligned(4); |
| 180 | }; | 182 | }; |
| 181 | 183 | ||
| 184 | static void fw_event_work_free(struct kref *r) | ||
| 185 | { | ||
| 186 | kfree(container_of(r, struct fw_event_work, refcount)); | ||
| 187 | } | ||
| 188 | |||
| 189 | static void fw_event_work_get(struct fw_event_work *fw_work) | ||
| 190 | { | ||
| 191 | kref_get(&fw_work->refcount); | ||
| 192 | } | ||
| 193 | |||
| 194 | static void fw_event_work_put(struct fw_event_work *fw_work) | ||
| 195 | { | ||
| 196 | kref_put(&fw_work->refcount, fw_event_work_free); | ||
| 197 | } | ||
| 198 | |||
| 199 | static struct fw_event_work *alloc_fw_event_work(int len) | ||
| 200 | { | ||
| 201 | struct fw_event_work *fw_event; | ||
| 202 | |||
| 203 | fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC); | ||
| 204 | if (!fw_event) | ||
| 205 | return NULL; | ||
| 206 | |||
| 207 | kref_init(&fw_event->refcount); | ||
| 208 | return fw_event; | ||
| 209 | } | ||
| 210 | |||
| 182 | /* raid transport support */ | 211 | /* raid transport support */ |
| 183 | static struct raid_template *mpt2sas_raid_template; | 212 | static struct raid_template *mpt2sas_raid_template; |
| 184 | 213 | ||
| @@ -293,8 +322,10 @@ _scsih_set_debug_level(const char *val, struct kernel_param *kp) | |||
| 293 | return ret; | 322 | return ret; |
| 294 | 323 | ||
| 295 | printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level); | 324 | printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level); |
| 325 | spin_lock(&gioc_lock); | ||
| 296 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) | 326 | list_for_each_entry(ioc, &mpt2sas_ioc_list, list) |
| 297 | ioc->logging_level = logging_level; | 327 | ioc->logging_level = logging_level; |
| 328 | spin_unlock(&gioc_lock); | ||
| 298 | return 0; | 329 | return 0; |
| 299 | } | 330 | } |
| 300 | module_param_call(logging_level, _scsih_set_debug_level, param_get_int, | 331 | module_param_call(logging_level, _scsih_set_debug_level, param_get_int, |
| @@ -526,8 +557,61 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc, | |||
| 526 | } | 557 | } |
| 527 | } | 558 | } |
| 528 | 559 | ||
| 560 | static struct _sas_device * | ||
| 561 | __mpt2sas_get_sdev_from_target(struct MPT2SAS_ADAPTER *ioc, | ||
| 562 | struct MPT2SAS_TARGET *tgt_priv) | ||
| 563 | { | ||
| 564 | struct _sas_device *ret; | ||
| 565 | |||
| 566 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 567 | |||
| 568 | ret = tgt_priv->sdev; | ||
| 569 | if (ret) | ||
| 570 | sas_device_get(ret); | ||
| 571 | |||
| 572 | return ret; | ||
| 573 | } | ||
| 574 | |||
| 575 | static struct _sas_device * | ||
| 576 | mpt2sas_get_sdev_from_target(struct MPT2SAS_ADAPTER *ioc, | ||
| 577 | struct MPT2SAS_TARGET *tgt_priv) | ||
| 578 | { | ||
| 579 | struct _sas_device *ret; | ||
| 580 | unsigned long flags; | ||
| 581 | |||
| 582 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 583 | ret = __mpt2sas_get_sdev_from_target(ioc, tgt_priv); | ||
| 584 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 585 | |||
| 586 | return ret; | ||
| 587 | } | ||
| 588 | |||
| 589 | |||
| 590 | struct _sas_device * | ||
| 591 | __mpt2sas_get_sdev_by_addr(struct MPT2SAS_ADAPTER *ioc, | ||
| 592 | u64 sas_address) | ||
| 593 | { | ||
| 594 | struct _sas_device *sas_device; | ||
| 595 | |||
| 596 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 597 | |||
| 598 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | ||
| 599 | if (sas_device->sas_address == sas_address) | ||
| 600 | goto found_device; | ||
| 601 | |||
| 602 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | ||
| 603 | if (sas_device->sas_address == sas_address) | ||
| 604 | goto found_device; | ||
| 605 | |||
| 606 | return NULL; | ||
| 607 | |||
| 608 | found_device: | ||
| 609 | sas_device_get(sas_device); | ||
| 610 | return sas_device; | ||
| 611 | } | ||
| 612 | |||
| 529 | /** | 613 | /** |
| 530 | * mpt2sas_scsih_sas_device_find_by_sas_address - sas device search | 614 | * mpt2sas_get_sdev_by_addr - sas device search |
| 531 | * @ioc: per adapter object | 615 | * @ioc: per adapter object |
| 532 | * @sas_address: sas address | 616 | * @sas_address: sas address |
| 533 | * Context: Calling function should acquire ioc->sas_device_lock | 617 | * Context: Calling function should acquire ioc->sas_device_lock |
| @@ -536,24 +620,44 @@ _scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc, | |||
| 536 | * object. | 620 | * object. |
| 537 | */ | 621 | */ |
| 538 | struct _sas_device * | 622 | struct _sas_device * |
| 539 | mpt2sas_scsih_sas_device_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc, | 623 | mpt2sas_get_sdev_by_addr(struct MPT2SAS_ADAPTER *ioc, |
| 540 | u64 sas_address) | 624 | u64 sas_address) |
| 541 | { | 625 | { |
| 542 | struct _sas_device *sas_device; | 626 | struct _sas_device *sas_device; |
| 627 | unsigned long flags; | ||
| 628 | |||
| 629 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 630 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, | ||
| 631 | sas_address); | ||
| 632 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 633 | |||
| 634 | return sas_device; | ||
| 635 | } | ||
| 636 | |||
| 637 | static struct _sas_device * | ||
| 638 | __mpt2sas_get_sdev_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
| 639 | { | ||
| 640 | struct _sas_device *sas_device; | ||
| 641 | |||
| 642 | assert_spin_locked(&ioc->sas_device_lock); | ||
| 543 | 643 | ||
| 544 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | 644 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) |
| 545 | if (sas_device->sas_address == sas_address) | 645 | if (sas_device->handle == handle) |
| 546 | return sas_device; | 646 | goto found_device; |
| 547 | 647 | ||
| 548 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | 648 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) |
| 549 | if (sas_device->sas_address == sas_address) | 649 | if (sas_device->handle == handle) |
| 550 | return sas_device; | 650 | goto found_device; |
| 551 | 651 | ||
| 552 | return NULL; | 652 | return NULL; |
| 653 | |||
| 654 | found_device: | ||
| 655 | sas_device_get(sas_device); | ||
| 656 | return sas_device; | ||
| 553 | } | 657 | } |
| 554 | 658 | ||
| 555 | /** | 659 | /** |
| 556 | * _scsih_sas_device_find_by_handle - sas device search | 660 | * mpt2sas_get_sdev_by_handle - sas device search |
| 557 | * @ioc: per adapter object | 661 | * @ioc: per adapter object |
| 558 | * @handle: sas device handle (assigned by firmware) | 662 | * @handle: sas device handle (assigned by firmware) |
| 559 | * Context: Calling function should acquire ioc->sas_device_lock | 663 | * Context: Calling function should acquire ioc->sas_device_lock |
| @@ -562,19 +666,16 @@ mpt2sas_scsih_sas_device_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc, | |||
| 562 | * object. | 666 | * object. |
| 563 | */ | 667 | */ |
| 564 | static struct _sas_device * | 668 | static struct _sas_device * |
| 565 | _scsih_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | 669 | mpt2sas_get_sdev_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) |
| 566 | { | 670 | { |
| 567 | struct _sas_device *sas_device; | 671 | struct _sas_device *sas_device; |
| 672 | unsigned long flags; | ||
| 568 | 673 | ||
| 569 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) | 674 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 570 | if (sas_device->handle == handle) | 675 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 571 | return sas_device; | 676 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 572 | |||
| 573 | list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) | ||
| 574 | if (sas_device->handle == handle) | ||
| 575 | return sas_device; | ||
| 576 | 677 | ||
| 577 | return NULL; | 678 | return sas_device; |
| 578 | } | 679 | } |
| 579 | 680 | ||
| 580 | /** | 681 | /** |
| @@ -583,7 +684,7 @@ _scsih_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 583 | * @sas_device: the sas_device object | 684 | * @sas_device: the sas_device object |
| 584 | * Context: This function will acquire ioc->sas_device_lock. | 685 | * Context: This function will acquire ioc->sas_device_lock. |
| 585 | * | 686 | * |
| 586 | * Removing object and freeing associated memory from the ioc->sas_device_list. | 687 | * If sas_device is on the list, remove it and decrement its reference count. |
| 587 | */ | 688 | */ |
| 588 | static void | 689 | static void |
| 589 | _scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc, | 690 | _scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc, |
| @@ -594,9 +695,15 @@ _scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc, | |||
| 594 | if (!sas_device) | 695 | if (!sas_device) |
| 595 | return; | 696 | return; |
| 596 | 697 | ||
| 698 | /* | ||
| 699 | * The lock serializes access to the list, but we still need to verify | ||
| 700 | * that nobody removed the entry while we were waiting on the lock. | ||
| 701 | */ | ||
| 597 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 702 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 598 | list_del(&sas_device->list); | 703 | if (!list_empty(&sas_device->list)) { |
| 599 | kfree(sas_device); | 704 | list_del_init(&sas_device->list); |
| 705 | sas_device_put(sas_device); | ||
| 706 | } | ||
| 600 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 707 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 601 | } | 708 | } |
| 602 | 709 | ||
| @@ -620,6 +727,7 @@ _scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 620 | sas_device->handle, (unsigned long long)sas_device->sas_address)); | 727 | sas_device->handle, (unsigned long long)sas_device->sas_address)); |
| 621 | 728 | ||
| 622 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 729 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 730 | sas_device_get(sas_device); | ||
| 623 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | 731 | list_add_tail(&sas_device->list, &ioc->sas_device_list); |
| 624 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 732 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 625 | 733 | ||
| @@ -659,6 +767,7 @@ _scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 659 | sas_device->handle, (unsigned long long)sas_device->sas_address)); | 767 | sas_device->handle, (unsigned long long)sas_device->sas_address)); |
| 660 | 768 | ||
| 661 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 769 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 770 | sas_device_get(sas_device); | ||
| 662 | list_add_tail(&sas_device->list, &ioc->sas_device_init_list); | 771 | list_add_tail(&sas_device->list, &ioc->sas_device_init_list); |
| 663 | _scsih_determine_boot_device(ioc, sas_device, 0); | 772 | _scsih_determine_boot_device(ioc, sas_device, 0); |
| 664 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 773 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| @@ -1208,12 +1317,15 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
| 1208 | goto not_sata; | 1317 | goto not_sata; |
| 1209 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) | 1318 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) |
| 1210 | goto not_sata; | 1319 | goto not_sata; |
| 1320 | |||
| 1211 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1321 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1212 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1322 | sas_device = __mpt2sas_get_sdev_from_target(ioc, sas_target_priv_data); |
| 1213 | sas_device_priv_data->sas_target->sas_address); | 1323 | if (sas_device) { |
| 1214 | if (sas_device && sas_device->device_info & | 1324 | if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) |
| 1215 | MPI2_SAS_DEVICE_INFO_SATA_DEVICE) | 1325 | max_depth = MPT2SAS_SATA_QUEUE_DEPTH; |
| 1216 | max_depth = MPT2SAS_SATA_QUEUE_DEPTH; | 1326 | |
| 1327 | sas_device_put(sas_device); | ||
| 1328 | } | ||
| 1217 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1329 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1218 | 1330 | ||
| 1219 | not_sata: | 1331 | not_sata: |
| @@ -1271,18 +1383,20 @@ _scsih_target_alloc(struct scsi_target *starget) | |||
| 1271 | /* sas/sata devices */ | 1383 | /* sas/sata devices */ |
| 1272 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1384 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1273 | rphy = dev_to_rphy(starget->dev.parent); | 1385 | rphy = dev_to_rphy(starget->dev.parent); |
| 1274 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1386 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 1275 | rphy->identify.sas_address); | 1387 | rphy->identify.sas_address); |
| 1276 | 1388 | ||
| 1277 | if (sas_device) { | 1389 | if (sas_device) { |
| 1278 | sas_target_priv_data->handle = sas_device->handle; | 1390 | sas_target_priv_data->handle = sas_device->handle; |
| 1279 | sas_target_priv_data->sas_address = sas_device->sas_address; | 1391 | sas_target_priv_data->sas_address = sas_device->sas_address; |
| 1392 | sas_target_priv_data->sdev = sas_device; | ||
| 1280 | sas_device->starget = starget; | 1393 | sas_device->starget = starget; |
| 1281 | sas_device->id = starget->id; | 1394 | sas_device->id = starget->id; |
| 1282 | sas_device->channel = starget->channel; | 1395 | sas_device->channel = starget->channel; |
| 1283 | if (test_bit(sas_device->handle, ioc->pd_handles)) | 1396 | if (test_bit(sas_device->handle, ioc->pd_handles)) |
| 1284 | sas_target_priv_data->flags |= | 1397 | sas_target_priv_data->flags |= |
| 1285 | MPT_TARGET_FLAGS_RAID_COMPONENT; | 1398 | MPT_TARGET_FLAGS_RAID_COMPONENT; |
| 1399 | |||
| 1286 | } | 1400 | } |
| 1287 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1401 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1288 | 1402 | ||
| @@ -1324,13 +1438,21 @@ _scsih_target_destroy(struct scsi_target *starget) | |||
| 1324 | 1438 | ||
| 1325 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1439 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1326 | rphy = dev_to_rphy(starget->dev.parent); | 1440 | rphy = dev_to_rphy(starget->dev.parent); |
| 1327 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1441 | sas_device = __mpt2sas_get_sdev_from_target(ioc, sas_target_priv_data); |
| 1328 | rphy->identify.sas_address); | ||
| 1329 | if (sas_device && (sas_device->starget == starget) && | 1442 | if (sas_device && (sas_device->starget == starget) && |
| 1330 | (sas_device->id == starget->id) && | 1443 | (sas_device->id == starget->id) && |
| 1331 | (sas_device->channel == starget->channel)) | 1444 | (sas_device->channel == starget->channel)) |
| 1332 | sas_device->starget = NULL; | 1445 | sas_device->starget = NULL; |
| 1333 | 1446 | ||
| 1447 | if (sas_device) { | ||
| 1448 | /* | ||
| 1449 | * Corresponding get() is in _scsih_target_alloc() | ||
| 1450 | */ | ||
| 1451 | sas_target_priv_data->sdev = NULL; | ||
| 1452 | sas_device_put(sas_device); | ||
| 1453 | |||
| 1454 | sas_device_put(sas_device); | ||
| 1455 | } | ||
| 1334 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1456 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1335 | 1457 | ||
| 1336 | out: | 1458 | out: |
| @@ -1386,7 +1508,7 @@ _scsih_slave_alloc(struct scsi_device *sdev) | |||
| 1386 | 1508 | ||
| 1387 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { | 1509 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { |
| 1388 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1510 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1389 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1511 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 1390 | sas_target_priv_data->sas_address); | 1512 | sas_target_priv_data->sas_address); |
| 1391 | if (sas_device && (sas_device->starget == NULL)) { | 1513 | if (sas_device && (sas_device->starget == NULL)) { |
| 1392 | sdev_printk(KERN_INFO, sdev, | 1514 | sdev_printk(KERN_INFO, sdev, |
| @@ -1394,6 +1516,10 @@ _scsih_slave_alloc(struct scsi_device *sdev) | |||
| 1394 | __func__, __LINE__); | 1516 | __func__, __LINE__); |
| 1395 | sas_device->starget = starget; | 1517 | sas_device->starget = starget; |
| 1396 | } | 1518 | } |
| 1519 | |||
| 1520 | if (sas_device) | ||
| 1521 | sas_device_put(sas_device); | ||
| 1522 | |||
| 1397 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1523 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1398 | } | 1524 | } |
| 1399 | 1525 | ||
| @@ -1428,10 +1554,13 @@ _scsih_slave_destroy(struct scsi_device *sdev) | |||
| 1428 | 1554 | ||
| 1429 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { | 1555 | if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { |
| 1430 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1556 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1431 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1557 | sas_device = __mpt2sas_get_sdev_from_target(ioc, |
| 1432 | sas_target_priv_data->sas_address); | 1558 | sas_target_priv_data); |
| 1433 | if (sas_device && !sas_target_priv_data->num_luns) | 1559 | if (sas_device && !sas_target_priv_data->num_luns) |
| 1434 | sas_device->starget = NULL; | 1560 | sas_device->starget = NULL; |
| 1561 | |||
| 1562 | if (sas_device) | ||
| 1563 | sas_device_put(sas_device); | ||
| 1435 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1564 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1436 | } | 1565 | } |
| 1437 | 1566 | ||
| @@ -2078,7 +2207,7 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 2078 | } | 2207 | } |
| 2079 | 2208 | ||
| 2080 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2209 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 2081 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 2210 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 2082 | sas_device_priv_data->sas_target->sas_address); | 2211 | sas_device_priv_data->sas_target->sas_address); |
| 2083 | if (!sas_device) { | 2212 | if (!sas_device) { |
| 2084 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2213 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| @@ -2112,17 +2241,18 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 2112 | (unsigned long long) sas_device->enclosure_logical_id, | 2241 | (unsigned long long) sas_device->enclosure_logical_id, |
| 2113 | sas_device->slot); | 2242 | sas_device->slot); |
| 2114 | 2243 | ||
| 2244 | sas_device_put(sas_device); | ||
| 2115 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2245 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 2116 | if (!ssp_target) | 2246 | if (!ssp_target) |
| 2117 | _scsih_display_sata_capabilities(ioc, handle, sdev); | 2247 | _scsih_display_sata_capabilities(ioc, handle, sdev); |
| 2118 | 2248 | ||
| 2119 | |||
| 2120 | _scsih_change_queue_depth(sdev, qdepth); | 2249 | _scsih_change_queue_depth(sdev, qdepth); |
| 2121 | 2250 | ||
| 2122 | if (ssp_target) { | 2251 | if (ssp_target) { |
| 2123 | sas_read_port_mode_page(sdev); | 2252 | sas_read_port_mode_page(sdev); |
| 2124 | _scsih_enable_tlr(ioc, sdev); | 2253 | _scsih_enable_tlr(ioc, sdev); |
| 2125 | } | 2254 | } |
| 2255 | |||
| 2126 | return 0; | 2256 | return 0; |
| 2127 | } | 2257 | } |
| 2128 | 2258 | ||
| @@ -2509,8 +2639,7 @@ _scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) | |||
| 2509 | device_str, (unsigned long long)priv_target->sas_address); | 2639 | device_str, (unsigned long long)priv_target->sas_address); |
| 2510 | } else { | 2640 | } else { |
| 2511 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2641 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 2512 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 2642 | sas_device = __mpt2sas_get_sdev_from_target(ioc, priv_target); |
| 2513 | priv_target->sas_address); | ||
| 2514 | if (sas_device) { | 2643 | if (sas_device) { |
| 2515 | if (priv_target->flags & | 2644 | if (priv_target->flags & |
| 2516 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2645 | MPT_TARGET_FLAGS_RAID_COMPONENT) { |
| @@ -2529,6 +2658,8 @@ _scsih_tm_display_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) | |||
| 2529 | "enclosure_logical_id(0x%016llx), slot(%d)\n", | 2658 | "enclosure_logical_id(0x%016llx), slot(%d)\n", |
| 2530 | (unsigned long long)sas_device->enclosure_logical_id, | 2659 | (unsigned long long)sas_device->enclosure_logical_id, |
| 2531 | sas_device->slot); | 2660 | sas_device->slot); |
| 2661 | |||
| 2662 | sas_device_put(sas_device); | ||
| 2532 | } | 2663 | } |
| 2533 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2664 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 2534 | } | 2665 | } |
| @@ -2604,12 +2735,12 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) | |||
| 2604 | { | 2735 | { |
| 2605 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2736 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| 2606 | struct MPT2SAS_DEVICE *sas_device_priv_data; | 2737 | struct MPT2SAS_DEVICE *sas_device_priv_data; |
| 2607 | struct _sas_device *sas_device; | 2738 | struct _sas_device *sas_device = NULL; |
| 2608 | unsigned long flags; | ||
| 2609 | u16 handle; | 2739 | u16 handle; |
| 2610 | int r; | 2740 | int r; |
| 2611 | 2741 | ||
| 2612 | struct scsi_target *starget = scmd->device->sdev_target; | 2742 | struct scsi_target *starget = scmd->device->sdev_target; |
| 2743 | struct MPT2SAS_TARGET *target_priv_data = starget->hostdata; | ||
| 2613 | 2744 | ||
| 2614 | starget_printk(KERN_INFO, starget, "attempting device reset! " | 2745 | starget_printk(KERN_INFO, starget, "attempting device reset! " |
| 2615 | "scmd(%p)\n", scmd); | 2746 | "scmd(%p)\n", scmd); |
| @@ -2629,12 +2760,10 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) | |||
| 2629 | handle = 0; | 2760 | handle = 0; |
| 2630 | if (sas_device_priv_data->sas_target->flags & | 2761 | if (sas_device_priv_data->sas_target->flags & |
| 2631 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2762 | MPT_TARGET_FLAGS_RAID_COMPONENT) { |
| 2632 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2763 | sas_device = mpt2sas_get_sdev_from_target(ioc, |
| 2633 | sas_device = _scsih_sas_device_find_by_handle(ioc, | 2764 | target_priv_data); |
| 2634 | sas_device_priv_data->sas_target->handle); | ||
| 2635 | if (sas_device) | 2765 | if (sas_device) |
| 2636 | handle = sas_device->volume_handle; | 2766 | handle = sas_device->volume_handle; |
| 2637 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 2638 | } else | 2767 | } else |
| 2639 | handle = sas_device_priv_data->sas_target->handle; | 2768 | handle = sas_device_priv_data->sas_target->handle; |
| 2640 | 2769 | ||
| @@ -2651,6 +2780,10 @@ _scsih_dev_reset(struct scsi_cmnd *scmd) | |||
| 2651 | out: | 2780 | out: |
| 2652 | sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", | 2781 | sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", |
| 2653 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | 2782 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); |
| 2783 | |||
| 2784 | if (sas_device) | ||
| 2785 | sas_device_put(sas_device); | ||
| 2786 | |||
| 2654 | return r; | 2787 | return r; |
| 2655 | } | 2788 | } |
| 2656 | 2789 | ||
| @@ -2665,11 +2798,11 @@ _scsih_target_reset(struct scsi_cmnd *scmd) | |||
| 2665 | { | 2798 | { |
| 2666 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); | 2799 | struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host); |
| 2667 | struct MPT2SAS_DEVICE *sas_device_priv_data; | 2800 | struct MPT2SAS_DEVICE *sas_device_priv_data; |
| 2668 | struct _sas_device *sas_device; | 2801 | struct _sas_device *sas_device = NULL; |
| 2669 | unsigned long flags; | ||
| 2670 | u16 handle; | 2802 | u16 handle; |
| 2671 | int r; | 2803 | int r; |
| 2672 | struct scsi_target *starget = scmd->device->sdev_target; | 2804 | struct scsi_target *starget = scmd->device->sdev_target; |
| 2805 | struct MPT2SAS_TARGET *target_priv_data = starget->hostdata; | ||
| 2673 | 2806 | ||
| 2674 | starget_printk(KERN_INFO, starget, "attempting target reset! " | 2807 | starget_printk(KERN_INFO, starget, "attempting target reset! " |
| 2675 | "scmd(%p)\n", scmd); | 2808 | "scmd(%p)\n", scmd); |
| @@ -2689,12 +2822,10 @@ _scsih_target_reset(struct scsi_cmnd *scmd) | |||
| 2689 | handle = 0; | 2822 | handle = 0; |
| 2690 | if (sas_device_priv_data->sas_target->flags & | 2823 | if (sas_device_priv_data->sas_target->flags & |
| 2691 | MPT_TARGET_FLAGS_RAID_COMPONENT) { | 2824 | MPT_TARGET_FLAGS_RAID_COMPONENT) { |
| 2692 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 2825 | sas_device = mpt2sas_get_sdev_from_target(ioc, |
| 2693 | sas_device = _scsih_sas_device_find_by_handle(ioc, | 2826 | target_priv_data); |
| 2694 | sas_device_priv_data->sas_target->handle); | ||
| 2695 | if (sas_device) | 2827 | if (sas_device) |
| 2696 | handle = sas_device->volume_handle; | 2828 | handle = sas_device->volume_handle; |
| 2697 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 2698 | } else | 2829 | } else |
| 2699 | handle = sas_device_priv_data->sas_target->handle; | 2830 | handle = sas_device_priv_data->sas_target->handle; |
| 2700 | 2831 | ||
| @@ -2711,6 +2842,10 @@ _scsih_target_reset(struct scsi_cmnd *scmd) | |||
| 2711 | out: | 2842 | out: |
| 2712 | starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", | 2843 | starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", |
| 2713 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); | 2844 | ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); |
| 2845 | |||
| 2846 | if (sas_device) | ||
| 2847 | sas_device_put(sas_device); | ||
| 2848 | |||
| 2714 | return r; | 2849 | return r; |
| 2715 | } | 2850 | } |
| 2716 | 2851 | ||
| @@ -2768,36 +2903,39 @@ _scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event) | |||
| 2768 | return; | 2903 | return; |
| 2769 | 2904 | ||
| 2770 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | 2905 | spin_lock_irqsave(&ioc->fw_event_lock, flags); |
| 2906 | fw_event_work_get(fw_event); | ||
| 2771 | list_add_tail(&fw_event->list, &ioc->fw_event_list); | 2907 | list_add_tail(&fw_event->list, &ioc->fw_event_list); |
| 2772 | INIT_DELAYED_WORK(&fw_event->delayed_work, _firmware_event_work); | 2908 | INIT_DELAYED_WORK(&fw_event->delayed_work, _firmware_event_work); |
| 2909 | fw_event_work_get(fw_event); | ||
| 2773 | queue_delayed_work(ioc->firmware_event_thread, | 2910 | queue_delayed_work(ioc->firmware_event_thread, |
| 2774 | &fw_event->delayed_work, 0); | 2911 | &fw_event->delayed_work, 0); |
| 2775 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 2912 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
| 2776 | } | 2913 | } |
| 2777 | 2914 | ||
| 2778 | /** | 2915 | /** |
| 2779 | * _scsih_fw_event_free - delete fw_event | 2916 | * _scsih_fw_event_del_from_list - delete fw_event from the list |
| 2780 | * @ioc: per adapter object | 2917 | * @ioc: per adapter object |
| 2781 | * @fw_event: object describing the event | 2918 | * @fw_event: object describing the event |
| 2782 | * Context: This function will acquire ioc->fw_event_lock. | 2919 | * Context: This function will acquire ioc->fw_event_lock. |
| 2783 | * | 2920 | * |
| 2784 | * This removes firmware event object from link list, frees associated memory. | 2921 | * If the fw_event is on the fw_event_list, remove it and do a put. |
| 2785 | * | 2922 | * |
| 2786 | * Return nothing. | 2923 | * Return nothing. |
| 2787 | */ | 2924 | */ |
| 2788 | static void | 2925 | static void |
| 2789 | _scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work | 2926 | _scsih_fw_event_del_from_list(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work |
| 2790 | *fw_event) | 2927 | *fw_event) |
| 2791 | { | 2928 | { |
| 2792 | unsigned long flags; | 2929 | unsigned long flags; |
| 2793 | 2930 | ||
| 2794 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | 2931 | spin_lock_irqsave(&ioc->fw_event_lock, flags); |
| 2795 | list_del(&fw_event->list); | 2932 | if (!list_empty(&fw_event->list)) { |
| 2796 | kfree(fw_event); | 2933 | list_del_init(&fw_event->list); |
| 2934 | fw_event_work_put(fw_event); | ||
| 2935 | } | ||
| 2797 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 2936 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
| 2798 | } | 2937 | } |
| 2799 | 2938 | ||
| 2800 | |||
| 2801 | /** | 2939 | /** |
| 2802 | * _scsih_error_recovery_delete_devices - remove devices not responding | 2940 | * _scsih_error_recovery_delete_devices - remove devices not responding |
| 2803 | * @ioc: per adapter object | 2941 | * @ioc: per adapter object |
| @@ -2812,13 +2950,14 @@ _scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 2812 | if (ioc->is_driver_loading) | 2950 | if (ioc->is_driver_loading) |
| 2813 | return; | 2951 | return; |
| 2814 | 2952 | ||
| 2815 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 2953 | fw_event = alloc_fw_event_work(0); |
| 2816 | if (!fw_event) | 2954 | if (!fw_event) |
| 2817 | return; | 2955 | return; |
| 2818 | 2956 | ||
| 2819 | fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES; | 2957 | fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES; |
| 2820 | fw_event->ioc = ioc; | 2958 | fw_event->ioc = ioc; |
| 2821 | _scsih_fw_event_add(ioc, fw_event); | 2959 | _scsih_fw_event_add(ioc, fw_event); |
| 2960 | fw_event_work_put(fw_event); | ||
| 2822 | } | 2961 | } |
| 2823 | 2962 | ||
| 2824 | /** | 2963 | /** |
| @@ -2832,12 +2971,29 @@ mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc) | |||
| 2832 | { | 2971 | { |
| 2833 | struct fw_event_work *fw_event; | 2972 | struct fw_event_work *fw_event; |
| 2834 | 2973 | ||
| 2835 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 2974 | fw_event = alloc_fw_event_work(0); |
| 2836 | if (!fw_event) | 2975 | if (!fw_event) |
| 2837 | return; | 2976 | return; |
| 2838 | fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE; | 2977 | fw_event->event = MPT2SAS_PORT_ENABLE_COMPLETE; |
| 2839 | fw_event->ioc = ioc; | 2978 | fw_event->ioc = ioc; |
| 2840 | _scsih_fw_event_add(ioc, fw_event); | 2979 | _scsih_fw_event_add(ioc, fw_event); |
| 2980 | fw_event_work_put(fw_event); | ||
| 2981 | } | ||
| 2982 | |||
| 2983 | static struct fw_event_work *dequeue_next_fw_event(struct MPT2SAS_ADAPTER *ioc) | ||
| 2984 | { | ||
| 2985 | unsigned long flags; | ||
| 2986 | struct fw_event_work *fw_event = NULL; | ||
| 2987 | |||
| 2988 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | ||
| 2989 | if (!list_empty(&ioc->fw_event_list)) { | ||
| 2990 | fw_event = list_first_entry(&ioc->fw_event_list, | ||
| 2991 | struct fw_event_work, list); | ||
| 2992 | list_del_init(&fw_event->list); | ||
| 2993 | } | ||
| 2994 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | ||
| 2995 | |||
| 2996 | return fw_event; | ||
| 2841 | } | 2997 | } |
| 2842 | 2998 | ||
| 2843 | /** | 2999 | /** |
| @@ -2852,17 +3008,25 @@ mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc) | |||
| 2852 | static void | 3008 | static void |
| 2853 | _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc) | 3009 | _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc) |
| 2854 | { | 3010 | { |
| 2855 | struct fw_event_work *fw_event, *next; | 3011 | struct fw_event_work *fw_event; |
| 2856 | 3012 | ||
| 2857 | if (list_empty(&ioc->fw_event_list) || | 3013 | if (list_empty(&ioc->fw_event_list) || |
| 2858 | !ioc->firmware_event_thread || in_interrupt()) | 3014 | !ioc->firmware_event_thread || in_interrupt()) |
| 2859 | return; | 3015 | return; |
| 2860 | 3016 | ||
| 2861 | list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) { | 3017 | while ((fw_event = dequeue_next_fw_event(ioc))) { |
| 2862 | if (cancel_delayed_work_sync(&fw_event->delayed_work)) { | 3018 | /* |
| 2863 | _scsih_fw_event_free(ioc, fw_event); | 3019 | * Wait on the fw_event to complete. If this returns 1, then |
| 2864 | continue; | 3020 | * the event was never executed, and we need a put for the |
| 2865 | } | 3021 | * reference the delayed_work had on the fw_event. |
| 3022 | * | ||
| 3023 | * If it did execute, we wait for it to finish, and the put will | ||
| 3024 | * happen from _firmware_event_work() | ||
| 3025 | */ | ||
| 3026 | if (cancel_delayed_work_sync(&fw_event->delayed_work)) | ||
| 3027 | fw_event_work_put(fw_event); | ||
| 3028 | |||
| 3029 | fw_event_work_put(fw_event); | ||
| 2866 | } | 3030 | } |
| 2867 | } | 3031 | } |
| 2868 | 3032 | ||
| @@ -3002,15 +3166,15 @@ _scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc, | |||
| 3002 | 3166 | ||
| 3003 | list_for_each_entry(mpt2sas_port, | 3167 | list_for_each_entry(mpt2sas_port, |
| 3004 | &sas_expander->sas_port_list, port_list) { | 3168 | &sas_expander->sas_port_list, port_list) { |
| 3005 | if (mpt2sas_port->remote_identify.device_type == | 3169 | if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE) { |
| 3006 | SAS_END_DEVICE) { | ||
| 3007 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 3170 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 3008 | sas_device = | 3171 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 3009 | mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 3172 | mpt2sas_port->remote_identify.sas_address); |
| 3010 | mpt2sas_port->remote_identify.sas_address); | 3173 | if (sas_device) { |
| 3011 | if (sas_device) | ||
| 3012 | set_bit(sas_device->handle, | 3174 | set_bit(sas_device->handle, |
| 3013 | ioc->blocking_handles); | 3175 | ioc->blocking_handles); |
| 3176 | sas_device_put(sas_device); | ||
| 3177 | } | ||
| 3014 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 3178 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 3015 | } | 3179 | } |
| 3016 | } | 3180 | } |
| @@ -3080,7 +3244,7 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3080 | { | 3244 | { |
| 3081 | Mpi2SCSITaskManagementRequest_t *mpi_request; | 3245 | Mpi2SCSITaskManagementRequest_t *mpi_request; |
| 3082 | u16 smid; | 3246 | u16 smid; |
| 3083 | struct _sas_device *sas_device; | 3247 | struct _sas_device *sas_device = NULL; |
| 3084 | struct MPT2SAS_TARGET *sas_target_priv_data = NULL; | 3248 | struct MPT2SAS_TARGET *sas_target_priv_data = NULL; |
| 3085 | u64 sas_address = 0; | 3249 | u64 sas_address = 0; |
| 3086 | unsigned long flags; | 3250 | unsigned long flags; |
| @@ -3110,7 +3274,7 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3110 | return; | 3274 | return; |
| 3111 | 3275 | ||
| 3112 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 3276 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 3113 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 3277 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 3114 | if (sas_device && sas_device->starget && | 3278 | if (sas_device && sas_device->starget && |
| 3115 | sas_device->starget->hostdata) { | 3279 | sas_device->starget->hostdata) { |
| 3116 | sas_target_priv_data = sas_device->starget->hostdata; | 3280 | sas_target_priv_data = sas_device->starget->hostdata; |
| @@ -3131,14 +3295,14 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3131 | if (!smid) { | 3295 | if (!smid) { |
| 3132 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | 3296 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); |
| 3133 | if (!delayed_tr) | 3297 | if (!delayed_tr) |
| 3134 | return; | 3298 | goto out; |
| 3135 | INIT_LIST_HEAD(&delayed_tr->list); | 3299 | INIT_LIST_HEAD(&delayed_tr->list); |
| 3136 | delayed_tr->handle = handle; | 3300 | delayed_tr->handle = handle; |
| 3137 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); | 3301 | list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); |
| 3138 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT | 3302 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT |
| 3139 | "DELAYED:tr:handle(0x%04x), (open)\n", | 3303 | "DELAYED:tr:handle(0x%04x), (open)\n", |
| 3140 | ioc->name, handle)); | 3304 | ioc->name, handle)); |
| 3141 | return; | 3305 | goto out; |
| 3142 | } | 3306 | } |
| 3143 | 3307 | ||
| 3144 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), " | 3308 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "tr_send:handle(0x%04x), " |
| @@ -3150,6 +3314,9 @@ _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 3150 | mpi_request->DevHandle = cpu_to_le16(handle); | 3314 | mpi_request->DevHandle = cpu_to_le16(handle); |
| 3151 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | 3315 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; |
| 3152 | mpt2sas_base_put_smid_hi_priority(ioc, smid); | 3316 | mpt2sas_base_put_smid_hi_priority(ioc, smid); |
| 3317 | out: | ||
| 3318 | if (sas_device) | ||
| 3319 | sas_device_put(sas_device); | ||
| 3153 | } | 3320 | } |
| 3154 | 3321 | ||
| 3155 | 3322 | ||
| @@ -4068,7 +4235,6 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 4068 | char *desc_scsi_state = ioc->tmp_string; | 4235 | char *desc_scsi_state = ioc->tmp_string; |
| 4069 | u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); | 4236 | u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); |
| 4070 | struct _sas_device *sas_device = NULL; | 4237 | struct _sas_device *sas_device = NULL; |
| 4071 | unsigned long flags; | ||
| 4072 | struct scsi_target *starget = scmd->device->sdev_target; | 4238 | struct scsi_target *starget = scmd->device->sdev_target; |
| 4073 | struct MPT2SAS_TARGET *priv_target = starget->hostdata; | 4239 | struct MPT2SAS_TARGET *priv_target = starget->hostdata; |
| 4074 | char *device_str = NULL; | 4240 | char *device_str = NULL; |
| @@ -4200,9 +4366,7 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 4200 | printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc->name, | 4366 | printk(MPT2SAS_WARN_FMT "\t%s wwid(0x%016llx)\n", ioc->name, |
| 4201 | device_str, (unsigned long long)priv_target->sas_address); | 4367 | device_str, (unsigned long long)priv_target->sas_address); |
| 4202 | } else { | 4368 | } else { |
| 4203 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 4369 | sas_device = mpt2sas_get_sdev_from_target(ioc, priv_target); |
| 4204 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 4205 | priv_target->sas_address); | ||
| 4206 | if (sas_device) { | 4370 | if (sas_device) { |
| 4207 | printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), " | 4371 | printk(MPT2SAS_WARN_FMT "\tsas_address(0x%016llx), " |
| 4208 | "phy(%d)\n", ioc->name, sas_device->sas_address, | 4372 | "phy(%d)\n", ioc->name, sas_device->sas_address, |
| @@ -4211,8 +4375,9 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 4211 | "\tenclosure_logical_id(0x%016llx), slot(%d)\n", | 4375 | "\tenclosure_logical_id(0x%016llx), slot(%d)\n", |
| 4212 | ioc->name, sas_device->enclosure_logical_id, | 4376 | ioc->name, sas_device->enclosure_logical_id, |
| 4213 | sas_device->slot); | 4377 | sas_device->slot); |
| 4378 | |||
| 4379 | sas_device_put(sas_device); | ||
| 4214 | } | 4380 | } |
| 4215 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 4216 | } | 4381 | } |
| 4217 | 4382 | ||
| 4218 | printk(MPT2SAS_WARN_FMT "\thandle(0x%04x), ioc_status(%s)(0x%04x), " | 4383 | printk(MPT2SAS_WARN_FMT "\thandle(0x%04x), ioc_status(%s)(0x%04x), " |
| @@ -4259,7 +4424,7 @@ _scsih_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4259 | Mpi2SepRequest_t mpi_request; | 4424 | Mpi2SepRequest_t mpi_request; |
| 4260 | struct _sas_device *sas_device; | 4425 | struct _sas_device *sas_device; |
| 4261 | 4426 | ||
| 4262 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 4427 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); |
| 4263 | if (!sas_device) | 4428 | if (!sas_device) |
| 4264 | return; | 4429 | return; |
| 4265 | 4430 | ||
| @@ -4274,7 +4439,7 @@ _scsih_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4274 | &mpi_request)) != 0) { | 4439 | &mpi_request)) != 0) { |
| 4275 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, | 4440 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, |
| 4276 | __FILE__, __LINE__, __func__); | 4441 | __FILE__, __LINE__, __func__); |
| 4277 | return; | 4442 | goto out; |
| 4278 | } | 4443 | } |
| 4279 | sas_device->pfa_led_on = 1; | 4444 | sas_device->pfa_led_on = 1; |
| 4280 | 4445 | ||
| @@ -4284,8 +4449,10 @@ _scsih_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4284 | "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n", | 4449 | "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n", |
| 4285 | ioc->name, le16_to_cpu(mpi_reply.IOCStatus), | 4450 | ioc->name, le16_to_cpu(mpi_reply.IOCStatus), |
| 4286 | le32_to_cpu(mpi_reply.IOCLogInfo))); | 4451 | le32_to_cpu(mpi_reply.IOCLogInfo))); |
| 4287 | return; | 4452 | goto out; |
| 4288 | } | 4453 | } |
| 4454 | out: | ||
| 4455 | sas_device_put(sas_device); | ||
| 4289 | } | 4456 | } |
| 4290 | 4457 | ||
| 4291 | /** | 4458 | /** |
| @@ -4340,13 +4507,14 @@ _scsih_send_event_to_turn_on_pfa_led(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4340 | { | 4507 | { |
| 4341 | struct fw_event_work *fw_event; | 4508 | struct fw_event_work *fw_event; |
| 4342 | 4509 | ||
| 4343 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 4510 | fw_event = alloc_fw_event_work(0); |
| 4344 | if (!fw_event) | 4511 | if (!fw_event) |
| 4345 | return; | 4512 | return; |
| 4346 | fw_event->event = MPT2SAS_TURN_ON_PFA_LED; | 4513 | fw_event->event = MPT2SAS_TURN_ON_PFA_LED; |
| 4347 | fw_event->device_handle = handle; | 4514 | fw_event->device_handle = handle; |
| 4348 | fw_event->ioc = ioc; | 4515 | fw_event->ioc = ioc; |
| 4349 | _scsih_fw_event_add(ioc, fw_event); | 4516 | _scsih_fw_event_add(ioc, fw_event); |
| 4517 | fw_event_work_put(fw_event); | ||
| 4350 | } | 4518 | } |
| 4351 | 4519 | ||
| 4352 | /** | 4520 | /** |
| @@ -4370,19 +4538,17 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4370 | 4538 | ||
| 4371 | /* only handle non-raid devices */ | 4539 | /* only handle non-raid devices */ |
| 4372 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 4540 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 4373 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 4541 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 4374 | if (!sas_device) { | 4542 | if (!sas_device) { |
| 4375 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4543 | goto out_unlock; |
| 4376 | return; | ||
| 4377 | } | 4544 | } |
| 4378 | starget = sas_device->starget; | 4545 | starget = sas_device->starget; |
| 4379 | sas_target_priv_data = starget->hostdata; | 4546 | sas_target_priv_data = starget->hostdata; |
| 4380 | 4547 | ||
| 4381 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) || | 4548 | if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) || |
| 4382 | ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) { | 4549 | ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) |
| 4383 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4550 | goto out_unlock; |
| 4384 | return; | 4551 | |
| 4385 | } | ||
| 4386 | starget_printk(KERN_WARNING, starget, "predicted fault\n"); | 4552 | starget_printk(KERN_WARNING, starget, "predicted fault\n"); |
| 4387 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4553 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 4388 | 4554 | ||
| @@ -4396,7 +4562,7 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4396 | if (!event_reply) { | 4562 | if (!event_reply) { |
| 4397 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 4563 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
| 4398 | ioc->name, __FILE__, __LINE__, __func__); | 4564 | ioc->name, __FILE__, __LINE__, __func__); |
| 4399 | return; | 4565 | goto out; |
| 4400 | } | 4566 | } |
| 4401 | 4567 | ||
| 4402 | event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; | 4568 | event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; |
| @@ -4413,6 +4579,14 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 4413 | event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address); | 4579 | event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address); |
| 4414 | mpt2sas_ctl_add_to_event_log(ioc, event_reply); | 4580 | mpt2sas_ctl_add_to_event_log(ioc, event_reply); |
| 4415 | kfree(event_reply); | 4581 | kfree(event_reply); |
| 4582 | out: | ||
| 4583 | if (sas_device) | ||
| 4584 | sas_device_put(sas_device); | ||
| 4585 | return; | ||
| 4586 | |||
| 4587 | out_unlock: | ||
| 4588 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 4589 | goto out; | ||
| 4416 | } | 4590 | } |
| 4417 | 4591 | ||
| 4418 | /** | 4592 | /** |
| @@ -5148,14 +5322,13 @@ _scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 5148 | 5322 | ||
| 5149 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5323 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 5150 | sas_address = le64_to_cpu(sas_device_pg0.SASAddress); | 5324 | sas_address = le64_to_cpu(sas_device_pg0.SASAddress); |
| 5151 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 5325 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 5152 | sas_address); | 5326 | sas_address); |
| 5153 | 5327 | ||
| 5154 | if (!sas_device) { | 5328 | if (!sas_device) { |
| 5155 | printk(MPT2SAS_ERR_FMT "device is not present " | 5329 | printk(MPT2SAS_ERR_FMT "device is not present " |
| 5156 | "handle(0x%04x), no sas_device!!!\n", ioc->name, handle); | 5330 | "handle(0x%04x), no sas_device!!!\n", ioc->name, handle); |
| 5157 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5331 | goto out_unlock; |
| 5158 | return; | ||
| 5159 | } | 5332 | } |
| 5160 | 5333 | ||
| 5161 | if (unlikely(sas_device->handle != handle)) { | 5334 | if (unlikely(sas_device->handle != handle)) { |
| @@ -5172,19 +5345,24 @@ _scsih_check_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 5172 | MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { | 5345 | MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { |
| 5173 | printk(MPT2SAS_ERR_FMT "device is not present " | 5346 | printk(MPT2SAS_ERR_FMT "device is not present " |
| 5174 | "handle(0x%04x), flags!!!\n", ioc->name, handle); | 5347 | "handle(0x%04x), flags!!!\n", ioc->name, handle); |
| 5175 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5348 | goto out_unlock; |
| 5176 | return; | ||
| 5177 | } | 5349 | } |
| 5178 | 5350 | ||
| 5179 | /* check if there were any issues with discovery */ | 5351 | /* check if there were any issues with discovery */ |
| 5180 | if (_scsih_check_access_status(ioc, sas_address, handle, | 5352 | if (_scsih_check_access_status(ioc, sas_address, handle, |
| 5181 | sas_device_pg0.AccessStatus)) { | 5353 | sas_device_pg0.AccessStatus)) |
| 5182 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5354 | goto out_unlock; |
| 5183 | return; | 5355 | |
| 5184 | } | ||
| 5185 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5356 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5186 | _scsih_ublock_io_device(ioc, sas_address); | 5357 | _scsih_ublock_io_device(ioc, sas_address); |
| 5358 | if (sas_device) | ||
| 5359 | sas_device_put(sas_device); | ||
| 5360 | return; | ||
| 5187 | 5361 | ||
| 5362 | out_unlock: | ||
| 5363 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 5364 | if (sas_device) | ||
| 5365 | sas_device_put(sas_device); | ||
| 5188 | } | 5366 | } |
| 5189 | 5367 | ||
| 5190 | /** | 5368 | /** |
| @@ -5208,7 +5386,6 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 5208 | u32 ioc_status; | 5386 | u32 ioc_status; |
| 5209 | __le64 sas_address; | 5387 | __le64 sas_address; |
| 5210 | u32 device_info; | 5388 | u32 device_info; |
| 5211 | unsigned long flags; | ||
| 5212 | 5389 | ||
| 5213 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | 5390 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, |
| 5214 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | 5391 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { |
| @@ -5250,14 +5427,13 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 5250 | return -1; | 5427 | return -1; |
| 5251 | } | 5428 | } |
| 5252 | 5429 | ||
| 5253 | 5430 | sas_device = mpt2sas_get_sdev_by_addr(ioc, | |
| 5254 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 5255 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 5256 | sas_address); | 5431 | sas_address); |
| 5257 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 5258 | 5432 | ||
| 5259 | if (sas_device) | 5433 | if (sas_device) { |
| 5434 | sas_device_put(sas_device); | ||
| 5260 | return 0; | 5435 | return 0; |
| 5436 | } | ||
| 5261 | 5437 | ||
| 5262 | sas_device = kzalloc(sizeof(struct _sas_device), | 5438 | sas_device = kzalloc(sizeof(struct _sas_device), |
| 5263 | GFP_KERNEL); | 5439 | GFP_KERNEL); |
| @@ -5267,6 +5443,7 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 5267 | return -1; | 5443 | return -1; |
| 5268 | } | 5444 | } |
| 5269 | 5445 | ||
| 5446 | kref_init(&sas_device->refcount); | ||
| 5270 | sas_device->handle = handle; | 5447 | sas_device->handle = handle; |
| 5271 | if (_scsih_get_sas_address(ioc, le16_to_cpu | 5448 | if (_scsih_get_sas_address(ioc, le16_to_cpu |
| 5272 | (sas_device_pg0.ParentDevHandle), | 5449 | (sas_device_pg0.ParentDevHandle), |
| @@ -5296,6 +5473,7 @@ _scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd) | |||
| 5296 | else | 5473 | else |
| 5297 | _scsih_sas_device_add(ioc, sas_device); | 5474 | _scsih_sas_device_add(ioc, sas_device); |
| 5298 | 5475 | ||
| 5476 | sas_device_put(sas_device); | ||
| 5299 | return 0; | 5477 | return 0; |
| 5300 | } | 5478 | } |
| 5301 | 5479 | ||
| @@ -5344,7 +5522,6 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, | |||
| 5344 | "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, | 5522 | "handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__, |
| 5345 | sas_device->handle, (unsigned long long) | 5523 | sas_device->handle, (unsigned long long) |
| 5346 | sas_device->sas_address)); | 5524 | sas_device->sas_address)); |
| 5347 | kfree(sas_device); | ||
| 5348 | } | 5525 | } |
| 5349 | /** | 5526 | /** |
| 5350 | * _scsih_device_remove_by_handle - removing device object by handle | 5527 | * _scsih_device_remove_by_handle - removing device object by handle |
| @@ -5363,12 +5540,17 @@ _scsih_device_remove_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
| 5363 | return; | 5540 | return; |
| 5364 | 5541 | ||
| 5365 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5542 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 5366 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 5543 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 5367 | if (sas_device) | 5544 | if (sas_device) { |
| 5368 | list_del(&sas_device->list); | 5545 | list_del_init(&sas_device->list); |
| 5546 | sas_device_put(sas_device); | ||
| 5547 | } | ||
| 5369 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5548 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5370 | if (sas_device) | 5549 | |
| 5550 | if (sas_device) { | ||
| 5371 | _scsih_remove_device(ioc, sas_device); | 5551 | _scsih_remove_device(ioc, sas_device); |
| 5552 | sas_device_put(sas_device); | ||
| 5553 | } | ||
| 5372 | } | 5554 | } |
| 5373 | 5555 | ||
| 5374 | /** | 5556 | /** |
| @@ -5389,13 +5571,17 @@ mpt2sas_device_remove_by_sas_address(struct MPT2SAS_ADAPTER *ioc, | |||
| 5389 | return; | 5571 | return; |
| 5390 | 5572 | ||
| 5391 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5573 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 5392 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 5574 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, sas_address); |
| 5393 | sas_address); | 5575 | if (sas_device) { |
| 5394 | if (sas_device) | 5576 | list_del_init(&sas_device->list); |
| 5395 | list_del(&sas_device->list); | 5577 | sas_device_put(sas_device); |
| 5578 | } | ||
| 5396 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5579 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5397 | if (sas_device) | 5580 | |
| 5581 | if (sas_device) { | ||
| 5398 | _scsih_remove_device(ioc, sas_device); | 5582 | _scsih_remove_device(ioc, sas_device); |
| 5583 | sas_device_put(sas_device); | ||
| 5584 | } | ||
| 5399 | } | 5585 | } |
| 5400 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 5586 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
| 5401 | /** | 5587 | /** |
| @@ -5716,26 +5902,28 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 5716 | 5902 | ||
| 5717 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 5903 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 5718 | sas_address = le64_to_cpu(event_data->SASAddress); | 5904 | sas_address = le64_to_cpu(event_data->SASAddress); |
| 5719 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 5905 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 5720 | sas_address); | 5906 | sas_address); |
| 5721 | 5907 | ||
| 5722 | if (!sas_device || !sas_device->starget) { | 5908 | if (!sas_device || !sas_device->starget) |
| 5723 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5909 | goto out; |
| 5724 | return; | ||
| 5725 | } | ||
| 5726 | 5910 | ||
| 5727 | target_priv_data = sas_device->starget->hostdata; | 5911 | target_priv_data = sas_device->starget->hostdata; |
| 5728 | if (!target_priv_data) { | 5912 | if (!target_priv_data) |
| 5729 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5913 | goto out; |
| 5730 | return; | ||
| 5731 | } | ||
| 5732 | 5914 | ||
| 5733 | if (event_data->ReasonCode == | 5915 | if (event_data->ReasonCode == |
| 5734 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) | 5916 | MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) |
| 5735 | target_priv_data->tm_busy = 1; | 5917 | target_priv_data->tm_busy = 1; |
| 5736 | else | 5918 | else |
| 5737 | target_priv_data->tm_busy = 0; | 5919 | target_priv_data->tm_busy = 0; |
| 5920 | |||
| 5921 | out: | ||
| 5922 | if (sas_device) | ||
| 5923 | sas_device_put(sas_device); | ||
| 5924 | |||
| 5738 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 5925 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 5926 | |||
| 5739 | } | 5927 | } |
| 5740 | 5928 | ||
| 5741 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 5929 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
| @@ -6123,7 +6311,7 @@ _scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc, | |||
| 6123 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | 6311 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); |
| 6124 | 6312 | ||
| 6125 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6313 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 6126 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 6314 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 6127 | if (sas_device) { | 6315 | if (sas_device) { |
| 6128 | sas_device->volume_handle = 0; | 6316 | sas_device->volume_handle = 0; |
| 6129 | sas_device->volume_wwid = 0; | 6317 | sas_device->volume_wwid = 0; |
| @@ -6142,6 +6330,8 @@ _scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc, | |||
| 6142 | /* exposing raid component */ | 6330 | /* exposing raid component */ |
| 6143 | if (starget) | 6331 | if (starget) |
| 6144 | starget_for_each_device(starget, NULL, _scsih_reprobe_lun); | 6332 | starget_for_each_device(starget, NULL, _scsih_reprobe_lun); |
| 6333 | |||
| 6334 | sas_device_put(sas_device); | ||
| 6145 | } | 6335 | } |
| 6146 | 6336 | ||
| 6147 | /** | 6337 | /** |
| @@ -6170,7 +6360,7 @@ _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc, | |||
| 6170 | &volume_wwid); | 6360 | &volume_wwid); |
| 6171 | 6361 | ||
| 6172 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6362 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 6173 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 6363 | sas_device = __mpt2sas_get_sdev_by_handle(ioc, handle); |
| 6174 | if (sas_device) { | 6364 | if (sas_device) { |
| 6175 | set_bit(handle, ioc->pd_handles); | 6365 | set_bit(handle, ioc->pd_handles); |
| 6176 | if (sas_device->starget && sas_device->starget->hostdata) { | 6366 | if (sas_device->starget && sas_device->starget->hostdata) { |
| @@ -6189,6 +6379,8 @@ _scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc, | |||
| 6189 | /* hiding raid component */ | 6379 | /* hiding raid component */ |
| 6190 | if (starget) | 6380 | if (starget) |
| 6191 | starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun); | 6381 | starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun); |
| 6382 | |||
| 6383 | sas_device_put(sas_device); | ||
| 6192 | } | 6384 | } |
| 6193 | 6385 | ||
| 6194 | /** | 6386 | /** |
| @@ -6221,7 +6413,6 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 6221 | Mpi2EventIrConfigElement_t *element) | 6413 | Mpi2EventIrConfigElement_t *element) |
| 6222 | { | 6414 | { |
| 6223 | struct _sas_device *sas_device; | 6415 | struct _sas_device *sas_device; |
| 6224 | unsigned long flags; | ||
| 6225 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); | 6416 | u16 handle = le16_to_cpu(element->PhysDiskDevHandle); |
| 6226 | Mpi2ConfigReply_t mpi_reply; | 6417 | Mpi2ConfigReply_t mpi_reply; |
| 6227 | Mpi2SasDevicePage0_t sas_device_pg0; | 6418 | Mpi2SasDevicePage0_t sas_device_pg0; |
| @@ -6231,11 +6422,11 @@ _scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc, | |||
| 6231 | 6422 | ||
| 6232 | set_bit(handle, ioc->pd_handles); | 6423 | set_bit(handle, ioc->pd_handles); |
| 6233 | 6424 | ||
| 6234 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6425 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); |
| 6235 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 6426 | if (sas_device) { |
| 6236 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 6427 | sas_device_put(sas_device); |
| 6237 | if (sas_device) | ||
| 6238 | return; | 6428 | return; |
| 6429 | } | ||
| 6239 | 6430 | ||
| 6240 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, | 6431 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, |
| 6241 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { | 6432 | MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { |
| @@ -6509,7 +6700,6 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 6509 | u16 handle, parent_handle; | 6700 | u16 handle, parent_handle; |
| 6510 | u32 state; | 6701 | u32 state; |
| 6511 | struct _sas_device *sas_device; | 6702 | struct _sas_device *sas_device; |
| 6512 | unsigned long flags; | ||
| 6513 | Mpi2ConfigReply_t mpi_reply; | 6703 | Mpi2ConfigReply_t mpi_reply; |
| 6514 | Mpi2SasDevicePage0_t sas_device_pg0; | 6704 | Mpi2SasDevicePage0_t sas_device_pg0; |
| 6515 | u32 ioc_status; | 6705 | u32 ioc_status; |
| @@ -6542,12 +6732,11 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, | |||
| 6542 | if (!ioc->is_warpdrive) | 6732 | if (!ioc->is_warpdrive) |
| 6543 | set_bit(handle, ioc->pd_handles); | 6733 | set_bit(handle, ioc->pd_handles); |
| 6544 | 6734 | ||
| 6545 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6735 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); |
| 6546 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 6736 | if (sas_device) { |
| 6547 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 6737 | sas_device_put(sas_device); |
| 6548 | |||
| 6549 | if (sas_device) | ||
| 6550 | return; | 6738 | return; |
| 6739 | } | ||
| 6551 | 6740 | ||
| 6552 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | 6741 | if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, |
| 6553 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | 6742 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, |
| @@ -7015,6 +7204,7 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 7015 | struct _raid_device *raid_device, *raid_device_next; | 7204 | struct _raid_device *raid_device, *raid_device_next; |
| 7016 | struct list_head tmp_list; | 7205 | struct list_head tmp_list; |
| 7017 | unsigned long flags; | 7206 | unsigned long flags; |
| 7207 | LIST_HEAD(head); | ||
| 7018 | 7208 | ||
| 7019 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n", | 7209 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: start\n", |
| 7020 | ioc->name); | 7210 | ioc->name); |
| @@ -7022,14 +7212,29 @@ _scsih_remove_unresponding_sas_devices(struct MPT2SAS_ADAPTER *ioc) | |||
| 7022 | /* removing unresponding end devices */ | 7212 | /* removing unresponding end devices */ |
| 7023 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: end-devices\n", | 7213 | printk(MPT2SAS_INFO_FMT "removing unresponding devices: end-devices\n", |
| 7024 | ioc->name); | 7214 | ioc->name); |
| 7215 | |||
| 7216 | /* | ||
| 7217 | * Iterate, pulling off devices marked as non-responding. We become the | ||
| 7218 | * owner for the reference the list had on any object we prune. | ||
| 7219 | */ | ||
| 7220 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 7025 | list_for_each_entry_safe(sas_device, sas_device_next, | 7221 | list_for_each_entry_safe(sas_device, sas_device_next, |
| 7026 | &ioc->sas_device_list, list) { | 7222 | &ioc->sas_device_list, list) { |
| 7027 | if (!sas_device->responding) | 7223 | if (!sas_device->responding) |
| 7028 | mpt2sas_device_remove_by_sas_address(ioc, | 7224 | list_move_tail(&sas_device->list, &head); |
| 7029 | sas_device->sas_address); | ||
| 7030 | else | 7225 | else |
| 7031 | sas_device->responding = 0; | 7226 | sas_device->responding = 0; |
| 7032 | } | 7227 | } |
| 7228 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 7229 | |||
| 7230 | /* | ||
| 7231 | * Now, uninitialize and remove the unresponding devices we pruned. | ||
| 7232 | */ | ||
| 7233 | list_for_each_entry_safe(sas_device, sas_device_next, &head, list) { | ||
| 7234 | _scsih_remove_device(ioc, sas_device); | ||
| 7235 | list_del_init(&sas_device->list); | ||
| 7236 | sas_device_put(sas_device); | ||
| 7237 | } | ||
| 7033 | 7238 | ||
| 7034 | /* removing unresponding volumes */ | 7239 | /* removing unresponding volumes */ |
| 7035 | if (ioc->ir_firmware) { | 7240 | if (ioc->ir_firmware) { |
| @@ -7179,11 +7384,11 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) | |||
| 7179 | } | 7384 | } |
| 7180 | phys_disk_num = pd_pg0.PhysDiskNum; | 7385 | phys_disk_num = pd_pg0.PhysDiskNum; |
| 7181 | handle = le16_to_cpu(pd_pg0.DevHandle); | 7386 | handle = le16_to_cpu(pd_pg0.DevHandle); |
| 7182 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 7387 | sas_device = mpt2sas_get_sdev_by_handle(ioc, handle); |
| 7183 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | 7388 | if (sas_device) { |
| 7184 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 7389 | sas_device_put(sas_device); |
| 7185 | if (sas_device) | ||
| 7186 | continue; | 7390 | continue; |
| 7391 | } | ||
| 7187 | if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, | 7392 | if (mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, |
| 7188 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, | 7393 | &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, |
| 7189 | handle) != 0) | 7394 | handle) != 0) |
| @@ -7302,12 +7507,12 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) | |||
| 7302 | if (!(_scsih_is_end_device( | 7507 | if (!(_scsih_is_end_device( |
| 7303 | le32_to_cpu(sas_device_pg0.DeviceInfo)))) | 7508 | le32_to_cpu(sas_device_pg0.DeviceInfo)))) |
| 7304 | continue; | 7509 | continue; |
| 7305 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 7510 | sas_device = mpt2sas_get_sdev_by_addr(ioc, |
| 7306 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 7307 | le64_to_cpu(sas_device_pg0.SASAddress)); | 7511 | le64_to_cpu(sas_device_pg0.SASAddress)); |
| 7308 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 7512 | if (sas_device) { |
| 7309 | if (sas_device) | 7513 | sas_device_put(sas_device); |
| 7310 | continue; | 7514 | continue; |
| 7515 | } | ||
| 7311 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); | 7516 | parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); |
| 7312 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { | 7517 | if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { |
| 7313 | printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: " | 7518 | printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: " |
| @@ -7410,17 +7615,27 @@ _firmware_event_work(struct work_struct *work) | |||
| 7410 | struct fw_event_work, delayed_work.work); | 7615 | struct fw_event_work, delayed_work.work); |
| 7411 | struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; | 7616 | struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; |
| 7412 | 7617 | ||
| 7618 | _scsih_fw_event_del_from_list(ioc, fw_event); | ||
| 7619 | |||
| 7413 | /* the queue is being flushed so ignore this event */ | 7620 | /* the queue is being flushed so ignore this event */ |
| 7414 | if (ioc->remove_host || | 7621 | if (ioc->remove_host || ioc->pci_error_recovery) { |
| 7415 | ioc->pci_error_recovery) { | 7622 | fw_event_work_put(fw_event); |
| 7416 | _scsih_fw_event_free(ioc, fw_event); | ||
| 7417 | return; | 7623 | return; |
| 7418 | } | 7624 | } |
| 7419 | 7625 | ||
| 7420 | switch (fw_event->event) { | 7626 | switch (fw_event->event) { |
| 7421 | case MPT2SAS_REMOVE_UNRESPONDING_DEVICES: | 7627 | case MPT2SAS_REMOVE_UNRESPONDING_DEVICES: |
| 7422 | while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery) | 7628 | while (scsi_host_in_recovery(ioc->shost) || |
| 7629 | ioc->shost_recovery) { | ||
| 7630 | /* | ||
| 7631 | * If we're unloading, bail. Otherwise, this can become | ||
| 7632 | * an infinite loop. | ||
| 7633 | */ | ||
| 7634 | if (ioc->remove_host) | ||
| 7635 | goto out; | ||
| 7636 | |||
| 7423 | ssleep(1); | 7637 | ssleep(1); |
| 7638 | } | ||
| 7424 | _scsih_remove_unresponding_sas_devices(ioc); | 7639 | _scsih_remove_unresponding_sas_devices(ioc); |
| 7425 | _scsih_scan_for_devices_after_reset(ioc); | 7640 | _scsih_scan_for_devices_after_reset(ioc); |
| 7426 | break; | 7641 | break; |
| @@ -7469,7 +7684,8 @@ _firmware_event_work(struct work_struct *work) | |||
| 7469 | _scsih_sas_ir_operation_status_event(ioc, fw_event); | 7684 | _scsih_sas_ir_operation_status_event(ioc, fw_event); |
| 7470 | break; | 7685 | break; |
| 7471 | } | 7686 | } |
| 7472 | _scsih_fw_event_free(ioc, fw_event); | 7687 | out: |
| 7688 | fw_event_work_put(fw_event); | ||
| 7473 | } | 7689 | } |
| 7474 | 7690 | ||
| 7475 | /** | 7691 | /** |
| @@ -7607,7 +7823,7 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
| 7607 | } | 7823 | } |
| 7608 | 7824 | ||
| 7609 | sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; | 7825 | sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; |
| 7610 | fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC); | 7826 | fw_event = alloc_fw_event_work(sz); |
| 7611 | if (!fw_event) { | 7827 | if (!fw_event) { |
| 7612 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 7828 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
| 7613 | ioc->name, __FILE__, __LINE__, __func__); | 7829 | ioc->name, __FILE__, __LINE__, __func__); |
| @@ -7620,6 +7836,7 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | |||
| 7620 | fw_event->VP_ID = mpi_reply->VP_ID; | 7836 | fw_event->VP_ID = mpi_reply->VP_ID; |
| 7621 | fw_event->event = event; | 7837 | fw_event->event = event; |
| 7622 | _scsih_fw_event_add(ioc, fw_event); | 7838 | _scsih_fw_event_add(ioc, fw_event); |
| 7839 | fw_event_work_put(fw_event); | ||
| 7623 | return; | 7840 | return; |
| 7624 | } | 7841 | } |
| 7625 | 7842 | ||
| @@ -7867,7 +8084,9 @@ _scsih_remove(struct pci_dev *pdev) | |||
| 7867 | sas_remove_host(shost); | 8084 | sas_remove_host(shost); |
| 7868 | scsi_remove_host(shost); | 8085 | scsi_remove_host(shost); |
| 7869 | mpt2sas_base_detach(ioc); | 8086 | mpt2sas_base_detach(ioc); |
| 8087 | spin_lock(&gioc_lock); | ||
| 7870 | list_del(&ioc->list); | 8088 | list_del(&ioc->list); |
| 8089 | spin_unlock(&gioc_lock); | ||
| 7871 | scsi_host_put(shost); | 8090 | scsi_host_put(shost); |
| 7872 | } | 8091 | } |
| 7873 | 8092 | ||
| @@ -7966,6 +8185,48 @@ _scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc) | |||
| 7966 | } | 8185 | } |
| 7967 | } | 8186 | } |
| 7968 | 8187 | ||
| 8188 | static struct _sas_device *get_next_sas_device(struct MPT2SAS_ADAPTER *ioc) | ||
| 8189 | { | ||
| 8190 | struct _sas_device *sas_device = NULL; | ||
| 8191 | unsigned long flags; | ||
| 8192 | |||
| 8193 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 8194 | if (!list_empty(&ioc->sas_device_init_list)) { | ||
| 8195 | sas_device = list_first_entry(&ioc->sas_device_init_list, | ||
| 8196 | struct _sas_device, list); | ||
| 8197 | sas_device_get(sas_device); | ||
| 8198 | } | ||
| 8199 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 8200 | |||
| 8201 | return sas_device; | ||
| 8202 | } | ||
| 8203 | |||
| 8204 | static void sas_device_make_active(struct MPT2SAS_ADAPTER *ioc, | ||
| 8205 | struct _sas_device *sas_device) | ||
| 8206 | { | ||
| 8207 | unsigned long flags; | ||
| 8208 | |||
| 8209 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
| 8210 | |||
| 8211 | /* | ||
| 8212 | * Since we dropped the lock during the call to port_add(), we need to | ||
| 8213 | * be careful here that somebody else didn't move or delete this item | ||
| 8214 | * while we were busy with other things. | ||
| 8215 | * | ||
| 8216 | * If it was on the list, we need a put() for the reference the list | ||
| 8217 | * had. Either way, we need a get() for the destination list. | ||
| 8218 | */ | ||
| 8219 | if (!list_empty(&sas_device->list)) { | ||
| 8220 | list_del_init(&sas_device->list); | ||
| 8221 | sas_device_put(sas_device); | ||
| 8222 | } | ||
| 8223 | |||
| 8224 | sas_device_get(sas_device); | ||
| 8225 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | ||
| 8226 | |||
| 8227 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
| 8228 | } | ||
| 8229 | |||
| 7969 | /** | 8230 | /** |
| 7970 | * _scsih_probe_sas - reporting sas devices to sas transport | 8231 | * _scsih_probe_sas - reporting sas devices to sas transport |
| 7971 | * @ioc: per adapter object | 8232 | * @ioc: per adapter object |
| @@ -7975,34 +8236,30 @@ _scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc) | |||
| 7975 | static void | 8236 | static void |
| 7976 | _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) | 8237 | _scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc) |
| 7977 | { | 8238 | { |
| 7978 | struct _sas_device *sas_device, *next; | 8239 | struct _sas_device *sas_device; |
| 7979 | unsigned long flags; | ||
| 7980 | |||
| 7981 | /* SAS Device List */ | ||
| 7982 | list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, | ||
| 7983 | list) { | ||
| 7984 | 8240 | ||
| 7985 | if (ioc->hide_drives) | 8241 | if (ioc->hide_drives) |
| 7986 | continue; | 8242 | return; |
| 7987 | 8243 | ||
| 8244 | while ((sas_device = get_next_sas_device(ioc))) { | ||
| 7988 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, | 8245 | if (!mpt2sas_transport_port_add(ioc, sas_device->handle, |
| 7989 | sas_device->sas_address_parent)) { | 8246 | sas_device->sas_address_parent)) { |
| 7990 | list_del(&sas_device->list); | 8247 | _scsih_sas_device_remove(ioc, sas_device); |
| 7991 | kfree(sas_device); | 8248 | sas_device_put(sas_device); |
| 7992 | continue; | 8249 | continue; |
| 7993 | } else if (!sas_device->starget) { | 8250 | } else if (!sas_device->starget) { |
| 7994 | if (!ioc->is_driver_loading) { | 8251 | if (!ioc->is_driver_loading) { |
| 7995 | mpt2sas_transport_port_remove(ioc, | 8252 | mpt2sas_transport_port_remove(ioc, |
| 7996 | sas_device->sas_address, | 8253 | sas_device->sas_address, |
| 7997 | sas_device->sas_address_parent); | 8254 | sas_device->sas_address_parent); |
| 7998 | list_del(&sas_device->list); | 8255 | _scsih_sas_device_remove(ioc, sas_device); |
| 7999 | kfree(sas_device); | 8256 | sas_device_put(sas_device); |
| 8000 | continue; | 8257 | continue; |
| 8001 | } | 8258 | } |
| 8002 | } | 8259 | } |
| 8003 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 8260 | |
| 8004 | list_move_tail(&sas_device->list, &ioc->sas_device_list); | 8261 | sas_device_make_active(ioc, sas_device); |
| 8005 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 8262 | sas_device_put(sas_device); |
| 8006 | } | 8263 | } |
| 8007 | } | 8264 | } |
| 8008 | 8265 | ||
| @@ -8142,7 +8399,9 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 8142 | ioc = shost_priv(shost); | 8399 | ioc = shost_priv(shost); |
| 8143 | memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER)); | 8400 | memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER)); |
| 8144 | INIT_LIST_HEAD(&ioc->list); | 8401 | INIT_LIST_HEAD(&ioc->list); |
| 8402 | spin_lock(&gioc_lock); | ||
| 8145 | list_add_tail(&ioc->list, &mpt2sas_ioc_list); | 8403 | list_add_tail(&ioc->list, &mpt2sas_ioc_list); |
| 8404 | spin_unlock(&gioc_lock); | ||
| 8146 | ioc->shost = shost; | 8405 | ioc->shost = shost; |
| 8147 | ioc->id = mpt_ids++; | 8406 | ioc->id = mpt_ids++; |
| 8148 | sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id); | 8407 | sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id); |
| @@ -8167,6 +8426,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 8167 | ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; | 8426 | ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; |
| 8168 | /* misc semaphores and spin locks */ | 8427 | /* misc semaphores and spin locks */ |
| 8169 | mutex_init(&ioc->reset_in_progress_mutex); | 8428 | mutex_init(&ioc->reset_in_progress_mutex); |
| 8429 | /* initializing pci_access_mutex lock */ | ||
| 8430 | mutex_init(&ioc->pci_access_mutex); | ||
| 8170 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); | 8431 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); |
| 8171 | spin_lock_init(&ioc->scsi_lookup_lock); | 8432 | spin_lock_init(&ioc->scsi_lookup_lock); |
| 8172 | spin_lock_init(&ioc->sas_device_lock); | 8433 | spin_lock_init(&ioc->sas_device_lock); |
| @@ -8269,7 +8530,9 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 8269 | out_attach_fail: | 8530 | out_attach_fail: |
| 8270 | destroy_workqueue(ioc->firmware_event_thread); | 8531 | destroy_workqueue(ioc->firmware_event_thread); |
| 8271 | out_thread_fail: | 8532 | out_thread_fail: |
| 8533 | spin_lock(&gioc_lock); | ||
| 8272 | list_del(&ioc->list); | 8534 | list_del(&ioc->list); |
| 8535 | spin_unlock(&gioc_lock); | ||
| 8273 | scsi_host_put(shost); | 8536 | scsi_host_put(shost); |
| 8274 | return rv; | 8537 | return rv; |
| 8275 | } | 8538 | } |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index ff2500ab9ba4..af868009395d 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c | |||
| @@ -1323,15 +1323,17 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) | |||
| 1323 | int rc; | 1323 | int rc; |
| 1324 | 1324 | ||
| 1325 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1325 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1326 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1326 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 1327 | rphy->identify.sas_address); | 1327 | rphy->identify.sas_address); |
| 1328 | if (sas_device) { | 1328 | if (sas_device) { |
| 1329 | *identifier = sas_device->enclosure_logical_id; | 1329 | *identifier = sas_device->enclosure_logical_id; |
| 1330 | rc = 0; | 1330 | rc = 0; |
| 1331 | sas_device_put(sas_device); | ||
| 1331 | } else { | 1332 | } else { |
| 1332 | *identifier = 0; | 1333 | *identifier = 0; |
| 1333 | rc = -ENXIO; | 1334 | rc = -ENXIO; |
| 1334 | } | 1335 | } |
| 1336 | |||
| 1335 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1337 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1336 | return rc; | 1338 | return rc; |
| 1337 | } | 1339 | } |
| @@ -1351,12 +1353,14 @@ _transport_get_bay_identifier(struct sas_rphy *rphy) | |||
| 1351 | int rc; | 1353 | int rc; |
| 1352 | 1354 | ||
| 1353 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 1355 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 1354 | sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc, | 1356 | sas_device = __mpt2sas_get_sdev_by_addr(ioc, |
| 1355 | rphy->identify.sas_address); | 1357 | rphy->identify.sas_address); |
| 1356 | if (sas_device) | 1358 | if (sas_device) { |
| 1357 | rc = sas_device->slot; | 1359 | rc = sas_device->slot; |
| 1358 | else | 1360 | sas_device_put(sas_device); |
| 1361 | } else { | ||
| 1359 | rc = -ENXIO; | 1362 | rc = -ENXIO; |
| 1363 | } | ||
| 1360 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1364 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1361 | return rc; | 1365 | return rc; |
| 1362 | } | 1366 | } |
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h index c34c1157907b..ec27ad2d186f 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | * scatter/gather formats. | 8 | * scatter/gather formats. |
| 9 | * Creation Date: June 21, 2006 | 9 | * Creation Date: June 21, 2006 |
| 10 | * | 10 | * |
| 11 | * mpi2.h Version: 02.00.31 | 11 | * mpi2.h Version: 02.00.35 |
| 12 | * | 12 | * |
| 13 | * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 | 13 | * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 |
| 14 | * prefix are for use only on MPI v2.5 products, and must not be used | 14 | * prefix are for use only on MPI v2.5 products, and must not be used |
| @@ -88,6 +88,10 @@ | |||
| 88 | * Added MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET. | 88 | * Added MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET. |
| 89 | * 04-09-13 02.00.30 Bumped MPI2_HEADER_VERSION_UNIT. | 89 | * 04-09-13 02.00.30 Bumped MPI2_HEADER_VERSION_UNIT. |
| 90 | * 04-17-13 02.00.31 Bumped MPI2_HEADER_VERSION_UNIT. | 90 | * 04-17-13 02.00.31 Bumped MPI2_HEADER_VERSION_UNIT. |
| 91 | * 08-19-13 02.00.32 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 92 | * 12-05-13 02.00.33 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 93 | * 01-08-14 02.00.34 Bumped MPI2_HEADER_VERSION_UNIT | ||
| 94 | * 06-13-14 02.00.35 Bumped MPI2_HEADER_VERSION_UNIT. | ||
| 91 | * -------------------------------------------------------------------------- | 95 | * -------------------------------------------------------------------------- |
| 92 | */ | 96 | */ |
| 93 | 97 | ||
| @@ -121,7 +125,7 @@ | |||
| 121 | #define MPI2_VERSION_02_05 (0x0205) | 125 | #define MPI2_VERSION_02_05 (0x0205) |
| 122 | 126 | ||
| 123 | /*Unit and Dev versioning for this MPI header set */ | 127 | /*Unit and Dev versioning for this MPI header set */ |
| 124 | #define MPI2_HEADER_VERSION_UNIT (0x1F) | 128 | #define MPI2_HEADER_VERSION_UNIT (0x23) |
| 125 | #define MPI2_HEADER_VERSION_DEV (0x00) | 129 | #define MPI2_HEADER_VERSION_DEV (0x00) |
| 126 | #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) | 130 | #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) |
| 127 | #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) | 131 | #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) |
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h index e261a3153bb3..581fdb375db5 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Title: MPI Configuration messages and pages | 6 | * Title: MPI Configuration messages and pages |
| 7 | * Creation Date: November 10, 2006 | 7 | * Creation Date: November 10, 2006 |
| 8 | * | 8 | * |
| 9 | * mpi2_cnfg.h Version: 02.00.26 | 9 | * mpi2_cnfg.h Version: 02.00.29 |
| 10 | * | 10 | * |
| 11 | * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 | 11 | * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 |
| 12 | * prefix are for use only on MPI v2.5 products, and must not be used | 12 | * prefix are for use only on MPI v2.5 products, and must not be used |
| @@ -165,6 +165,20 @@ | |||
| 165 | * match the specification. | 165 | * match the specification. |
| 166 | * 08-19-13 02.00.26 Added reserved words to MPI2_CONFIG_PAGE_IO_UNIT_7 for | 166 | * 08-19-13 02.00.26 Added reserved words to MPI2_CONFIG_PAGE_IO_UNIT_7 for |
| 167 | * future use. | 167 | * future use. |
| 168 | * 12-05-13 02.00.27 Added MPI2_MANPAGE7_FLAG_BASE_ENCLOSURE_LEVEL for | ||
| 169 | * MPI2_CONFIG_PAGE_MAN_7. | ||
| 170 | * Added EnclosureLevel and ConnectorName fields to | ||
| 171 | * MPI2_CONFIG_PAGE_SAS_DEV_0. | ||
| 172 | * Added MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID for | ||
| 173 | * MPI2_CONFIG_PAGE_SAS_DEV_0. | ||
| 174 | * Added EnclosureLevel field to | ||
| 175 | * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. | ||
| 176 | * Added MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID for | ||
| 177 | * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. | ||
| 178 | * 01-08-14 02.00.28 Added more defines for the BiosOptions field of | ||
| 179 | * MPI2_CONFIG_PAGE_BIOS_1. | ||
| 180 | * 06-13-14 02.00.29 Added SSUTimeout field to MPI2_CONFIG_PAGE_BIOS_1, and | ||
| 181 | * more defines for the BiosOptions field.. | ||
| 168 | * -------------------------------------------------------------------------- | 182 | * -------------------------------------------------------------------------- |
| 169 | */ | 183 | */ |
| 170 | 184 | ||
| @@ -724,6 +738,7 @@ typedef struct _MPI2_CONFIG_PAGE_MAN_7 { | |||
| 724 | #define MPI2_MANUFACTURING7_PAGEVERSION (0x01) | 738 | #define MPI2_MANUFACTURING7_PAGEVERSION (0x01) |
| 725 | 739 | ||
| 726 | /*defines for the Flags field */ | 740 | /*defines for the Flags field */ |
| 741 | #define MPI2_MANPAGE7_FLAG_BASE_ENCLOSURE_LEVEL (0x00000008) | ||
| 727 | #define MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER (0x00000002) | 742 | #define MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER (0x00000002) |
| 728 | #define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) | 743 | #define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) |
| 729 | 744 | ||
| @@ -1311,7 +1326,9 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_1 { | |||
| 1311 | MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ | 1326 | MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ |
| 1312 | U32 BiosOptions; /*0x04 */ | 1327 | U32 BiosOptions; /*0x04 */ |
| 1313 | U32 IOCSettings; /*0x08 */ | 1328 | U32 IOCSettings; /*0x08 */ |
| 1314 | U32 Reserved1; /*0x0C */ | 1329 | U8 SSUTimeout; /*0x0C */ |
| 1330 | U8 Reserved1; /*0x0D */ | ||
| 1331 | U16 Reserved2; /*0x0E */ | ||
| 1315 | U32 DeviceSettings; /*0x10 */ | 1332 | U32 DeviceSettings; /*0x10 */ |
| 1316 | U16 NumberOfDevices; /*0x14 */ | 1333 | U16 NumberOfDevices; /*0x14 */ |
| 1317 | U16 UEFIVersion; /*0x16 */ | 1334 | U16 UEFIVersion; /*0x16 */ |
| @@ -1323,9 +1340,24 @@ typedef struct _MPI2_CONFIG_PAGE_BIOS_1 { | |||
| 1323 | *PTR_MPI2_CONFIG_PAGE_BIOS_1, | 1340 | *PTR_MPI2_CONFIG_PAGE_BIOS_1, |
| 1324 | Mpi2BiosPage1_t, *pMpi2BiosPage1_t; | 1341 | Mpi2BiosPage1_t, *pMpi2BiosPage1_t; |
| 1325 | 1342 | ||
| 1326 | #define MPI2_BIOSPAGE1_PAGEVERSION (0x05) | 1343 | #define MPI2_BIOSPAGE1_PAGEVERSION (0x07) |
| 1327 | 1344 | ||
| 1328 | /*values for BIOS Page 1 BiosOptions field */ | 1345 | /*values for BIOS Page 1 BiosOptions field */ |
| 1346 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_MASK (0x00003800) | ||
| 1347 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_PBDHL (0x00000000) | ||
| 1348 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_ENCSLOSURE (0x00000800) | ||
| 1349 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_LWWID (0x00001000) | ||
| 1350 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_PSENS (0x00001800) | ||
| 1351 | #define MPI2_BIOSPAGE1_OPTIONS_PNS_ESPHY (0x00002000) | ||
| 1352 | |||
| 1353 | #define MPI2_BIOSPAGE1_OPTIONS_X86_DISABLE_BIOS (0x00000400) | ||
| 1354 | |||
| 1355 | #define MPI2_BIOSPAGE1_OPTIONS_MASK_REGISTRATION_UEFI_BSD (0x00000300) | ||
| 1356 | #define MPI2_BIOSPAGE1_OPTIONS_USE_BIT0_REGISTRATION_UEFI_BSD (0x00000000) | ||
| 1357 | #define MPI2_BIOSPAGE1_OPTIONS_FULL_REGISTRATION_UEFI_BSD (0x00000100) | ||
| 1358 | #define MPI2_BIOSPAGE1_OPTIONS_ADAPTER_REGISTRATION_UEFI_BSD (0x00000200) | ||
| 1359 | #define MPI2_BIOSPAGE1_OPTIONS_DISABLE_REGISTRATION_UEFI_BSD (0x00000300) | ||
| 1360 | |||
| 1329 | #define MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID (0x000000F0) | 1361 | #define MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID (0x000000F0) |
| 1330 | #define MPI2_BIOSPAGE1_OPTIONS_LSI_OEM_ID (0x00000000) | 1362 | #define MPI2_BIOSPAGE1_OPTIONS_LSI_OEM_ID (0x00000000) |
| 1331 | 1363 | ||
| @@ -2633,9 +2665,9 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 { | |||
| 2633 | U8 | 2665 | U8 |
| 2634 | ControlGroup; /*0x2E */ | 2666 | ControlGroup; /*0x2E */ |
| 2635 | U8 | 2667 | U8 |
| 2636 | Reserved1; /*0x2F */ | 2668 | EnclosureLevel; /*0x2F */ |
| 2637 | U32 | 2669 | U32 |
| 2638 | Reserved2; /*0x30 */ | 2670 | ConnectorName[4]; /*0x30 */ |
| 2639 | U32 | 2671 | U32 |
| 2640 | Reserved3; /*0x34 */ | 2672 | Reserved3; /*0x34 */ |
| 2641 | } MPI2_CONFIG_PAGE_SAS_DEV_0, | 2673 | } MPI2_CONFIG_PAGE_SAS_DEV_0, |
| @@ -2643,7 +2675,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 { | |||
| 2643 | Mpi2SasDevicePage0_t, | 2675 | Mpi2SasDevicePage0_t, |
| 2644 | *pMpi2SasDevicePage0_t; | 2676 | *pMpi2SasDevicePage0_t; |
| 2645 | 2677 | ||
| 2646 | #define MPI2_SASDEVICE0_PAGEVERSION (0x08) | 2678 | #define MPI2_SASDEVICE0_PAGEVERSION (0x09) |
| 2647 | 2679 | ||
| 2648 | /*values for SAS Device Page 0 AccessStatus field */ | 2680 | /*values for SAS Device Page 0 AccessStatus field */ |
| 2649 | #define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) | 2681 | #define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) |
| @@ -2683,6 +2715,7 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 { | |||
| 2683 | #define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) | 2715 | #define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) |
| 2684 | #define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) | 2716 | #define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) |
| 2685 | #define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) | 2717 | #define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) |
| 2718 | #define MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID (0x0002) | ||
| 2686 | #define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) | 2719 | #define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) |
| 2687 | 2720 | ||
| 2688 | 2721 | ||
| @@ -3019,8 +3052,10 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 { | |||
| 3019 | NumSlots; /*0x18 */ | 3052 | NumSlots; /*0x18 */ |
| 3020 | U16 | 3053 | U16 |
| 3021 | StartSlot; /*0x1A */ | 3054 | StartSlot; /*0x1A */ |
| 3022 | U16 | 3055 | U8 |
| 3023 | Reserved2; /*0x1C */ | 3056 | Reserved2; /*0x1C */ |
| 3057 | U8 | ||
| 3058 | EnclosureLevel; /*0x1D */ | ||
| 3024 | U16 | 3059 | U16 |
| 3025 | SEPDevHandle; /*0x1E */ | 3060 | SEPDevHandle; /*0x1E */ |
| 3026 | U32 | 3061 | U32 |
| @@ -3031,9 +3066,10 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 { | |||
| 3031 | *PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, | 3066 | *PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, |
| 3032 | Mpi2SasEnclosurePage0_t, *pMpi2SasEnclosurePage0_t; | 3067 | Mpi2SasEnclosurePage0_t, *pMpi2SasEnclosurePage0_t; |
| 3033 | 3068 | ||
| 3034 | #define MPI2_SASENCLOSURE0_PAGEVERSION (0x03) | 3069 | #define MPI2_SASENCLOSURE0_PAGEVERSION (0x04) |
| 3035 | 3070 | ||
| 3036 | /*values for SAS Enclosure Page 0 Flags field */ | 3071 | /*values for SAS Enclosure Page 0 Flags field */ |
| 3072 | #define MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID (0x0010) | ||
| 3037 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F) | 3073 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F) |
| 3038 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) | 3074 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) |
| 3039 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) | 3075 | #define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) |
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h index 490830957806..d7598cc4bb8e 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages | 6 | * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages |
| 7 | * Creation Date: October 11, 2006 | 7 | * Creation Date: October 11, 2006 |
| 8 | * | 8 | * |
| 9 | * mpi2_ioc.h Version: 02.00.23 | 9 | * mpi2_ioc.h Version: 02.00.24 |
| 10 | * | 10 | * |
| 11 | * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 | 11 | * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 |
| 12 | * prefix are for use only on MPI v2.5 products, and must not be used | 12 | * prefix are for use only on MPI v2.5 products, and must not be used |
| @@ -132,6 +132,7 @@ | |||
| 132 | * Added MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE. | 132 | * Added MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE. |
| 133 | * Added MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY. | 133 | * Added MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY. |
| 134 | * Added Encrypted Hash Extended Image. | 134 | * Added Encrypted Hash Extended Image. |
| 135 | * 12-05-13 02.00.24 Added MPI25_HASH_IMAGE_TYPE_BIOS. | ||
| 135 | * -------------------------------------------------------------------------- | 136 | * -------------------------------------------------------------------------- |
| 136 | */ | 137 | */ |
| 137 | 138 | ||
| @@ -1598,6 +1599,7 @@ Mpi25EncryptedHashEntry_t, *pMpi25EncryptedHashEntry_t; | |||
| 1598 | /* values for HashImageType */ | 1599 | /* values for HashImageType */ |
| 1599 | #define MPI25_HASH_IMAGE_TYPE_UNUSED (0x00) | 1600 | #define MPI25_HASH_IMAGE_TYPE_UNUSED (0x00) |
| 1600 | #define MPI25_HASH_IMAGE_TYPE_FIRMWARE (0x01) | 1601 | #define MPI25_HASH_IMAGE_TYPE_FIRMWARE (0x01) |
| 1602 | #define MPI25_HASH_IMAGE_TYPE_BIOS (0x02) | ||
| 1601 | 1603 | ||
| 1602 | /* values for HashAlgorithm */ | 1604 | /* values for HashAlgorithm */ |
| 1603 | #define MPI25_HASH_ALGORITHM_UNUSED (0x00) | 1605 | #define MPI25_HASH_ALGORITHM_UNUSED (0x00) |
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h index 904910d8a737..1629e5bce7e1 100644 --- a/drivers/scsi/mpt3sas/mpi/mpi2_tool.h +++ b/drivers/scsi/mpt3sas/mpi/mpi2_tool.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Title: MPI diagnostic tool structures and definitions | 6 | * Title: MPI diagnostic tool structures and definitions |
| 7 | * Creation Date: March 26, 2007 | 7 | * Creation Date: March 26, 2007 |
| 8 | * | 8 | * |
| 9 | * mpi2_tool.h Version: 02.00.11 | 9 | * mpi2_tool.h Version: 02.00.12 |
| 10 | * | 10 | * |
| 11 | * Version History | 11 | * Version History |
| 12 | * --------------- | 12 | * --------------- |
| @@ -33,6 +33,7 @@ | |||
| 33 | * 07-26-12 02.00.10 Modified MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST so that | 33 | * 07-26-12 02.00.10 Modified MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST so that |
| 34 | * it uses MPI Chain SGE as well as MPI Simple SGE. | 34 | * it uses MPI Chain SGE as well as MPI Simple SGE. |
| 35 | * 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info. | 35 | * 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info. |
| 36 | * 01-08-14 02.00.12 Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC. | ||
| 36 | * -------------------------------------------------------------------------- | 37 | * -------------------------------------------------------------------------- |
| 37 | */ | 38 | */ |
| 38 | 39 | ||
| @@ -100,6 +101,7 @@ typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST { | |||
| 100 | #define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000) | 101 | #define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000) |
| 101 | #define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000) | 102 | #define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000) |
| 102 | #define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000) | 103 | #define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000) |
| 104 | #define MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC (0x04000000) | ||
| 103 | #define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000) | 105 | #define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000) |
| 104 | #define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000) | 106 | #define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000) |
| 105 | #define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004) | 107 | #define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004) |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 43f87e904b98..d4f1dcdb8361 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c | |||
| @@ -83,10 +83,10 @@ static int msix_disable = -1; | |||
| 83 | module_param(msix_disable, int, 0); | 83 | module_param(msix_disable, int, 0); |
| 84 | MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); | 84 | MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); |
| 85 | 85 | ||
| 86 | static int max_msix_vectors = 8; | 86 | static int max_msix_vectors = -1; |
| 87 | module_param(max_msix_vectors, int, 0); | 87 | module_param(max_msix_vectors, int, 0); |
| 88 | MODULE_PARM_DESC(max_msix_vectors, | 88 | MODULE_PARM_DESC(max_msix_vectors, |
| 89 | " max msix vectors - (default=8)"); | 89 | " max msix vectors"); |
| 90 | 90 | ||
| 91 | static int mpt3sas_fwfault_debug; | 91 | static int mpt3sas_fwfault_debug; |
| 92 | MODULE_PARM_DESC(mpt3sas_fwfault_debug, | 92 | MODULE_PARM_DESC(mpt3sas_fwfault_debug, |
| @@ -1009,8 +1009,30 @@ _base_interrupt(int irq, void *bus_id) | |||
| 1009 | } | 1009 | } |
| 1010 | 1010 | ||
| 1011 | wmb(); | 1011 | wmb(); |
| 1012 | writel(reply_q->reply_post_host_index | (msix_index << | 1012 | |
| 1013 | MPI2_RPHI_MSIX_INDEX_SHIFT), &ioc->chip->ReplyPostHostIndex); | 1013 | /* Update Reply Post Host Index. |
| 1014 | * For those HBA's which support combined reply queue feature | ||
| 1015 | * 1. Get the correct Supplemental Reply Post Host Index Register. | ||
| 1016 | * i.e. (msix_index / 8)th entry from Supplemental Reply Post Host | ||
| 1017 | * Index Register address bank i.e replyPostRegisterIndex[], | ||
| 1018 | * 2. Then update this register with new reply host index value | ||
| 1019 | * in ReplyPostIndex field and the MSIxIndex field with | ||
| 1020 | * msix_index value reduced to a value between 0 and 7, | ||
| 1021 | * using a modulo 8 operation. Since each Supplemental Reply Post | ||
| 1022 | * Host Index Register supports 8 MSI-X vectors. | ||
| 1023 | * | ||
| 1024 | * For other HBA's just update the Reply Post Host Index register with | ||
| 1025 | * new reply host index value in ReplyPostIndex Field and msix_index | ||
| 1026 | * value in MSIxIndex field. | ||
| 1027 | */ | ||
| 1028 | if (ioc->msix96_vector) | ||
| 1029 | writel(reply_q->reply_post_host_index | ((msix_index & 7) << | ||
| 1030 | MPI2_RPHI_MSIX_INDEX_SHIFT), | ||
| 1031 | ioc->replyPostRegisterIndex[msix_index/8]); | ||
| 1032 | else | ||
| 1033 | writel(reply_q->reply_post_host_index | (msix_index << | ||
| 1034 | MPI2_RPHI_MSIX_INDEX_SHIFT), | ||
| 1035 | &ioc->chip->ReplyPostHostIndex); | ||
| 1014 | atomic_dec(&reply_q->busy); | 1036 | atomic_dec(&reply_q->busy); |
| 1015 | return IRQ_HANDLED; | 1037 | return IRQ_HANDLED; |
| 1016 | } | 1038 | } |
| @@ -1338,7 +1360,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc, | |||
| 1338 | 1360 | ||
| 1339 | sg_scmd = scsi_sglist(scmd); | 1361 | sg_scmd = scsi_sglist(scmd); |
| 1340 | sges_left = scsi_dma_map(scmd); | 1362 | sges_left = scsi_dma_map(scmd); |
| 1341 | if (!sges_left) { | 1363 | if (sges_left < 0) { |
| 1342 | sdev_printk(KERN_ERR, scmd->device, | 1364 | sdev_printk(KERN_ERR, scmd->device, |
| 1343 | "pci_map_sg failed: request for %d bytes!\n", | 1365 | "pci_map_sg failed: request for %d bytes!\n", |
| 1344 | scsi_bufflen(scmd)); | 1366 | scsi_bufflen(scmd)); |
| @@ -1407,7 +1429,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc, | |||
| 1407 | fill_in_last_segment: | 1429 | fill_in_last_segment: |
| 1408 | 1430 | ||
| 1409 | /* fill the last segment */ | 1431 | /* fill the last segment */ |
| 1410 | while (sges_left) { | 1432 | while (sges_left > 0) { |
| 1411 | if (sges_left == 1) | 1433 | if (sges_left == 1) |
| 1412 | _base_add_sg_single_ieee(sg_local, | 1434 | _base_add_sg_single_ieee(sg_local, |
| 1413 | simple_sgl_flags_last, 0, sg_dma_len(sg_scmd), | 1435 | simple_sgl_flags_last, 0, sg_dma_len(sg_scmd), |
| @@ -1560,8 +1582,6 @@ _base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc) | |||
| 1560 | 1582 | ||
| 1561 | pci_read_config_word(ioc->pdev, base + 2, &message_control); | 1583 | pci_read_config_word(ioc->pdev, base + 2, &message_control); |
| 1562 | ioc->msix_vector_count = (message_control & 0x3FF) + 1; | 1584 | ioc->msix_vector_count = (message_control & 0x3FF) + 1; |
| 1563 | if (ioc->msix_vector_count > 8) | ||
| 1564 | ioc->msix_vector_count = 8; | ||
| 1565 | dinitprintk(ioc, pr_info(MPT3SAS_FMT | 1585 | dinitprintk(ioc, pr_info(MPT3SAS_FMT |
| 1566 | "msix is supported, vector_count(%d)\n", | 1586 | "msix is supported, vector_count(%d)\n", |
| 1567 | ioc->name, ioc->msix_vector_count)); | 1587 | ioc->name, ioc->msix_vector_count)); |
| @@ -1793,6 +1813,36 @@ _base_enable_msix(struct MPT3SAS_ADAPTER *ioc) | |||
| 1793 | } | 1813 | } |
| 1794 | 1814 | ||
| 1795 | /** | 1815 | /** |
| 1816 | * mpt3sas_base_unmap_resources - free controller resources | ||
| 1817 | * @ioc: per adapter object | ||
| 1818 | */ | ||
| 1819 | void | ||
| 1820 | mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc) | ||
| 1821 | { | ||
| 1822 | struct pci_dev *pdev = ioc->pdev; | ||
| 1823 | |||
| 1824 | dexitprintk(ioc, printk(MPT3SAS_FMT "%s\n", | ||
| 1825 | ioc->name, __func__)); | ||
| 1826 | |||
| 1827 | _base_free_irq(ioc); | ||
| 1828 | _base_disable_msix(ioc); | ||
| 1829 | |||
| 1830 | if (ioc->msix96_vector) | ||
| 1831 | kfree(ioc->replyPostRegisterIndex); | ||
| 1832 | |||
| 1833 | if (ioc->chip_phys) { | ||
| 1834 | iounmap(ioc->chip); | ||
| 1835 | ioc->chip_phys = 0; | ||
| 1836 | } | ||
| 1837 | |||
| 1838 | if (pci_is_enabled(pdev)) { | ||
| 1839 | pci_release_selected_regions(ioc->pdev, ioc->bars); | ||
| 1840 | pci_disable_pcie_error_reporting(pdev); | ||
| 1841 | pci_disable_device(pdev); | ||
| 1842 | } | ||
| 1843 | } | ||
| 1844 | |||
| 1845 | /** | ||
| 1796 | * mpt3sas_base_map_resources - map in controller resources (io/irq/memap) | 1846 | * mpt3sas_base_map_resources - map in controller resources (io/irq/memap) |
| 1797 | * @ioc: per adapter object | 1847 | * @ioc: per adapter object |
| 1798 | * | 1848 | * |
| @@ -1882,6 +1932,36 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) | |||
| 1882 | if (r) | 1932 | if (r) |
| 1883 | goto out_fail; | 1933 | goto out_fail; |
| 1884 | 1934 | ||
| 1935 | /* Use the Combined reply queue feature only for SAS3 C0 & higher | ||
| 1936 | * revision HBAs and also only when reply queue count is greater than 8 | ||
| 1937 | */ | ||
| 1938 | if (ioc->msix96_vector && ioc->reply_queue_count > 8) { | ||
| 1939 | /* Determine the Supplemental Reply Post Host Index Registers | ||
| 1940 | * Addresse. Supplemental Reply Post Host Index Registers | ||
| 1941 | * starts at offset MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET and | ||
| 1942 | * each register is at offset bytes of | ||
| 1943 | * MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET from previous one. | ||
| 1944 | */ | ||
| 1945 | ioc->replyPostRegisterIndex = kcalloc( | ||
| 1946 | MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT, | ||
| 1947 | sizeof(resource_size_t *), GFP_KERNEL); | ||
| 1948 | if (!ioc->replyPostRegisterIndex) { | ||
| 1949 | dfailprintk(ioc, printk(MPT3SAS_FMT | ||
| 1950 | "allocation for reply Post Register Index failed!!!\n", | ||
| 1951 | ioc->name)); | ||
| 1952 | r = -ENOMEM; | ||
| 1953 | goto out_fail; | ||
| 1954 | } | ||
| 1955 | |||
| 1956 | for (i = 0; i < MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT; i++) { | ||
| 1957 | ioc->replyPostRegisterIndex[i] = (resource_size_t *) | ||
| 1958 | ((u8 *)&ioc->chip->Doorbell + | ||
| 1959 | MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET + | ||
| 1960 | (i * MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET)); | ||
| 1961 | } | ||
| 1962 | } else | ||
| 1963 | ioc->msix96_vector = 0; | ||
| 1964 | |||
| 1885 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) | 1965 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) |
| 1886 | pr_info(MPT3SAS_FMT "%s: IRQ %d\n", | 1966 | pr_info(MPT3SAS_FMT "%s: IRQ %d\n", |
| 1887 | reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" : | 1967 | reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" : |
| @@ -1897,12 +1977,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) | |||
| 1897 | return 0; | 1977 | return 0; |
| 1898 | 1978 | ||
| 1899 | out_fail: | 1979 | out_fail: |
| 1900 | if (ioc->chip_phys) | 1980 | mpt3sas_base_unmap_resources(ioc); |
| 1901 | iounmap(ioc->chip); | ||
| 1902 | ioc->chip_phys = 0; | ||
| 1903 | pci_release_selected_regions(ioc->pdev, ioc->bars); | ||
| 1904 | pci_disable_pcie_error_reporting(pdev); | ||
| 1905 | pci_disable_device(pdev); | ||
| 1906 | return r; | 1981 | return r; |
| 1907 | } | 1982 | } |
| 1908 | 1983 | ||
| @@ -2292,6 +2367,99 @@ _base_display_intel_branding(struct MPT3SAS_ADAPTER *ioc) | |||
| 2292 | 2367 | ||
| 2293 | 2368 | ||
| 2294 | /** | 2369 | /** |
| 2370 | * _base_display_dell_branding - Display branding string | ||
| 2371 | * @ioc: per adapter object | ||
| 2372 | * | ||
| 2373 | * Return nothing. | ||
| 2374 | */ | ||
| 2375 | static void | ||
| 2376 | _base_display_dell_branding(struct MPT3SAS_ADAPTER *ioc) | ||
| 2377 | { | ||
| 2378 | if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL) | ||
| 2379 | return; | ||
| 2380 | |||
| 2381 | switch (ioc->pdev->device) { | ||
| 2382 | case MPI25_MFGPAGE_DEVID_SAS3008: | ||
| 2383 | switch (ioc->pdev->subsystem_device) { | ||
| 2384 | case MPT3SAS_DELL_12G_HBA_SSDID: | ||
| 2385 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2386 | MPT3SAS_DELL_12G_HBA_BRANDING); | ||
| 2387 | break; | ||
| 2388 | default: | ||
| 2389 | pr_info(MPT3SAS_FMT | ||
| 2390 | "Dell 12Gbps HBA: Subsystem ID: 0x%X\n", ioc->name, | ||
| 2391 | ioc->pdev->subsystem_device); | ||
| 2392 | break; | ||
| 2393 | } | ||
| 2394 | break; | ||
| 2395 | default: | ||
| 2396 | pr_info(MPT3SAS_FMT | ||
| 2397 | "Dell 12Gbps HBA: Subsystem ID: 0x%X\n", ioc->name, | ||
| 2398 | ioc->pdev->subsystem_device); | ||
| 2399 | break; | ||
| 2400 | } | ||
| 2401 | } | ||
| 2402 | |||
| 2403 | /** | ||
| 2404 | * _base_display_cisco_branding - Display branding string | ||
| 2405 | * @ioc: per adapter object | ||
| 2406 | * | ||
| 2407 | * Return nothing. | ||
| 2408 | */ | ||
| 2409 | static void | ||
| 2410 | _base_display_cisco_branding(struct MPT3SAS_ADAPTER *ioc) | ||
| 2411 | { | ||
| 2412 | if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_CISCO) | ||
| 2413 | return; | ||
| 2414 | |||
| 2415 | switch (ioc->pdev->device) { | ||
| 2416 | case MPI25_MFGPAGE_DEVID_SAS3008: | ||
| 2417 | switch (ioc->pdev->subsystem_device) { | ||
| 2418 | case MPT3SAS_CISCO_12G_8E_HBA_SSDID: | ||
| 2419 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2420 | MPT3SAS_CISCO_12G_8E_HBA_BRANDING); | ||
| 2421 | break; | ||
| 2422 | case MPT3SAS_CISCO_12G_8I_HBA_SSDID: | ||
| 2423 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2424 | MPT3SAS_CISCO_12G_8I_HBA_BRANDING); | ||
| 2425 | break; | ||
| 2426 | case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID: | ||
| 2427 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2428 | MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING); | ||
| 2429 | break; | ||
| 2430 | default: | ||
| 2431 | pr_info(MPT3SAS_FMT | ||
| 2432 | "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n", | ||
| 2433 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2434 | break; | ||
| 2435 | } | ||
| 2436 | break; | ||
| 2437 | case MPI25_MFGPAGE_DEVID_SAS3108_1: | ||
| 2438 | switch (ioc->pdev->subsystem_device) { | ||
| 2439 | case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID: | ||
| 2440 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2441 | MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING); | ||
| 2442 | break; | ||
| 2443 | case MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_SSDID: | ||
| 2444 | pr_info(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 2445 | MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING); | ||
| 2446 | break; | ||
| 2447 | default: | ||
| 2448 | pr_info(MPT3SAS_FMT | ||
| 2449 | "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n", | ||
| 2450 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2451 | break; | ||
| 2452 | } | ||
| 2453 | break; | ||
| 2454 | default: | ||
| 2455 | pr_info(MPT3SAS_FMT | ||
| 2456 | "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n", | ||
| 2457 | ioc->name, ioc->pdev->subsystem_device); | ||
| 2458 | break; | ||
| 2459 | } | ||
| 2460 | } | ||
| 2461 | |||
| 2462 | /** | ||
| 2295 | * _base_display_ioc_capabilities - Disply IOC's capabilities. | 2463 | * _base_display_ioc_capabilities - Disply IOC's capabilities. |
| 2296 | * @ioc: per adapter object | 2464 | * @ioc: per adapter object |
| 2297 | * | 2465 | * |
| @@ -2321,6 +2489,8 @@ _base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc) | |||
| 2321 | bios_version & 0x000000FF); | 2489 | bios_version & 0x000000FF); |
| 2322 | 2490 | ||
| 2323 | _base_display_intel_branding(ioc); | 2491 | _base_display_intel_branding(ioc); |
| 2492 | _base_display_dell_branding(ioc); | ||
| 2493 | _base_display_cisco_branding(ioc); | ||
| 2324 | 2494 | ||
| 2325 | pr_info(MPT3SAS_FMT "Protocol=(", ioc->name); | 2495 | pr_info(MPT3SAS_FMT "Protocol=(", ioc->name); |
| 2326 | 2496 | ||
| @@ -3139,6 +3309,9 @@ _base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout, | |||
| 3139 | * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. | 3309 | * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. |
| 3140 | */ | 3310 | */ |
| 3141 | static int | 3311 | static int |
| 3312 | _base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag); | ||
| 3313 | |||
| 3314 | static int | ||
| 3142 | _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, | 3315 | _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, |
| 3143 | int sleep_flag) | 3316 | int sleep_flag) |
| 3144 | { | 3317 | { |
| @@ -3681,6 +3854,64 @@ _base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port, int sleep_flag) | |||
| 3681 | } | 3854 | } |
| 3682 | 3855 | ||
| 3683 | /** | 3856 | /** |
| 3857 | * _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL | ||
| 3858 | * @ioc: per adapter object | ||
| 3859 | * @timeout: | ||
| 3860 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | ||
| 3861 | * | ||
| 3862 | * Returns 0 for success, non-zero for failure. | ||
| 3863 | */ | ||
| 3864 | static int | ||
| 3865 | _base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout, | ||
| 3866 | int sleep_flag) | ||
| 3867 | { | ||
| 3868 | u32 ioc_state; | ||
| 3869 | int rc; | ||
| 3870 | |||
| 3871 | dinitprintk(ioc, printk(MPT3SAS_FMT "%s\n", ioc->name, | ||
| 3872 | __func__)); | ||
| 3873 | |||
| 3874 | if (ioc->pci_error_recovery) { | ||
| 3875 | dfailprintk(ioc, printk(MPT3SAS_FMT | ||
| 3876 | "%s: host in pci error recovery\n", ioc->name, __func__)); | ||
| 3877 | return -EFAULT; | ||
| 3878 | } | ||
| 3879 | |||
| 3880 | ioc_state = mpt3sas_base_get_iocstate(ioc, 0); | ||
| 3881 | dhsprintk(ioc, printk(MPT3SAS_FMT "%s: ioc_state(0x%08x)\n", | ||
| 3882 | ioc->name, __func__, ioc_state)); | ||
| 3883 | |||
| 3884 | if (((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY) || | ||
| 3885 | (ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL) | ||
| 3886 | return 0; | ||
| 3887 | |||
| 3888 | if (ioc_state & MPI2_DOORBELL_USED) { | ||
| 3889 | dhsprintk(ioc, printk(MPT3SAS_FMT | ||
| 3890 | "unexpected doorbell active!\n", ioc->name)); | ||
| 3891 | goto issue_diag_reset; | ||
| 3892 | } | ||
| 3893 | |||
| 3894 | if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { | ||
| 3895 | mpt3sas_base_fault_info(ioc, ioc_state & | ||
| 3896 | MPI2_DOORBELL_DATA_MASK); | ||
| 3897 | goto issue_diag_reset; | ||
| 3898 | } | ||
| 3899 | |||
| 3900 | ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, | ||
| 3901 | timeout, sleep_flag); | ||
| 3902 | if (ioc_state) { | ||
| 3903 | dfailprintk(ioc, printk(MPT3SAS_FMT | ||
| 3904 | "%s: failed going to ready state (ioc_state=0x%x)\n", | ||
| 3905 | ioc->name, __func__, ioc_state)); | ||
| 3906 | return -EFAULT; | ||
| 3907 | } | ||
| 3908 | |||
| 3909 | issue_diag_reset: | ||
| 3910 | rc = _base_diag_reset(ioc, sleep_flag); | ||
| 3911 | return rc; | ||
| 3912 | } | ||
| 3913 | |||
| 3914 | /** | ||
| 3684 | * _base_get_ioc_facts - obtain ioc facts reply and save in ioc | 3915 | * _base_get_ioc_facts - obtain ioc facts reply and save in ioc |
| 3685 | * @ioc: per adapter object | 3916 | * @ioc: per adapter object |
| 3686 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | 3917 | * @sleep_flag: CAN_SLEEP or NO_SLEEP |
| @@ -3698,6 +3929,13 @@ _base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
| 3698 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 3929 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 3699 | __func__)); | 3930 | __func__)); |
| 3700 | 3931 | ||
| 3932 | r = _base_wait_for_iocstate(ioc, 10, sleep_flag); | ||
| 3933 | if (r) { | ||
| 3934 | dfailprintk(ioc, printk(MPT3SAS_FMT | ||
| 3935 | "%s: failed getting to correct state\n", | ||
| 3936 | ioc->name, __func__)); | ||
| 3937 | return r; | ||
| 3938 | } | ||
| 3701 | mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t); | 3939 | mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t); |
| 3702 | mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t); | 3940 | mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t); |
| 3703 | memset(&mpi_request, 0, mpi_request_sz); | 3941 | memset(&mpi_request, 0, mpi_request_sz); |
| @@ -3783,7 +4021,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
| 3783 | mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; | 4021 | mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; |
| 3784 | mpi_request.VF_ID = 0; /* TODO */ | 4022 | mpi_request.VF_ID = 0; /* TODO */ |
| 3785 | mpi_request.VP_ID = 0; | 4023 | mpi_request.VP_ID = 0; |
| 3786 | mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); | 4024 | mpi_request.MsgVersion = cpu_to_le16(MPI25_VERSION); |
| 3787 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); | 4025 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); |
| 3788 | 4026 | ||
| 3789 | if (_base_is_controller_msix_enabled(ioc)) | 4027 | if (_base_is_controller_msix_enabled(ioc)) |
| @@ -4524,8 +4762,15 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
| 4524 | 4762 | ||
| 4525 | /* initialize reply post host index */ | 4763 | /* initialize reply post host index */ |
| 4526 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { | 4764 | list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { |
| 4527 | writel(reply_q->msix_index << MPI2_RPHI_MSIX_INDEX_SHIFT, | 4765 | if (ioc->msix96_vector) |
| 4528 | &ioc->chip->ReplyPostHostIndex); | 4766 | writel((reply_q->msix_index & 7)<< |
| 4767 | MPI2_RPHI_MSIX_INDEX_SHIFT, | ||
| 4768 | ioc->replyPostRegisterIndex[reply_q->msix_index/8]); | ||
| 4769 | else | ||
| 4770 | writel(reply_q->msix_index << | ||
| 4771 | MPI2_RPHI_MSIX_INDEX_SHIFT, | ||
| 4772 | &ioc->chip->ReplyPostHostIndex); | ||
| 4773 | |||
| 4529 | if (!_base_is_controller_msix_enabled(ioc)) | 4774 | if (!_base_is_controller_msix_enabled(ioc)) |
| 4530 | goto skip_init_reply_post_host_index; | 4775 | goto skip_init_reply_post_host_index; |
| 4531 | } | 4776 | } |
| @@ -4564,8 +4809,6 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) | |||
| 4564 | void | 4809 | void |
| 4565 | mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) | 4810 | mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) |
| 4566 | { | 4811 | { |
| 4567 | struct pci_dev *pdev = ioc->pdev; | ||
| 4568 | |||
| 4569 | dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 4812 | dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 4570 | __func__)); | 4813 | __func__)); |
| 4571 | 4814 | ||
| @@ -4576,18 +4819,7 @@ mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) | |||
| 4576 | ioc->shost_recovery = 0; | 4819 | ioc->shost_recovery = 0; |
| 4577 | } | 4820 | } |
| 4578 | 4821 | ||
| 4579 | _base_free_irq(ioc); | 4822 | mpt3sas_base_unmap_resources(ioc); |
| 4580 | _base_disable_msix(ioc); | ||
| 4581 | |||
| 4582 | if (ioc->chip_phys && ioc->chip) | ||
| 4583 | iounmap(ioc->chip); | ||
| 4584 | ioc->chip_phys = 0; | ||
| 4585 | |||
| 4586 | if (pci_is_enabled(pdev)) { | ||
| 4587 | pci_release_selected_regions(ioc->pdev, ioc->bars); | ||
| 4588 | pci_disable_pcie_error_reporting(pdev); | ||
| 4589 | pci_disable_device(pdev); | ||
| 4590 | } | ||
| 4591 | return; | 4823 | return; |
| 4592 | } | 4824 | } |
| 4593 | 4825 | ||
| @@ -4602,6 +4834,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) | |||
| 4602 | { | 4834 | { |
| 4603 | int r, i; | 4835 | int r, i; |
| 4604 | int cpu_id, last_cpu_id = 0; | 4836 | int cpu_id, last_cpu_id = 0; |
| 4837 | u8 revision; | ||
| 4605 | 4838 | ||
| 4606 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, | 4839 | dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, |
| 4607 | __func__)); | 4840 | __func__)); |
| @@ -4621,6 +4854,20 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) | |||
| 4621 | goto out_free_resources; | 4854 | goto out_free_resources; |
| 4622 | } | 4855 | } |
| 4623 | 4856 | ||
| 4857 | /* Check whether the controller revision is C0 or above. | ||
| 4858 | * only C0 and above revision controllers support 96 MSI-X vectors. | ||
| 4859 | */ | ||
| 4860 | revision = ioc->pdev->revision; | ||
| 4861 | |||
| 4862 | if ((ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3004 || | ||
| 4863 | ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3008 || | ||
| 4864 | ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_1 || | ||
| 4865 | ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_2 || | ||
| 4866 | ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_5 || | ||
| 4867 | ioc->pdev->device == MPI25_MFGPAGE_DEVID_SAS3108_6) && | ||
| 4868 | (revision >= 0x02)) | ||
| 4869 | ioc->msix96_vector = 1; | ||
| 4870 | |||
| 4624 | ioc->rdpq_array_enable_assigned = 0; | 4871 | ioc->rdpq_array_enable_assigned = 0; |
| 4625 | ioc->dma_mask = 0; | 4872 | ioc->dma_mask = 0; |
| 4626 | r = mpt3sas_base_map_resources(ioc); | 4873 | r = mpt3sas_base_map_resources(ioc); |
| @@ -4643,7 +4890,6 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) | |||
| 4643 | ioc->build_sg_scmd = &_base_build_sg_scmd_ieee; | 4890 | ioc->build_sg_scmd = &_base_build_sg_scmd_ieee; |
| 4644 | ioc->build_sg = &_base_build_sg_ieee; | 4891 | ioc->build_sg = &_base_build_sg_ieee; |
| 4645 | ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee; | 4892 | ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee; |
| 4646 | ioc->mpi25 = 1; | ||
| 4647 | ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t); | 4893 | ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t); |
| 4648 | 4894 | ||
| 4649 | /* | 4895 | /* |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h index afa881682bef..f0e462b0880d 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.h +++ b/drivers/scsi/mpt3sas/mpt3sas_base.h | |||
| @@ -71,8 +71,8 @@ | |||
| 71 | #define MPT3SAS_DRIVER_NAME "mpt3sas" | 71 | #define MPT3SAS_DRIVER_NAME "mpt3sas" |
| 72 | #define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>" | 72 | #define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>" |
| 73 | #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" | 73 | #define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" |
| 74 | #define MPT3SAS_DRIVER_VERSION "04.100.00.00" | 74 | #define MPT3SAS_DRIVER_VERSION "09.100.00.00" |
| 75 | #define MPT3SAS_MAJOR_VERSION 4 | 75 | #define MPT3SAS_MAJOR_VERSION 9 |
| 76 | #define MPT3SAS_MINOR_VERSION 100 | 76 | #define MPT3SAS_MINOR_VERSION 100 |
| 77 | #define MPT3SAS_BUILD_VERSION 0 | 77 | #define MPT3SAS_BUILD_VERSION 0 |
| 78 | #define MPT3SAS_RELEASE_VERSION 00 | 78 | #define MPT3SAS_RELEASE_VERSION 00 |
| @@ -152,12 +152,49 @@ | |||
| 152 | #define MPT3SAS_INTEL_RS3UC080_SSDID 0x3524 | 152 | #define MPT3SAS_INTEL_RS3UC080_SSDID 0x3524 |
| 153 | 153 | ||
| 154 | /* | 154 | /* |
| 155 | * Dell HBA branding | ||
| 156 | */ | ||
| 157 | #define MPT3SAS_DELL_12G_HBA_BRANDING \ | ||
| 158 | "Dell 12Gbps HBA" | ||
| 159 | |||
| 160 | /* | ||
| 161 | * Dell HBA SSDIDs | ||
| 162 | */ | ||
| 163 | #define MPT3SAS_DELL_12G_HBA_SSDID 0x1F46 | ||
| 164 | |||
| 165 | /* | ||
| 166 | * Cisco HBA branding | ||
| 167 | */ | ||
| 168 | #define MPT3SAS_CISCO_12G_8E_HBA_BRANDING \ | ||
| 169 | "Cisco 9300-8E 12G SAS HBA" | ||
| 170 | #define MPT3SAS_CISCO_12G_8I_HBA_BRANDING \ | ||
| 171 | "Cisco 9300-8i 12G SAS HBA" | ||
| 172 | #define MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING \ | ||
| 173 | "Cisco 12G Modular SAS Pass through Controller" | ||
| 174 | #define MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING \ | ||
| 175 | "UCS C3X60 12G SAS Pass through Controller" | ||
| 176 | /* | ||
| 177 | * Cisco HBA SSSDIDs | ||
| 178 | */ | ||
| 179 | #define MPT3SAS_CISCO_12G_8E_HBA_SSDID 0x14C | ||
| 180 | #define MPT3SAS_CISCO_12G_8I_HBA_SSDID 0x154 | ||
| 181 | #define MPT3SAS_CISCO_12G_AVILA_HBA_SSDID 0x155 | ||
| 182 | #define MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_SSDID 0x156 | ||
| 183 | |||
| 184 | /* | ||
| 155 | * status bits for ioc->diag_buffer_status | 185 | * status bits for ioc->diag_buffer_status |
| 156 | */ | 186 | */ |
| 157 | #define MPT3_DIAG_BUFFER_IS_REGISTERED (0x01) | 187 | #define MPT3_DIAG_BUFFER_IS_REGISTERED (0x01) |
| 158 | #define MPT3_DIAG_BUFFER_IS_RELEASED (0x02) | 188 | #define MPT3_DIAG_BUFFER_IS_RELEASED (0x02) |
| 159 | #define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04) | 189 | #define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04) |
| 160 | 190 | ||
| 191 | /* | ||
| 192 | * Combined Reply Queue constants, | ||
| 193 | * There are twelve Supplemental Reply Post Host Index Registers | ||
| 194 | * and each register is at offset 0x10 bytes from the previous one. | ||
| 195 | */ | ||
| 196 | #define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT 12 | ||
| 197 | #define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET (0x10) | ||
| 161 | 198 | ||
| 162 | /* OEM Identifiers */ | 199 | /* OEM Identifiers */ |
| 163 | #define MFG10_OEM_ID_INVALID (0x00000000) | 200 | #define MFG10_OEM_ID_INVALID (0x00000000) |
| @@ -173,6 +210,8 @@ | |||
| 173 | #define MFG10_GF0_SSD_DATA_SCRUB_DISABLE (0x00000008) | 210 | #define MFG10_GF0_SSD_DATA_SCRUB_DISABLE (0x00000008) |
| 174 | #define MFG10_GF0_SINGLE_DRIVE_R0 (0x00000010) | 211 | #define MFG10_GF0_SINGLE_DRIVE_R0 (0x00000010) |
| 175 | 212 | ||
| 213 | #define VIRTUAL_IO_FAILED_RETRY (0x32010081) | ||
| 214 | |||
| 176 | /* OEM Specific Flags will come from OEM specific header files */ | 215 | /* OEM Specific Flags will come from OEM specific header files */ |
| 177 | struct Mpi2ManufacturingPage10_t { | 216 | struct Mpi2ManufacturingPage10_t { |
| 178 | MPI2_CONFIG_PAGE_HEADER Header; /* 00h */ | 217 | MPI2_CONFIG_PAGE_HEADER Header; /* 00h */ |
| @@ -294,7 +333,8 @@ struct _internal_cmd { | |||
| 294 | * @responding: used in _scsih_sas_device_mark_responding | 333 | * @responding: used in _scsih_sas_device_mark_responding |
| 295 | * @fast_path: fast path feature enable bit | 334 | * @fast_path: fast path feature enable bit |
| 296 | * @pfa_led_on: flag for PFA LED status | 335 | * @pfa_led_on: flag for PFA LED status |
| 297 | * | 336 | * @pend_sas_rphy_add: flag to check if device is in sas_rphy_add() |
| 337 | * addition routine. | ||
| 298 | */ | 338 | */ |
| 299 | struct _sas_device { | 339 | struct _sas_device { |
| 300 | struct list_head list; | 340 | struct list_head list; |
| @@ -315,6 +355,9 @@ struct _sas_device { | |||
| 315 | u8 responding; | 355 | u8 responding; |
| 316 | u8 fast_path; | 356 | u8 fast_path; |
| 317 | u8 pfa_led_on; | 357 | u8 pfa_led_on; |
| 358 | u8 pend_sas_rphy_add; | ||
| 359 | u8 enclosure_level; | ||
| 360 | u8 connector_name[4]; | ||
| 318 | }; | 361 | }; |
| 319 | 362 | ||
| 320 | /** | 363 | /** |
| @@ -728,7 +771,8 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); | |||
| 728 | * is assigned only ones | 771 | * is assigned only ones |
| 729 | * @reply_queue_count: number of reply queue's | 772 | * @reply_queue_count: number of reply queue's |
| 730 | * @reply_queue_list: link list contaning the reply queue info | 773 | * @reply_queue_list: link list contaning the reply queue info |
| 731 | * @reply_post_host_index: head index in the pool where FW completes IO | 774 | * @msix96_vector: 96 MSI-X vector support |
| 775 | * @replyPostRegisterIndex: index of next position in Reply Desc Post Queue | ||
| 732 | * @delayed_tr_list: target reset link list | 776 | * @delayed_tr_list: target reset link list |
| 733 | * @delayed_tr_volume_list: volume target reset link list | 777 | * @delayed_tr_volume_list: volume target reset link list |
| 734 | * @@temp_sensors_count: flag to carry the number of temperature sensors | 778 | * @@temp_sensors_count: flag to carry the number of temperature sensors |
| @@ -814,7 +858,6 @@ struct MPT3SAS_ADAPTER { | |||
| 814 | MPT_BUILD_SG_SCMD build_sg_scmd; | 858 | MPT_BUILD_SG_SCMD build_sg_scmd; |
| 815 | MPT_BUILD_SG build_sg; | 859 | MPT_BUILD_SG build_sg; |
| 816 | MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge; | 860 | MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge; |
| 817 | u8 mpi25; | ||
| 818 | u16 sge_size_ieee; | 861 | u16 sge_size_ieee; |
| 819 | 862 | ||
| 820 | /* function ptr for MPI sg elements only */ | 863 | /* function ptr for MPI sg elements only */ |
| @@ -937,6 +980,10 @@ struct MPT3SAS_ADAPTER { | |||
| 937 | u8 reply_queue_count; | 980 | u8 reply_queue_count; |
| 938 | struct list_head reply_queue_list; | 981 | struct list_head reply_queue_list; |
| 939 | 982 | ||
| 983 | u8 msix96_vector; | ||
| 984 | /* reply post register index */ | ||
| 985 | resource_size_t **replyPostRegisterIndex; | ||
| 986 | |||
| 940 | struct list_head delayed_tr_list; | 987 | struct list_head delayed_tr_list; |
| 941 | struct list_head delayed_tr_volume_list; | 988 | struct list_head delayed_tr_volume_list; |
| 942 | u8 temp_sensors_count; | 989 | u8 temp_sensors_count; |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 5a97e3286719..8ccef38523fa 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c | |||
| @@ -585,6 +585,22 @@ _scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc, | |||
| 585 | 585 | ||
| 586 | if (!sas_device) | 586 | if (!sas_device) |
| 587 | return; | 587 | return; |
| 588 | pr_info(MPT3SAS_FMT | ||
| 589 | "removing handle(0x%04x), sas_addr(0x%016llx)\n", | ||
| 590 | ioc->name, sas_device->handle, | ||
| 591 | (unsigned long long) sas_device->sas_address); | ||
| 592 | |||
| 593 | if (sas_device->enclosure_handle != 0) | ||
| 594 | pr_info(MPT3SAS_FMT | ||
| 595 | "removing enclosure logical id(0x%016llx), slot(%d)\n", | ||
| 596 | ioc->name, (unsigned long long) | ||
| 597 | sas_device->enclosure_logical_id, sas_device->slot); | ||
| 598 | |||
| 599 | if (sas_device->connector_name[0] != '\0') | ||
| 600 | pr_info(MPT3SAS_FMT | ||
| 601 | "removing enclosure level(0x%04x), connector name( %s)\n", | ||
| 602 | ioc->name, sas_device->enclosure_level, | ||
| 603 | sas_device->connector_name); | ||
| 588 | 604 | ||
| 589 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 605 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 590 | list_del(&sas_device->list); | 606 | list_del(&sas_device->list); |
| @@ -663,6 +679,18 @@ _scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, | |||
| 663 | ioc->name, __func__, sas_device->handle, | 679 | ioc->name, __func__, sas_device->handle, |
| 664 | (unsigned long long)sas_device->sas_address)); | 680 | (unsigned long long)sas_device->sas_address)); |
| 665 | 681 | ||
| 682 | if (sas_device->enclosure_handle != 0) | ||
| 683 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 684 | "%s: enclosure logical id(0x%016llx), slot( %d)\n", | ||
| 685 | ioc->name, __func__, (unsigned long long) | ||
| 686 | sas_device->enclosure_logical_id, sas_device->slot)); | ||
| 687 | |||
| 688 | if (sas_device->connector_name[0] != '\0') | ||
| 689 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 690 | "%s: enclosure level(0x%04x), connector name( %s)\n", | ||
| 691 | ioc->name, __func__, | ||
| 692 | sas_device->enclosure_level, sas_device->connector_name)); | ||
| 693 | |||
| 666 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 694 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 667 | list_add_tail(&sas_device->list, &ioc->sas_device_list); | 695 | list_add_tail(&sas_device->list, &ioc->sas_device_list); |
| 668 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 696 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| @@ -704,6 +732,18 @@ _scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc, | |||
| 704 | __func__, sas_device->handle, | 732 | __func__, sas_device->handle, |
| 705 | (unsigned long long)sas_device->sas_address)); | 733 | (unsigned long long)sas_device->sas_address)); |
| 706 | 734 | ||
| 735 | if (sas_device->enclosure_handle != 0) | ||
| 736 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 737 | "%s: enclosure logical id(0x%016llx), slot( %d)\n", | ||
| 738 | ioc->name, __func__, (unsigned long long) | ||
| 739 | sas_device->enclosure_logical_id, sas_device->slot)); | ||
| 740 | |||
| 741 | if (sas_device->connector_name[0] != '\0') | ||
| 742 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 743 | "%s: enclosure level(0x%04x), connector name( %s)\n", | ||
| 744 | ioc->name, __func__, sas_device->enclosure_level, | ||
| 745 | sas_device->connector_name)); | ||
| 746 | |||
| 707 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 747 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 708 | list_add_tail(&sas_device->list, &ioc->sas_device_init_list); | 748 | list_add_tail(&sas_device->list, &ioc->sas_device_init_list); |
| 709 | _scsih_determine_boot_device(ioc, sas_device, 0); | 749 | _scsih_determine_boot_device(ioc, sas_device, 0); |
| @@ -1772,10 +1812,16 @@ _scsih_slave_configure(struct scsi_device *sdev) | |||
| 1772 | "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n", | 1812 | "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n", |
| 1773 | ds, handle, (unsigned long long)sas_device->sas_address, | 1813 | ds, handle, (unsigned long long)sas_device->sas_address, |
| 1774 | sas_device->phy, (unsigned long long)sas_device->device_name); | 1814 | sas_device->phy, (unsigned long long)sas_device->device_name); |
| 1775 | sdev_printk(KERN_INFO, sdev, | 1815 | if (sas_device->enclosure_handle != 0) |
| 1776 | "%s: enclosure_logical_id(0x%016llx), slot(%d)\n", | 1816 | sdev_printk(KERN_INFO, sdev, |
| 1777 | ds, (unsigned long long) | 1817 | "%s: enclosure_logical_id(0x%016llx), slot(%d)\n", |
| 1778 | sas_device->enclosure_logical_id, sas_device->slot); | 1818 | ds, (unsigned long long) |
| 1819 | sas_device->enclosure_logical_id, sas_device->slot); | ||
| 1820 | if (sas_device->connector_name[0] != '\0') | ||
| 1821 | sdev_printk(KERN_INFO, sdev, | ||
| 1822 | "%s: enclosure level(0x%04x), connector name( %s)\n", | ||
| 1823 | ds, sas_device->enclosure_level, | ||
| 1824 | sas_device->connector_name); | ||
| 1779 | 1825 | ||
| 1780 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 1826 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 1781 | 1827 | ||
| @@ -2189,10 +2235,17 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) | |||
| 2189 | sas_device->handle, | 2235 | sas_device->handle, |
| 2190 | (unsigned long long)sas_device->sas_address, | 2236 | (unsigned long long)sas_device->sas_address, |
| 2191 | sas_device->phy); | 2237 | sas_device->phy); |
| 2192 | starget_printk(KERN_INFO, starget, | 2238 | if (sas_device->enclosure_handle != 0) |
| 2193 | "enclosure_logical_id(0x%016llx), slot(%d)\n", | 2239 | starget_printk(KERN_INFO, starget, |
| 2194 | (unsigned long long)sas_device->enclosure_logical_id, | 2240 | "enclosure_logical_id(0x%016llx), slot(%d)\n", |
| 2195 | sas_device->slot); | 2241 | (unsigned long long) |
| 2242 | sas_device->enclosure_logical_id, | ||
| 2243 | sas_device->slot); | ||
| 2244 | if (sas_device->connector_name) | ||
| 2245 | starget_printk(KERN_INFO, starget, | ||
| 2246 | "enclosure level(0x%04x),connector name(%s)\n", | ||
| 2247 | sas_device->enclosure_level, | ||
| 2248 | sas_device->connector_name); | ||
| 2196 | } | 2249 | } |
| 2197 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 2250 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 2198 | } | 2251 | } |
| @@ -2552,6 +2605,75 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) | |||
| 2552 | } | 2605 | } |
| 2553 | 2606 | ||
| 2554 | /** | 2607 | /** |
| 2608 | * _scsih_internal_device_block - block the sdev device | ||
| 2609 | * @sdev: per device object | ||
| 2610 | * @sas_device_priv_data : per device driver private data | ||
| 2611 | * | ||
| 2612 | * make sure device is blocked without error, if not | ||
| 2613 | * print an error | ||
| 2614 | */ | ||
| 2615 | static void | ||
| 2616 | _scsih_internal_device_block(struct scsi_device *sdev, | ||
| 2617 | struct MPT3SAS_DEVICE *sas_device_priv_data) | ||
| 2618 | { | ||
| 2619 | int r = 0; | ||
| 2620 | |||
| 2621 | sdev_printk(KERN_INFO, sdev, "device_block, handle(0x%04x)\n", | ||
| 2622 | sas_device_priv_data->sas_target->handle); | ||
| 2623 | sas_device_priv_data->block = 1; | ||
| 2624 | |||
| 2625 | r = scsi_internal_device_block(sdev); | ||
| 2626 | if (r == -EINVAL) | ||
| 2627 | sdev_printk(KERN_WARNING, sdev, | ||
| 2628 | "device_block failed with return(%d) for handle(0x%04x)\n", | ||
| 2629 | sas_device_priv_data->sas_target->handle, r); | ||
| 2630 | } | ||
| 2631 | |||
| 2632 | /** | ||
| 2633 | * _scsih_internal_device_unblock - unblock the sdev device | ||
| 2634 | * @sdev: per device object | ||
| 2635 | * @sas_device_priv_data : per device driver private data | ||
| 2636 | * make sure device is unblocked without error, if not retry | ||
| 2637 | * by blocking and then unblocking | ||
| 2638 | */ | ||
| 2639 | |||
| 2640 | static void | ||
| 2641 | _scsih_internal_device_unblock(struct scsi_device *sdev, | ||
| 2642 | struct MPT3SAS_DEVICE *sas_device_priv_data) | ||
| 2643 | { | ||
| 2644 | int r = 0; | ||
| 2645 | |||
| 2646 | sdev_printk(KERN_WARNING, sdev, "device_unblock and setting to running, " | ||
| 2647 | "handle(0x%04x)\n", sas_device_priv_data->sas_target->handle); | ||
| 2648 | sas_device_priv_data->block = 0; | ||
| 2649 | r = scsi_internal_device_unblock(sdev, SDEV_RUNNING); | ||
| 2650 | if (r == -EINVAL) { | ||
| 2651 | /* The device has been set to SDEV_RUNNING by SD layer during | ||
| 2652 | * device addition but the request queue is still stopped by | ||
| 2653 | * our earlier block call. We need to perform a block again | ||
| 2654 | * to get the device to SDEV_BLOCK and then to SDEV_RUNNING */ | ||
| 2655 | |||
| 2656 | sdev_printk(KERN_WARNING, sdev, | ||
| 2657 | "device_unblock failed with return(%d) for handle(0x%04x) " | ||
| 2658 | "performing a block followed by an unblock\n", | ||
| 2659 | sas_device_priv_data->sas_target->handle, r); | ||
| 2660 | sas_device_priv_data->block = 1; | ||
| 2661 | r = scsi_internal_device_block(sdev); | ||
| 2662 | if (r) | ||
| 2663 | sdev_printk(KERN_WARNING, sdev, "retried device_block " | ||
| 2664 | "failed with return(%d) for handle(0x%04x)\n", | ||
| 2665 | sas_device_priv_data->sas_target->handle, r); | ||
| 2666 | |||
| 2667 | sas_device_priv_data->block = 0; | ||
| 2668 | r = scsi_internal_device_unblock(sdev, SDEV_RUNNING); | ||
| 2669 | if (r) | ||
| 2670 | sdev_printk(KERN_WARNING, sdev, "retried device_unblock" | ||
| 2671 | " failed with return(%d) for handle(0x%04x)\n", | ||
| 2672 | sas_device_priv_data->sas_target->handle, r); | ||
| 2673 | } | ||
| 2674 | } | ||
| 2675 | |||
| 2676 | /** | ||
| 2555 | * _scsih_ublock_io_all_device - unblock every device | 2677 | * _scsih_ublock_io_all_device - unblock every device |
| 2556 | * @ioc: per adapter object | 2678 | * @ioc: per adapter object |
| 2557 | * | 2679 | * |
| @@ -2570,11 +2692,10 @@ _scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc) | |||
| 2570 | if (!sas_device_priv_data->block) | 2692 | if (!sas_device_priv_data->block) |
| 2571 | continue; | 2693 | continue; |
| 2572 | 2694 | ||
| 2573 | sas_device_priv_data->block = 0; | ||
| 2574 | dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, | 2695 | dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, |
| 2575 | "device_running, handle(0x%04x)\n", | 2696 | "device_running, handle(0x%04x)\n", |
| 2576 | sas_device_priv_data->sas_target->handle)); | 2697 | sas_device_priv_data->sas_target->handle)); |
| 2577 | scsi_internal_device_unblock(sdev, SDEV_RUNNING); | 2698 | _scsih_internal_device_unblock(sdev, sas_device_priv_data); |
| 2578 | } | 2699 | } |
| 2579 | } | 2700 | } |
| 2580 | 2701 | ||
| @@ -2599,10 +2720,9 @@ _scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) | |||
| 2599 | if (sas_device_priv_data->sas_target->sas_address | 2720 | if (sas_device_priv_data->sas_target->sas_address |
| 2600 | != sas_address) | 2721 | != sas_address) |
| 2601 | continue; | 2722 | continue; |
| 2602 | if (sas_device_priv_data->block) { | 2723 | if (sas_device_priv_data->block) |
| 2603 | sas_device_priv_data->block = 0; | 2724 | _scsih_internal_device_unblock(sdev, |
| 2604 | scsi_internal_device_unblock(sdev, SDEV_RUNNING); | 2725 | sas_device_priv_data); |
| 2605 | } | ||
| 2606 | } | 2726 | } |
| 2607 | } | 2727 | } |
| 2608 | 2728 | ||
| @@ -2625,10 +2745,7 @@ _scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc) | |||
| 2625 | continue; | 2745 | continue; |
| 2626 | if (sas_device_priv_data->block) | 2746 | if (sas_device_priv_data->block) |
| 2627 | continue; | 2747 | continue; |
| 2628 | sas_device_priv_data->block = 1; | 2748 | _scsih_internal_device_block(sdev, sas_device_priv_data); |
| 2629 | scsi_internal_device_block(sdev); | ||
| 2630 | sdev_printk(KERN_INFO, sdev, "device_blocked, handle(0x%04x)\n", | ||
| 2631 | sas_device_priv_data->sas_target->handle); | ||
| 2632 | } | 2749 | } |
| 2633 | } | 2750 | } |
| 2634 | 2751 | ||
| @@ -2644,6 +2761,11 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 2644 | { | 2761 | { |
| 2645 | struct MPT3SAS_DEVICE *sas_device_priv_data; | 2762 | struct MPT3SAS_DEVICE *sas_device_priv_data; |
| 2646 | struct scsi_device *sdev; | 2763 | struct scsi_device *sdev; |
| 2764 | struct _sas_device *sas_device; | ||
| 2765 | |||
| 2766 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
| 2767 | if (!sas_device) | ||
| 2768 | return; | ||
| 2647 | 2769 | ||
| 2648 | shost_for_each_device(sdev, ioc->shost) { | 2770 | shost_for_each_device(sdev, ioc->shost) { |
| 2649 | sas_device_priv_data = sdev->hostdata; | 2771 | sas_device_priv_data = sdev->hostdata; |
| @@ -2653,10 +2775,9 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 2653 | continue; | 2775 | continue; |
| 2654 | if (sas_device_priv_data->block) | 2776 | if (sas_device_priv_data->block) |
| 2655 | continue; | 2777 | continue; |
| 2656 | sas_device_priv_data->block = 1; | 2778 | if (sas_device->pend_sas_rphy_add) |
| 2657 | scsi_internal_device_block(sdev); | 2779 | continue; |
| 2658 | sdev_printk(KERN_INFO, sdev, | 2780 | _scsih_internal_device_block(sdev, sas_device_priv_data); |
| 2659 | "device_blocked, handle(0x%04x)\n", handle); | ||
| 2660 | } | 2781 | } |
| 2661 | } | 2782 | } |
| 2662 | 2783 | ||
| @@ -2806,6 +2927,18 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 2806 | "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n", | 2927 | "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n", |
| 2807 | ioc->name, handle, | 2928 | ioc->name, handle, |
| 2808 | (unsigned long long)sas_address)); | 2929 | (unsigned long long)sas_address)); |
| 2930 | if (sas_device->enclosure_handle != 0) | ||
| 2931 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 2932 | "setting delete flag:enclosure logical id(0x%016llx)," | ||
| 2933 | " slot(%d)\n", ioc->name, (unsigned long long) | ||
| 2934 | sas_device->enclosure_logical_id, | ||
| 2935 | sas_device->slot)); | ||
| 2936 | if (sas_device->connector_name) | ||
| 2937 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 2938 | "setting delete flag: enclosure level(0x%04x)," | ||
| 2939 | " connector name( %s)\n", ioc->name, | ||
| 2940 | sas_device->enclosure_level, | ||
| 2941 | sas_device->connector_name)); | ||
| 2809 | _scsih_ublock_io_device(ioc, sas_address); | 2942 | _scsih_ublock_io_device(ioc, sas_address); |
| 2810 | sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE; | 2943 | sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE; |
| 2811 | } | 2944 | } |
| @@ -3821,10 +3954,19 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
| 3821 | "\tsas_address(0x%016llx), phy(%d)\n", | 3954 | "\tsas_address(0x%016llx), phy(%d)\n", |
| 3822 | ioc->name, (unsigned long long) | 3955 | ioc->name, (unsigned long long) |
| 3823 | sas_device->sas_address, sas_device->phy); | 3956 | sas_device->sas_address, sas_device->phy); |
| 3824 | pr_warn(MPT3SAS_FMT | 3957 | if (sas_device->enclosure_handle != 0) |
| 3825 | "\tenclosure_logical_id(0x%016llx), slot(%d)\n", | 3958 | pr_warn(MPT3SAS_FMT |
| 3826 | ioc->name, (unsigned long long) | 3959 | "\tenclosure_logical_id(0x%016llx)," |
| 3827 | sas_device->enclosure_logical_id, sas_device->slot); | 3960 | "slot(%d)\n", ioc->name, |
| 3961 | (unsigned long long) | ||
| 3962 | sas_device->enclosure_logical_id, | ||
| 3963 | sas_device->slot); | ||
| 3964 | if (sas_device->connector_name[0]) | ||
| 3965 | pr_warn(MPT3SAS_FMT | ||
| 3966 | "\tenclosure level(0x%04x)," | ||
| 3967 | " connector name( %s)\n", ioc->name, | ||
| 3968 | sas_device->enclosure_level, | ||
| 3969 | sas_device->connector_name); | ||
| 3828 | } | 3970 | } |
| 3829 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 3971 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 3830 | } | 3972 | } |
| @@ -3999,7 +4141,16 @@ _scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle) | |||
| 3999 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4141 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 4000 | return; | 4142 | return; |
| 4001 | } | 4143 | } |
| 4002 | starget_printk(KERN_WARNING, starget, "predicted fault\n"); | 4144 | if (sas_device->enclosure_handle != 0) |
| 4145 | starget_printk(KERN_INFO, starget, "predicted fault, " | ||
| 4146 | "enclosure logical id(0x%016llx), slot(%d)\n", | ||
| 4147 | (unsigned long long)sas_device->enclosure_logical_id, | ||
| 4148 | sas_device->slot); | ||
| 4149 | if (sas_device->connector_name[0] != '\0') | ||
| 4150 | starget_printk(KERN_WARNING, starget, "predicted fault, " | ||
| 4151 | "enclosure level(0x%04x), connector name( %s)\n", | ||
| 4152 | sas_device->enclosure_level, | ||
| 4153 | sas_device->connector_name); | ||
| 4003 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | 4154 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); |
| 4004 | 4155 | ||
| 4005 | if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) | 4156 | if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) |
| @@ -4119,8 +4270,15 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 4119 | _scsih_smart_predicted_fault(ioc, | 4270 | _scsih_smart_predicted_fault(ioc, |
| 4120 | le16_to_cpu(mpi_reply->DevHandle)); | 4271 | le16_to_cpu(mpi_reply->DevHandle)); |
| 4121 | mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq); | 4272 | mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq); |
| 4122 | } | ||
| 4123 | 4273 | ||
| 4274 | #ifdef CONFIG_SCSI_MPT3SAS_LOGGING | ||
| 4275 | if (!(ioc->logging_level & MPT_DEBUG_REPLY) && | ||
| 4276 | ((scmd->sense_buffer[2] == UNIT_ATTENTION) || | ||
| 4277 | (scmd->sense_buffer[2] == MEDIUM_ERROR) || | ||
| 4278 | (scmd->sense_buffer[2] == HARDWARE_ERROR))) | ||
| 4279 | _scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid); | ||
| 4280 | #endif | ||
| 4281 | } | ||
| 4124 | switch (ioc_status) { | 4282 | switch (ioc_status) { |
| 4125 | case MPI2_IOCSTATUS_BUSY: | 4283 | case MPI2_IOCSTATUS_BUSY: |
| 4126 | case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES: | 4284 | case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES: |
| @@ -4146,6 +4304,9 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) | |||
| 4146 | scmd->device->expecting_cc_ua = 1; | 4304 | scmd->device->expecting_cc_ua = 1; |
| 4147 | } | 4305 | } |
| 4148 | break; | 4306 | break; |
| 4307 | } else if (log_info == VIRTUAL_IO_FAILED_RETRY) { | ||
| 4308 | scmd->result = DID_RESET << 16; | ||
| 4309 | break; | ||
| 4149 | } | 4310 | } |
| 4150 | scmd->result = DID_SOFT_ERROR << 16; | 4311 | scmd->result = DID_SOFT_ERROR << 16; |
| 4151 | break; | 4312 | break; |
| @@ -4788,6 +4949,16 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc, | |||
| 4788 | sas_device->handle, handle); | 4949 | sas_device->handle, handle); |
| 4789 | sas_target_priv_data->handle = handle; | 4950 | sas_target_priv_data->handle = handle; |
| 4790 | sas_device->handle = handle; | 4951 | sas_device->handle = handle; |
| 4952 | if (sas_device_pg0.Flags & | ||
| 4953 | MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { | ||
| 4954 | sas_device->enclosure_level = | ||
| 4955 | le16_to_cpu(sas_device_pg0.EnclosureLevel); | ||
| 4956 | memcpy(&sas_device->connector_name[0], | ||
| 4957 | &sas_device_pg0.ConnectorName[0], 4); | ||
| 4958 | } else { | ||
| 4959 | sas_device->enclosure_level = 0; | ||
| 4960 | sas_device->connector_name[0] = '\0'; | ||
| 4961 | } | ||
| 4791 | } | 4962 | } |
| 4792 | 4963 | ||
| 4793 | /* check if device is present */ | 4964 | /* check if device is present */ |
| @@ -4894,14 +5065,24 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, | |||
| 4894 | ioc->name, __FILE__, __LINE__, __func__); | 5065 | ioc->name, __FILE__, __LINE__, __func__); |
| 4895 | sas_device->enclosure_handle = | 5066 | sas_device->enclosure_handle = |
| 4896 | le16_to_cpu(sas_device_pg0.EnclosureHandle); | 5067 | le16_to_cpu(sas_device_pg0.EnclosureHandle); |
| 4897 | sas_device->slot = | 5068 | if (sas_device->enclosure_handle != 0) |
| 4898 | le16_to_cpu(sas_device_pg0.Slot); | 5069 | sas_device->slot = |
| 5070 | le16_to_cpu(sas_device_pg0.Slot); | ||
| 4899 | sas_device->device_info = device_info; | 5071 | sas_device->device_info = device_info; |
| 4900 | sas_device->sas_address = sas_address; | 5072 | sas_device->sas_address = sas_address; |
| 4901 | sas_device->phy = sas_device_pg0.PhyNum; | 5073 | sas_device->phy = sas_device_pg0.PhyNum; |
| 4902 | sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) & | 5074 | sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) & |
| 4903 | MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0; | 5075 | MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0; |
| 4904 | 5076 | ||
| 5077 | if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { | ||
| 5078 | sas_device->enclosure_level = | ||
| 5079 | le16_to_cpu(sas_device_pg0.EnclosureLevel); | ||
| 5080 | memcpy(&sas_device->connector_name[0], | ||
| 5081 | &sas_device_pg0.ConnectorName[0], 4); | ||
| 5082 | } else { | ||
| 5083 | sas_device->enclosure_level = 0; | ||
| 5084 | sas_device->connector_name[0] = '\0'; | ||
| 5085 | } | ||
| 4905 | /* get enclosure_logical_id */ | 5086 | /* get enclosure_logical_id */ |
| 4906 | if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0( | 5087 | if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0( |
| 4907 | ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, | 5088 | ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, |
| @@ -4943,6 +5124,18 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, | |||
| 4943 | ioc->name, __func__, | 5124 | ioc->name, __func__, |
| 4944 | sas_device->handle, (unsigned long long) | 5125 | sas_device->handle, (unsigned long long) |
| 4945 | sas_device->sas_address)); | 5126 | sas_device->sas_address)); |
| 5127 | if (sas_device->enclosure_handle != 0) | ||
| 5128 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 5129 | "%s: enter: enclosure logical id(0x%016llx), slot(%d)\n", | ||
| 5130 | ioc->name, __func__, | ||
| 5131 | (unsigned long long)sas_device->enclosure_logical_id, | ||
| 5132 | sas_device->slot)); | ||
| 5133 | if (sas_device->connector_name[0] != '\0') | ||
| 5134 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 5135 | "%s: enter: enclosure level(0x%04x), connector name( %s)\n", | ||
| 5136 | ioc->name, __func__, | ||
| 5137 | sas_device->enclosure_level, | ||
| 5138 | sas_device->connector_name)); | ||
| 4946 | 5139 | ||
| 4947 | if (sas_device->starget && sas_device->starget->hostdata) { | 5140 | if (sas_device->starget && sas_device->starget->hostdata) { |
| 4948 | sas_target_priv_data = sas_device->starget->hostdata; | 5141 | sas_target_priv_data = sas_device->starget->hostdata; |
| @@ -4959,12 +5152,34 @@ _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, | |||
| 4959 | "removing handle(0x%04x), sas_addr(0x%016llx)\n", | 5152 | "removing handle(0x%04x), sas_addr(0x%016llx)\n", |
| 4960 | ioc->name, sas_device->handle, | 5153 | ioc->name, sas_device->handle, |
| 4961 | (unsigned long long) sas_device->sas_address); | 5154 | (unsigned long long) sas_device->sas_address); |
| 5155 | if (sas_device->enclosure_handle != 0) | ||
| 5156 | pr_info(MPT3SAS_FMT | ||
| 5157 | "removing : enclosure logical id(0x%016llx), slot(%d)\n", | ||
| 5158 | ioc->name, | ||
| 5159 | (unsigned long long)sas_device->enclosure_logical_id, | ||
| 5160 | sas_device->slot); | ||
| 5161 | if (sas_device->connector_name[0] != '\0') | ||
| 5162 | pr_info(MPT3SAS_FMT | ||
| 5163 | "removing enclosure level(0x%04x), connector name( %s)\n", | ||
| 5164 | ioc->name, sas_device->enclosure_level, | ||
| 5165 | sas_device->connector_name); | ||
| 4962 | 5166 | ||
| 4963 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | 5167 | dewtprintk(ioc, pr_info(MPT3SAS_FMT |
| 4964 | "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n", | 5168 | "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n", |
| 4965 | ioc->name, __func__, | 5169 | ioc->name, __func__, |
| 4966 | sas_device->handle, (unsigned long long) | 5170 | sas_device->handle, (unsigned long long) |
| 4967 | sas_device->sas_address)); | 5171 | sas_device->sas_address)); |
| 5172 | if (sas_device->enclosure_handle != 0) | ||
| 5173 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 5174 | "%s: exit: enclosure logical id(0x%016llx), slot(%d)\n", | ||
| 5175 | ioc->name, __func__, | ||
| 5176 | (unsigned long long)sas_device->enclosure_logical_id, | ||
| 5177 | sas_device->slot)); | ||
| 5178 | if (sas_device->connector_name[0] != '\0') | ||
| 5179 | dewtprintk(ioc, pr_info(MPT3SAS_FMT | ||
| 5180 | "%s: exit: enclosure level(0x%04x), connector name(%s)\n", | ||
| 5181 | ioc->name, __func__, sas_device->enclosure_level, | ||
| 5182 | sas_device->connector_name)); | ||
| 4968 | 5183 | ||
| 4969 | kfree(sas_device); | 5184 | kfree(sas_device); |
| 4970 | } | 5185 | } |
| @@ -6357,9 +6572,7 @@ _scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc) | |||
| 6357 | /** | 6572 | /** |
| 6358 | * _scsih_mark_responding_sas_device - mark a sas_devices as responding | 6573 | * _scsih_mark_responding_sas_device - mark a sas_devices as responding |
| 6359 | * @ioc: per adapter object | 6574 | * @ioc: per adapter object |
| 6360 | * @sas_address: sas address | 6575 | * @sas_device_pg0: SAS Device page 0 |
| 6361 | * @slot: enclosure slot id | ||
| 6362 | * @handle: device handle | ||
| 6363 | * | 6576 | * |
| 6364 | * After host reset, find out whether devices are still responding. | 6577 | * After host reset, find out whether devices are still responding. |
| 6365 | * Used in _scsih_remove_unresponsive_sas_devices. | 6578 | * Used in _scsih_remove_unresponsive_sas_devices. |
| @@ -6367,8 +6580,8 @@ _scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc) | |||
| 6367 | * Return nothing. | 6580 | * Return nothing. |
| 6368 | */ | 6581 | */ |
| 6369 | static void | 6582 | static void |
| 6370 | _scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, | 6583 | _scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, |
| 6371 | u16 slot, u16 handle) | 6584 | Mpi2SasDevicePage0_t *sas_device_pg0) |
| 6372 | { | 6585 | { |
| 6373 | struct MPT3SAS_TARGET *sas_target_priv_data = NULL; | 6586 | struct MPT3SAS_TARGET *sas_target_priv_data = NULL; |
| 6374 | struct scsi_target *starget; | 6587 | struct scsi_target *starget; |
| @@ -6377,8 +6590,8 @@ _scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, | |||
| 6377 | 6590 | ||
| 6378 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | 6591 | spin_lock_irqsave(&ioc->sas_device_lock, flags); |
| 6379 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) { | 6592 | list_for_each_entry(sas_device, &ioc->sas_device_list, list) { |
| 6380 | if (sas_device->sas_address == sas_address && | 6593 | if ((sas_device->sas_address == sas_device_pg0->SASAddress) && |
| 6381 | sas_device->slot == slot) { | 6594 | (sas_device->slot == sas_device_pg0->Slot)) { |
| 6382 | sas_device->responding = 1; | 6595 | sas_device->responding = 1; |
| 6383 | starget = sas_device->starget; | 6596 | starget = sas_device->starget; |
| 6384 | if (starget && starget->hostdata) { | 6597 | if (starget && starget->hostdata) { |
| @@ -6387,22 +6600,40 @@ _scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, | |||
| 6387 | sas_target_priv_data->deleted = 0; | 6600 | sas_target_priv_data->deleted = 0; |
| 6388 | } else | 6601 | } else |
| 6389 | sas_target_priv_data = NULL; | 6602 | sas_target_priv_data = NULL; |
| 6390 | if (starget) | 6603 | if (starget) { |
| 6391 | starget_printk(KERN_INFO, starget, | 6604 | starget_printk(KERN_INFO, starget, |
| 6392 | "handle(0x%04x), sas_addr(0x%016llx), " | 6605 | "handle(0x%04x), sas_addr(0x%016llx)\n", |
| 6393 | "enclosure logical id(0x%016llx), " | 6606 | sas_device_pg0->DevHandle, |
| 6394 | "slot(%d)\n", handle, | ||
| 6395 | (unsigned long long)sas_device->sas_address, | ||
| 6396 | (unsigned long long) | 6607 | (unsigned long long) |
| 6397 | sas_device->enclosure_logical_id, | 6608 | sas_device->sas_address); |
| 6398 | sas_device->slot); | 6609 | |
| 6399 | if (sas_device->handle == handle) | 6610 | if (sas_device->enclosure_handle != 0) |
| 6611 | starget_printk(KERN_INFO, starget, | ||
| 6612 | "enclosure logical id(0x%016llx)," | ||
| 6613 | " slot(%d)\n", | ||
| 6614 | (unsigned long long) | ||
| 6615 | sas_device->enclosure_logical_id, | ||
| 6616 | sas_device->slot); | ||
| 6617 | } | ||
| 6618 | if (sas_device_pg0->Flags & | ||
| 6619 | MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { | ||
| 6620 | sas_device->enclosure_level = | ||
| 6621 | le16_to_cpu(sas_device_pg0->EnclosureLevel); | ||
| 6622 | memcpy(&sas_device->connector_name[0], | ||
| 6623 | &sas_device_pg0->ConnectorName[0], 4); | ||
| 6624 | } else { | ||
| 6625 | sas_device->enclosure_level = 0; | ||
| 6626 | sas_device->connector_name[0] = '\0'; | ||
| 6627 | } | ||
| 6628 | |||
| 6629 | if (sas_device->handle == sas_device_pg0->DevHandle) | ||
| 6400 | goto out; | 6630 | goto out; |
| 6401 | pr_info("\thandle changed from(0x%04x)!!!\n", | 6631 | pr_info("\thandle changed from(0x%04x)!!!\n", |
| 6402 | sas_device->handle); | 6632 | sas_device->handle); |
| 6403 | sas_device->handle = handle; | 6633 | sas_device->handle = sas_device_pg0->DevHandle; |
| 6404 | if (sas_target_priv_data) | 6634 | if (sas_target_priv_data) |
| 6405 | sas_target_priv_data->handle = handle; | 6635 | sas_target_priv_data->handle = |
| 6636 | sas_device_pg0->DevHandle; | ||
| 6406 | goto out; | 6637 | goto out; |
| 6407 | } | 6638 | } |
| 6408 | } | 6639 | } |
| @@ -6441,13 +6672,15 @@ _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc) | |||
| 6441 | MPI2_IOCSTATUS_MASK; | 6672 | MPI2_IOCSTATUS_MASK; |
| 6442 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) | 6673 | if (ioc_status != MPI2_IOCSTATUS_SUCCESS) |
| 6443 | break; | 6674 | break; |
| 6444 | handle = le16_to_cpu(sas_device_pg0.DevHandle); | 6675 | handle = sas_device_pg0.DevHandle = |
| 6676 | le16_to_cpu(sas_device_pg0.DevHandle); | ||
| 6445 | device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); | 6677 | device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); |
| 6446 | if (!(_scsih_is_end_device(device_info))) | 6678 | if (!(_scsih_is_end_device(device_info))) |
| 6447 | continue; | 6679 | continue; |
| 6448 | _scsih_mark_responding_sas_device(ioc, | 6680 | sas_device_pg0.SASAddress = |
| 6449 | le64_to_cpu(sas_device_pg0.SASAddress), | 6681 | le64_to_cpu(sas_device_pg0.SASAddress); |
| 6450 | le16_to_cpu(sas_device_pg0.Slot), handle); | 6682 | sas_device_pg0.Slot = le16_to_cpu(sas_device_pg0.Slot); |
| 6683 | _scsih_mark_responding_sas_device(ioc, &sas_device_pg0); | ||
| 6451 | } | 6684 | } |
| 6452 | 6685 | ||
| 6453 | out: | 6686 | out: |
| @@ -7854,8 +8087,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 7854 | /* event thread */ | 8087 | /* event thread */ |
| 7855 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), | 8088 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), |
| 7856 | "fw_event%d", ioc->id); | 8089 | "fw_event%d", ioc->id); |
| 7857 | ioc->firmware_event_thread = create_singlethread_workqueue( | 8090 | ioc->firmware_event_thread = alloc_ordered_workqueue( |
| 7858 | ioc->firmware_event_name); | 8091 | ioc->firmware_event_name, WQ_MEM_RECLAIM); |
| 7859 | if (!ioc->firmware_event_thread) { | 8092 | if (!ioc->firmware_event_thread) { |
| 7860 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", | 8093 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", |
| 7861 | ioc->name, __FILE__, __LINE__, __func__); | 8094 | ioc->name, __FILE__, __LINE__, __func__); |
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c b/drivers/scsi/mpt3sas/mpt3sas_transport.c index efb98afc46e0..70fd019e7ee5 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_transport.c +++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c | |||
| @@ -649,6 +649,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, | |||
| 649 | unsigned long flags; | 649 | unsigned long flags; |
| 650 | struct _sas_node *sas_node; | 650 | struct _sas_node *sas_node; |
| 651 | struct sas_rphy *rphy; | 651 | struct sas_rphy *rphy; |
| 652 | struct _sas_device *sas_device = NULL; | ||
| 652 | int i; | 653 | int i; |
| 653 | struct sas_port *port; | 654 | struct sas_port *port; |
| 654 | 655 | ||
| @@ -731,10 +732,27 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, | |||
| 731 | mpt3sas_port->remote_identify.device_type); | 732 | mpt3sas_port->remote_identify.device_type); |
| 732 | 733 | ||
| 733 | rphy->identify = mpt3sas_port->remote_identify; | 734 | rphy->identify = mpt3sas_port->remote_identify; |
| 735 | |||
| 736 | if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { | ||
| 737 | sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, | ||
| 738 | mpt3sas_port->remote_identify.sas_address); | ||
| 739 | if (!sas_device) { | ||
| 740 | dfailprintk(ioc, printk(MPT3SAS_FMT | ||
| 741 | "failure at %s:%d/%s()!\n", | ||
| 742 | ioc->name, __FILE__, __LINE__, __func__)); | ||
| 743 | goto out_fail; | ||
| 744 | } | ||
| 745 | sas_device->pend_sas_rphy_add = 1; | ||
| 746 | } | ||
| 747 | |||
| 734 | if ((sas_rphy_add(rphy))) { | 748 | if ((sas_rphy_add(rphy))) { |
| 735 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", | 749 | pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", |
| 736 | ioc->name, __FILE__, __LINE__, __func__); | 750 | ioc->name, __FILE__, __LINE__, __func__); |
| 737 | } | 751 | } |
| 752 | |||
| 753 | if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) | ||
| 754 | sas_device->pend_sas_rphy_add = 0; | ||
| 755 | |||
| 738 | if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) | 756 | if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) |
| 739 | dev_printk(KERN_INFO, &rphy->dev, | 757 | dev_printk(KERN_INFO, &rphy->dev, |
| 740 | "add: handle(0x%04x), sas_addr(0x%016llx)\n", | 758 | "add: handle(0x%04x), sas_addr(0x%016llx)\n", |
| @@ -1946,7 +1964,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1946 | } else { | 1964 | } else { |
| 1947 | dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio), | 1965 | dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio), |
| 1948 | blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL); | 1966 | blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL); |
| 1949 | if (!dma_addr_out) { | 1967 | if (pci_dma_mapping_error(ioc->pdev, dma_addr_out)) { |
| 1950 | pr_info(MPT3SAS_FMT "%s(): DMA Addr out = NULL\n", | 1968 | pr_info(MPT3SAS_FMT "%s(): DMA Addr out = NULL\n", |
| 1951 | ioc->name, __func__); | 1969 | ioc->name, __func__); |
| 1952 | rc = -ENOMEM; | 1970 | rc = -ENOMEM; |
| @@ -1968,7 +1986,7 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1968 | } else { | 1986 | } else { |
| 1969 | dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio), | 1987 | dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio), |
| 1970 | blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL); | 1988 | blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL); |
| 1971 | if (!dma_addr_in) { | 1989 | if (pci_dma_mapping_error(ioc->pdev, dma_addr_in)) { |
| 1972 | pr_info(MPT3SAS_FMT "%s(): DMA Addr in = NULL\n", | 1990 | pr_info(MPT3SAS_FMT "%s(): DMA Addr in = NULL\n", |
| 1973 | ioc->name, __func__); | 1991 | ioc->name, __func__); |
| 1974 | rc = -ENOMEM; | 1992 | rc = -ENOMEM; |
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 39306b1e704c..04e67a190652 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
| @@ -2642,6 +2642,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 2642 | ts->resp = SAS_TASK_COMPLETE; | 2642 | ts->resp = SAS_TASK_COMPLETE; |
| 2643 | ts->stat = SAS_OPEN_REJECT; | 2643 | ts->stat = SAS_OPEN_REJECT; |
| 2644 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | 2644 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; |
| 2645 | break; | ||
| 2645 | default: | 2646 | default: |
| 2646 | PM8001_IO_DBG(pm8001_ha, | 2647 | PM8001_IO_DBG(pm8001_ha, |
| 2647 | pm8001_printk("Unknown status 0x%x\n", status)); | 2648 | pm8001_printk("Unknown status 0x%x\n", status)); |
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 0e1628f2018e..9a389f1508de 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c | |||
| @@ -2337,6 +2337,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) | |||
| 2337 | ts->resp = SAS_TASK_COMPLETE; | 2337 | ts->resp = SAS_TASK_COMPLETE; |
| 2338 | ts->stat = SAS_OPEN_REJECT; | 2338 | ts->stat = SAS_OPEN_REJECT; |
| 2339 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; | 2339 | ts->open_rej_reason = SAS_OREJ_RSVD_RETRY; |
| 2340 | break; | ||
| 2340 | default: | 2341 | default: |
| 2341 | PM8001_IO_DBG(pm8001_ha, | 2342 | PM8001_IO_DBG(pm8001_ha, |
| 2342 | pm8001_printk("Unknown status 0x%x\n", status)); | 2343 | pm8001_printk("Unknown status 0x%x\n", status)); |
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 33f60c92e20e..a0f732b138e4 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig | |||
| @@ -32,10 +32,10 @@ config SCSI_QLA_FC | |||
| 32 | They are also included in the linux-firmware tree as well. | 32 | They are also included in the linux-firmware tree as well. |
| 33 | 33 | ||
| 34 | config TCM_QLA2XXX | 34 | config TCM_QLA2XXX |
| 35 | tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs" | 35 | tristate "TCM_QLA2XXX fabric module for QLogic 24xx+ series target mode HBAs" |
| 36 | depends on SCSI_QLA_FC && TARGET_CORE | 36 | depends on SCSI_QLA_FC && TARGET_CORE |
| 37 | depends on LIBFC | 37 | depends on LIBFC |
| 38 | select BTREE | 38 | select BTREE |
| 39 | default n | 39 | default n |
| 40 | ---help--- | 40 | ---help--- |
| 41 | Say Y here to enable the TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs | 41 | Say Y here to enable the TCM_QLA2XXX fabric module for QLogic 24xx+ series target mode HBAs |
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 7ed7bae6172b..ac65cb7b4886 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c | |||
| @@ -1359,9 +1359,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) | |||
| 1359 | struct qla_hw_data *ha = tgt->ha; | 1359 | struct qla_hw_data *ha = tgt->ha; |
| 1360 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); | 1360 | scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev); |
| 1361 | struct se_session *se_sess; | 1361 | struct se_session *se_sess; |
| 1362 | struct se_node_acl *se_nacl; | ||
| 1363 | struct tcm_qla2xxx_lport *lport; | 1362 | struct tcm_qla2xxx_lport *lport; |
| 1364 | struct tcm_qla2xxx_nacl *nacl; | ||
| 1365 | 1363 | ||
| 1366 | BUG_ON(in_interrupt()); | 1364 | BUG_ON(in_interrupt()); |
| 1367 | 1365 | ||
| @@ -1371,8 +1369,6 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess) | |||
| 1371 | dump_stack(); | 1369 | dump_stack(); |
| 1372 | return; | 1370 | return; |
| 1373 | } | 1371 | } |
| 1374 | se_nacl = se_sess->se_node_acl; | ||
| 1375 | nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl); | ||
| 1376 | 1372 | ||
| 1377 | lport = vha->vha_tgt.target_lport_ptr; | 1373 | lport = vha->vha_tgt.target_lport_ptr; |
| 1378 | if (!lport) { | 1374 | if (!lport) { |
| @@ -1680,7 +1676,6 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha, | |||
| 1680 | (struct tcm_qla2xxx_lport *)target_lport_ptr; | 1676 | (struct tcm_qla2xxx_lport *)target_lport_ptr; |
| 1681 | struct tcm_qla2xxx_lport *base_lport = | 1677 | struct tcm_qla2xxx_lport *base_lport = |
| 1682 | (struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr; | 1678 | (struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr; |
| 1683 | struct tcm_qla2xxx_tpg *base_tpg; | ||
| 1684 | struct fc_vport_identifiers vport_id; | 1679 | struct fc_vport_identifiers vport_id; |
| 1685 | 1680 | ||
| 1686 | if (!qla_tgt_mode_enabled(base_vha)) { | 1681 | if (!qla_tgt_mode_enabled(base_vha)) { |
| @@ -1693,7 +1688,6 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha, | |||
| 1693 | pr_err("qla2xxx base_lport or tpg_1 not available\n"); | 1688 | pr_err("qla2xxx base_lport or tpg_1 not available\n"); |
| 1694 | return -EPERM; | 1689 | return -EPERM; |
| 1695 | } | 1690 | } |
| 1696 | base_tpg = base_lport->tpg_1; | ||
| 1697 | 1691 | ||
| 1698 | memset(&vport_id, 0, sizeof(vport_id)); | 1692 | memset(&vport_id, 0, sizeof(vport_id)); |
| 1699 | vport_id.port_name = npiv_wwpn; | 1693 | vport_id.port_name = npiv_wwpn; |
| @@ -1810,6 +1804,11 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = { | |||
| 1810 | .module = THIS_MODULE, | 1804 | .module = THIS_MODULE, |
| 1811 | .name = "qla2xxx", | 1805 | .name = "qla2xxx", |
| 1812 | .node_acl_size = sizeof(struct tcm_qla2xxx_nacl), | 1806 | .node_acl_size = sizeof(struct tcm_qla2xxx_nacl), |
| 1807 | /* | ||
| 1808 | * XXX: Limit assumes single page per scatter-gather-list entry. | ||
| 1809 | * Current maximum is ~4.9 MB per se_cmd->t_data_sg with PAGE_SIZE=4096 | ||
| 1810 | */ | ||
| 1811 | .max_data_sg_nents = 1200, | ||
| 1813 | .get_fabric_name = tcm_qla2xxx_get_fabric_name, | 1812 | .get_fabric_name = tcm_qla2xxx_get_fabric_name, |
| 1814 | .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, | 1813 | .tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn, |
| 1815 | .tpg_get_tag = tcm_qla2xxx_get_tag, | 1814 | .tpg_get_tag = tcm_qla2xxx_get_tag, |
| @@ -1958,7 +1957,7 @@ static void __exit tcm_qla2xxx_exit(void) | |||
| 1958 | tcm_qla2xxx_deregister_configfs(); | 1957 | tcm_qla2xxx_deregister_configfs(); |
| 1959 | } | 1958 | } |
| 1960 | 1959 | ||
| 1961 | MODULE_DESCRIPTION("TCM QLA2XXX series NPIV enabled fabric driver"); | 1960 | MODULE_DESCRIPTION("TCM QLA24XX+ series NPIV enabled fabric driver"); |
| 1962 | MODULE_LICENSE("GPL"); | 1961 | MODULE_LICENSE("GPL"); |
| 1963 | module_init(tcm_qla2xxx_init); | 1962 | module_init(tcm_qla2xxx_init); |
| 1964 | module_exit(tcm_qla2xxx_exit); | 1963 | module_exit(tcm_qla2xxx_exit); |
diff --git a/drivers/scsi/scsi_common.c b/drivers/scsi/scsi_common.c index 2ff092252b76..c126966130ab 100644 --- a/drivers/scsi/scsi_common.c +++ b/drivers/scsi/scsi_common.c | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | #include <linux/bug.h> | 5 | #include <linux/bug.h> |
| 6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| 7 | #include <linux/string.h> | 7 | #include <linux/string.h> |
| 8 | #include <linux/errno.h> | ||
| 9 | #include <asm/unaligned.h> | ||
| 8 | #include <scsi/scsi_common.h> | 10 | #include <scsi/scsi_common.h> |
| 9 | 11 | ||
| 10 | /* NB: These are exposed through /proc/scsi/scsi and form part of the ABI. | 12 | /* NB: These are exposed through /proc/scsi/scsi and form part of the ABI. |
| @@ -176,3 +178,110 @@ bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len, | |||
| 176 | return true; | 178 | return true; |
| 177 | } | 179 | } |
| 178 | EXPORT_SYMBOL(scsi_normalize_sense); | 180 | EXPORT_SYMBOL(scsi_normalize_sense); |
| 181 | |||
| 182 | /** | ||
| 183 | * scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format. | ||
| 184 | * @sense_buffer: byte array of descriptor format sense data | ||
| 185 | * @sb_len: number of valid bytes in sense_buffer | ||
| 186 | * @desc_type: value of descriptor type to find | ||
| 187 | * (e.g. 0 -> information) | ||
| 188 | * | ||
| 189 | * Notes: | ||
| 190 | * only valid when sense data is in descriptor format | ||
| 191 | * | ||
| 192 | * Return value: | ||
| 193 | * pointer to start of (first) descriptor if found else NULL | ||
| 194 | */ | ||
| 195 | const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, | ||
| 196 | int desc_type) | ||
| 197 | { | ||
| 198 | int add_sen_len, add_len, desc_len, k; | ||
| 199 | const u8 * descp; | ||
| 200 | |||
| 201 | if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7]))) | ||
| 202 | return NULL; | ||
| 203 | if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73)) | ||
| 204 | return NULL; | ||
| 205 | add_sen_len = (add_sen_len < (sb_len - 8)) ? | ||
| 206 | add_sen_len : (sb_len - 8); | ||
| 207 | descp = &sense_buffer[8]; | ||
| 208 | for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) { | ||
| 209 | descp += desc_len; | ||
| 210 | add_len = (k < (add_sen_len - 1)) ? descp[1]: -1; | ||
| 211 | desc_len = add_len + 2; | ||
| 212 | if (descp[0] == desc_type) | ||
| 213 | return descp; | ||
| 214 | if (add_len < 0) // short descriptor ?? | ||
| 215 | break; | ||
| 216 | } | ||
| 217 | return NULL; | ||
| 218 | } | ||
| 219 | EXPORT_SYMBOL(scsi_sense_desc_find); | ||
| 220 | |||
| 221 | /** | ||
| 222 | * scsi_build_sense_buffer - build sense data in a buffer | ||
| 223 | * @desc: Sense format (non zero == descriptor format, | ||
| 224 | * 0 == fixed format) | ||
| 225 | * @buf: Where to build sense data | ||
| 226 | * @key: Sense key | ||
| 227 | * @asc: Additional sense code | ||
| 228 | * @ascq: Additional sense code qualifier | ||
| 229 | * | ||
| 230 | **/ | ||
| 231 | void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) | ||
| 232 | { | ||
| 233 | if (desc) { | ||
| 234 | buf[0] = 0x72; /* descriptor, current */ | ||
| 235 | buf[1] = key; | ||
| 236 | buf[2] = asc; | ||
| 237 | buf[3] = ascq; | ||
| 238 | buf[7] = 0; | ||
| 239 | } else { | ||
| 240 | buf[0] = 0x70; /* fixed, current */ | ||
| 241 | buf[2] = key; | ||
| 242 | buf[7] = 0xa; | ||
| 243 | buf[12] = asc; | ||
| 244 | buf[13] = ascq; | ||
| 245 | } | ||
| 246 | } | ||
| 247 | EXPORT_SYMBOL(scsi_build_sense_buffer); | ||
| 248 | |||
| 249 | /** | ||
| 250 | * scsi_set_sense_information - set the information field in a | ||
| 251 | * formatted sense data buffer | ||
| 252 | * @buf: Where to build sense data | ||
| 253 | * @buf_len: buffer length | ||
| 254 | * @info: 64-bit information value to be set | ||
| 255 | * | ||
| 256 | * Return value: | ||
| 257 | * 0 on success or EINVAL for invalid sense buffer length | ||
| 258 | **/ | ||
| 259 | int scsi_set_sense_information(u8 *buf, int buf_len, u64 info) | ||
| 260 | { | ||
| 261 | if ((buf[0] & 0x7f) == 0x72) { | ||
| 262 | u8 *ucp, len; | ||
| 263 | |||
| 264 | len = buf[7]; | ||
| 265 | ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0); | ||
| 266 | if (!ucp) { | ||
| 267 | buf[7] = len + 0xc; | ||
| 268 | ucp = buf + 8 + len; | ||
| 269 | } | ||
| 270 | |||
| 271 | if (buf_len < len + 0xc) | ||
| 272 | /* Not enough room for info */ | ||
| 273 | return -EINVAL; | ||
| 274 | |||
| 275 | ucp[0] = 0; | ||
| 276 | ucp[1] = 0xa; | ||
| 277 | ucp[2] = 0x80; /* Valid bit */ | ||
| 278 | ucp[3] = 0; | ||
| 279 | put_unaligned_be64(info, &ucp[4]); | ||
| 280 | } else if ((buf[0] & 0x7f) == 0x70) { | ||
| 281 | buf[0] |= 0x80; | ||
| 282 | put_unaligned_be64(info, &buf[3]); | ||
| 283 | } | ||
| 284 | |||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | EXPORT_SYMBOL(scsi_set_sense_information); | ||
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 30268bb2ddb6..dfcc45bb03b1 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
| @@ -25,6 +25,9 @@ | |||
| 25 | * module options to "modprobe scsi_debug num_tgts=2" [20021221] | 25 | * module options to "modprobe scsi_debug num_tgts=2" [20021221] |
| 26 | */ | 26 | */ |
| 27 | 27 | ||
| 28 | |||
| 29 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ | ||
| 30 | |||
| 28 | #include <linux/module.h> | 31 | #include <linux/module.h> |
| 29 | 32 | ||
| 30 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
| @@ -201,7 +204,6 @@ static const char *scsi_debug_version_date = "20141022"; | |||
| 201 | /* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1) | 204 | /* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1) |
| 202 | * or "peripheral device" addressing (value 0) */ | 205 | * or "peripheral device" addressing (value 0) */ |
| 203 | #define SAM2_LUN_ADDRESS_METHOD 0 | 206 | #define SAM2_LUN_ADDRESS_METHOD 0 |
| 204 | #define SAM2_WLUN_REPORT_LUNS 0xc101 | ||
| 205 | 207 | ||
| 206 | /* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued | 208 | /* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued |
| 207 | * (for response) at one time. Can be reduced by max_queue option. Command | 209 | * (for response) at one time. Can be reduced by max_queue option. Command |
| @@ -698,7 +700,7 @@ static void sdebug_max_tgts_luns(void) | |||
| 698 | else | 700 | else |
| 699 | hpnt->max_id = scsi_debug_num_tgts; | 701 | hpnt->max_id = scsi_debug_num_tgts; |
| 700 | /* scsi_debug_max_luns; */ | 702 | /* scsi_debug_max_luns; */ |
| 701 | hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; | 703 | hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1; |
| 702 | } | 704 | } |
| 703 | spin_unlock(&sdebug_host_list_lock); | 705 | spin_unlock(&sdebug_host_list_lock); |
| 704 | } | 706 | } |
| @@ -1288,7 +1290,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) | |||
| 1288 | arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); | 1290 | arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); |
| 1289 | if (! arr) | 1291 | if (! arr) |
| 1290 | return DID_REQUEUE << 16; | 1292 | return DID_REQUEUE << 16; |
| 1291 | have_wlun = (scp->device->lun == SAM2_WLUN_REPORT_LUNS); | 1293 | have_wlun = (scp->device->lun == SCSI_W_LUN_REPORT_LUNS); |
| 1292 | if (have_wlun) | 1294 | if (have_wlun) |
| 1293 | pq_pdt = 0x1e; /* present, wlun */ | 1295 | pq_pdt = 0x1e; /* present, wlun */ |
| 1294 | else if (scsi_debug_no_lun_0 && (0 == devip->lun)) | 1296 | else if (scsi_debug_no_lun_0 && (0 == devip->lun)) |
| @@ -1427,12 +1429,11 @@ static int resp_requests(struct scsi_cmnd * scp, | |||
| 1427 | unsigned char * sbuff; | 1429 | unsigned char * sbuff; |
| 1428 | unsigned char *cmd = scp->cmnd; | 1430 | unsigned char *cmd = scp->cmnd; |
| 1429 | unsigned char arr[SCSI_SENSE_BUFFERSIZE]; | 1431 | unsigned char arr[SCSI_SENSE_BUFFERSIZE]; |
| 1430 | bool dsense, want_dsense; | 1432 | bool dsense; |
| 1431 | int len = 18; | 1433 | int len = 18; |
| 1432 | 1434 | ||
| 1433 | memset(arr, 0, sizeof(arr)); | 1435 | memset(arr, 0, sizeof(arr)); |
| 1434 | dsense = !!(cmd[1] & 1); | 1436 | dsense = !!(cmd[1] & 1); |
| 1435 | want_dsense = dsense || scsi_debug_dsense; | ||
| 1436 | sbuff = scp->sense_buffer; | 1437 | sbuff = scp->sense_buffer; |
| 1437 | if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { | 1438 | if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { |
| 1438 | if (dsense) { | 1439 | if (dsense) { |
| @@ -2446,8 +2447,7 @@ static int dif_verify(struct sd_dif_tuple *sdt, const void *data, | |||
| 2446 | __be16 csum = dif_compute_csum(data, scsi_debug_sector_size); | 2447 | __be16 csum = dif_compute_csum(data, scsi_debug_sector_size); |
| 2447 | 2448 | ||
| 2448 | if (sdt->guard_tag != csum) { | 2449 | if (sdt->guard_tag != csum) { |
| 2449 | pr_err("%s: GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n", | 2450 | pr_err("GUARD check failed on sector %lu rcvd 0x%04x, data 0x%04x\n", |
| 2450 | __func__, | ||
| 2451 | (unsigned long)sector, | 2451 | (unsigned long)sector, |
| 2452 | be16_to_cpu(sdt->guard_tag), | 2452 | be16_to_cpu(sdt->guard_tag), |
| 2453 | be16_to_cpu(csum)); | 2453 | be16_to_cpu(csum)); |
| @@ -2455,14 +2455,14 @@ static int dif_verify(struct sd_dif_tuple *sdt, const void *data, | |||
| 2455 | } | 2455 | } |
| 2456 | if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && | 2456 | if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && |
| 2457 | be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { | 2457 | be32_to_cpu(sdt->ref_tag) != (sector & 0xffffffff)) { |
| 2458 | pr_err("%s: REF check failed on sector %lu\n", | 2458 | pr_err("REF check failed on sector %lu\n", |
| 2459 | __func__, (unsigned long)sector); | 2459 | (unsigned long)sector); |
| 2460 | return 0x03; | 2460 | return 0x03; |
| 2461 | } | 2461 | } |
| 2462 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && | 2462 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && |
| 2463 | be32_to_cpu(sdt->ref_tag) != ei_lba) { | 2463 | be32_to_cpu(sdt->ref_tag) != ei_lba) { |
| 2464 | pr_err("%s: REF check failed on sector %lu\n", | 2464 | pr_err("REF check failed on sector %lu\n", |
| 2465 | __func__, (unsigned long)sector); | 2465 | (unsigned long)sector); |
| 2466 | return 0x03; | 2466 | return 0x03; |
| 2467 | } | 2467 | } |
| 2468 | return 0; | 2468 | return 0; |
| @@ -2680,7 +2680,7 @@ resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip) | |||
| 2680 | return 0; | 2680 | return 0; |
| 2681 | } | 2681 | } |
| 2682 | 2682 | ||
| 2683 | void dump_sector(unsigned char *buf, int len) | 2683 | static void dump_sector(unsigned char *buf, int len) |
| 2684 | { | 2684 | { |
| 2685 | int i, j, n; | 2685 | int i, j, n; |
| 2686 | 2686 | ||
| @@ -3365,8 +3365,8 @@ static int resp_report_luns(struct scsi_cmnd * scp, | |||
| 3365 | one_lun[i].scsi_lun[1] = lun & 0xff; | 3365 | one_lun[i].scsi_lun[1] = lun & 0xff; |
| 3366 | } | 3366 | } |
| 3367 | if (want_wlun) { | 3367 | if (want_wlun) { |
| 3368 | one_lun[i].scsi_lun[0] = (SAM2_WLUN_REPORT_LUNS >> 8) & 0xff; | 3368 | one_lun[i].scsi_lun[0] = (SCSI_W_LUN_REPORT_LUNS >> 8) & 0xff; |
| 3369 | one_lun[i].scsi_lun[1] = SAM2_WLUN_REPORT_LUNS & 0xff; | 3369 | one_lun[i].scsi_lun[1] = SCSI_W_LUN_REPORT_LUNS & 0xff; |
| 3370 | i++; | 3370 | i++; |
| 3371 | } | 3371 | } |
| 3372 | alloc_len = (unsigned char *)(one_lun + i) - arr; | 3372 | alloc_len = (unsigned char *)(one_lun + i) - arr; |
| @@ -3449,7 +3449,7 @@ static void sdebug_q_cmd_complete(unsigned long indx) | |||
| 3449 | atomic_inc(&sdebug_completions); | 3449 | atomic_inc(&sdebug_completions); |
| 3450 | qa_indx = indx; | 3450 | qa_indx = indx; |
| 3451 | if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { | 3451 | if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { |
| 3452 | pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx); | 3452 | pr_err("wild qa_indx=%d\n", qa_indx); |
| 3453 | return; | 3453 | return; |
| 3454 | } | 3454 | } |
| 3455 | spin_lock_irqsave(&queued_arr_lock, iflags); | 3455 | spin_lock_irqsave(&queued_arr_lock, iflags); |
| @@ -3457,21 +3457,21 @@ static void sdebug_q_cmd_complete(unsigned long indx) | |||
| 3457 | scp = sqcp->a_cmnd; | 3457 | scp = sqcp->a_cmnd; |
| 3458 | if (NULL == scp) { | 3458 | if (NULL == scp) { |
| 3459 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | 3459 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
| 3460 | pr_err("%s: scp is NULL\n", __func__); | 3460 | pr_err("scp is NULL\n"); |
| 3461 | return; | 3461 | return; |
| 3462 | } | 3462 | } |
| 3463 | devip = (struct sdebug_dev_info *)scp->device->hostdata; | 3463 | devip = (struct sdebug_dev_info *)scp->device->hostdata; |
| 3464 | if (devip) | 3464 | if (devip) |
| 3465 | atomic_dec(&devip->num_in_q); | 3465 | atomic_dec(&devip->num_in_q); |
| 3466 | else | 3466 | else |
| 3467 | pr_err("%s: devip=NULL\n", __func__); | 3467 | pr_err("devip=NULL\n"); |
| 3468 | if (atomic_read(&retired_max_queue) > 0) | 3468 | if (atomic_read(&retired_max_queue) > 0) |
| 3469 | retiring = 1; | 3469 | retiring = 1; |
| 3470 | 3470 | ||
| 3471 | sqcp->a_cmnd = NULL; | 3471 | sqcp->a_cmnd = NULL; |
| 3472 | if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { | 3472 | if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { |
| 3473 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | 3473 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
| 3474 | pr_err("%s: Unexpected completion\n", __func__); | 3474 | pr_err("Unexpected completion\n"); |
| 3475 | return; | 3475 | return; |
| 3476 | } | 3476 | } |
| 3477 | 3477 | ||
| @@ -3481,7 +3481,7 @@ static void sdebug_q_cmd_complete(unsigned long indx) | |||
| 3481 | retval = atomic_read(&retired_max_queue); | 3481 | retval = atomic_read(&retired_max_queue); |
| 3482 | if (qa_indx >= retval) { | 3482 | if (qa_indx >= retval) { |
| 3483 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | 3483 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
| 3484 | pr_err("%s: index %d too large\n", __func__, retval); | 3484 | pr_err("index %d too large\n", retval); |
| 3485 | return; | 3485 | return; |
| 3486 | } | 3486 | } |
| 3487 | k = find_last_bit(queued_in_use_bm, retval); | 3487 | k = find_last_bit(queued_in_use_bm, retval); |
| @@ -3509,7 +3509,7 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer) | |||
| 3509 | atomic_inc(&sdebug_completions); | 3509 | atomic_inc(&sdebug_completions); |
| 3510 | qa_indx = sd_hrtp->qa_indx; | 3510 | qa_indx = sd_hrtp->qa_indx; |
| 3511 | if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { | 3511 | if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { |
| 3512 | pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx); | 3512 | pr_err("wild qa_indx=%d\n", qa_indx); |
| 3513 | goto the_end; | 3513 | goto the_end; |
| 3514 | } | 3514 | } |
| 3515 | spin_lock_irqsave(&queued_arr_lock, iflags); | 3515 | spin_lock_irqsave(&queued_arr_lock, iflags); |
| @@ -3517,21 +3517,21 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer) | |||
| 3517 | scp = sqcp->a_cmnd; | 3517 | scp = sqcp->a_cmnd; |
| 3518 | if (NULL == scp) { | 3518 | if (NULL == scp) { |
| 3519 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | 3519 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
| 3520 | pr_err("%s: scp is NULL\n", __func__); | 3520 | pr_err("scp is NULL\n"); |
| 3521 | goto the_end; | 3521 | goto the_end; |
| 3522 | } | 3522 | } |
| 3523 | devip = (struct sdebug_dev_info *)scp->device->hostdata; | 3523 | devip = (struct sdebug_dev_info *)scp->device->hostdata; |
| 3524 | if (devip) | 3524 | if (devip) |
| 3525 | atomic_dec(&devip->num_in_q); | 3525 | atomic_dec(&devip->num_in_q); |
| 3526 | else | 3526 | else |
| 3527 | pr_err("%s: devip=NULL\n", __func__); | 3527 | pr_err("devip=NULL\n"); |
| 3528 | if (atomic_read(&retired_max_queue) > 0) | 3528 | if (atomic_read(&retired_max_queue) > 0) |
| 3529 | retiring = 1; | 3529 | retiring = 1; |
| 3530 | 3530 | ||
| 3531 | sqcp->a_cmnd = NULL; | 3531 | sqcp->a_cmnd = NULL; |
| 3532 | if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { | 3532 | if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { |
| 3533 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | 3533 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
| 3534 | pr_err("%s: Unexpected completion\n", __func__); | 3534 | pr_err("Unexpected completion\n"); |
| 3535 | goto the_end; | 3535 | goto the_end; |
| 3536 | } | 3536 | } |
| 3537 | 3537 | ||
| @@ -3541,7 +3541,7 @@ sdebug_q_cmd_hrt_complete(struct hrtimer *timer) | |||
| 3541 | retval = atomic_read(&retired_max_queue); | 3541 | retval = atomic_read(&retired_max_queue); |
| 3542 | if (qa_indx >= retval) { | 3542 | if (qa_indx >= retval) { |
| 3543 | spin_unlock_irqrestore(&queued_arr_lock, iflags); | 3543 | spin_unlock_irqrestore(&queued_arr_lock, iflags); |
| 3544 | pr_err("%s: index %d too large\n", __func__, retval); | 3544 | pr_err("index %d too large\n", retval); |
| 3545 | goto the_end; | 3545 | goto the_end; |
| 3546 | } | 3546 | } |
| 3547 | k = find_last_bit(queued_in_use_bm, retval); | 3547 | k = find_last_bit(queued_in_use_bm, retval); |
| @@ -3580,7 +3580,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) | |||
| 3580 | return devip; | 3580 | return devip; |
| 3581 | sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host); | 3581 | sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host); |
| 3582 | if (!sdbg_host) { | 3582 | if (!sdbg_host) { |
| 3583 | pr_err("%s: Host info NULL\n", __func__); | 3583 | pr_err("Host info NULL\n"); |
| 3584 | return NULL; | 3584 | return NULL; |
| 3585 | } | 3585 | } |
| 3586 | list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { | 3586 | list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { |
| @@ -3596,8 +3596,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) | |||
| 3596 | if (!open_devip) { /* try and make a new one */ | 3596 | if (!open_devip) { /* try and make a new one */ |
| 3597 | open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC); | 3597 | open_devip = sdebug_device_create(sdbg_host, GFP_ATOMIC); |
| 3598 | if (!open_devip) { | 3598 | if (!open_devip) { |
| 3599 | printk(KERN_ERR "%s: out of memory at line %d\n", | 3599 | pr_err("out of memory at line %d\n", __LINE__); |
| 3600 | __func__, __LINE__); | ||
| 3601 | return NULL; | 3600 | return NULL; |
| 3602 | } | 3601 | } |
| 3603 | } | 3602 | } |
| @@ -3615,7 +3614,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) | |||
| 3615 | static int scsi_debug_slave_alloc(struct scsi_device *sdp) | 3614 | static int scsi_debug_slave_alloc(struct scsi_device *sdp) |
| 3616 | { | 3615 | { |
| 3617 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 3616 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
| 3618 | printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %llu>\n", | 3617 | pr_info("slave_alloc <%u %u %u %llu>\n", |
| 3619 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); | 3618 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); |
| 3620 | queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue); | 3619 | queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue); |
| 3621 | return 0; | 3620 | return 0; |
| @@ -3626,7 +3625,7 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp) | |||
| 3626 | struct sdebug_dev_info *devip; | 3625 | struct sdebug_dev_info *devip; |
| 3627 | 3626 | ||
| 3628 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 3627 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
| 3629 | printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %llu>\n", | 3628 | pr_info("slave_configure <%u %u %u %llu>\n", |
| 3630 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); | 3629 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); |
| 3631 | if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) | 3630 | if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) |
| 3632 | sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; | 3631 | sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; |
| @@ -3646,7 +3645,7 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) | |||
| 3646 | (struct sdebug_dev_info *)sdp->hostdata; | 3645 | (struct sdebug_dev_info *)sdp->hostdata; |
| 3647 | 3646 | ||
| 3648 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 3647 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
| 3649 | printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %llu>\n", | 3648 | pr_info("slave_destroy <%u %u %u %llu>\n", |
| 3650 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); | 3649 | sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); |
| 3651 | if (devip) { | 3650 | if (devip) { |
| 3652 | /* make this slot available for re-use */ | 3651 | /* make this slot available for re-use */ |
| @@ -3897,8 +3896,7 @@ static void __init sdebug_build_parts(unsigned char *ramp, | |||
| 3897 | return; | 3896 | return; |
| 3898 | if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) { | 3897 | if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) { |
| 3899 | scsi_debug_num_parts = SDEBUG_MAX_PARTS; | 3898 | scsi_debug_num_parts = SDEBUG_MAX_PARTS; |
| 3900 | pr_warn("%s: reducing partitions to %d\n", __func__, | 3899 | pr_warn("reducing partitions to %d\n", SDEBUG_MAX_PARTS); |
| 3901 | SDEBUG_MAX_PARTS); | ||
| 3902 | } | 3900 | } |
| 3903 | num_sectors = (int)sdebug_store_sectors; | 3901 | num_sectors = (int)sdebug_store_sectors; |
| 3904 | sectors_per_part = (num_sectors - sdebug_sectors_per) | 3902 | sectors_per_part = (num_sectors - sdebug_sectors_per) |
| @@ -3942,14 +3940,20 @@ schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, | |||
| 3942 | unsigned long iflags; | 3940 | unsigned long iflags; |
| 3943 | int k, num_in_q, qdepth, inject; | 3941 | int k, num_in_q, qdepth, inject; |
| 3944 | struct sdebug_queued_cmd *sqcp = NULL; | 3942 | struct sdebug_queued_cmd *sqcp = NULL; |
| 3945 | struct scsi_device *sdp = cmnd->device; | 3943 | struct scsi_device *sdp; |
| 3944 | |||
| 3945 | /* this should never happen */ | ||
| 3946 | if (WARN_ON(!cmnd)) | ||
| 3947 | return SCSI_MLQUEUE_HOST_BUSY; | ||
| 3946 | 3948 | ||
| 3947 | if (NULL == cmnd || NULL == devip) { | 3949 | if (NULL == devip) { |
| 3948 | pr_warn("%s: called with NULL cmnd or devip pointer\n", | 3950 | pr_warn("called devip == NULL\n"); |
| 3949 | __func__); | ||
| 3950 | /* no particularly good error to report back */ | 3951 | /* no particularly good error to report back */ |
| 3951 | return SCSI_MLQUEUE_HOST_BUSY; | 3952 | return SCSI_MLQUEUE_HOST_BUSY; |
| 3952 | } | 3953 | } |
| 3954 | |||
| 3955 | sdp = cmnd->device; | ||
| 3956 | |||
| 3953 | if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) | 3957 | if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) |
| 3954 | sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", | 3958 | sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", |
| 3955 | __func__, scsi_result); | 3959 | __func__, scsi_result); |
| @@ -4383,8 +4387,7 @@ static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf, | |||
| 4383 | 4387 | ||
| 4384 | fake_storep = vmalloc(sz); | 4388 | fake_storep = vmalloc(sz); |
| 4385 | if (NULL == fake_storep) { | 4389 | if (NULL == fake_storep) { |
| 4386 | pr_err("%s: out of memory, 9\n", | 4390 | pr_err("out of memory, 9\n"); |
| 4387 | __func__); | ||
| 4388 | return -ENOMEM; | 4391 | return -ENOMEM; |
| 4389 | } | 4392 | } |
| 4390 | memset(fake_storep, 0, sz); | 4393 | memset(fake_storep, 0, sz); |
| @@ -4784,8 +4787,7 @@ static int __init scsi_debug_init(void) | |||
| 4784 | atomic_set(&retired_max_queue, 0); | 4787 | atomic_set(&retired_max_queue, 0); |
| 4785 | 4788 | ||
| 4786 | if (scsi_debug_ndelay >= 1000000000) { | 4789 | if (scsi_debug_ndelay >= 1000000000) { |
| 4787 | pr_warn("%s: ndelay must be less than 1 second, ignored\n", | 4790 | pr_warn("ndelay must be less than 1 second, ignored\n"); |
| 4788 | __func__); | ||
| 4789 | scsi_debug_ndelay = 0; | 4791 | scsi_debug_ndelay = 0; |
| 4790 | } else if (scsi_debug_ndelay > 0) | 4792 | } else if (scsi_debug_ndelay > 0) |
| 4791 | scsi_debug_delay = DELAY_OVERRIDDEN; | 4793 | scsi_debug_delay = DELAY_OVERRIDDEN; |
| @@ -4797,8 +4799,7 @@ static int __init scsi_debug_init(void) | |||
| 4797 | case 4096: | 4799 | case 4096: |
| 4798 | break; | 4800 | break; |
| 4799 | default: | 4801 | default: |
| 4800 | pr_err("%s: invalid sector_size %d\n", __func__, | 4802 | pr_err("invalid sector_size %d\n", scsi_debug_sector_size); |
| 4801 | scsi_debug_sector_size); | ||
| 4802 | return -EINVAL; | 4803 | return -EINVAL; |
| 4803 | } | 4804 | } |
| 4804 | 4805 | ||
| @@ -4811,29 +4812,28 @@ static int __init scsi_debug_init(void) | |||
| 4811 | break; | 4812 | break; |
| 4812 | 4813 | ||
| 4813 | default: | 4814 | default: |
| 4814 | pr_err("%s: dif must be 0, 1, 2 or 3\n", __func__); | 4815 | pr_err("dif must be 0, 1, 2 or 3\n"); |
| 4815 | return -EINVAL; | 4816 | return -EINVAL; |
| 4816 | } | 4817 | } |
| 4817 | 4818 | ||
| 4818 | if (scsi_debug_guard > 1) { | 4819 | if (scsi_debug_guard > 1) { |
| 4819 | pr_err("%s: guard must be 0 or 1\n", __func__); | 4820 | pr_err("guard must be 0 or 1\n"); |
| 4820 | return -EINVAL; | 4821 | return -EINVAL; |
| 4821 | } | 4822 | } |
| 4822 | 4823 | ||
| 4823 | if (scsi_debug_ato > 1) { | 4824 | if (scsi_debug_ato > 1) { |
| 4824 | pr_err("%s: ato must be 0 or 1\n", __func__); | 4825 | pr_err("ato must be 0 or 1\n"); |
| 4825 | return -EINVAL; | 4826 | return -EINVAL; |
| 4826 | } | 4827 | } |
| 4827 | 4828 | ||
| 4828 | if (scsi_debug_physblk_exp > 15) { | 4829 | if (scsi_debug_physblk_exp > 15) { |
| 4829 | pr_err("%s: invalid physblk_exp %u\n", __func__, | 4830 | pr_err("invalid physblk_exp %u\n", scsi_debug_physblk_exp); |
| 4830 | scsi_debug_physblk_exp); | ||
| 4831 | return -EINVAL; | 4831 | return -EINVAL; |
| 4832 | } | 4832 | } |
| 4833 | 4833 | ||
| 4834 | if (scsi_debug_lowest_aligned > 0x3fff) { | 4834 | if (scsi_debug_lowest_aligned > 0x3fff) { |
| 4835 | pr_err("%s: lowest_aligned too big: %u\n", __func__, | 4835 | pr_err("lowest_aligned too big: %u\n", |
| 4836 | scsi_debug_lowest_aligned); | 4836 | scsi_debug_lowest_aligned); |
| 4837 | return -EINVAL; | 4837 | return -EINVAL; |
| 4838 | } | 4838 | } |
| 4839 | 4839 | ||
| @@ -4863,7 +4863,7 @@ static int __init scsi_debug_init(void) | |||
| 4863 | if (0 == scsi_debug_fake_rw) { | 4863 | if (0 == scsi_debug_fake_rw) { |
| 4864 | fake_storep = vmalloc(sz); | 4864 | fake_storep = vmalloc(sz); |
| 4865 | if (NULL == fake_storep) { | 4865 | if (NULL == fake_storep) { |
| 4866 | pr_err("%s: out of memory, 1\n", __func__); | 4866 | pr_err("out of memory, 1\n"); |
| 4867 | return -ENOMEM; | 4867 | return -ENOMEM; |
| 4868 | } | 4868 | } |
| 4869 | memset(fake_storep, 0, sz); | 4869 | memset(fake_storep, 0, sz); |
| @@ -4877,11 +4877,10 @@ static int __init scsi_debug_init(void) | |||
| 4877 | dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); | 4877 | dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); |
| 4878 | dif_storep = vmalloc(dif_size); | 4878 | dif_storep = vmalloc(dif_size); |
| 4879 | 4879 | ||
| 4880 | pr_err("%s: dif_storep %u bytes @ %p\n", __func__, dif_size, | 4880 | pr_err("dif_storep %u bytes @ %p\n", dif_size, dif_storep); |
| 4881 | dif_storep); | ||
| 4882 | 4881 | ||
| 4883 | if (dif_storep == NULL) { | 4882 | if (dif_storep == NULL) { |
| 4884 | pr_err("%s: out of mem. (DIX)\n", __func__); | 4883 | pr_err("out of mem. (DIX)\n"); |
| 4885 | ret = -ENOMEM; | 4884 | ret = -ENOMEM; |
| 4886 | goto free_vm; | 4885 | goto free_vm; |
| 4887 | } | 4886 | } |
| @@ -4903,18 +4902,17 @@ static int __init scsi_debug_init(void) | |||
| 4903 | if (scsi_debug_unmap_alignment && | 4902 | if (scsi_debug_unmap_alignment && |
| 4904 | scsi_debug_unmap_granularity <= | 4903 | scsi_debug_unmap_granularity <= |
| 4905 | scsi_debug_unmap_alignment) { | 4904 | scsi_debug_unmap_alignment) { |
| 4906 | pr_err("%s: ERR: unmap_granularity <= unmap_alignment\n", | 4905 | pr_err("ERR: unmap_granularity <= unmap_alignment\n"); |
| 4907 | __func__); | ||
| 4908 | return -EINVAL; | 4906 | return -EINVAL; |
| 4909 | } | 4907 | } |
| 4910 | 4908 | ||
| 4911 | map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1; | 4909 | map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1; |
| 4912 | map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long)); | 4910 | map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long)); |
| 4913 | 4911 | ||
| 4914 | pr_info("%s: %lu provisioning blocks\n", __func__, map_size); | 4912 | pr_info("%lu provisioning blocks\n", map_size); |
| 4915 | 4913 | ||
| 4916 | if (map_storep == NULL) { | 4914 | if (map_storep == NULL) { |
| 4917 | pr_err("%s: out of mem. (MAP)\n", __func__); | 4915 | pr_err("out of mem. (MAP)\n"); |
| 4918 | ret = -ENOMEM; | 4916 | ret = -ENOMEM; |
| 4919 | goto free_vm; | 4917 | goto free_vm; |
| 4920 | } | 4918 | } |
| @@ -4928,18 +4926,18 @@ static int __init scsi_debug_init(void) | |||
| 4928 | 4926 | ||
| 4929 | pseudo_primary = root_device_register("pseudo_0"); | 4927 | pseudo_primary = root_device_register("pseudo_0"); |
| 4930 | if (IS_ERR(pseudo_primary)) { | 4928 | if (IS_ERR(pseudo_primary)) { |
| 4931 | pr_warn("%s: root_device_register() error\n", __func__); | 4929 | pr_warn("root_device_register() error\n"); |
| 4932 | ret = PTR_ERR(pseudo_primary); | 4930 | ret = PTR_ERR(pseudo_primary); |
| 4933 | goto free_vm; | 4931 | goto free_vm; |
| 4934 | } | 4932 | } |
| 4935 | ret = bus_register(&pseudo_lld_bus); | 4933 | ret = bus_register(&pseudo_lld_bus); |
| 4936 | if (ret < 0) { | 4934 | if (ret < 0) { |
| 4937 | pr_warn("%s: bus_register error: %d\n", __func__, ret); | 4935 | pr_warn("bus_register error: %d\n", ret); |
| 4938 | goto dev_unreg; | 4936 | goto dev_unreg; |
| 4939 | } | 4937 | } |
| 4940 | ret = driver_register(&sdebug_driverfs_driver); | 4938 | ret = driver_register(&sdebug_driverfs_driver); |
| 4941 | if (ret < 0) { | 4939 | if (ret < 0) { |
| 4942 | pr_warn("%s: driver_register error: %d\n", __func__, ret); | 4940 | pr_warn("driver_register error: %d\n", ret); |
| 4943 | goto bus_unreg; | 4941 | goto bus_unreg; |
| 4944 | } | 4942 | } |
| 4945 | 4943 | ||
| @@ -4948,16 +4946,14 @@ static int __init scsi_debug_init(void) | |||
| 4948 | 4946 | ||
| 4949 | for (k = 0; k < host_to_add; k++) { | 4947 | for (k = 0; k < host_to_add; k++) { |
| 4950 | if (sdebug_add_adapter()) { | 4948 | if (sdebug_add_adapter()) { |
| 4951 | pr_err("%s: sdebug_add_adapter failed k=%d\n", | 4949 | pr_err("sdebug_add_adapter failed k=%d\n", k); |
| 4952 | __func__, k); | ||
| 4953 | break; | 4950 | break; |
| 4954 | } | 4951 | } |
| 4955 | } | 4952 | } |
| 4956 | 4953 | ||
| 4957 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { | 4954 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
| 4958 | pr_info("%s: built %d host(s)\n", __func__, | 4955 | pr_info("built %d host(s)\n", scsi_debug_add_host); |
| 4959 | scsi_debug_add_host); | 4956 | |
| 4960 | } | ||
| 4961 | return 0; | 4957 | return 0; |
| 4962 | 4958 | ||
| 4963 | bus_unreg: | 4959 | bus_unreg: |
| @@ -4965,10 +4961,8 @@ bus_unreg: | |||
| 4965 | dev_unreg: | 4961 | dev_unreg: |
| 4966 | root_device_unregister(pseudo_primary); | 4962 | root_device_unregister(pseudo_primary); |
| 4967 | free_vm: | 4963 | free_vm: |
| 4968 | if (map_storep) | 4964 | vfree(map_storep); |
| 4969 | vfree(map_storep); | 4965 | vfree(dif_storep); |
| 4970 | if (dif_storep) | ||
| 4971 | vfree(dif_storep); | ||
| 4972 | vfree(fake_storep); | 4966 | vfree(fake_storep); |
| 4973 | 4967 | ||
| 4974 | return ret; | 4968 | return ret; |
| @@ -4986,9 +4980,7 @@ static void __exit scsi_debug_exit(void) | |||
| 4986 | bus_unregister(&pseudo_lld_bus); | 4980 | bus_unregister(&pseudo_lld_bus); |
| 4987 | root_device_unregister(pseudo_primary); | 4981 | root_device_unregister(pseudo_primary); |
| 4988 | 4982 | ||
| 4989 | if (dif_storep) | 4983 | vfree(dif_storep); |
| 4990 | vfree(dif_storep); | ||
| 4991 | |||
| 4992 | vfree(fake_storep); | 4984 | vfree(fake_storep); |
| 4993 | } | 4985 | } |
| 4994 | 4986 | ||
| @@ -5012,8 +5004,7 @@ static int sdebug_add_adapter(void) | |||
| 5012 | 5004 | ||
| 5013 | sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL); | 5005 | sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL); |
| 5014 | if (NULL == sdbg_host) { | 5006 | if (NULL == sdbg_host) { |
| 5015 | printk(KERN_ERR "%s: out of memory at line %d\n", | 5007 | pr_err("out of memory at line %d\n", __LINE__); |
| 5016 | __func__, __LINE__); | ||
| 5017 | return -ENOMEM; | 5008 | return -ENOMEM; |
| 5018 | } | 5009 | } |
| 5019 | 5010 | ||
| @@ -5023,8 +5014,7 @@ static int sdebug_add_adapter(void) | |||
| 5023 | for (k = 0; k < devs_per_host; k++) { | 5014 | for (k = 0; k < devs_per_host; k++) { |
| 5024 | sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL); | 5015 | sdbg_devinfo = sdebug_device_create(sdbg_host, GFP_KERNEL); |
| 5025 | if (!sdbg_devinfo) { | 5016 | if (!sdbg_devinfo) { |
| 5026 | printk(KERN_ERR "%s: out of memory at line %d\n", | 5017 | pr_err("out of memory at line %d\n", __LINE__); |
| 5027 | __func__, __LINE__); | ||
| 5028 | error = -ENOMEM; | 5018 | error = -ENOMEM; |
| 5029 | goto clean; | 5019 | goto clean; |
| 5030 | } | 5020 | } |
| @@ -5178,7 +5168,7 @@ scsi_debug_queuecommand(struct scsi_cmnd *scp) | |||
| 5178 | } | 5168 | } |
| 5179 | sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b); | 5169 | sdev_printk(KERN_INFO, sdp, "%s: cmd %s\n", my_name, b); |
| 5180 | } | 5170 | } |
| 5181 | has_wlun_rl = (sdp->lun == SAM2_WLUN_REPORT_LUNS); | 5171 | has_wlun_rl = (sdp->lun == SCSI_W_LUN_REPORT_LUNS); |
| 5182 | if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl) | 5172 | if ((sdp->lun >= scsi_debug_max_luns) && !has_wlun_rl) |
| 5183 | return schedule_resp(scp, NULL, errsts_no_connect, 0); | 5173 | return schedule_resp(scp, NULL, errsts_no_connect, 0); |
| 5184 | 5174 | ||
| @@ -5338,7 +5328,7 @@ static int sdebug_driver_probe(struct device * dev) | |||
| 5338 | sdebug_driver_template.use_clustering = ENABLE_CLUSTERING; | 5328 | sdebug_driver_template.use_clustering = ENABLE_CLUSTERING; |
| 5339 | hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); | 5329 | hpnt = scsi_host_alloc(&sdebug_driver_template, sizeof(sdbg_host)); |
| 5340 | if (NULL == hpnt) { | 5330 | if (NULL == hpnt) { |
| 5341 | pr_err("%s: scsi_host_alloc failed\n", __func__); | 5331 | pr_err("scsi_host_alloc failed\n"); |
| 5342 | error = -ENODEV; | 5332 | error = -ENODEV; |
| 5343 | return error; | 5333 | return error; |
| 5344 | } | 5334 | } |
| @@ -5349,7 +5339,8 @@ static int sdebug_driver_probe(struct device * dev) | |||
| 5349 | hpnt->max_id = scsi_debug_num_tgts + 1; | 5339 | hpnt->max_id = scsi_debug_num_tgts + 1; |
| 5350 | else | 5340 | else |
| 5351 | hpnt->max_id = scsi_debug_num_tgts; | 5341 | hpnt->max_id = scsi_debug_num_tgts; |
| 5352 | hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */ | 5342 | /* = scsi_debug_max_luns; */ |
| 5343 | hpnt->max_lun = SCSI_W_LUN_REPORT_LUNS + 1; | ||
| 5353 | 5344 | ||
| 5354 | host_prot = 0; | 5345 | host_prot = 0; |
| 5355 | 5346 | ||
| @@ -5381,7 +5372,7 @@ static int sdebug_driver_probe(struct device * dev) | |||
| 5381 | 5372 | ||
| 5382 | scsi_host_set_prot(hpnt, host_prot); | 5373 | scsi_host_set_prot(hpnt, host_prot); |
| 5383 | 5374 | ||
| 5384 | printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n", | 5375 | pr_info("host protection%s%s%s%s%s%s%s\n", |
| 5385 | (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "", | 5376 | (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "", |
| 5386 | (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "", | 5377 | (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "", |
| 5387 | (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "", | 5378 | (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "", |
| @@ -5409,7 +5400,7 @@ static int sdebug_driver_probe(struct device * dev) | |||
| 5409 | 5400 | ||
| 5410 | error = scsi_add_host(hpnt, &sdbg_host->dev); | 5401 | error = scsi_add_host(hpnt, &sdbg_host->dev); |
| 5411 | if (error) { | 5402 | if (error) { |
| 5412 | printk(KERN_ERR "%s: scsi_add_host failed\n", __func__); | 5403 | pr_err("scsi_add_host failed\n"); |
| 5413 | error = -ENODEV; | 5404 | error = -ENODEV; |
| 5414 | scsi_host_put(hpnt); | 5405 | scsi_host_put(hpnt); |
| 5415 | } else | 5406 | } else |
| @@ -5426,8 +5417,7 @@ static int sdebug_driver_remove(struct device * dev) | |||
| 5426 | sdbg_host = to_sdebug_host(dev); | 5417 | sdbg_host = to_sdebug_host(dev); |
| 5427 | 5418 | ||
| 5428 | if (!sdbg_host) { | 5419 | if (!sdbg_host) { |
| 5429 | printk(KERN_ERR "%s: Unable to locate host info\n", | 5420 | pr_err("Unable to locate host info\n"); |
| 5430 | __func__); | ||
| 5431 | return -ENODEV; | 5421 | return -ENODEV; |
| 5432 | } | 5422 | } |
| 5433 | 5423 | ||
diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c new file mode 100644 index 000000000000..edb044a7b56d --- /dev/null +++ b/drivers/scsi/scsi_dh.c | |||
| @@ -0,0 +1,437 @@ | |||
| 1 | /* | ||
| 2 | * SCSI device handler infrastruture. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify it | ||
| 5 | * under the terms of the GNU General Public License as published by the | ||
| 6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 7 | * option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, but | ||
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License along | ||
| 15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 16 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 17 | * | ||
| 18 | * Copyright IBM Corporation, 2007 | ||
| 19 | * Authors: | ||
| 20 | * Chandra Seetharaman <sekharan@us.ibm.com> | ||
| 21 | * Mike Anderson <andmike@linux.vnet.ibm.com> | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <scsi/scsi_dh.h> | ||
| 27 | #include "scsi_priv.h" | ||
| 28 | |||
| 29 | static DEFINE_SPINLOCK(list_lock); | ||
| 30 | static LIST_HEAD(scsi_dh_list); | ||
| 31 | |||
| 32 | struct scsi_dh_blist { | ||
| 33 | const char *vendor; | ||
| 34 | const char *model; | ||
| 35 | const char *driver; | ||
| 36 | }; | ||
| 37 | |||
| 38 | static const struct scsi_dh_blist scsi_dh_blist[] = { | ||
| 39 | {"DGC", "RAID", "clariion" }, | ||
| 40 | {"DGC", "DISK", "clariion" }, | ||
| 41 | {"DGC", "VRAID", "clariion" }, | ||
| 42 | |||
| 43 | {"COMPAQ", "MSA1000 VOLUME", "hp_sw" }, | ||
| 44 | {"COMPAQ", "HSV110", "hp_sw" }, | ||
| 45 | {"HP", "HSV100", "hp_sw"}, | ||
| 46 | {"DEC", "HSG80", "hp_sw"}, | ||
| 47 | |||
| 48 | {"IBM", "1722", "rdac", }, | ||
| 49 | {"IBM", "1724", "rdac", }, | ||
| 50 | {"IBM", "1726", "rdac", }, | ||
| 51 | {"IBM", "1742", "rdac", }, | ||
| 52 | {"IBM", "1745", "rdac", }, | ||
| 53 | {"IBM", "1746", "rdac", }, | ||
| 54 | {"IBM", "1813", "rdac", }, | ||
| 55 | {"IBM", "1814", "rdac", }, | ||
| 56 | {"IBM", "1815", "rdac", }, | ||
| 57 | {"IBM", "1818", "rdac", }, | ||
| 58 | {"IBM", "3526", "rdac", }, | ||
| 59 | {"SGI", "TP9", "rdac", }, | ||
| 60 | {"SGI", "IS", "rdac", }, | ||
| 61 | {"STK", "OPENstorage D280", "rdac", }, | ||
| 62 | {"STK", "FLEXLINE 380", "rdac", }, | ||
| 63 | {"SUN", "CSM", "rdac", }, | ||
| 64 | {"SUN", "LCSM100", "rdac", }, | ||
| 65 | {"SUN", "STK6580_6780", "rdac", }, | ||
| 66 | {"SUN", "SUN_6180", "rdac", }, | ||
| 67 | {"SUN", "ArrayStorage", "rdac", }, | ||
| 68 | {"DELL", "MD3", "rdac", }, | ||
| 69 | {"NETAPP", "INF-01-00", "rdac", }, | ||
| 70 | {"LSI", "INF-01-00", "rdac", }, | ||
| 71 | {"ENGENIO", "INF-01-00", "rdac", }, | ||
| 72 | {NULL, NULL, NULL }, | ||
| 73 | }; | ||
| 74 | |||
| 75 | static const char * | ||
| 76 | scsi_dh_find_driver(struct scsi_device *sdev) | ||
| 77 | { | ||
| 78 | const struct scsi_dh_blist *b; | ||
| 79 | |||
| 80 | if (scsi_device_tpgs(sdev)) | ||
| 81 | return "alua"; | ||
| 82 | |||
| 83 | for (b = scsi_dh_blist; b->vendor; b++) { | ||
| 84 | if (!strncmp(sdev->vendor, b->vendor, strlen(b->vendor)) && | ||
| 85 | !strncmp(sdev->model, b->model, strlen(b->model))) { | ||
| 86 | return b->driver; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | return NULL; | ||
| 90 | } | ||
| 91 | |||
| 92 | |||
| 93 | static struct scsi_device_handler *__scsi_dh_lookup(const char *name) | ||
| 94 | { | ||
| 95 | struct scsi_device_handler *tmp, *found = NULL; | ||
| 96 | |||
| 97 | spin_lock(&list_lock); | ||
| 98 | list_for_each_entry(tmp, &scsi_dh_list, list) { | ||
| 99 | if (!strncmp(tmp->name, name, strlen(tmp->name))) { | ||
| 100 | found = tmp; | ||
| 101 | break; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | spin_unlock(&list_lock); | ||
| 105 | return found; | ||
| 106 | } | ||
| 107 | |||
| 108 | static struct scsi_device_handler *scsi_dh_lookup(const char *name) | ||
| 109 | { | ||
| 110 | struct scsi_device_handler *dh; | ||
| 111 | |||
| 112 | dh = __scsi_dh_lookup(name); | ||
| 113 | if (!dh) { | ||
| 114 | request_module(name); | ||
| 115 | dh = __scsi_dh_lookup(name); | ||
| 116 | } | ||
| 117 | |||
| 118 | return dh; | ||
| 119 | } | ||
| 120 | |||
| 121 | /* | ||
| 122 | * scsi_dh_handler_attach - Attach a device handler to a device | ||
| 123 | * @sdev - SCSI device the device handler should attach to | ||
| 124 | * @scsi_dh - The device handler to attach | ||
| 125 | */ | ||
| 126 | static int scsi_dh_handler_attach(struct scsi_device *sdev, | ||
| 127 | struct scsi_device_handler *scsi_dh) | ||
| 128 | { | ||
| 129 | int error; | ||
| 130 | |||
| 131 | if (!try_module_get(scsi_dh->module)) | ||
| 132 | return -EINVAL; | ||
| 133 | |||
| 134 | error = scsi_dh->attach(sdev); | ||
| 135 | if (error) { | ||
| 136 | sdev_printk(KERN_ERR, sdev, "%s: Attach failed (%d)\n", | ||
| 137 | scsi_dh->name, error); | ||
| 138 | module_put(scsi_dh->module); | ||
| 139 | } else | ||
| 140 | sdev->handler = scsi_dh; | ||
| 141 | |||
| 142 | return error; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* | ||
| 146 | * scsi_dh_handler_detach - Detach a device handler from a device | ||
| 147 | * @sdev - SCSI device the device handler should be detached from | ||
| 148 | */ | ||
| 149 | static void scsi_dh_handler_detach(struct scsi_device *sdev) | ||
| 150 | { | ||
| 151 | sdev->handler->detach(sdev); | ||
| 152 | sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", sdev->handler->name); | ||
| 153 | module_put(sdev->handler->module); | ||
| 154 | } | ||
| 155 | |||
| 156 | /* | ||
| 157 | * Functions for sysfs attribute 'dh_state' | ||
| 158 | */ | ||
| 159 | static ssize_t | ||
| 160 | store_dh_state(struct device *dev, struct device_attribute *attr, | ||
| 161 | const char *buf, size_t count) | ||
| 162 | { | ||
| 163 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 164 | struct scsi_device_handler *scsi_dh; | ||
| 165 | int err = -EINVAL; | ||
| 166 | |||
| 167 | if (sdev->sdev_state == SDEV_CANCEL || | ||
| 168 | sdev->sdev_state == SDEV_DEL) | ||
| 169 | return -ENODEV; | ||
| 170 | |||
| 171 | if (!sdev->handler) { | ||
| 172 | /* | ||
| 173 | * Attach to a device handler | ||
| 174 | */ | ||
| 175 | scsi_dh = scsi_dh_lookup(buf); | ||
| 176 | if (!scsi_dh) | ||
| 177 | return err; | ||
| 178 | err = scsi_dh_handler_attach(sdev, scsi_dh); | ||
| 179 | } else { | ||
| 180 | if (!strncmp(buf, "detach", 6)) { | ||
| 181 | /* | ||
| 182 | * Detach from a device handler | ||
| 183 | */ | ||
| 184 | sdev_printk(KERN_WARNING, sdev, | ||
| 185 | "can't detach handler %s.\n", | ||
| 186 | sdev->handler->name); | ||
| 187 | err = -EINVAL; | ||
| 188 | } else if (!strncmp(buf, "activate", 8)) { | ||
| 189 | /* | ||
| 190 | * Activate a device handler | ||
| 191 | */ | ||
| 192 | if (sdev->handler->activate) | ||
| 193 | err = sdev->handler->activate(sdev, NULL, NULL); | ||
| 194 | else | ||
| 195 | err = 0; | ||
| 196 | } | ||
| 197 | } | ||
| 198 | |||
| 199 | return err<0?err:count; | ||
| 200 | } | ||
| 201 | |||
| 202 | static ssize_t | ||
| 203 | show_dh_state(struct device *dev, struct device_attribute *attr, char *buf) | ||
| 204 | { | ||
| 205 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 206 | |||
| 207 | if (!sdev->handler) | ||
| 208 | return snprintf(buf, 20, "detached\n"); | ||
| 209 | |||
| 210 | return snprintf(buf, 20, "%s\n", sdev->handler->name); | ||
| 211 | } | ||
| 212 | |||
| 213 | static struct device_attribute scsi_dh_state_attr = | ||
| 214 | __ATTR(dh_state, S_IRUGO | S_IWUSR, show_dh_state, | ||
| 215 | store_dh_state); | ||
| 216 | |||
| 217 | int scsi_dh_add_device(struct scsi_device *sdev) | ||
| 218 | { | ||
| 219 | struct scsi_device_handler *devinfo = NULL; | ||
| 220 | const char *drv; | ||
| 221 | int err; | ||
| 222 | |||
| 223 | err = device_create_file(&sdev->sdev_gendev, &scsi_dh_state_attr); | ||
| 224 | if (err) | ||
| 225 | return err; | ||
| 226 | |||
| 227 | drv = scsi_dh_find_driver(sdev); | ||
| 228 | if (drv) | ||
| 229 | devinfo = scsi_dh_lookup(drv); | ||
| 230 | if (devinfo) | ||
| 231 | err = scsi_dh_handler_attach(sdev, devinfo); | ||
| 232 | return err; | ||
| 233 | } | ||
| 234 | |||
| 235 | void scsi_dh_remove_device(struct scsi_device *sdev) | ||
| 236 | { | ||
| 237 | if (sdev->handler) | ||
| 238 | scsi_dh_handler_detach(sdev); | ||
| 239 | device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr); | ||
| 240 | } | ||
| 241 | |||
| 242 | /* | ||
| 243 | * scsi_register_device_handler - register a device handler personality | ||
| 244 | * module. | ||
| 245 | * @scsi_dh - device handler to be registered. | ||
| 246 | * | ||
| 247 | * Returns 0 on success, -EBUSY if handler already registered. | ||
| 248 | */ | ||
| 249 | int scsi_register_device_handler(struct scsi_device_handler *scsi_dh) | ||
| 250 | { | ||
| 251 | if (__scsi_dh_lookup(scsi_dh->name)) | ||
| 252 | return -EBUSY; | ||
| 253 | |||
| 254 | if (!scsi_dh->attach || !scsi_dh->detach) | ||
| 255 | return -EINVAL; | ||
| 256 | |||
| 257 | spin_lock(&list_lock); | ||
| 258 | list_add(&scsi_dh->list, &scsi_dh_list); | ||
| 259 | spin_unlock(&list_lock); | ||
| 260 | |||
| 261 | printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name); | ||
| 262 | |||
| 263 | return SCSI_DH_OK; | ||
| 264 | } | ||
| 265 | EXPORT_SYMBOL_GPL(scsi_register_device_handler); | ||
| 266 | |||
| 267 | /* | ||
| 268 | * scsi_unregister_device_handler - register a device handler personality | ||
| 269 | * module. | ||
| 270 | * @scsi_dh - device handler to be unregistered. | ||
| 271 | * | ||
| 272 | * Returns 0 on success, -ENODEV if handler not registered. | ||
| 273 | */ | ||
| 274 | int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh) | ||
| 275 | { | ||
| 276 | if (!__scsi_dh_lookup(scsi_dh->name)) | ||
| 277 | return -ENODEV; | ||
| 278 | |||
| 279 | spin_lock(&list_lock); | ||
| 280 | list_del(&scsi_dh->list); | ||
| 281 | spin_unlock(&list_lock); | ||
| 282 | printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name); | ||
| 283 | |||
| 284 | return SCSI_DH_OK; | ||
| 285 | } | ||
| 286 | EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); | ||
| 287 | |||
| 288 | static struct scsi_device *get_sdev_from_queue(struct request_queue *q) | ||
| 289 | { | ||
| 290 | struct scsi_device *sdev; | ||
| 291 | unsigned long flags; | ||
| 292 | |||
| 293 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 294 | sdev = q->queuedata; | ||
| 295 | if (!sdev || !get_device(&sdev->sdev_gendev)) | ||
| 296 | sdev = NULL; | ||
| 297 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 298 | |||
| 299 | return sdev; | ||
| 300 | } | ||
| 301 | |||
| 302 | /* | ||
| 303 | * scsi_dh_activate - activate the path associated with the scsi_device | ||
| 304 | * corresponding to the given request queue. | ||
| 305 | * Returns immediately without waiting for activation to be completed. | ||
| 306 | * @q - Request queue that is associated with the scsi_device to be | ||
| 307 | * activated. | ||
| 308 | * @fn - Function to be called upon completion of the activation. | ||
| 309 | * Function fn is called with data (below) and the error code. | ||
| 310 | * Function fn may be called from the same calling context. So, | ||
| 311 | * do not hold the lock in the caller which may be needed in fn. | ||
| 312 | * @data - data passed to the function fn upon completion. | ||
| 313 | * | ||
| 314 | */ | ||
| 315 | int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data) | ||
| 316 | { | ||
| 317 | struct scsi_device *sdev; | ||
| 318 | int err = SCSI_DH_NOSYS; | ||
| 319 | |||
| 320 | sdev = get_sdev_from_queue(q); | ||
| 321 | if (!sdev) { | ||
| 322 | if (fn) | ||
| 323 | fn(data, err); | ||
| 324 | return err; | ||
| 325 | } | ||
| 326 | |||
| 327 | if (!sdev->handler) | ||
| 328 | goto out_fn; | ||
| 329 | err = SCSI_DH_NOTCONN; | ||
| 330 | if (sdev->sdev_state == SDEV_CANCEL || | ||
| 331 | sdev->sdev_state == SDEV_DEL) | ||
| 332 | goto out_fn; | ||
| 333 | |||
| 334 | err = SCSI_DH_DEV_OFFLINED; | ||
| 335 | if (sdev->sdev_state == SDEV_OFFLINE) | ||
| 336 | goto out_fn; | ||
| 337 | |||
| 338 | if (sdev->handler->activate) | ||
| 339 | err = sdev->handler->activate(sdev, fn, data); | ||
| 340 | |||
| 341 | out_put_device: | ||
| 342 | put_device(&sdev->sdev_gendev); | ||
| 343 | return err; | ||
| 344 | |||
| 345 | out_fn: | ||
| 346 | if (fn) | ||
| 347 | fn(data, err); | ||
| 348 | goto out_put_device; | ||
| 349 | } | ||
| 350 | EXPORT_SYMBOL_GPL(scsi_dh_activate); | ||
| 351 | |||
| 352 | /* | ||
| 353 | * scsi_dh_set_params - set the parameters for the device as per the | ||
| 354 | * string specified in params. | ||
| 355 | * @q - Request queue that is associated with the scsi_device for | ||
| 356 | * which the parameters to be set. | ||
| 357 | * @params - parameters in the following format | ||
| 358 | * "no_of_params\0param1\0param2\0param3\0...\0" | ||
| 359 | * for example, string for 2 parameters with value 10 and 21 | ||
| 360 | * is specified as "2\010\021\0". | ||
| 361 | */ | ||
| 362 | int scsi_dh_set_params(struct request_queue *q, const char *params) | ||
| 363 | { | ||
| 364 | struct scsi_device *sdev; | ||
| 365 | int err = -SCSI_DH_NOSYS; | ||
| 366 | |||
| 367 | sdev = get_sdev_from_queue(q); | ||
| 368 | if (!sdev) | ||
| 369 | return err; | ||
| 370 | |||
| 371 | if (sdev->handler && sdev->handler->set_params) | ||
| 372 | err = sdev->handler->set_params(sdev, params); | ||
| 373 | put_device(&sdev->sdev_gendev); | ||
| 374 | return err; | ||
| 375 | } | ||
| 376 | EXPORT_SYMBOL_GPL(scsi_dh_set_params); | ||
| 377 | |||
| 378 | /* | ||
| 379 | * scsi_dh_attach - Attach device handler | ||
| 380 | * @q - Request queue that is associated with the scsi_device | ||
| 381 | * the handler should be attached to | ||
| 382 | * @name - name of the handler to attach | ||
| 383 | */ | ||
| 384 | int scsi_dh_attach(struct request_queue *q, const char *name) | ||
| 385 | { | ||
| 386 | struct scsi_device *sdev; | ||
| 387 | struct scsi_device_handler *scsi_dh; | ||
| 388 | int err = 0; | ||
| 389 | |||
| 390 | sdev = get_sdev_from_queue(q); | ||
| 391 | if (!sdev) | ||
| 392 | return -ENODEV; | ||
| 393 | |||
| 394 | scsi_dh = scsi_dh_lookup(name); | ||
| 395 | if (!scsi_dh) { | ||
| 396 | err = -EINVAL; | ||
| 397 | goto out_put_device; | ||
| 398 | } | ||
| 399 | |||
| 400 | if (sdev->handler) { | ||
| 401 | if (sdev->handler != scsi_dh) | ||
| 402 | err = -EBUSY; | ||
| 403 | goto out_put_device; | ||
| 404 | } | ||
| 405 | |||
| 406 | err = scsi_dh_handler_attach(sdev, scsi_dh); | ||
| 407 | |||
| 408 | out_put_device: | ||
| 409 | put_device(&sdev->sdev_gendev); | ||
| 410 | return err; | ||
| 411 | } | ||
| 412 | EXPORT_SYMBOL_GPL(scsi_dh_attach); | ||
| 413 | |||
| 414 | /* | ||
| 415 | * scsi_dh_attached_handler_name - Get attached device handler's name | ||
| 416 | * @q - Request queue that is associated with the scsi_device | ||
| 417 | * that may have a device handler attached | ||
| 418 | * @gfp - the GFP mask used in the kmalloc() call when allocating memory | ||
| 419 | * | ||
| 420 | * Returns name of attached handler, NULL if no handler is attached. | ||
| 421 | * Caller must take care to free the returned string. | ||
| 422 | */ | ||
| 423 | const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp) | ||
| 424 | { | ||
| 425 | struct scsi_device *sdev; | ||
| 426 | const char *handler_name = NULL; | ||
| 427 | |||
| 428 | sdev = get_sdev_from_queue(q); | ||
| 429 | if (!sdev) | ||
| 430 | return NULL; | ||
| 431 | |||
| 432 | if (sdev->handler) | ||
| 433 | handler_name = kstrdup(sdev->handler->name, gfp); | ||
| 434 | put_device(&sdev->sdev_gendev); | ||
| 435 | return handler_name; | ||
| 436 | } | ||
| 437 | EXPORT_SYMBOL_GPL(scsi_dh_attached_handler_name); | ||
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index afd34a608fe7..66a96cd98b97 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
| @@ -33,9 +33,11 @@ | |||
| 33 | #include <scsi/scsi_device.h> | 33 | #include <scsi/scsi_device.h> |
| 34 | #include <scsi/scsi_driver.h> | 34 | #include <scsi/scsi_driver.h> |
| 35 | #include <scsi/scsi_eh.h> | 35 | #include <scsi/scsi_eh.h> |
| 36 | #include <scsi/scsi_common.h> | ||
| 36 | #include <scsi/scsi_transport.h> | 37 | #include <scsi/scsi_transport.h> |
| 37 | #include <scsi/scsi_host.h> | 38 | #include <scsi/scsi_host.h> |
| 38 | #include <scsi/scsi_ioctl.h> | 39 | #include <scsi/scsi_ioctl.h> |
| 40 | #include <scsi/scsi_dh.h> | ||
| 39 | #include <scsi/sg.h> | 41 | #include <scsi/sg.h> |
| 40 | 42 | ||
| 41 | #include "scsi_priv.h" | 43 | #include "scsi_priv.h" |
| @@ -463,11 +465,10 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) | |||
| 463 | if (scsi_sense_is_deferred(&sshdr)) | 465 | if (scsi_sense_is_deferred(&sshdr)) |
| 464 | return NEEDS_RETRY; | 466 | return NEEDS_RETRY; |
| 465 | 467 | ||
| 466 | if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh && | 468 | if (sdev->handler && sdev->handler->check_sense) { |
| 467 | sdev->scsi_dh_data->scsi_dh->check_sense) { | ||
| 468 | int rc; | 469 | int rc; |
| 469 | 470 | ||
| 470 | rc = sdev->scsi_dh_data->scsi_dh->check_sense(sdev, &sshdr); | 471 | rc = sdev->handler->check_sense(sdev, &sshdr); |
| 471 | if (rc != SCSI_RETURN_NOT_HANDLED) | 472 | if (rc != SCSI_RETURN_NOT_HANDLED) |
| 472 | return rc; | 473 | return rc; |
| 473 | /* handler does not care. Drop down to default handling */ | 474 | /* handler does not care. Drop down to default handling */ |
| @@ -2178,8 +2179,17 @@ int scsi_error_handler(void *data) | |||
| 2178 | * We never actually get interrupted because kthread_run | 2179 | * We never actually get interrupted because kthread_run |
| 2179 | * disables signal delivery for the created thread. | 2180 | * disables signal delivery for the created thread. |
| 2180 | */ | 2181 | */ |
| 2181 | while (!kthread_should_stop()) { | 2182 | while (true) { |
| 2183 | /* | ||
| 2184 | * The sequence in kthread_stop() sets the stop flag first | ||
| 2185 | * then wakes the process. To avoid missed wakeups, the task | ||
| 2186 | * should always be in a non running state before the stop | ||
| 2187 | * flag is checked | ||
| 2188 | */ | ||
| 2182 | set_current_state(TASK_INTERRUPTIBLE); | 2189 | set_current_state(TASK_INTERRUPTIBLE); |
| 2190 | if (kthread_should_stop()) | ||
| 2191 | break; | ||
| 2192 | |||
| 2183 | if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || | 2193 | if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || |
| 2184 | shost->host_failed != atomic_read(&shost->host_busy)) { | 2194 | shost->host_failed != atomic_read(&shost->host_busy)) { |
| 2185 | SCSI_LOG_ERROR_RECOVERY(1, | 2195 | SCSI_LOG_ERROR_RECOVERY(1, |
| @@ -2416,45 +2426,6 @@ bool scsi_command_normalize_sense(const struct scsi_cmnd *cmd, | |||
| 2416 | EXPORT_SYMBOL(scsi_command_normalize_sense); | 2426 | EXPORT_SYMBOL(scsi_command_normalize_sense); |
| 2417 | 2427 | ||
| 2418 | /** | 2428 | /** |
| 2419 | * scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format. | ||
| 2420 | * @sense_buffer: byte array of descriptor format sense data | ||
| 2421 | * @sb_len: number of valid bytes in sense_buffer | ||
| 2422 | * @desc_type: value of descriptor type to find | ||
| 2423 | * (e.g. 0 -> information) | ||
| 2424 | * | ||
| 2425 | * Notes: | ||
| 2426 | * only valid when sense data is in descriptor format | ||
| 2427 | * | ||
| 2428 | * Return value: | ||
| 2429 | * pointer to start of (first) descriptor if found else NULL | ||
| 2430 | */ | ||
| 2431 | const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len, | ||
| 2432 | int desc_type) | ||
| 2433 | { | ||
| 2434 | int add_sen_len, add_len, desc_len, k; | ||
| 2435 | const u8 * descp; | ||
| 2436 | |||
| 2437 | if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7]))) | ||
| 2438 | return NULL; | ||
| 2439 | if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73)) | ||
| 2440 | return NULL; | ||
| 2441 | add_sen_len = (add_sen_len < (sb_len - 8)) ? | ||
| 2442 | add_sen_len : (sb_len - 8); | ||
| 2443 | descp = &sense_buffer[8]; | ||
| 2444 | for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) { | ||
| 2445 | descp += desc_len; | ||
| 2446 | add_len = (k < (add_sen_len - 1)) ? descp[1]: -1; | ||
| 2447 | desc_len = add_len + 2; | ||
| 2448 | if (descp[0] == desc_type) | ||
| 2449 | return descp; | ||
| 2450 | if (add_len < 0) // short descriptor ?? | ||
| 2451 | break; | ||
| 2452 | } | ||
| 2453 | return NULL; | ||
| 2454 | } | ||
| 2455 | EXPORT_SYMBOL(scsi_sense_desc_find); | ||
| 2456 | |||
| 2457 | /** | ||
| 2458 | * scsi_get_sense_info_fld - get information field from sense data (either fixed or descriptor format) | 2429 | * scsi_get_sense_info_fld - get information field from sense data (either fixed or descriptor format) |
| 2459 | * @sense_buffer: byte array of sense data | 2430 | * @sense_buffer: byte array of sense data |
| 2460 | * @sb_len: number of valid bytes in sense_buffer | 2431 | * @sb_len: number of valid bytes in sense_buffer |
| @@ -2503,31 +2474,3 @@ int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len, | |||
| 2503 | } | 2474 | } |
| 2504 | } | 2475 | } |
| 2505 | EXPORT_SYMBOL(scsi_get_sense_info_fld); | 2476 | EXPORT_SYMBOL(scsi_get_sense_info_fld); |
| 2506 | |||
| 2507 | /** | ||
| 2508 | * scsi_build_sense_buffer - build sense data in a buffer | ||
| 2509 | * @desc: Sense format (non zero == descriptor format, | ||
| 2510 | * 0 == fixed format) | ||
| 2511 | * @buf: Where to build sense data | ||
| 2512 | * @key: Sense key | ||
| 2513 | * @asc: Additional sense code | ||
| 2514 | * @ascq: Additional sense code qualifier | ||
| 2515 | * | ||
| 2516 | **/ | ||
| 2517 | void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq) | ||
| 2518 | { | ||
| 2519 | if (desc) { | ||
| 2520 | buf[0] = 0x72; /* descriptor, current */ | ||
| 2521 | buf[1] = key; | ||
| 2522 | buf[2] = asc; | ||
| 2523 | buf[3] = ascq; | ||
| 2524 | buf[7] = 0; | ||
| 2525 | } else { | ||
| 2526 | buf[0] = 0x70; /* fixed, current */ | ||
| 2527 | buf[2] = key; | ||
| 2528 | buf[7] = 0xa; | ||
| 2529 | buf[12] = asc; | ||
| 2530 | buf[13] = ascq; | ||
| 2531 | } | ||
| 2532 | } | ||
| 2533 | EXPORT_SYMBOL(scsi_build_sense_buffer); | ||
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 882864f5cbae..cbfc5990052b 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <scsi/scsi_driver.h> | 31 | #include <scsi/scsi_driver.h> |
| 32 | #include <scsi/scsi_eh.h> | 32 | #include <scsi/scsi_eh.h> |
| 33 | #include <scsi/scsi_host.h> | 33 | #include <scsi/scsi_host.h> |
| 34 | #include <scsi/scsi_dh.h> | ||
| 34 | 35 | ||
| 35 | #include <trace/events/scsi.h> | 36 | #include <trace/events/scsi.h> |
| 36 | 37 | ||
| @@ -1248,9 +1249,8 @@ static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) | |||
| 1248 | { | 1249 | { |
| 1249 | struct scsi_cmnd *cmd = req->special; | 1250 | struct scsi_cmnd *cmd = req->special; |
| 1250 | 1251 | ||
| 1251 | if (unlikely(sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh | 1252 | if (unlikely(sdev->handler && sdev->handler->prep_fn)) { |
| 1252 | && sdev->scsi_dh_data->scsi_dh->prep_fn)) { | 1253 | int ret = sdev->handler->prep_fn(sdev, req); |
| 1253 | int ret = sdev->scsi_dh_data->scsi_dh->prep_fn(sdev, req); | ||
| 1254 | if (ret != BLKPREP_OK) | 1254 | if (ret != BLKPREP_OK) |
| 1255 | return ret; | 1255 | return ret; |
| 1256 | } | 1256 | } |
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index e3902fc66278..644bb7339b55 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
| @@ -170,6 +170,15 @@ static inline void scsi_autopm_put_host(struct Scsi_Host *h) {} | |||
| 170 | extern struct async_domain scsi_sd_pm_domain; | 170 | extern struct async_domain scsi_sd_pm_domain; |
| 171 | extern struct async_domain scsi_sd_probe_domain; | 171 | extern struct async_domain scsi_sd_probe_domain; |
| 172 | 172 | ||
| 173 | /* scsi_dh.c */ | ||
| 174 | #ifdef CONFIG_SCSI_DH | ||
| 175 | int scsi_dh_add_device(struct scsi_device *sdev); | ||
| 176 | void scsi_dh_remove_device(struct scsi_device *sdev); | ||
| 177 | #else | ||
| 178 | static inline int scsi_dh_add_device(struct scsi_device *sdev) { return 0; } | ||
| 179 | static inline void scsi_dh_remove_device(struct scsi_device *sdev) { } | ||
| 180 | #endif | ||
| 181 | |||
| 173 | /* | 182 | /* |
| 174 | * internal scsi timeout functions: for use by mid-layer and transport | 183 | * internal scsi timeout functions: for use by mid-layer and transport |
| 175 | * classes. | 184 | * classes. |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 9ad41168d26d..b333389f248f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
| @@ -1030,11 +1030,20 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) | |||
| 1030 | "failed to add device: %d\n", error); | 1030 | "failed to add device: %d\n", error); |
| 1031 | return error; | 1031 | return error; |
| 1032 | } | 1032 | } |
| 1033 | |||
| 1034 | error = scsi_dh_add_device(sdev); | ||
| 1035 | if (error) { | ||
| 1036 | sdev_printk(KERN_INFO, sdev, | ||
| 1037 | "failed to add device handler: %d\n", error); | ||
| 1038 | return error; | ||
| 1039 | } | ||
| 1040 | |||
| 1033 | device_enable_async_suspend(&sdev->sdev_dev); | 1041 | device_enable_async_suspend(&sdev->sdev_dev); |
| 1034 | error = device_add(&sdev->sdev_dev); | 1042 | error = device_add(&sdev->sdev_dev); |
| 1035 | if (error) { | 1043 | if (error) { |
| 1036 | sdev_printk(KERN_INFO, sdev, | 1044 | sdev_printk(KERN_INFO, sdev, |
| 1037 | "failed to add class device: %d\n", error); | 1045 | "failed to add class device: %d\n", error); |
| 1046 | scsi_dh_remove_device(sdev); | ||
| 1038 | device_del(&sdev->sdev_gendev); | 1047 | device_del(&sdev->sdev_gendev); |
| 1039 | return error; | 1048 | return error; |
| 1040 | } | 1049 | } |
| @@ -1074,6 +1083,7 @@ void __scsi_remove_device(struct scsi_device *sdev) | |||
| 1074 | bsg_unregister_queue(sdev->request_queue); | 1083 | bsg_unregister_queue(sdev->request_queue); |
| 1075 | device_unregister(&sdev->sdev_dev); | 1084 | device_unregister(&sdev->sdev_dev); |
| 1076 | transport_remove_device(dev); | 1085 | transport_remove_device(dev); |
| 1086 | scsi_dh_remove_device(sdev); | ||
| 1077 | device_del(dev); | 1087 | device_del(dev); |
| 1078 | } else | 1088 | } else |
| 1079 | put_device(&sdev->sdev_dev); | 1089 | put_device(&sdev->sdev_dev); |
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 9a058194b9bd..30d26e345dcc 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c | |||
| @@ -1222,13 +1222,6 @@ show_sas_rphy_enclosure_identifier(struct device *dev, | |||
| 1222 | u64 identifier; | 1222 | u64 identifier; |
| 1223 | int error; | 1223 | int error; |
| 1224 | 1224 | ||
| 1225 | /* | ||
| 1226 | * Only devices behind an expander are supported, because the | ||
| 1227 | * enclosure identifier is a SMP feature. | ||
| 1228 | */ | ||
| 1229 | if (scsi_is_sas_phy_local(phy)) | ||
| 1230 | return -EINVAL; | ||
| 1231 | |||
| 1232 | error = i->f->get_enclosure_identifier(rphy, &identifier); | 1225 | error = i->f->get_enclosure_identifier(rphy, &identifier); |
| 1233 | if (error) | 1226 | if (error) |
| 1234 | return error; | 1227 | return error; |
| @@ -1248,9 +1241,6 @@ show_sas_rphy_bay_identifier(struct device *dev, | |||
| 1248 | struct sas_internal *i = to_sas_internal(shost->transportt); | 1241 | struct sas_internal *i = to_sas_internal(shost->transportt); |
| 1249 | int val; | 1242 | int val; |
| 1250 | 1243 | ||
| 1251 | if (scsi_is_sas_phy_local(phy)) | ||
| 1252 | return -EINVAL; | ||
| 1253 | |||
| 1254 | val = i->f->get_bay_identifier(rphy); | 1244 | val = i->f->get_bay_identifier(rphy); |
| 1255 | if (val < 0) | 1245 | if (val < 0) |
| 1256 | return val; | 1246 | return val; |
