blob: aa2078d7e23e28a4dc2673add8848afb2e9ab3b0 [file] [log] [blame]
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301/*
2 * Scsi Host Layer for MPT (Message Passing Technology) based controllers
3 *
4 * This code is based on drivers/scsi/mpt3sas/mpt3sas_scsih.c
Sreekanth Reddya4ffce02014-09-12 15:35:29 +05305 * Copyright (C) 2012-2014 LSI Corporation
Sreekanth Reddya03bd152015-01-12 11:39:02 +05306 * Copyright (C) 2013-2014 Avago Technologies
7 * (mailto: MPT-FusionLinux.pdl@avagotech.com)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * NO WARRANTY
20 * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
21 * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
22 * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
23 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
24 * solely responsible for determining the appropriateness of using and
25 * distributing the Program and assumes all risks associated with its
26 * exercise of rights under this Agreement, including but not limited to
27 * the risks and costs of program errors, damage to or loss of data,
28 * programs or equipment, and unavailability or interruption of operations.
29
30 * DISCLAIMER OF LIABILITY
31 * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
32 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
35 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
36 * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
37 * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
38
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
42 * USA.
43 */
44
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053045#include <linux/module.h>
46#include <linux/kernel.h>
47#include <linux/init.h>
48#include <linux/errno.h>
49#include <linux/blkdev.h>
50#include <linux/sched.h>
51#include <linux/workqueue.h>
52#include <linux/delay.h>
53#include <linux/pci.h>
ojabb5d5f282016-12-28 11:05:24 +000054#include <linux/pci-aspm.h>
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053055#include <linux/interrupt.h>
56#include <linux/aer.h>
57#include <linux/raid_class.h>
Sreekanth Reddy7786ab62015-11-11 17:30:28 +053058#include <asm/unaligned.h>
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053059
60#include "mpt3sas_base.h"
61
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053062#define RAID_CHANNEL 1
63/* forward proto's */
64static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
65 struct _sas_node *sas_expander);
66static void _firmware_event_work(struct work_struct *work);
67
68static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
69 struct _sas_device *sas_device);
70static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
71 u8 retry_count, u8 is_pd);
72
73static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
74
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053075/* global parameters */
76LIST_HEAD(mpt3sas_ioc_list);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +053077/* global ioc lock for list operations */
78DEFINE_SPINLOCK(gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053079
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +053080MODULE_AUTHOR(MPT3SAS_AUTHOR);
81MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION);
82MODULE_LICENSE("GPL");
83MODULE_VERSION(MPT3SAS_DRIVER_VERSION);
84MODULE_ALIAS("mpt2sas");
85
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053086/* local parameters */
87static u8 scsi_io_cb_idx = -1;
88static u8 tm_cb_idx = -1;
89static u8 ctl_cb_idx = -1;
90static u8 base_cb_idx = -1;
91static u8 port_enable_cb_idx = -1;
92static u8 transport_cb_idx = -1;
93static u8 scsih_cb_idx = -1;
94static u8 config_cb_idx = -1;
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +053095static int mpt2_ids;
96static int mpt3_ids;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053097
98static u8 tm_tr_cb_idx = -1 ;
99static u8 tm_tr_volume_cb_idx = -1 ;
100static u8 tm_sas_control_cb_idx = -1;
101
102/* command line options */
103static u32 logging_level;
104MODULE_PARM_DESC(logging_level,
105 " bits for enabling additional logging info (default=0)");
106
107
108static ushort max_sectors = 0xFFFF;
109module_param(max_sectors, ushort, 0);
110MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767");
111
112
113static int missing_delay[2] = {-1, -1};
114module_param_array(missing_delay, int, NULL, 0);
115MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
116
117/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
118#define MPT3SAS_MAX_LUN (16895)
Hannes Reinecke1abf6352014-06-25 15:27:38 +0200119static u64 max_lun = MPT3SAS_MAX_LUN;
120module_param(max_lun, ullong, 0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530121MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
122
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530123static ushort hbas_to_enumerate;
124module_param(hbas_to_enumerate, ushort, 0);
125MODULE_PARM_DESC(hbas_to_enumerate,
126 " 0 - enumerates both SAS 2.0 & SAS 3.0 generation HBAs\n \
127 1 - enumerates only SAS 2.0 generation HBAs\n \
128 2 - enumerates only SAS 3.0 generation HBAs (default=0)");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530129
130/* diag_buffer_enable is bitwise
131 * bit 0 set = TRACE
132 * bit 1 set = SNAPSHOT
133 * bit 2 set = EXTENDED
134 *
135 * Either bit can be set, or both
136 */
137static int diag_buffer_enable = -1;
138module_param(diag_buffer_enable, int, 0);
139MODULE_PARM_DESC(diag_buffer_enable,
140 " post diag buffers (TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
141static int disable_discovery = -1;
142module_param(disable_discovery, int, 0);
143MODULE_PARM_DESC(disable_discovery, " disable discovery ");
144
145
146/* permit overriding the host protection capabilities mask (EEDP/T10 PI) */
147static int prot_mask = -1;
148module_param(prot_mask, int, 0);
149MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
150
151
152/* raid transport support */
Sreekanth Reddy7497392a2015-11-11 17:30:19 +0530153struct raid_template *mpt3sas_raid_template;
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530154struct raid_template *mpt2sas_raid_template;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530155
156
157/**
158 * struct sense_info - common structure for obtaining sense keys
159 * @skey: sense key
160 * @asc: additional sense code
161 * @ascq: additional sense code qualifier
162 */
163struct sense_info {
164 u8 skey;
165 u8 asc;
166 u8 ascq;
167};
168
169#define MPT3SAS_PROCESS_TRIGGER_DIAG (0xFFFB)
Sreekanth Reddy0f624c32014-09-12 15:35:26 +0530170#define MPT3SAS_TURN_ON_PFA_LED (0xFFFC)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530171#define MPT3SAS_PORT_ENABLE_COMPLETE (0xFFFD)
172#define MPT3SAS_ABRT_TASK_SET (0xFFFE)
173#define MPT3SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
174/**
175 * struct fw_event_work - firmware event struct
176 * @list: link list framework
177 * @work: work object (ioc->fault_reset_work_q)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530178 * @ioc: per adapter object
179 * @device_handle: device handle
180 * @VF_ID: virtual function id
181 * @VP_ID: virtual port id
182 * @ignore: flag meaning this event has been marked to ignore
Joe Lawrenceb8ac0cc2016-04-18 10:50:12 -0400183 * @event: firmware event MPI2_EVENT_XXX defined in mpi2_ioc.h
184 * @refcount: kref for this event
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530185 * @event_data: reply event data payload follows
186 *
187 * This object stored on ioc->fw_event_list.
188 */
189struct fw_event_work {
190 struct list_head list;
191 struct work_struct work;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530192
193 struct MPT3SAS_ADAPTER *ioc;
194 u16 device_handle;
195 u8 VF_ID;
196 u8 VP_ID;
197 u8 ignore;
198 u16 event;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +0530199 struct kref refcount;
Joe Lawrence35b62362014-06-25 17:05:34 -0400200 char event_data[0] __aligned(4);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530201};
202
Sreekanth Reddy146b16c2015-11-11 17:30:31 +0530203static void fw_event_work_free(struct kref *r)
204{
205 kfree(container_of(r, struct fw_event_work, refcount));
206}
207
208static void fw_event_work_get(struct fw_event_work *fw_work)
209{
210 kref_get(&fw_work->refcount);
211}
212
213static void fw_event_work_put(struct fw_event_work *fw_work)
214{
215 kref_put(&fw_work->refcount, fw_event_work_free);
216}
217
218static struct fw_event_work *alloc_fw_event_work(int len)
219{
220 struct fw_event_work *fw_event;
221
222 fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC);
223 if (!fw_event)
224 return NULL;
225
226 kref_init(&fw_event->refcount);
227 return fw_event;
228}
229
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530230/**
231 * struct _scsi_io_transfer - scsi io transfer
232 * @handle: sas device handle (assigned by firmware)
233 * @is_raid: flag set for hidden raid components
234 * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE,
235 * @data_length: data transfer length
236 * @data_dma: dma pointer to data
237 * @sense: sense data
238 * @lun: lun number
239 * @cdb_length: cdb length
240 * @cdb: cdb contents
241 * @timeout: timeout for this command
242 * @VF_ID: virtual function id
243 * @VP_ID: virtual port id
244 * @valid_reply: flag set for reply message
245 * @sense_length: sense length
246 * @ioc_status: ioc status
247 * @scsi_state: scsi state
248 * @scsi_status: scsi staus
249 * @log_info: log information
250 * @transfer_length: data length transfer when there is a reply message
251 *
252 * Used for sending internal scsi commands to devices within this module.
253 * Refer to _scsi_send_scsi_io().
254 */
255struct _scsi_io_transfer {
256 u16 handle;
257 u8 is_raid;
258 enum dma_data_direction dir;
259 u32 data_length;
260 dma_addr_t data_dma;
261 u8 sense[SCSI_SENSE_BUFFERSIZE];
262 u32 lun;
263 u8 cdb_length;
264 u8 cdb[32];
265 u8 timeout;
266 u8 VF_ID;
267 u8 VP_ID;
268 u8 valid_reply;
269 /* the following bits are only valid when 'valid_reply = 1' */
270 u32 sense_length;
271 u16 ioc_status;
272 u8 scsi_state;
273 u8 scsi_status;
274 u32 log_info;
275 u32 transfer_length;
276};
277
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530278/**
279 * _scsih_set_debug_level - global setting of ioc->logging_level.
280 *
281 * Note: The logging levels are defined in mpt3sas_debug.h.
282 */
283static int
284_scsih_set_debug_level(const char *val, struct kernel_param *kp)
285{
286 int ret = param_set_int(val, kp);
287 struct MPT3SAS_ADAPTER *ioc;
288
289 if (ret)
290 return ret;
291
292 pr_info("setting logging_level(0x%08x)\n", logging_level);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +0530293 spin_lock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530294 list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
295 ioc->logging_level = logging_level;
Sreekanth Reddy08c4d552015-11-11 17:30:33 +0530296 spin_unlock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530297 return 0;
298}
299module_param_call(logging_level, _scsih_set_debug_level, param_get_int,
300 &logging_level, 0644);
301
302/**
303 * _scsih_srch_boot_sas_address - search based on sas_address
304 * @sas_address: sas address
305 * @boot_device: boot device object from bios page 2
306 *
307 * Returns 1 when there's a match, 0 means no match.
308 */
309static inline int
310_scsih_srch_boot_sas_address(u64 sas_address,
311 Mpi2BootDeviceSasWwid_t *boot_device)
312{
313 return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0;
314}
315
316/**
317 * _scsih_srch_boot_device_name - search based on device name
318 * @device_name: device name specified in INDENTIFY fram
319 * @boot_device: boot device object from bios page 2
320 *
321 * Returns 1 when there's a match, 0 means no match.
322 */
323static inline int
324_scsih_srch_boot_device_name(u64 device_name,
325 Mpi2BootDeviceDeviceName_t *boot_device)
326{
327 return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0;
328}
329
330/**
331 * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot
332 * @enclosure_logical_id: enclosure logical id
333 * @slot_number: slot number
334 * @boot_device: boot device object from bios page 2
335 *
336 * Returns 1 when there's a match, 0 means no match.
337 */
338static inline int
339_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
340 Mpi2BootDeviceEnclosureSlot_t *boot_device)
341{
342 return (enclosure_logical_id == le64_to_cpu(boot_device->
343 EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device->
344 SlotNumber)) ? 1 : 0;
345}
346
347/**
348 * _scsih_is_boot_device - search for matching boot device.
349 * @sas_address: sas address
350 * @device_name: device name specified in INDENTIFY fram
351 * @enclosure_logical_id: enclosure logical id
352 * @slot_number: slot number
353 * @form: specifies boot device form
354 * @boot_device: boot device object from bios page 2
355 *
356 * Returns 1 when there's a match, 0 means no match.
357 */
358static int
359_scsih_is_boot_device(u64 sas_address, u64 device_name,
360 u64 enclosure_logical_id, u16 slot, u8 form,
361 Mpi2BiosPage2BootDevice_t *boot_device)
362{
363 int rc = 0;
364
365 switch (form) {
366 case MPI2_BIOSPAGE2_FORM_SAS_WWID:
367 if (!sas_address)
368 break;
369 rc = _scsih_srch_boot_sas_address(
370 sas_address, &boot_device->SasWwid);
371 break;
372 case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT:
373 if (!enclosure_logical_id)
374 break;
375 rc = _scsih_srch_boot_encl_slot(
376 enclosure_logical_id,
377 slot, &boot_device->EnclosureSlot);
378 break;
379 case MPI2_BIOSPAGE2_FORM_DEVICE_NAME:
380 if (!device_name)
381 break;
382 rc = _scsih_srch_boot_device_name(
383 device_name, &boot_device->DeviceName);
384 break;
385 case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED:
386 break;
387 }
388
389 return rc;
390}
391
392/**
393 * _scsih_get_sas_address - set the sas_address for given device handle
394 * @handle: device handle
395 * @sas_address: sas address
396 *
397 * Returns 0 success, non-zero when failure
398 */
399static int
400_scsih_get_sas_address(struct MPT3SAS_ADAPTER *ioc, u16 handle,
401 u64 *sas_address)
402{
403 Mpi2SasDevicePage0_t sas_device_pg0;
404 Mpi2ConfigReply_t mpi_reply;
405 u32 ioc_status;
406
407 *sas_address = 0;
408
409 if (handle <= ioc->sas_hba.num_phys) {
410 *sas_address = ioc->sas_hba.sas_address;
411 return 0;
412 }
413
414 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
415 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
416 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
417 __FILE__, __LINE__, __func__);
418 return -ENXIO;
419 }
420
421 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
422 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
423 *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
424 return 0;
425 }
426
427 /* we hit this becuase the given parent handle doesn't exist */
428 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
429 return -ENXIO;
430
431 /* else error case */
432 pr_err(MPT3SAS_FMT
433 "handle(0x%04x), ioc_status(0x%04x), failure at %s:%d/%s()!\n",
434 ioc->name, handle, ioc_status,
435 __FILE__, __LINE__, __func__);
436 return -EIO;
437}
438
439/**
440 * _scsih_determine_boot_device - determine boot device.
441 * @ioc: per adapter object
442 * @device: either sas_device or raid_device object
443 * @is_raid: [flag] 1 = raid object, 0 = sas object
444 *
445 * Determines whether this device should be first reported device to
446 * to scsi-ml or sas transport, this purpose is for persistent boot device.
447 * There are primary, alternate, and current entries in bios page 2. The order
448 * priority is primary, alternate, then current. This routine saves
449 * the corresponding device object and is_raid flag in the ioc object.
450 * The saved data to be used later in _scsih_probe_boot_devices().
451 */
452static void
453_scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc,
454 void *device, u8 is_raid)
455{
456 struct _sas_device *sas_device;
457 struct _raid_device *raid_device;
458 u64 sas_address;
459 u64 device_name;
460 u64 enclosure_logical_id;
461 u16 slot;
462
463 /* only process this function when driver loads */
464 if (!ioc->is_driver_loading)
465 return;
466
467 /* no Bios, return immediately */
468 if (!ioc->bios_pg3.BiosVersion)
469 return;
470
471 if (!is_raid) {
472 sas_device = device;
473 sas_address = sas_device->sas_address;
474 device_name = sas_device->device_name;
475 enclosure_logical_id = sas_device->enclosure_logical_id;
476 slot = sas_device->slot;
477 } else {
478 raid_device = device;
479 sas_address = raid_device->wwid;
480 device_name = 0;
481 enclosure_logical_id = 0;
482 slot = 0;
483 }
484
485 if (!ioc->req_boot_device.device) {
486 if (_scsih_is_boot_device(sas_address, device_name,
487 enclosure_logical_id, slot,
488 (ioc->bios_pg2.ReqBootDeviceForm &
489 MPI2_BIOSPAGE2_FORM_MASK),
490 &ioc->bios_pg2.RequestedBootDevice)) {
491 dinitprintk(ioc, pr_info(MPT3SAS_FMT
492 "%s: req_boot_device(0x%016llx)\n",
493 ioc->name, __func__,
494 (unsigned long long)sas_address));
495 ioc->req_boot_device.device = device;
496 ioc->req_boot_device.is_raid = is_raid;
497 }
498 }
499
500 if (!ioc->req_alt_boot_device.device) {
501 if (_scsih_is_boot_device(sas_address, device_name,
502 enclosure_logical_id, slot,
503 (ioc->bios_pg2.ReqAltBootDeviceForm &
504 MPI2_BIOSPAGE2_FORM_MASK),
505 &ioc->bios_pg2.RequestedAltBootDevice)) {
506 dinitprintk(ioc, pr_info(MPT3SAS_FMT
507 "%s: req_alt_boot_device(0x%016llx)\n",
508 ioc->name, __func__,
509 (unsigned long long)sas_address));
510 ioc->req_alt_boot_device.device = device;
511 ioc->req_alt_boot_device.is_raid = is_raid;
512 }
513 }
514
515 if (!ioc->current_boot_device.device) {
516 if (_scsih_is_boot_device(sas_address, device_name,
517 enclosure_logical_id, slot,
518 (ioc->bios_pg2.CurrentBootDeviceForm &
519 MPI2_BIOSPAGE2_FORM_MASK),
520 &ioc->bios_pg2.CurrentBootDevice)) {
521 dinitprintk(ioc, pr_info(MPT3SAS_FMT
522 "%s: current_boot_device(0x%016llx)\n",
523 ioc->name, __func__,
524 (unsigned long long)sas_address));
525 ioc->current_boot_device.device = device;
526 ioc->current_boot_device.is_raid = is_raid;
527 }
528 }
529}
530
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530531static struct _sas_device *
532__mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc,
533 struct MPT3SAS_TARGET *tgt_priv)
534{
535 struct _sas_device *ret;
536
537 assert_spin_locked(&ioc->sas_device_lock);
538
539 ret = tgt_priv->sdev;
540 if (ret)
541 sas_device_get(ret);
542
543 return ret;
544}
545
546static struct _sas_device *
547mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc,
548 struct MPT3SAS_TARGET *tgt_priv)
549{
550 struct _sas_device *ret;
551 unsigned long flags;
552
553 spin_lock_irqsave(&ioc->sas_device_lock, flags);
554 ret = __mpt3sas_get_sdev_from_target(ioc, tgt_priv);
555 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
556
557 return ret;
558}
559
560
561struct _sas_device *
562__mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
563 u64 sas_address)
564{
565 struct _sas_device *sas_device;
566
567 assert_spin_locked(&ioc->sas_device_lock);
568
569 list_for_each_entry(sas_device, &ioc->sas_device_list, list)
570 if (sas_device->sas_address == sas_address)
571 goto found_device;
572
573 list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
574 if (sas_device->sas_address == sas_address)
575 goto found_device;
576
577 return NULL;
578
579found_device:
580 sas_device_get(sas_device);
581 return sas_device;
582}
583
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530584/**
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530585 * mpt3sas_get_sdev_by_addr - sas device search
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530586 * @ioc: per adapter object
587 * @sas_address: sas address
588 * Context: Calling function should acquire ioc->sas_device_lock
589 *
590 * This searches for sas_device based on sas_address, then return sas_device
591 * object.
592 */
593struct _sas_device *
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530594mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530595 u64 sas_address)
596{
597 struct _sas_device *sas_device;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530598 unsigned long flags;
599
600 spin_lock_irqsave(&ioc->sas_device_lock, flags);
601 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
602 sas_address);
603 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
604
605 return sas_device;
606}
607
608static struct _sas_device *
609__mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
610{
611 struct _sas_device *sas_device;
612
613 assert_spin_locked(&ioc->sas_device_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530614
615 list_for_each_entry(sas_device, &ioc->sas_device_list, list)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530616 if (sas_device->handle == handle)
617 goto found_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530618
619 list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530620 if (sas_device->handle == handle)
621 goto found_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530622
623 return NULL;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530624
625found_device:
626 sas_device_get(sas_device);
627 return sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530628}
629
630/**
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530631 * mpt3sas_get_sdev_by_handle - sas device search
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530632 * @ioc: per adapter object
633 * @handle: sas device handle (assigned by firmware)
634 * Context: Calling function should acquire ioc->sas_device_lock
635 *
636 * This searches for sas_device based on sas_address, then return sas_device
637 * object.
638 */
639static struct _sas_device *
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530640mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530641{
642 struct _sas_device *sas_device;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530643 unsigned long flags;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530644
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530645 spin_lock_irqsave(&ioc->sas_device_lock, flags);
646 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
647 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530648
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530649 return sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530650}
651
652/**
653 * _scsih_sas_device_remove - remove sas_device from list.
654 * @ioc: per adapter object
655 * @sas_device: the sas_device object
656 * Context: This function will acquire ioc->sas_device_lock.
657 *
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530658 * If sas_device is on the list, remove it and decrement its reference count.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530659 */
660static void
661_scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
662 struct _sas_device *sas_device)
663{
664 unsigned long flags;
665
666 if (!sas_device)
667 return;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +0530668 pr_info(MPT3SAS_FMT
669 "removing handle(0x%04x), sas_addr(0x%016llx)\n",
670 ioc->name, sas_device->handle,
671 (unsigned long long) sas_device->sas_address);
672
673 if (sas_device->enclosure_handle != 0)
674 pr_info(MPT3SAS_FMT
675 "removing enclosure logical id(0x%016llx), slot(%d)\n",
676 ioc->name, (unsigned long long)
677 sas_device->enclosure_logical_id, sas_device->slot);
678
679 if (sas_device->connector_name[0] != '\0')
680 pr_info(MPT3SAS_FMT
681 "removing enclosure level(0x%04x), connector name( %s)\n",
682 ioc->name, sas_device->enclosure_level,
683 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530684
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530685 /*
686 * The lock serializes access to the list, but we still need to verify
687 * that nobody removed the entry while we were waiting on the lock.
688 */
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530689 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530690 if (!list_empty(&sas_device->list)) {
691 list_del_init(&sas_device->list);
692 sas_device_put(sas_device);
693 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530694 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
695}
696
697/**
698 * _scsih_device_remove_by_handle - removing device object by handle
699 * @ioc: per adapter object
700 * @handle: device handle
701 *
702 * Return nothing.
703 */
704static void
705_scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
706{
707 struct _sas_device *sas_device;
708 unsigned long flags;
709
710 if (ioc->shost_recovery)
711 return;
712
713 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530714 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
715 if (sas_device) {
716 list_del_init(&sas_device->list);
717 sas_device_put(sas_device);
718 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530719 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530720 if (sas_device) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530721 _scsih_remove_device(ioc, sas_device);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530722 sas_device_put(sas_device);
723 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530724}
725
726/**
727 * mpt3sas_device_remove_by_sas_address - removing device object by sas address
728 * @ioc: per adapter object
729 * @sas_address: device sas_address
730 *
731 * Return nothing.
732 */
733void
734mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
735 u64 sas_address)
736{
737 struct _sas_device *sas_device;
738 unsigned long flags;
739
740 if (ioc->shost_recovery)
741 return;
742
743 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530744 sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address);
745 if (sas_device) {
746 list_del_init(&sas_device->list);
747 sas_device_put(sas_device);
748 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530749 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530750 if (sas_device) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530751 _scsih_remove_device(ioc, sas_device);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530752 sas_device_put(sas_device);
753 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530754}
755
756/**
757 * _scsih_sas_device_add - insert sas_device to the list.
758 * @ioc: per adapter object
759 * @sas_device: the sas_device object
760 * Context: This function will acquire ioc->sas_device_lock.
761 *
762 * Adding new object to the ioc->sas_device_list.
763 */
764static void
765_scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
766 struct _sas_device *sas_device)
767{
768 unsigned long flags;
769
770 dewtprintk(ioc, pr_info(MPT3SAS_FMT
771 "%s: handle(0x%04x), sas_addr(0x%016llx)\n",
772 ioc->name, __func__, sas_device->handle,
773 (unsigned long long)sas_device->sas_address));
774
Sreekanth Reddye6d45e32015-06-30 12:24:52 +0530775 if (sas_device->enclosure_handle != 0)
776 dewtprintk(ioc, pr_info(MPT3SAS_FMT
777 "%s: enclosure logical id(0x%016llx), slot( %d)\n",
778 ioc->name, __func__, (unsigned long long)
779 sas_device->enclosure_logical_id, sas_device->slot));
780
781 if (sas_device->connector_name[0] != '\0')
782 dewtprintk(ioc, pr_info(MPT3SAS_FMT
783 "%s: enclosure level(0x%04x), connector name( %s)\n",
784 ioc->name, __func__,
785 sas_device->enclosure_level, sas_device->connector_name));
786
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530787 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530788 sas_device_get(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530789 list_add_tail(&sas_device->list, &ioc->sas_device_list);
790 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
791
792 if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
793 sas_device->sas_address_parent)) {
794 _scsih_sas_device_remove(ioc, sas_device);
795 } else if (!sas_device->starget) {
796 /*
797 * When asyn scanning is enabled, its not possible to remove
798 * devices while scanning is turned on due to an oops in
799 * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start()
800 */
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +0530801 if (!ioc->is_driver_loading) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530802 mpt3sas_transport_port_remove(ioc,
803 sas_device->sas_address,
804 sas_device->sas_address_parent);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +0530805 _scsih_sas_device_remove(ioc, sas_device);
806 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530807 }
808}
809
810/**
811 * _scsih_sas_device_init_add - insert sas_device to the list.
812 * @ioc: per adapter object
813 * @sas_device: the sas_device object
814 * Context: This function will acquire ioc->sas_device_lock.
815 *
816 * Adding new object at driver load time to the ioc->sas_device_init_list.
817 */
818static void
819_scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc,
820 struct _sas_device *sas_device)
821{
822 unsigned long flags;
823
824 dewtprintk(ioc, pr_info(MPT3SAS_FMT
825 "%s: handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
826 __func__, sas_device->handle,
827 (unsigned long long)sas_device->sas_address));
828
Sreekanth Reddye6d45e32015-06-30 12:24:52 +0530829 if (sas_device->enclosure_handle != 0)
830 dewtprintk(ioc, pr_info(MPT3SAS_FMT
831 "%s: enclosure logical id(0x%016llx), slot( %d)\n",
832 ioc->name, __func__, (unsigned long long)
833 sas_device->enclosure_logical_id, sas_device->slot));
834
835 if (sas_device->connector_name[0] != '\0')
836 dewtprintk(ioc, pr_info(MPT3SAS_FMT
837 "%s: enclosure level(0x%04x), connector name( %s)\n",
838 ioc->name, __func__, sas_device->enclosure_level,
839 sas_device->connector_name));
840
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530841 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530842 sas_device_get(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530843 list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
844 _scsih_determine_boot_device(ioc, sas_device, 0);
845 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
846}
847
848/**
849 * _scsih_raid_device_find_by_id - raid device search
850 * @ioc: per adapter object
851 * @id: sas device target id
852 * @channel: sas device channel
853 * Context: Calling function should acquire ioc->raid_device_lock
854 *
855 * This searches for raid_device based on target id, then return raid_device
856 * object.
857 */
858static struct _raid_device *
859_scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel)
860{
861 struct _raid_device *raid_device, *r;
862
863 r = NULL;
864 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
865 if (raid_device->id == id && raid_device->channel == channel) {
866 r = raid_device;
867 goto out;
868 }
869 }
870
871 out:
872 return r;
873}
874
875/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530876 * mpt3sas_raid_device_find_by_handle - raid device search
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530877 * @ioc: per adapter object
878 * @handle: sas device handle (assigned by firmware)
879 * Context: Calling function should acquire ioc->raid_device_lock
880 *
881 * This searches for raid_device based on handle, then return raid_device
882 * object.
883 */
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +0530884struct _raid_device *
885mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530886{
887 struct _raid_device *raid_device, *r;
888
889 r = NULL;
890 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
891 if (raid_device->handle != handle)
892 continue;
893 r = raid_device;
894 goto out;
895 }
896
897 out:
898 return r;
899}
900
901/**
902 * _scsih_raid_device_find_by_wwid - raid device search
903 * @ioc: per adapter object
904 * @handle: sas device handle (assigned by firmware)
905 * Context: Calling function should acquire ioc->raid_device_lock
906 *
907 * This searches for raid_device based on wwid, then return raid_device
908 * object.
909 */
910static struct _raid_device *
911_scsih_raid_device_find_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid)
912{
913 struct _raid_device *raid_device, *r;
914
915 r = NULL;
916 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
917 if (raid_device->wwid != wwid)
918 continue;
919 r = raid_device;
920 goto out;
921 }
922
923 out:
924 return r;
925}
926
927/**
928 * _scsih_raid_device_add - add raid_device object
929 * @ioc: per adapter object
930 * @raid_device: raid_device object
931 *
932 * This is added to the raid_device_list link list.
933 */
934static void
935_scsih_raid_device_add(struct MPT3SAS_ADAPTER *ioc,
936 struct _raid_device *raid_device)
937{
938 unsigned long flags;
939
940 dewtprintk(ioc, pr_info(MPT3SAS_FMT
941 "%s: handle(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
942 raid_device->handle, (unsigned long long)raid_device->wwid));
943
944 spin_lock_irqsave(&ioc->raid_device_lock, flags);
945 list_add_tail(&raid_device->list, &ioc->raid_device_list);
946 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
947}
948
949/**
950 * _scsih_raid_device_remove - delete raid_device object
951 * @ioc: per adapter object
952 * @raid_device: raid_device object
953 *
954 */
955static void
956_scsih_raid_device_remove(struct MPT3SAS_ADAPTER *ioc,
957 struct _raid_device *raid_device)
958{
959 unsigned long flags;
960
961 spin_lock_irqsave(&ioc->raid_device_lock, flags);
962 list_del(&raid_device->list);
963 kfree(raid_device);
964 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
965}
966
967/**
968 * mpt3sas_scsih_expander_find_by_handle - expander device search
969 * @ioc: per adapter object
970 * @handle: expander handle (assigned by firmware)
971 * Context: Calling function should acquire ioc->sas_device_lock
972 *
973 * This searches for expander device based on handle, then returns the
974 * sas_node object.
975 */
976struct _sas_node *
977mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
978{
979 struct _sas_node *sas_expander, *r;
980
981 r = NULL;
982 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
983 if (sas_expander->handle != handle)
984 continue;
985 r = sas_expander;
986 goto out;
987 }
988 out:
989 return r;
990}
991
992/**
993 * mpt3sas_scsih_expander_find_by_sas_address - expander device search
994 * @ioc: per adapter object
995 * @sas_address: sas address
996 * Context: Calling function should acquire ioc->sas_node_lock.
997 *
998 * This searches for expander device based on sas_address, then returns the
999 * sas_node object.
1000 */
1001struct _sas_node *
1002mpt3sas_scsih_expander_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
1003 u64 sas_address)
1004{
1005 struct _sas_node *sas_expander, *r;
1006
1007 r = NULL;
1008 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
1009 if (sas_expander->sas_address != sas_address)
1010 continue;
1011 r = sas_expander;
1012 goto out;
1013 }
1014 out:
1015 return r;
1016}
1017
1018/**
1019 * _scsih_expander_node_add - insert expander device to the list.
1020 * @ioc: per adapter object
1021 * @sas_expander: the sas_device object
1022 * Context: This function will acquire ioc->sas_node_lock.
1023 *
1024 * Adding new object to the ioc->sas_expander_list.
1025 *
1026 * Return nothing.
1027 */
1028static void
1029_scsih_expander_node_add(struct MPT3SAS_ADAPTER *ioc,
1030 struct _sas_node *sas_expander)
1031{
1032 unsigned long flags;
1033
1034 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1035 list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
1036 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1037}
1038
1039/**
1040 * _scsih_is_end_device - determines if device is an end device
1041 * @device_info: bitfield providing information about the device.
1042 * Context: none
1043 *
1044 * Returns 1 if end device.
1045 */
1046static int
1047_scsih_is_end_device(u32 device_info)
1048{
1049 if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
1050 ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
1051 (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
1052 (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
1053 return 1;
1054 else
1055 return 0;
1056}
1057
1058/**
1059 * _scsih_scsi_lookup_get - returns scmd entry
1060 * @ioc: per adapter object
1061 * @smid: system request message index
1062 *
1063 * Returns the smid stored scmd pointer.
1064 */
1065static struct scsi_cmnd *
1066_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
1067{
1068 return ioc->scsi_lookup[smid - 1].scmd;
1069}
1070
1071/**
1072 * _scsih_scsi_lookup_get_clear - returns scmd entry
1073 * @ioc: per adapter object
1074 * @smid: system request message index
1075 *
1076 * Returns the smid stored scmd pointer.
1077 * Then will derefrence the stored scmd pointer.
1078 */
1079static inline struct scsi_cmnd *
1080_scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, u16 smid)
1081{
1082 unsigned long flags;
1083 struct scsi_cmnd *scmd;
1084
1085 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1086 scmd = ioc->scsi_lookup[smid - 1].scmd;
1087 ioc->scsi_lookup[smid - 1].scmd = NULL;
1088 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1089
1090 return scmd;
1091}
1092
1093/**
1094 * _scsih_scsi_lookup_find_by_scmd - scmd lookup
1095 * @ioc: per adapter object
1096 * @smid: system request message index
1097 * @scmd: pointer to scsi command object
1098 * Context: This function will acquire ioc->scsi_lookup_lock.
1099 *
1100 * This will search for a scmd pointer in the scsi_lookup array,
1101 * returning the revelent smid. A returned value of zero means invalid.
1102 */
1103static u16
1104_scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd
1105 *scmd)
1106{
1107 u16 smid;
1108 unsigned long flags;
1109 int i;
1110
1111 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1112 smid = 0;
1113 for (i = 0; i < ioc->scsiio_depth; i++) {
1114 if (ioc->scsi_lookup[i].scmd == scmd) {
1115 smid = ioc->scsi_lookup[i].smid;
1116 goto out;
1117 }
1118 }
1119 out:
1120 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1121 return smid;
1122}
1123
1124/**
1125 * _scsih_scsi_lookup_find_by_target - search for matching channel:id
1126 * @ioc: per adapter object
1127 * @id: target id
1128 * @channel: channel
1129 * Context: This function will acquire ioc->scsi_lookup_lock.
1130 *
1131 * This will search for a matching channel:id in the scsi_lookup array,
1132 * returning 1 if found.
1133 */
1134static u8
1135_scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id,
1136 int channel)
1137{
1138 u8 found;
1139 unsigned long flags;
1140 int i;
1141
1142 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1143 found = 0;
1144 for (i = 0 ; i < ioc->scsiio_depth; i++) {
1145 if (ioc->scsi_lookup[i].scmd &&
1146 (ioc->scsi_lookup[i].scmd->device->id == id &&
1147 ioc->scsi_lookup[i].scmd->device->channel == channel)) {
1148 found = 1;
1149 goto out;
1150 }
1151 }
1152 out:
1153 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1154 return found;
1155}
1156
1157/**
1158 * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
1159 * @ioc: per adapter object
1160 * @id: target id
1161 * @lun: lun number
1162 * @channel: channel
1163 * Context: This function will acquire ioc->scsi_lookup_lock.
1164 *
1165 * This will search for a matching channel:id:lun in the scsi_lookup array,
1166 * returning 1 if found.
1167 */
1168static u8
1169_scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
1170 unsigned int lun, int channel)
1171{
1172 u8 found;
1173 unsigned long flags;
1174 int i;
1175
1176 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1177 found = 0;
1178 for (i = 0 ; i < ioc->scsiio_depth; i++) {
1179 if (ioc->scsi_lookup[i].scmd &&
1180 (ioc->scsi_lookup[i].scmd->device->id == id &&
1181 ioc->scsi_lookup[i].scmd->device->channel == channel &&
1182 ioc->scsi_lookup[i].scmd->device->lun == lun)) {
1183 found = 1;
1184 goto out;
1185 }
1186 }
1187 out:
1188 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1189 return found;
1190}
1191
Christoph Hellwigcf75d5d2014-11-13 15:13:20 +01001192/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301193 * scsih_change_queue_depth - setting device queue depth
Christoph Hellwigcf75d5d2014-11-13 15:13:20 +01001194 * @sdev: scsi device struct
1195 * @qdepth: requested queue depth
1196 *
1197 * Returns queue depth.
1198 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001199static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301200scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301201{
1202 struct Scsi_Host *shost = sdev->host;
1203 int max_depth;
1204 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1205 struct MPT3SAS_DEVICE *sas_device_priv_data;
1206 struct MPT3SAS_TARGET *sas_target_priv_data;
1207 struct _sas_device *sas_device;
1208 unsigned long flags;
1209
1210 max_depth = shost->can_queue;
1211
1212 /* limit max device queue for SATA to 32 */
1213 sas_device_priv_data = sdev->hostdata;
1214 if (!sas_device_priv_data)
1215 goto not_sata;
1216 sas_target_priv_data = sas_device_priv_data->sas_target;
1217 if (!sas_target_priv_data)
1218 goto not_sata;
1219 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))
1220 goto not_sata;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301221
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301222 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301223 sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
1224 if (sas_device) {
1225 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1226 max_depth = MPT3SAS_SATA_QUEUE_DEPTH;
1227
1228 sas_device_put(sas_device);
1229 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301230 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1231
1232 not_sata:
1233
1234 if (!sdev->tagged_supported)
1235 max_depth = 1;
1236 if (qdepth > max_depth)
1237 qdepth = max_depth;
Christoph Hellwigcf75d5d2014-11-13 15:13:20 +01001238 return scsi_change_queue_depth(sdev, qdepth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301239}
1240
1241/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301242 * scsih_target_alloc - target add routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301243 * @starget: scsi target struct
1244 *
1245 * Returns 0 if ok. Any other return is assumed to be an error and
1246 * the device is ignored.
1247 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001248static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301249scsih_target_alloc(struct scsi_target *starget)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301250{
1251 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1252 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1253 struct MPT3SAS_TARGET *sas_target_priv_data;
1254 struct _sas_device *sas_device;
1255 struct _raid_device *raid_device;
1256 unsigned long flags;
1257 struct sas_rphy *rphy;
1258
Joe Lawrence62c4da42014-06-25 17:04:22 -04001259 sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data),
1260 GFP_KERNEL);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301261 if (!sas_target_priv_data)
1262 return -ENOMEM;
1263
1264 starget->hostdata = sas_target_priv_data;
1265 sas_target_priv_data->starget = starget;
1266 sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
1267
1268 /* RAID volumes */
1269 if (starget->channel == RAID_CHANNEL) {
1270 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1271 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1272 starget->channel);
1273 if (raid_device) {
1274 sas_target_priv_data->handle = raid_device->handle;
1275 sas_target_priv_data->sas_address = raid_device->wwid;
1276 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301277 if (ioc->is_warpdrive)
Sreekanth Reddy6d3a56e2016-10-28 10:09:12 +05301278 sas_target_priv_data->raid_device = raid_device;
1279 raid_device->starget = starget;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301280 }
1281 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1282 return 0;
1283 }
1284
1285 /* sas/sata devices */
1286 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1287 rphy = dev_to_rphy(starget->dev.parent);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301288 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301289 rphy->identify.sas_address);
1290
1291 if (sas_device) {
1292 sas_target_priv_data->handle = sas_device->handle;
1293 sas_target_priv_data->sas_address = sas_device->sas_address;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301294 sas_target_priv_data->sdev = sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301295 sas_device->starget = starget;
1296 sas_device->id = starget->id;
1297 sas_device->channel = starget->channel;
1298 if (test_bit(sas_device->handle, ioc->pd_handles))
1299 sas_target_priv_data->flags |=
1300 MPT_TARGET_FLAGS_RAID_COMPONENT;
1301 if (sas_device->fast_path)
1302 sas_target_priv_data->flags |= MPT_TARGET_FASTPATH_IO;
1303 }
1304 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1305
1306 return 0;
1307}
1308
1309/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301310 * scsih_target_destroy - target destroy routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301311 * @starget: scsi target struct
1312 *
1313 * Returns nothing.
1314 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001315static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301316scsih_target_destroy(struct scsi_target *starget)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301317{
1318 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1319 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1320 struct MPT3SAS_TARGET *sas_target_priv_data;
1321 struct _sas_device *sas_device;
1322 struct _raid_device *raid_device;
1323 unsigned long flags;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301324
1325 sas_target_priv_data = starget->hostdata;
1326 if (!sas_target_priv_data)
1327 return;
1328
1329 if (starget->channel == RAID_CHANNEL) {
1330 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1331 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1332 starget->channel);
1333 if (raid_device) {
1334 raid_device->starget = NULL;
1335 raid_device->sdev = NULL;
1336 }
1337 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1338 goto out;
1339 }
1340
1341 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301342 sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301343 if (sas_device && (sas_device->starget == starget) &&
1344 (sas_device->id == starget->id) &&
1345 (sas_device->channel == starget->channel))
1346 sas_device->starget = NULL;
1347
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301348 if (sas_device) {
1349 /*
1350 * Corresponding get() is in _scsih_target_alloc()
1351 */
1352 sas_target_priv_data->sdev = NULL;
1353 sas_device_put(sas_device);
1354
1355 sas_device_put(sas_device);
1356 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301357 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1358
1359 out:
1360 kfree(sas_target_priv_data);
1361 starget->hostdata = NULL;
1362}
1363
1364/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301365 * scsih_slave_alloc - device add routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301366 * @sdev: scsi device struct
1367 *
1368 * Returns 0 if ok. Any other return is assumed to be an error and
1369 * the device is ignored.
1370 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001371static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301372scsih_slave_alloc(struct scsi_device *sdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301373{
1374 struct Scsi_Host *shost;
1375 struct MPT3SAS_ADAPTER *ioc;
1376 struct MPT3SAS_TARGET *sas_target_priv_data;
1377 struct MPT3SAS_DEVICE *sas_device_priv_data;
1378 struct scsi_target *starget;
1379 struct _raid_device *raid_device;
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301380 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301381 unsigned long flags;
1382
Joe Lawrence62c4da42014-06-25 17:04:22 -04001383 sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data),
1384 GFP_KERNEL);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301385 if (!sas_device_priv_data)
1386 return -ENOMEM;
1387
1388 sas_device_priv_data->lun = sdev->lun;
1389 sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
1390
1391 starget = scsi_target(sdev);
1392 sas_target_priv_data = starget->hostdata;
1393 sas_target_priv_data->num_luns++;
1394 sas_device_priv_data->sas_target = sas_target_priv_data;
1395 sdev->hostdata = sas_device_priv_data;
1396 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
1397 sdev->no_uld_attach = 1;
1398
1399 shost = dev_to_shost(&starget->dev);
1400 ioc = shost_priv(shost);
1401 if (starget->channel == RAID_CHANNEL) {
1402 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1403 raid_device = _scsih_raid_device_find_by_id(ioc,
1404 starget->id, starget->channel);
1405 if (raid_device)
1406 raid_device->sdev = sdev; /* raid is single lun */
1407 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1408 }
1409
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301410 if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
1411 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301412 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301413 sas_target_priv_data->sas_address);
1414 if (sas_device && (sas_device->starget == NULL)) {
1415 sdev_printk(KERN_INFO, sdev,
1416 "%s : sas_device->starget set to starget @ %d\n",
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301417 __func__, __LINE__);
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301418 sas_device->starget = starget;
1419 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301420
1421 if (sas_device)
1422 sas_device_put(sas_device);
1423
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301424 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1425 }
1426
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301427 return 0;
1428}
1429
1430/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301431 * scsih_slave_destroy - device destroy routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301432 * @sdev: scsi device struct
1433 *
1434 * Returns nothing.
1435 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001436static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301437scsih_slave_destroy(struct scsi_device *sdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301438{
1439 struct MPT3SAS_TARGET *sas_target_priv_data;
1440 struct scsi_target *starget;
1441 struct Scsi_Host *shost;
1442 struct MPT3SAS_ADAPTER *ioc;
1443 struct _sas_device *sas_device;
1444 unsigned long flags;
1445
1446 if (!sdev->hostdata)
1447 return;
1448
1449 starget = scsi_target(sdev);
1450 sas_target_priv_data = starget->hostdata;
1451 sas_target_priv_data->num_luns--;
1452
1453 shost = dev_to_shost(&starget->dev);
1454 ioc = shost_priv(shost);
1455
1456 if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
1457 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301458 sas_device = __mpt3sas_get_sdev_from_target(ioc,
1459 sas_target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301460 if (sas_device && !sas_target_priv_data->num_luns)
1461 sas_device->starget = NULL;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301462
1463 if (sas_device)
1464 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301465 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1466 }
1467
1468 kfree(sdev->hostdata);
1469 sdev->hostdata = NULL;
1470}
1471
1472/**
1473 * _scsih_display_sata_capabilities - sata capabilities
1474 * @ioc: per adapter object
1475 * @handle: device handle
1476 * @sdev: scsi device struct
1477 */
1478static void
1479_scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc,
1480 u16 handle, struct scsi_device *sdev)
1481{
1482 Mpi2ConfigReply_t mpi_reply;
1483 Mpi2SasDevicePage0_t sas_device_pg0;
1484 u32 ioc_status;
1485 u16 flags;
1486 u32 device_info;
1487
1488 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
1489 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
1490 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1491 ioc->name, __FILE__, __LINE__, __func__);
1492 return;
1493 }
1494
1495 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1496 MPI2_IOCSTATUS_MASK;
1497 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1498 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1499 ioc->name, __FILE__, __LINE__, __func__);
1500 return;
1501 }
1502
1503 flags = le16_to_cpu(sas_device_pg0.Flags);
1504 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
1505
1506 sdev_printk(KERN_INFO, sdev,
1507 "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
1508 "sw_preserve(%s)\n",
1509 (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
1510 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
1511 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
1512 "n",
1513 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
1514 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
1515 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
1516}
1517
1518/*
1519 * raid transport support -
1520 * Enabled for SLES11 and newer, in older kernels the driver will panic when
1521 * unloading the driver followed by a load - I beleive that the subroutine
1522 * raid_class_release() is not cleaning up properly.
1523 */
1524
1525/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301526 * scsih_is_raid - return boolean indicating device is raid volume
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301527 * @dev the device struct object
1528 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001529static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301530scsih_is_raid(struct device *dev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301531{
1532 struct scsi_device *sdev = to_scsi_device(dev);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301533 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301534
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301535 if (ioc->is_warpdrive)
1536 return 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301537 return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
1538}
1539
1540/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301541 * scsih_get_resync - get raid volume resync percent complete
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301542 * @dev the device struct object
1543 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001544static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301545scsih_get_resync(struct device *dev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301546{
1547 struct scsi_device *sdev = to_scsi_device(dev);
1548 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
1549 static struct _raid_device *raid_device;
1550 unsigned long flags;
1551 Mpi2RaidVolPage0_t vol_pg0;
1552 Mpi2ConfigReply_t mpi_reply;
1553 u32 volume_status_flags;
1554 u8 percent_complete;
1555 u16 handle;
1556
1557 percent_complete = 0;
1558 handle = 0;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301559 if (ioc->is_warpdrive)
1560 goto out;
1561
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301562 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1563 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1564 sdev->channel);
1565 if (raid_device) {
1566 handle = raid_device->handle;
1567 percent_complete = raid_device->percent_complete;
1568 }
1569 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1570
1571 if (!handle)
1572 goto out;
1573
1574 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
1575 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
1576 sizeof(Mpi2RaidVolPage0_t))) {
1577 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1578 ioc->name, __FILE__, __LINE__, __func__);
1579 percent_complete = 0;
1580 goto out;
1581 }
1582
1583 volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1584 if (!(volume_status_flags &
1585 MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS))
1586 percent_complete = 0;
1587
1588 out:
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05301589
1590 switch (ioc->hba_mpi_version_belonged) {
1591 case MPI2_VERSION:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301592 raid_set_resync(mpt2sas_raid_template, dev, percent_complete);
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05301593 break;
1594 case MPI25_VERSION:
1595 case MPI26_VERSION:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301596 raid_set_resync(mpt3sas_raid_template, dev, percent_complete);
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05301597 break;
1598 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301599}
1600
1601/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301602 * scsih_get_state - get raid volume level
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301603 * @dev the device struct object
1604 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001605static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301606scsih_get_state(struct device *dev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301607{
1608 struct scsi_device *sdev = to_scsi_device(dev);
1609 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
1610 static struct _raid_device *raid_device;
1611 unsigned long flags;
1612 Mpi2RaidVolPage0_t vol_pg0;
1613 Mpi2ConfigReply_t mpi_reply;
1614 u32 volstate;
1615 enum raid_state state = RAID_STATE_UNKNOWN;
1616 u16 handle = 0;
1617
1618 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1619 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1620 sdev->channel);
1621 if (raid_device)
1622 handle = raid_device->handle;
1623 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1624
1625 if (!raid_device)
1626 goto out;
1627
1628 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
1629 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
1630 sizeof(Mpi2RaidVolPage0_t))) {
1631 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1632 ioc->name, __FILE__, __LINE__, __func__);
1633 goto out;
1634 }
1635
1636 volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1637 if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
1638 state = RAID_STATE_RESYNCING;
1639 goto out;
1640 }
1641
1642 switch (vol_pg0.VolumeState) {
1643 case MPI2_RAID_VOL_STATE_OPTIMAL:
1644 case MPI2_RAID_VOL_STATE_ONLINE:
1645 state = RAID_STATE_ACTIVE;
1646 break;
1647 case MPI2_RAID_VOL_STATE_DEGRADED:
1648 state = RAID_STATE_DEGRADED;
1649 break;
1650 case MPI2_RAID_VOL_STATE_FAILED:
1651 case MPI2_RAID_VOL_STATE_MISSING:
1652 state = RAID_STATE_OFFLINE;
1653 break;
1654 }
1655 out:
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05301656 switch (ioc->hba_mpi_version_belonged) {
1657 case MPI2_VERSION:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301658 raid_set_state(mpt2sas_raid_template, dev, state);
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05301659 break;
1660 case MPI25_VERSION:
1661 case MPI26_VERSION:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301662 raid_set_state(mpt3sas_raid_template, dev, state);
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05301663 break;
1664 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301665}
1666
1667/**
1668 * _scsih_set_level - set raid level
1669 * @sdev: scsi device struct
1670 * @volume_type: volume type
1671 */
1672static void
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301673_scsih_set_level(struct MPT3SAS_ADAPTER *ioc,
1674 struct scsi_device *sdev, u8 volume_type)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301675{
1676 enum raid_level level = RAID_LEVEL_UNKNOWN;
1677
1678 switch (volume_type) {
1679 case MPI2_RAID_VOL_TYPE_RAID0:
1680 level = RAID_LEVEL_0;
1681 break;
1682 case MPI2_RAID_VOL_TYPE_RAID10:
1683 level = RAID_LEVEL_10;
1684 break;
1685 case MPI2_RAID_VOL_TYPE_RAID1E:
1686 level = RAID_LEVEL_1E;
1687 break;
1688 case MPI2_RAID_VOL_TYPE_RAID1:
1689 level = RAID_LEVEL_1;
1690 break;
1691 }
1692
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05301693 switch (ioc->hba_mpi_version_belonged) {
1694 case MPI2_VERSION:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301695 raid_set_level(mpt2sas_raid_template,
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05301696 &sdev->sdev_gendev, level);
1697 break;
1698 case MPI25_VERSION:
1699 case MPI26_VERSION:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301700 raid_set_level(mpt3sas_raid_template,
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05301701 &sdev->sdev_gendev, level);
1702 break;
1703 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301704}
1705
1706
1707/**
1708 * _scsih_get_volume_capabilities - volume capabilities
1709 * @ioc: per adapter object
1710 * @sas_device: the raid_device object
1711 *
1712 * Returns 0 for success, else 1
1713 */
1714static int
1715_scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc,
1716 struct _raid_device *raid_device)
1717{
1718 Mpi2RaidVolPage0_t *vol_pg0;
1719 Mpi2RaidPhysDiskPage0_t pd_pg0;
1720 Mpi2SasDevicePage0_t sas_device_pg0;
1721 Mpi2ConfigReply_t mpi_reply;
1722 u16 sz;
1723 u8 num_pds;
1724
1725 if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle,
1726 &num_pds)) || !num_pds) {
1727 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1728 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1729 __func__));
1730 return 1;
1731 }
1732
1733 raid_device->num_pds = num_pds;
1734 sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
1735 sizeof(Mpi2RaidVol0PhysDisk_t));
1736 vol_pg0 = kzalloc(sz, GFP_KERNEL);
1737 if (!vol_pg0) {
1738 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1739 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1740 __func__));
1741 return 1;
1742 }
1743
1744 if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
1745 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
1746 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1747 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1748 __func__));
1749 kfree(vol_pg0);
1750 return 1;
1751 }
1752
1753 raid_device->volume_type = vol_pg0->VolumeType;
1754
1755 /* figure out what the underlying devices are by
1756 * obtaining the device_info bits for the 1st device
1757 */
1758 if (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
1759 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
1760 vol_pg0->PhysDisk[0].PhysDiskNum))) {
1761 if (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
1762 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
1763 le16_to_cpu(pd_pg0.DevHandle)))) {
1764 raid_device->device_info =
1765 le32_to_cpu(sas_device_pg0.DeviceInfo);
1766 }
1767 }
1768
1769 kfree(vol_pg0);
1770 return 0;
1771}
1772
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301773/**
1774 * _scsih_enable_tlr - setting TLR flags
1775 * @ioc: per adapter object
1776 * @sdev: scsi device struct
1777 *
1778 * Enabling Transaction Layer Retries for tape devices when
1779 * vpd page 0x90 is present
1780 *
1781 */
1782static void
1783_scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev)
1784{
1785
1786 /* only for TAPE */
1787 if (sdev->type != TYPE_TAPE)
1788 return;
1789
1790 if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR))
1791 return;
1792
1793 sas_enable_tlr(sdev);
1794 sdev_printk(KERN_INFO, sdev, "TLR %s\n",
1795 sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled");
1796 return;
1797
1798}
1799
1800/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301801 * scsih_slave_configure - device configure routine.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301802 * @sdev: scsi device struct
1803 *
1804 * Returns 0 if ok. Any other return is assumed to be an error and
1805 * the device is ignored.
1806 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07001807static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301808scsih_slave_configure(struct scsi_device *sdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301809{
1810 struct Scsi_Host *shost = sdev->host;
1811 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1812 struct MPT3SAS_DEVICE *sas_device_priv_data;
1813 struct MPT3SAS_TARGET *sas_target_priv_data;
1814 struct _sas_device *sas_device;
1815 struct _raid_device *raid_device;
1816 unsigned long flags;
1817 int qdepth;
1818 u8 ssp_target = 0;
1819 char *ds = "";
1820 char *r_level = "";
1821 u16 handle, volume_handle = 0;
1822 u64 volume_wwid = 0;
1823
1824 qdepth = 1;
1825 sas_device_priv_data = sdev->hostdata;
1826 sas_device_priv_data->configured_lun = 1;
1827 sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
1828 sas_target_priv_data = sas_device_priv_data->sas_target;
1829 handle = sas_target_priv_data->handle;
1830
1831 /* raid volume handling */
1832 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
1833
1834 spin_lock_irqsave(&ioc->raid_device_lock, flags);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301835 raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301836 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1837 if (!raid_device) {
1838 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1839 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
1840 __LINE__, __func__));
1841 return 1;
1842 }
1843
1844 if (_scsih_get_volume_capabilities(ioc, raid_device)) {
1845 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1846 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
1847 __LINE__, __func__));
1848 return 1;
1849 }
1850
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301851 /*
1852 * WARPDRIVE: Initialize the required data for Direct IO
1853 */
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301854 mpt3sas_init_warpdrive_properties(ioc, raid_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301855
1856 /* RAID Queue Depth Support
1857 * IS volume = underlying qdepth of drive type, either
1858 * MPT3SAS_SAS_QUEUE_DEPTH or MPT3SAS_SATA_QUEUE_DEPTH
1859 * IM/IME/R10 = 128 (MPT3SAS_RAID_QUEUE_DEPTH)
1860 */
1861 if (raid_device->device_info &
1862 MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1863 qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
1864 ds = "SSP";
1865 } else {
1866 qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
1867 if (raid_device->device_info &
1868 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1869 ds = "SATA";
1870 else
1871 ds = "STP";
1872 }
1873
1874 switch (raid_device->volume_type) {
1875 case MPI2_RAID_VOL_TYPE_RAID0:
1876 r_level = "RAID0";
1877 break;
1878 case MPI2_RAID_VOL_TYPE_RAID1E:
1879 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1880 if (ioc->manu_pg10.OEMIdentifier &&
1881 (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
1882 MFG10_GF0_R10_DISPLAY) &&
1883 !(raid_device->num_pds % 2))
1884 r_level = "RAID10";
1885 else
1886 r_level = "RAID1E";
1887 break;
1888 case MPI2_RAID_VOL_TYPE_RAID1:
1889 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1890 r_level = "RAID1";
1891 break;
1892 case MPI2_RAID_VOL_TYPE_RAID10:
1893 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1894 r_level = "RAID10";
1895 break;
1896 case MPI2_RAID_VOL_TYPE_UNKNOWN:
1897 default:
1898 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1899 r_level = "RAIDX";
1900 break;
1901 }
1902
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301903 if (!ioc->hide_ir_msg)
1904 sdev_printk(KERN_INFO, sdev,
1905 "%s: handle(0x%04x), wwid(0x%016llx),"
1906 " pd_count(%d), type(%s)\n",
1907 r_level, raid_device->handle,
1908 (unsigned long long)raid_device->wwid,
1909 raid_device->num_pds, ds);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301910
Chaitra P B6c197092016-05-06 14:29:30 +05301911 if (shost->max_sectors > MPT3SAS_RAID_MAX_SECTORS) {
1912 blk_queue_max_hw_sectors(sdev->request_queue,
1913 MPT3SAS_RAID_MAX_SECTORS);
1914 sdev_printk(KERN_INFO, sdev,
1915 "Set queue's max_sector to: %u\n",
1916 MPT3SAS_RAID_MAX_SECTORS);
1917 }
1918
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301919 scsih_change_queue_depth(sdev, qdepth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301920
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301921 /* raid transport support */
1922 if (!ioc->is_warpdrive)
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05301923 _scsih_set_level(ioc, sdev, raid_device->volume_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301924 return 0;
1925 }
1926
1927 /* non-raid handling */
1928 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1929 if (mpt3sas_config_get_volume_handle(ioc, handle,
1930 &volume_handle)) {
1931 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1932 "failure at %s:%d/%s()!\n", ioc->name,
1933 __FILE__, __LINE__, __func__));
1934 return 1;
1935 }
1936 if (volume_handle && mpt3sas_config_get_volume_wwid(ioc,
1937 volume_handle, &volume_wwid)) {
1938 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1939 "failure at %s:%d/%s()!\n", ioc->name,
1940 __FILE__, __LINE__, __func__));
1941 return 1;
1942 }
1943 }
1944
1945 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301946 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301947 sas_device_priv_data->sas_target->sas_address);
1948 if (!sas_device) {
1949 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1950 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1951 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1952 __func__));
1953 return 1;
1954 }
1955
1956 sas_device->volume_handle = volume_handle;
1957 sas_device->volume_wwid = volume_wwid;
1958 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1959 qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
1960 ssp_target = 1;
Suganath prabu Subramani30158dc2016-01-28 12:07:01 +05301961 if (sas_device->device_info &
1962 MPI2_SAS_DEVICE_INFO_SEP) {
1963 sdev_printk(KERN_WARNING, sdev,
1964 "set ignore_delay_remove for handle(0x%04x)\n",
1965 sas_device_priv_data->sas_target->handle);
1966 sas_device_priv_data->ignore_delay_remove = 1;
1967 ds = "SES";
1968 } else
1969 ds = "SSP";
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301970 } else {
1971 qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
1972 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
1973 ds = "STP";
1974 else if (sas_device->device_info &
1975 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1976 ds = "SATA";
1977 }
1978
1979 sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " \
1980 "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
1981 ds, handle, (unsigned long long)sas_device->sas_address,
1982 sas_device->phy, (unsigned long long)sas_device->device_name);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05301983 if (sas_device->enclosure_handle != 0)
1984 sdev_printk(KERN_INFO, sdev,
1985 "%s: enclosure_logical_id(0x%016llx), slot(%d)\n",
1986 ds, (unsigned long long)
1987 sas_device->enclosure_logical_id, sas_device->slot);
1988 if (sas_device->connector_name[0] != '\0')
1989 sdev_printk(KERN_INFO, sdev,
1990 "%s: enclosure level(0x%04x), connector name( %s)\n",
1991 ds, sas_device->enclosure_level,
1992 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301993
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301994 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301995 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1996
1997 if (!ssp_target)
1998 _scsih_display_sata_capabilities(ioc, handle, sdev);
1999
2000
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302001 scsih_change_queue_depth(sdev, qdepth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302002
2003 if (ssp_target) {
2004 sas_read_port_mode_page(sdev);
2005 _scsih_enable_tlr(ioc, sdev);
2006 }
2007
2008 return 0;
2009}
2010
2011/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302012 * scsih_bios_param - fetch head, sector, cylinder info for a disk
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302013 * @sdev: scsi device struct
2014 * @bdev: pointer to block device context
2015 * @capacity: device size (in 512 byte sectors)
2016 * @params: three element array to place output:
2017 * params[0] number of heads (max 255)
2018 * params[1] number of sectors (max 63)
2019 * params[2] number of cylinders
2020 *
2021 * Return nothing.
2022 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002023static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302024scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302025 sector_t capacity, int params[])
2026{
2027 int heads;
2028 int sectors;
2029 sector_t cylinders;
2030 ulong dummy;
2031
2032 heads = 64;
2033 sectors = 32;
2034
2035 dummy = heads * sectors;
2036 cylinders = capacity;
2037 sector_div(cylinders, dummy);
2038
2039 /*
2040 * Handle extended translation size for logical drives
2041 * > 1Gb
2042 */
2043 if ((ulong)capacity >= 0x200000) {
2044 heads = 255;
2045 sectors = 63;
2046 dummy = heads * sectors;
2047 cylinders = capacity;
2048 sector_div(cylinders, dummy);
2049 }
2050
2051 /* return result */
2052 params[0] = heads;
2053 params[1] = sectors;
2054 params[2] = cylinders;
2055
2056 return 0;
2057}
2058
2059/**
2060 * _scsih_response_code - translation of device response code
2061 * @ioc: per adapter object
2062 * @response_code: response code returned by the device
2063 *
2064 * Return nothing.
2065 */
2066static void
2067_scsih_response_code(struct MPT3SAS_ADAPTER *ioc, u8 response_code)
2068{
2069 char *desc;
2070
2071 switch (response_code) {
2072 case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
2073 desc = "task management request completed";
2074 break;
2075 case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
2076 desc = "invalid frame";
2077 break;
2078 case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2079 desc = "task management request not supported";
2080 break;
2081 case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
2082 desc = "task management request failed";
2083 break;
2084 case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2085 desc = "task management request succeeded";
2086 break;
2087 case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2088 desc = "invalid lun";
2089 break;
2090 case 0xA:
2091 desc = "overlapped tag attempted";
2092 break;
2093 case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2094 desc = "task queued, however not sent to target";
2095 break;
2096 default:
2097 desc = "unknown";
2098 break;
2099 }
2100 pr_warn(MPT3SAS_FMT "response_code(0x%01x): %s\n",
2101 ioc->name, response_code, desc);
2102}
2103
2104/**
2105 * _scsih_tm_done - tm completion routine
2106 * @ioc: per adapter object
2107 * @smid: system request message index
2108 * @msix_index: MSIX table index supplied by the OS
2109 * @reply: reply message frame(lower 32bit addr)
2110 * Context: none.
2111 *
2112 * The callback handler when using scsih_issue_tm.
2113 *
2114 * Return 1 meaning mf should be freed from _base_interrupt
2115 * 0 means the mf is freed from this function.
2116 */
2117static u8
2118_scsih_tm_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
2119{
2120 MPI2DefaultReply_t *mpi_reply;
2121
2122 if (ioc->tm_cmds.status == MPT3_CMD_NOT_USED)
2123 return 1;
2124 if (ioc->tm_cmds.smid != smid)
2125 return 1;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302126 ioc->tm_cmds.status |= MPT3_CMD_COMPLETE;
2127 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
2128 if (mpi_reply) {
2129 memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
2130 ioc->tm_cmds.status |= MPT3_CMD_REPLY_VALID;
2131 }
2132 ioc->tm_cmds.status &= ~MPT3_CMD_PENDING;
2133 complete(&ioc->tm_cmds.done);
2134 return 1;
2135}
2136
2137/**
2138 * mpt3sas_scsih_set_tm_flag - set per target tm_busy
2139 * @ioc: per adapter object
2140 * @handle: device handle
2141 *
2142 * During taskmangement request, we need to freeze the device queue.
2143 */
2144void
2145mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2146{
2147 struct MPT3SAS_DEVICE *sas_device_priv_data;
2148 struct scsi_device *sdev;
2149 u8 skip = 0;
2150
2151 shost_for_each_device(sdev, ioc->shost) {
2152 if (skip)
2153 continue;
2154 sas_device_priv_data = sdev->hostdata;
2155 if (!sas_device_priv_data)
2156 continue;
2157 if (sas_device_priv_data->sas_target->handle == handle) {
2158 sas_device_priv_data->sas_target->tm_busy = 1;
2159 skip = 1;
2160 ioc->ignore_loginfos = 1;
2161 }
2162 }
2163}
2164
2165/**
2166 * mpt3sas_scsih_clear_tm_flag - clear per target tm_busy
2167 * @ioc: per adapter object
2168 * @handle: device handle
2169 *
2170 * During taskmangement request, we need to freeze the device queue.
2171 */
2172void
2173mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2174{
2175 struct MPT3SAS_DEVICE *sas_device_priv_data;
2176 struct scsi_device *sdev;
2177 u8 skip = 0;
2178
2179 shost_for_each_device(sdev, ioc->shost) {
2180 if (skip)
2181 continue;
2182 sas_device_priv_data = sdev->hostdata;
2183 if (!sas_device_priv_data)
2184 continue;
2185 if (sas_device_priv_data->sas_target->handle == handle) {
2186 sas_device_priv_data->sas_target->tm_busy = 0;
2187 skip = 1;
2188 ioc->ignore_loginfos = 0;
2189 }
2190 }
2191}
2192
2193/**
2194 * mpt3sas_scsih_issue_tm - main routine for sending tm requests
2195 * @ioc: per adapter struct
2196 * @device_handle: device handle
2197 * @channel: the channel assigned by the OS
2198 * @id: the id assigned by the OS
2199 * @lun: lun number
2200 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
2201 * @smid_task: smid assigned to the task
2202 * @timeout: timeout in seconds
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302203 * Context: user
2204 *
2205 * A generic API for sending task management requests to firmware.
2206 *
2207 * The callback index is set inside `ioc->tm_cb_idx`.
2208 *
2209 * Return SUCCESS or FAILED.
2210 */
2211int
2212mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
Calvin Owens96902832016-07-28 21:38:20 -07002213 uint id, uint lun, u8 type, u16 smid_task, ulong timeout)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302214{
2215 Mpi2SCSITaskManagementRequest_t *mpi_request;
2216 Mpi2SCSITaskManagementReply_t *mpi_reply;
2217 u16 smid = 0;
2218 u32 ioc_state;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302219 struct scsiio_tracker *scsi_lookup = NULL;
2220 int rc;
Suganath prabu Subramani03d1fb32016-01-28 12:07:06 +05302221 u16 msix_task = 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302222
Calvin Owens96902832016-07-28 21:38:20 -07002223 lockdep_assert_held(&ioc->tm_cmds.mutex);
2224
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302225 if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) {
2226 pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n",
2227 __func__, ioc->name);
Calvin Owens96902832016-07-28 21:38:20 -07002228 return FAILED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302229 }
2230
2231 if (ioc->shost_recovery || ioc->remove_host ||
2232 ioc->pci_error_recovery) {
2233 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
2234 __func__, ioc->name);
Calvin Owens96902832016-07-28 21:38:20 -07002235 return FAILED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302236 }
2237
2238 ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
2239 if (ioc_state & MPI2_DOORBELL_USED) {
2240 dhsprintk(ioc, pr_info(MPT3SAS_FMT
2241 "unexpected doorbell active!\n", ioc->name));
Calvin Owens98c56ad2016-07-28 21:38:21 -07002242 rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Calvin Owens96902832016-07-28 21:38:20 -07002243 return (!rc) ? SUCCESS : FAILED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302244 }
2245
2246 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
2247 mpt3sas_base_fault_info(ioc, ioc_state &
2248 MPI2_DOORBELL_DATA_MASK);
Calvin Owens98c56ad2016-07-28 21:38:21 -07002249 rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Calvin Owens96902832016-07-28 21:38:20 -07002250 return (!rc) ? SUCCESS : FAILED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302251 }
2252
2253 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
2254 if (!smid) {
2255 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
2256 ioc->name, __func__);
Calvin Owens96902832016-07-28 21:38:20 -07002257 return FAILED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302258 }
2259
2260 if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2261 scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
2262
2263 dtmprintk(ioc, pr_info(MPT3SAS_FMT
2264 "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n",
2265 ioc->name, handle, type, smid_task));
2266 ioc->tm_cmds.status = MPT3_CMD_PENDING;
2267 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2268 ioc->tm_cmds.smid = smid;
2269 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
2270 memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
2271 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
2272 mpi_request->DevHandle = cpu_to_le16(handle);
2273 mpi_request->TaskType = type;
2274 mpi_request->TaskMID = cpu_to_le16(smid_task);
2275 int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
2276 mpt3sas_scsih_set_tm_flag(ioc, handle);
2277 init_completion(&ioc->tm_cmds.done);
Suganath prabu Subramani03d1fb32016-01-28 12:07:06 +05302278 if ((type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) &&
2279 (scsi_lookup->msix_io < ioc->reply_queue_count))
2280 msix_task = scsi_lookup->msix_io;
2281 else
2282 msix_task = 0;
2283 mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task);
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002284 wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302285 if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) {
2286 pr_err(MPT3SAS_FMT "%s: timeout\n",
2287 ioc->name, __func__);
2288 _debug_dump_mf(mpi_request,
2289 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2290 if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) {
Calvin Owens98c56ad2016-07-28 21:38:21 -07002291 rc = mpt3sas_base_hard_reset_handler(ioc,
2292 FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302293 rc = (!rc) ? SUCCESS : FAILED;
Calvin Owens96902832016-07-28 21:38:20 -07002294 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302295 }
2296 }
2297
Chaitra P B5f0dfb72016-05-06 14:29:31 +05302298 /* sync IRQs in case those were busy during flush. */
2299 mpt3sas_base_sync_reply_irqs(ioc);
2300
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302301 if (ioc->tm_cmds.status & MPT3_CMD_REPLY_VALID) {
2302 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
2303 mpi_reply = ioc->tm_cmds.reply;
2304 dtmprintk(ioc, pr_info(MPT3SAS_FMT "complete tm: " \
2305 "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
2306 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
2307 le32_to_cpu(mpi_reply->IOCLogInfo),
2308 le32_to_cpu(mpi_reply->TerminationCount)));
2309 if (ioc->logging_level & MPT_DEBUG_TM) {
2310 _scsih_response_code(ioc, mpi_reply->ResponseCode);
2311 if (mpi_reply->IOCStatus)
2312 _debug_dump_mf(mpi_request,
2313 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2314 }
2315 }
2316
2317 switch (type) {
2318 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2319 rc = SUCCESS;
2320 if (scsi_lookup->scmd == NULL)
2321 break;
2322 rc = FAILED;
2323 break;
2324
2325 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2326 if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
2327 rc = FAILED;
2328 else
2329 rc = SUCCESS;
2330 break;
2331 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
2332 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
2333 if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
2334 rc = FAILED;
2335 else
2336 rc = SUCCESS;
2337 break;
2338 case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
2339 rc = SUCCESS;
2340 break;
2341 default:
2342 rc = FAILED;
2343 break;
2344 }
2345
Calvin Owens96902832016-07-28 21:38:20 -07002346out:
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302347 mpt3sas_scsih_clear_tm_flag(ioc, handle);
2348 ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302349 return rc;
Calvin Owens96902832016-07-28 21:38:20 -07002350}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302351
Calvin Owens96902832016-07-28 21:38:20 -07002352int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
2353 uint channel, uint id, uint lun, u8 type, u16 smid_task, ulong timeout)
2354{
2355 int ret;
2356
2357 mutex_lock(&ioc->tm_cmds.mutex);
2358 ret = mpt3sas_scsih_issue_tm(ioc, handle, channel, id, lun, type,
2359 smid_task, timeout);
2360 mutex_unlock(&ioc->tm_cmds.mutex);
2361
2362 return ret;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302363}
2364
2365/**
2366 * _scsih_tm_display_info - displays info about the device
2367 * @ioc: per adapter struct
2368 * @scmd: pointer to scsi command object
2369 *
2370 * Called by task management callback handlers.
2371 */
2372static void
2373_scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
2374{
2375 struct scsi_target *starget = scmd->device->sdev_target;
2376 struct MPT3SAS_TARGET *priv_target = starget->hostdata;
2377 struct _sas_device *sas_device = NULL;
2378 unsigned long flags;
2379 char *device_str = NULL;
2380
2381 if (!priv_target)
2382 return;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05302383 if (ioc->hide_ir_msg)
2384 device_str = "WarpDrive";
2385 else
2386 device_str = "volume";
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302387
2388 scsi_print_command(scmd);
2389 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
2390 starget_printk(KERN_INFO, starget,
2391 "%s handle(0x%04x), %s wwid(0x%016llx)\n",
2392 device_str, priv_target->handle,
2393 device_str, (unsigned long long)priv_target->sas_address);
2394 } else {
2395 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302396 sas_device = __mpt3sas_get_sdev_from_target(ioc, priv_target);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302397 if (sas_device) {
2398 if (priv_target->flags &
2399 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2400 starget_printk(KERN_INFO, starget,
2401 "volume handle(0x%04x), "
2402 "volume wwid(0x%016llx)\n",
2403 sas_device->volume_handle,
2404 (unsigned long long)sas_device->volume_wwid);
2405 }
2406 starget_printk(KERN_INFO, starget,
2407 "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
2408 sas_device->handle,
2409 (unsigned long long)sas_device->sas_address,
2410 sas_device->phy);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05302411 if (sas_device->enclosure_handle != 0)
2412 starget_printk(KERN_INFO, starget,
2413 "enclosure_logical_id(0x%016llx), slot(%d)\n",
2414 (unsigned long long)
2415 sas_device->enclosure_logical_id,
2416 sas_device->slot);
Suganath prabu Subramani869817f2016-01-28 12:07:00 +05302417 if (sas_device->connector_name[0] != '\0')
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05302418 starget_printk(KERN_INFO, starget,
2419 "enclosure level(0x%04x),connector name(%s)\n",
2420 sas_device->enclosure_level,
2421 sas_device->connector_name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302422
2423 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302424 }
2425 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2426 }
2427}
2428
2429/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302430 * scsih_abort - eh threads main abort routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302431 * @scmd: pointer to scsi command object
2432 *
2433 * Returns SUCCESS if command aborted else FAILED
2434 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002435static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302436scsih_abort(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302437{
2438 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2439 struct MPT3SAS_DEVICE *sas_device_priv_data;
2440 u16 smid;
2441 u16 handle;
2442 int r;
2443
2444 sdev_printk(KERN_INFO, scmd->device,
2445 "attempting task abort! scmd(%p)\n", scmd);
2446 _scsih_tm_display_info(ioc, scmd);
2447
2448 sas_device_priv_data = scmd->device->hostdata;
2449 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2450 sdev_printk(KERN_INFO, scmd->device,
2451 "device been deleted! scmd(%p)\n", scmd);
2452 scmd->result = DID_NO_CONNECT << 16;
2453 scmd->scsi_done(scmd);
2454 r = SUCCESS;
2455 goto out;
2456 }
2457
2458 /* search for the command */
2459 smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
2460 if (!smid) {
2461 scmd->result = DID_RESET << 16;
2462 r = SUCCESS;
2463 goto out;
2464 }
2465
2466 /* for hidden raid components and volumes this is not supported */
2467 if (sas_device_priv_data->sas_target->flags &
2468 MPT_TARGET_FLAGS_RAID_COMPONENT ||
2469 sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
2470 scmd->result = DID_RESET << 16;
2471 r = FAILED;
2472 goto out;
2473 }
2474
2475 mpt3sas_halt_firmware(ioc);
2476
2477 handle = sas_device_priv_data->sas_target->handle;
Calvin Owens96902832016-07-28 21:38:20 -07002478 r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302479 scmd->device->id, scmd->device->lun,
Calvin Owens96902832016-07-28 21:38:20 -07002480 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302481
2482 out:
2483 sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
2484 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2485 return r;
2486}
2487
2488/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302489 * scsih_dev_reset - eh threads main device reset routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302490 * @scmd: pointer to scsi command object
2491 *
2492 * Returns SUCCESS if command aborted else FAILED
2493 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002494static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302495scsih_dev_reset(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302496{
2497 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2498 struct MPT3SAS_DEVICE *sas_device_priv_data;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302499 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302500 u16 handle;
2501 int r;
2502
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302503 struct scsi_target *starget = scmd->device->sdev_target;
2504 struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
2505
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302506 sdev_printk(KERN_INFO, scmd->device,
2507 "attempting device reset! scmd(%p)\n", scmd);
2508 _scsih_tm_display_info(ioc, scmd);
2509
2510 sas_device_priv_data = scmd->device->hostdata;
2511 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2512 sdev_printk(KERN_INFO, scmd->device,
2513 "device been deleted! scmd(%p)\n", scmd);
2514 scmd->result = DID_NO_CONNECT << 16;
2515 scmd->scsi_done(scmd);
2516 r = SUCCESS;
2517 goto out;
2518 }
2519
2520 /* for hidden raid components obtain the volume_handle */
2521 handle = 0;
2522 if (sas_device_priv_data->sas_target->flags &
2523 MPT_TARGET_FLAGS_RAID_COMPONENT) {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302524 sas_device = mpt3sas_get_sdev_from_target(ioc,
2525 target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302526 if (sas_device)
2527 handle = sas_device->volume_handle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302528 } else
2529 handle = sas_device_priv_data->sas_target->handle;
2530
2531 if (!handle) {
2532 scmd->result = DID_RESET << 16;
2533 r = FAILED;
2534 goto out;
2535 }
2536
Calvin Owens96902832016-07-28 21:38:20 -07002537 r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302538 scmd->device->id, scmd->device->lun,
Calvin Owens96902832016-07-28 21:38:20 -07002539 MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302540
2541 out:
2542 sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
2543 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302544
2545 if (sas_device)
2546 sas_device_put(sas_device);
2547
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302548 return r;
2549}
2550
2551/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302552 * scsih_target_reset - eh threads main target reset routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302553 * @scmd: pointer to scsi command object
2554 *
2555 * Returns SUCCESS if command aborted else FAILED
2556 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002557static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302558scsih_target_reset(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302559{
2560 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2561 struct MPT3SAS_DEVICE *sas_device_priv_data;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302562 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302563 u16 handle;
2564 int r;
2565 struct scsi_target *starget = scmd->device->sdev_target;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302566 struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302567
2568 starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n",
2569 scmd);
2570 _scsih_tm_display_info(ioc, scmd);
2571
2572 sas_device_priv_data = scmd->device->hostdata;
2573 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2574 starget_printk(KERN_INFO, starget, "target been deleted! scmd(%p)\n",
2575 scmd);
2576 scmd->result = DID_NO_CONNECT << 16;
2577 scmd->scsi_done(scmd);
2578 r = SUCCESS;
2579 goto out;
2580 }
2581
2582 /* for hidden raid components obtain the volume_handle */
2583 handle = 0;
2584 if (sas_device_priv_data->sas_target->flags &
2585 MPT_TARGET_FLAGS_RAID_COMPONENT) {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302586 sas_device = mpt3sas_get_sdev_from_target(ioc,
2587 target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302588 if (sas_device)
2589 handle = sas_device->volume_handle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302590 } else
2591 handle = sas_device_priv_data->sas_target->handle;
2592
2593 if (!handle) {
2594 scmd->result = DID_RESET << 16;
2595 r = FAILED;
2596 goto out;
2597 }
2598
Calvin Owens96902832016-07-28 21:38:20 -07002599 r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302600 scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
Calvin Owens96902832016-07-28 21:38:20 -07002601 30);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302602
2603 out:
2604 starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
2605 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302606
2607 if (sas_device)
2608 sas_device_put(sas_device);
2609
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302610 return r;
2611}
2612
2613
2614/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302615 * scsih_host_reset - eh threads main host reset routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302616 * @scmd: pointer to scsi command object
2617 *
2618 * Returns SUCCESS if command aborted else FAILED
2619 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07002620static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302621scsih_host_reset(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302622{
2623 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2624 int r, retval;
2625
2626 pr_info(MPT3SAS_FMT "attempting host reset! scmd(%p)\n",
2627 ioc->name, scmd);
2628 scsi_print_command(scmd);
2629
Sreekanth Reddyddb588b2015-01-12 11:38:57 +05302630 if (ioc->is_driver_loading) {
2631 pr_info(MPT3SAS_FMT "Blocking the host reset\n",
2632 ioc->name);
2633 r = FAILED;
2634 goto out;
2635 }
2636
Calvin Owens98c56ad2016-07-28 21:38:21 -07002637 retval = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302638 r = (retval < 0) ? FAILED : SUCCESS;
Sreekanth Reddyddb588b2015-01-12 11:38:57 +05302639out:
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302640 pr_info(MPT3SAS_FMT "host reset: %s scmd(%p)\n",
2641 ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2642
2643 return r;
2644}
2645
2646/**
2647 * _scsih_fw_event_add - insert and queue up fw_event
2648 * @ioc: per adapter object
2649 * @fw_event: object describing the event
2650 * Context: This function will acquire ioc->fw_event_lock.
2651 *
2652 * This adds the firmware event object into link list, then queues it up to
2653 * be processed from user context.
2654 *
2655 * Return nothing.
2656 */
2657static void
2658_scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
2659{
2660 unsigned long flags;
2661
2662 if (ioc->firmware_event_thread == NULL)
2663 return;
2664
2665 spin_lock_irqsave(&ioc->fw_event_lock, flags);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302666 fw_event_work_get(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302667 INIT_LIST_HEAD(&fw_event->list);
2668 list_add_tail(&fw_event->list, &ioc->fw_event_list);
2669 INIT_WORK(&fw_event->work, _firmware_event_work);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302670 fw_event_work_get(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302671 queue_work(ioc->firmware_event_thread, &fw_event->work);
2672 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2673}
2674
2675/**
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302676 * _scsih_fw_event_del_from_list - delete fw_event from the list
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302677 * @ioc: per adapter object
2678 * @fw_event: object describing the event
2679 * Context: This function will acquire ioc->fw_event_lock.
2680 *
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302681 * If the fw_event is on the fw_event_list, remove it and do a put.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302682 *
2683 * Return nothing.
2684 */
2685static void
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302686_scsih_fw_event_del_from_list(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302687 *fw_event)
2688{
2689 unsigned long flags;
2690
2691 spin_lock_irqsave(&ioc->fw_event_lock, flags);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302692 if (!list_empty(&fw_event->list)) {
2693 list_del_init(&fw_event->list);
2694 fw_event_work_put(fw_event);
2695 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302696 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2697}
2698
2699
2700 /**
2701 * mpt3sas_send_trigger_data_event - send event for processing trigger data
2702 * @ioc: per adapter object
2703 * @event_data: trigger event data
2704 *
2705 * Return nothing.
2706 */
2707void
2708mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
2709 struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
2710{
2711 struct fw_event_work *fw_event;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302712 u16 sz;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302713
2714 if (ioc->is_driver_loading)
2715 return;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302716 sz = sizeof(*event_data);
2717 fw_event = alloc_fw_event_work(sz);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302718 if (!fw_event)
2719 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302720 fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG;
2721 fw_event->ioc = ioc;
2722 memcpy(fw_event->event_data, event_data, sizeof(*event_data));
2723 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302724 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302725}
2726
2727/**
2728 * _scsih_error_recovery_delete_devices - remove devices not responding
2729 * @ioc: per adapter object
2730 *
2731 * Return nothing.
2732 */
2733static void
2734_scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc)
2735{
2736 struct fw_event_work *fw_event;
2737
2738 if (ioc->is_driver_loading)
2739 return;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302740 fw_event = alloc_fw_event_work(0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302741 if (!fw_event)
2742 return;
2743 fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES;
2744 fw_event->ioc = ioc;
2745 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302746 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302747}
2748
2749/**
2750 * mpt3sas_port_enable_complete - port enable completed (fake event)
2751 * @ioc: per adapter object
2752 *
2753 * Return nothing.
2754 */
2755void
2756mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc)
2757{
2758 struct fw_event_work *fw_event;
2759
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302760 fw_event = alloc_fw_event_work(0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302761 if (!fw_event)
2762 return;
2763 fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE;
2764 fw_event->ioc = ioc;
2765 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302766 fw_event_work_put(fw_event);
2767}
2768
2769static struct fw_event_work *dequeue_next_fw_event(struct MPT3SAS_ADAPTER *ioc)
2770{
2771 unsigned long flags;
2772 struct fw_event_work *fw_event = NULL;
2773
2774 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2775 if (!list_empty(&ioc->fw_event_list)) {
2776 fw_event = list_first_entry(&ioc->fw_event_list,
2777 struct fw_event_work, list);
2778 list_del_init(&fw_event->list);
2779 }
2780 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2781
2782 return fw_event;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302783}
2784
2785/**
2786 * _scsih_fw_event_cleanup_queue - cleanup event queue
2787 * @ioc: per adapter object
2788 *
2789 * Walk the firmware event queue, either killing timers, or waiting
2790 * for outstanding events to complete
2791 *
2792 * Return nothing.
2793 */
2794static void
2795_scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
2796{
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302797 struct fw_event_work *fw_event;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302798
2799 if (list_empty(&ioc->fw_event_list) ||
2800 !ioc->firmware_event_thread || in_interrupt())
2801 return;
2802
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302803 while ((fw_event = dequeue_next_fw_event(ioc))) {
2804 /*
2805 * Wait on the fw_event to complete. If this returns 1, then
2806 * the event was never executed, and we need a put for the
Joe Lawrenceb8ac0cc2016-04-18 10:50:12 -04002807 * reference the work had on the fw_event.
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302808 *
2809 * If it did execute, we wait for it to finish, and the put will
2810 * happen from _firmware_event_work()
2811 */
Joe Lawrenceb8ac0cc2016-04-18 10:50:12 -04002812 if (cancel_work_sync(&fw_event->work))
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302813 fw_event_work_put(fw_event);
2814
2815 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302816 }
2817}
2818
2819/**
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302820 * _scsih_internal_device_block - block the sdev device
2821 * @sdev: per device object
2822 * @sas_device_priv_data : per device driver private data
2823 *
2824 * make sure device is blocked without error, if not
2825 * print an error
2826 */
2827static void
2828_scsih_internal_device_block(struct scsi_device *sdev,
2829 struct MPT3SAS_DEVICE *sas_device_priv_data)
2830{
2831 int r = 0;
2832
2833 sdev_printk(KERN_INFO, sdev, "device_block, handle(0x%04x)\n",
2834 sas_device_priv_data->sas_target->handle);
2835 sas_device_priv_data->block = 1;
2836
2837 r = scsi_internal_device_block(sdev);
2838 if (r == -EINVAL)
2839 sdev_printk(KERN_WARNING, sdev,
2840 "device_block failed with return(%d) for handle(0x%04x)\n",
2841 sas_device_priv_data->sas_target->handle, r);
2842}
2843
2844/**
2845 * _scsih_internal_device_unblock - unblock the sdev device
2846 * @sdev: per device object
2847 * @sas_device_priv_data : per device driver private data
2848 * make sure device is unblocked without error, if not retry
2849 * by blocking and then unblocking
2850 */
2851
2852static void
2853_scsih_internal_device_unblock(struct scsi_device *sdev,
2854 struct MPT3SAS_DEVICE *sas_device_priv_data)
2855{
2856 int r = 0;
2857
2858 sdev_printk(KERN_WARNING, sdev, "device_unblock and setting to running, "
2859 "handle(0x%04x)\n", sas_device_priv_data->sas_target->handle);
2860 sas_device_priv_data->block = 0;
2861 r = scsi_internal_device_unblock(sdev, SDEV_RUNNING);
2862 if (r == -EINVAL) {
2863 /* The device has been set to SDEV_RUNNING by SD layer during
2864 * device addition but the request queue is still stopped by
2865 * our earlier block call. We need to perform a block again
2866 * to get the device to SDEV_BLOCK and then to SDEV_RUNNING */
2867
2868 sdev_printk(KERN_WARNING, sdev,
2869 "device_unblock failed with return(%d) for handle(0x%04x) "
2870 "performing a block followed by an unblock\n",
2871 sas_device_priv_data->sas_target->handle, r);
2872 sas_device_priv_data->block = 1;
2873 r = scsi_internal_device_block(sdev);
2874 if (r)
2875 sdev_printk(KERN_WARNING, sdev, "retried device_block "
2876 "failed with return(%d) for handle(0x%04x)\n",
2877 sas_device_priv_data->sas_target->handle, r);
2878
2879 sas_device_priv_data->block = 0;
2880 r = scsi_internal_device_unblock(sdev, SDEV_RUNNING);
2881 if (r)
2882 sdev_printk(KERN_WARNING, sdev, "retried device_unblock"
2883 " failed with return(%d) for handle(0x%04x)\n",
2884 sas_device_priv_data->sas_target->handle, r);
2885 }
2886}
2887
2888/**
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302889 * _scsih_ublock_io_all_device - unblock every device
2890 * @ioc: per adapter object
2891 *
2892 * change the device state from block to running
2893 */
2894static void
2895_scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
2896{
2897 struct MPT3SAS_DEVICE *sas_device_priv_data;
2898 struct scsi_device *sdev;
2899
2900 shost_for_each_device(sdev, ioc->shost) {
2901 sas_device_priv_data = sdev->hostdata;
2902 if (!sas_device_priv_data)
2903 continue;
2904 if (!sas_device_priv_data->block)
2905 continue;
2906
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302907 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2908 "device_running, handle(0x%04x)\n",
2909 sas_device_priv_data->sas_target->handle));
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302910 _scsih_internal_device_unblock(sdev, sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302911 }
2912}
2913
2914
2915/**
2916 * _scsih_ublock_io_device - prepare device to be deleted
2917 * @ioc: per adapter object
2918 * @sas_addr: sas address
2919 *
2920 * unblock then put device in offline state
2921 */
2922static void
2923_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
2924{
2925 struct MPT3SAS_DEVICE *sas_device_priv_data;
2926 struct scsi_device *sdev;
2927
2928 shost_for_each_device(sdev, ioc->shost) {
2929 sas_device_priv_data = sdev->hostdata;
2930 if (!sas_device_priv_data)
2931 continue;
2932 if (sas_device_priv_data->sas_target->sas_address
2933 != sas_address)
2934 continue;
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302935 if (sas_device_priv_data->block)
2936 _scsih_internal_device_unblock(sdev,
2937 sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302938 }
2939}
2940
2941/**
2942 * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
2943 * @ioc: per adapter object
2944 * @handle: device handle
2945 *
2946 * During device pull we need to appropiately set the sdev state.
2947 */
2948static void
2949_scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc)
2950{
2951 struct MPT3SAS_DEVICE *sas_device_priv_data;
2952 struct scsi_device *sdev;
2953
2954 shost_for_each_device(sdev, ioc->shost) {
2955 sas_device_priv_data = sdev->hostdata;
2956 if (!sas_device_priv_data)
2957 continue;
2958 if (sas_device_priv_data->block)
2959 continue;
Suganath prabu Subramani30158dc2016-01-28 12:07:01 +05302960 if (sas_device_priv_data->ignore_delay_remove) {
2961 sdev_printk(KERN_INFO, sdev,
2962 "%s skip device_block for SES handle(0x%04x)\n",
2963 __func__, sas_device_priv_data->sas_target->handle);
2964 continue;
2965 }
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302966 _scsih_internal_device_block(sdev, sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302967 }
2968}
2969
2970/**
2971 * _scsih_block_io_device - set the device state to SDEV_BLOCK
2972 * @ioc: per adapter object
2973 * @handle: device handle
2974 *
2975 * During device pull we need to appropiately set the sdev state.
2976 */
2977static void
2978_scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2979{
2980 struct MPT3SAS_DEVICE *sas_device_priv_data;
2981 struct scsi_device *sdev;
Sreekanth Reddye4bc7f52015-06-30 12:24:49 +05302982 struct _sas_device *sas_device;
2983
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302984 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddye4bc7f52015-06-30 12:24:49 +05302985 if (!sas_device)
2986 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302987
2988 shost_for_each_device(sdev, ioc->shost) {
2989 sas_device_priv_data = sdev->hostdata;
2990 if (!sas_device_priv_data)
2991 continue;
2992 if (sas_device_priv_data->sas_target->handle != handle)
2993 continue;
2994 if (sas_device_priv_data->block)
2995 continue;
Sreekanth Reddye4bc7f52015-06-30 12:24:49 +05302996 if (sas_device->pend_sas_rphy_add)
2997 continue;
Suganath prabu Subramani30158dc2016-01-28 12:07:01 +05302998 if (sas_device_priv_data->ignore_delay_remove) {
2999 sdev_printk(KERN_INFO, sdev,
3000 "%s skip device_block for SES handle(0x%04x)\n",
3001 __func__, sas_device_priv_data->sas_target->handle);
3002 continue;
3003 }
Sreekanth Reddydf838f92015-06-30 12:25:05 +05303004 _scsih_internal_device_block(sdev, sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303005 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303006
3007 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303008}
3009
3010/**
3011 * _scsih_block_io_to_children_attached_to_ex
3012 * @ioc: per adapter object
3013 * @sas_expander: the sas_device object
3014 *
3015 * This routine set sdev state to SDEV_BLOCK for all devices
3016 * attached to this expander. This function called when expander is
3017 * pulled.
3018 */
3019static void
3020_scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc,
3021 struct _sas_node *sas_expander)
3022{
3023 struct _sas_port *mpt3sas_port;
3024 struct _sas_device *sas_device;
3025 struct _sas_node *expander_sibling;
3026 unsigned long flags;
3027
3028 if (!sas_expander)
3029 return;
3030
3031 list_for_each_entry(mpt3sas_port,
3032 &sas_expander->sas_port_list, port_list) {
3033 if (mpt3sas_port->remote_identify.device_type ==
3034 SAS_END_DEVICE) {
3035 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303036 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
3037 mpt3sas_port->remote_identify.sas_address);
3038 if (sas_device) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303039 set_bit(sas_device->handle,
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303040 ioc->blocking_handles);
3041 sas_device_put(sas_device);
3042 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303043 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3044 }
3045 }
3046
3047 list_for_each_entry(mpt3sas_port,
3048 &sas_expander->sas_port_list, port_list) {
3049
3050 if (mpt3sas_port->remote_identify.device_type ==
3051 SAS_EDGE_EXPANDER_DEVICE ||
3052 mpt3sas_port->remote_identify.device_type ==
3053 SAS_FANOUT_EXPANDER_DEVICE) {
3054 expander_sibling =
3055 mpt3sas_scsih_expander_find_by_sas_address(
3056 ioc, mpt3sas_port->remote_identify.sas_address);
3057 _scsih_block_io_to_children_attached_to_ex(ioc,
3058 expander_sibling);
3059 }
3060 }
3061}
3062
3063/**
3064 * _scsih_block_io_to_children_attached_directly
3065 * @ioc: per adapter object
3066 * @event_data: topology change event data
3067 *
3068 * This routine set sdev state to SDEV_BLOCK for all devices
3069 * direct attached during device pull.
3070 */
3071static void
3072_scsih_block_io_to_children_attached_directly(struct MPT3SAS_ADAPTER *ioc,
3073 Mpi2EventDataSasTopologyChangeList_t *event_data)
3074{
3075 int i;
3076 u16 handle;
3077 u16 reason_code;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303078
3079 for (i = 0; i < event_data->NumEntries; i++) {
3080 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3081 if (!handle)
3082 continue;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303083 reason_code = event_data->PHY[i].PhyStatus &
3084 MPI2_EVENT_SAS_TOPO_RC_MASK;
3085 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
3086 _scsih_block_io_device(ioc, handle);
3087 }
3088}
3089
3090/**
3091 * _scsih_tm_tr_send - send task management request
3092 * @ioc: per adapter object
3093 * @handle: device handle
3094 * Context: interrupt time.
3095 *
3096 * This code is to initiate the device removal handshake protocol
3097 * with controller firmware. This function will issue target reset
3098 * using high priority request queue. It will send a sas iounit
3099 * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
3100 *
3101 * This is designed to send muliple task management request at the same
3102 * time to the fifo. If the fifo is full, we will append the request,
3103 * and process it in a future completion.
3104 */
3105static void
3106_scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3107{
3108 Mpi2SCSITaskManagementRequest_t *mpi_request;
3109 u16 smid;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303110 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303111 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
3112 u64 sas_address = 0;
3113 unsigned long flags;
3114 struct _tr_list *delayed_tr;
3115 u32 ioc_state;
3116
3117 if (ioc->remove_host) {
3118 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3119 "%s: host has been removed: handle(0x%04x)\n",
3120 __func__, ioc->name, handle));
3121 return;
3122 } else if (ioc->pci_error_recovery) {
3123 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3124 "%s: host in pci error recovery: handle(0x%04x)\n",
3125 __func__, ioc->name,
3126 handle));
3127 return;
3128 }
3129 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3130 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3131 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3132 "%s: host is not operational: handle(0x%04x)\n",
3133 __func__, ioc->name,
3134 handle));
3135 return;
3136 }
3137
3138 /* if PD, then return */
3139 if (test_bit(handle, ioc->pd_handles))
3140 return;
3141
3142 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303143 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303144 if (sas_device && sas_device->starget &&
3145 sas_device->starget->hostdata) {
3146 sas_target_priv_data = sas_device->starget->hostdata;
3147 sas_target_priv_data->deleted = 1;
3148 sas_address = sas_device->sas_address;
3149 }
3150 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3151
3152 if (sas_target_priv_data) {
3153 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3154 "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n",
3155 ioc->name, handle,
3156 (unsigned long long)sas_address));
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05303157 if (sas_device->enclosure_handle != 0)
3158 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3159 "setting delete flag:enclosure logical id(0x%016llx),"
3160 " slot(%d)\n", ioc->name, (unsigned long long)
3161 sas_device->enclosure_logical_id,
3162 sas_device->slot));
Suganath prabu Subramani869817f2016-01-28 12:07:00 +05303163 if (sas_device->connector_name[0] != '\0')
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05303164 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3165 "setting delete flag: enclosure level(0x%04x),"
3166 " connector name( %s)\n", ioc->name,
3167 sas_device->enclosure_level,
3168 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303169 _scsih_ublock_io_device(ioc, sas_address);
3170 sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
3171 }
3172
3173 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
3174 if (!smid) {
3175 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3176 if (!delayed_tr)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303177 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303178 INIT_LIST_HEAD(&delayed_tr->list);
3179 delayed_tr->handle = handle;
3180 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3181 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3182 "DELAYED:tr:handle(0x%04x), (open)\n",
3183 ioc->name, handle));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303184 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303185 }
3186
3187 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3188 "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3189 ioc->name, handle, smid,
3190 ioc->tm_tr_cb_idx));
3191 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3192 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3193 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3194 mpi_request->DevHandle = cpu_to_le16(handle);
3195 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
Suganath prabu Subramani03d1fb32016-01-28 12:07:06 +05303196 mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303197 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303198
3199out:
3200 if (sas_device)
3201 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303202}
3203
3204/**
3205 * _scsih_tm_tr_complete -
3206 * @ioc: per adapter object
3207 * @smid: system request message index
3208 * @msix_index: MSIX table index supplied by the OS
3209 * @reply: reply message frame(lower 32bit addr)
3210 * Context: interrupt time.
3211 *
3212 * This is the target reset completion routine.
3213 * This code is part of the code to initiate the device removal
3214 * handshake protocol with controller firmware.
3215 * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE)
3216 *
3217 * Return 1 meaning mf should be freed from _base_interrupt
3218 * 0 means the mf is freed from this function.
3219 */
3220static u8
3221_scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
3222 u32 reply)
3223{
3224 u16 handle;
3225 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
3226 Mpi2SCSITaskManagementReply_t *mpi_reply =
3227 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3228 Mpi2SasIoUnitControlRequest_t *mpi_request;
3229 u16 smid_sas_ctrl;
3230 u32 ioc_state;
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05303231 struct _sc_list *delayed_sc;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303232
3233 if (ioc->remove_host) {
3234 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3235 "%s: host has been removed\n", __func__, ioc->name));
3236 return 1;
3237 } else if (ioc->pci_error_recovery) {
3238 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3239 "%s: host in pci error recovery\n", __func__,
3240 ioc->name));
3241 return 1;
3242 }
3243 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3244 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3245 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3246 "%s: host is not operational\n", __func__, ioc->name));
3247 return 1;
3248 }
3249 if (unlikely(!mpi_reply)) {
3250 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3251 ioc->name, __FILE__, __LINE__, __func__);
3252 return 1;
3253 }
3254 mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
3255 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3256 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3257 dewtprintk(ioc, pr_err(MPT3SAS_FMT
3258 "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
3259 ioc->name, handle,
3260 le16_to_cpu(mpi_reply->DevHandle), smid));
3261 return 0;
3262 }
3263
3264 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
3265 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3266 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3267 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3268 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3269 le32_to_cpu(mpi_reply->IOCLogInfo),
3270 le32_to_cpu(mpi_reply->TerminationCount)));
3271
3272 smid_sas_ctrl = mpt3sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx);
3273 if (!smid_sas_ctrl) {
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05303274 delayed_sc = kzalloc(sizeof(*delayed_sc), GFP_ATOMIC);
3275 if (!delayed_sc)
3276 return _scsih_check_for_pending_tm(ioc, smid);
3277 INIT_LIST_HEAD(&delayed_sc->list);
3278 delayed_sc->handle = mpi_request_tm->DevHandle;
3279 list_add_tail(&delayed_sc->list, &ioc->delayed_sc_list);
3280 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3281 "DELAYED:sc:handle(0x%04x), (open)\n",
3282 ioc->name, handle));
3283 return _scsih_check_for_pending_tm(ioc, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303284 }
3285
3286 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3287 "sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3288 ioc->name, handle, smid_sas_ctrl,
3289 ioc->tm_sas_control_cb_idx));
3290 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid_sas_ctrl);
3291 memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
3292 mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
3293 mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
3294 mpi_request->DevHandle = mpi_request_tm->DevHandle;
3295 mpt3sas_base_put_smid_default(ioc, smid_sas_ctrl);
3296
3297 return _scsih_check_for_pending_tm(ioc, smid);
3298}
3299
Suganath Prabuf8c80f62018-10-31 18:53:36 +05303300/** _scsih_allow_scmd_to_device - check whether scmd needs to
3301 * issue to IOC or not.
3302 * @ioc: per adapter object
3303 * @scmd: pointer to scsi command object
3304 *
3305 * Returns true if scmd can be issued to IOC otherwise returns false.
3306 */
3307inline bool _scsih_allow_scmd_to_device(struct MPT3SAS_ADAPTER *ioc,
3308 struct scsi_cmnd *scmd)
3309{
3310
3311 if (ioc->pci_error_recovery)
3312 return false;
3313
3314 if (ioc->hba_mpi_version_belonged == MPI2_VERSION) {
3315 if (ioc->remove_host)
3316 return false;
3317
3318 return true;
3319 }
3320
3321 if (ioc->remove_host) {
3322
3323 switch (scmd->cmnd[0]) {
3324 case SYNCHRONIZE_CACHE:
3325 case START_STOP:
3326 return true;
3327 default:
3328 return false;
3329 }
3330 }
3331
3332 return true;
3333}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303334
3335/**
3336 * _scsih_sas_control_complete - completion routine
3337 * @ioc: per adapter object
3338 * @smid: system request message index
3339 * @msix_index: MSIX table index supplied by the OS
3340 * @reply: reply message frame(lower 32bit addr)
3341 * Context: interrupt time.
3342 *
3343 * This is the sas iounit control completion routine.
3344 * This code is part of the code to initiate the device removal
3345 * handshake protocol with controller firmware.
3346 *
3347 * Return 1 meaning mf should be freed from _base_interrupt
3348 * 0 means the mf is freed from this function.
3349 */
3350static u8
3351_scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
3352 u8 msix_index, u32 reply)
3353{
3354 Mpi2SasIoUnitControlReply_t *mpi_reply =
3355 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3356
3357 if (likely(mpi_reply)) {
3358 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3359 "sc_complete:handle(0x%04x), (open) "
3360 "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
3361 ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
3362 le16_to_cpu(mpi_reply->IOCStatus),
3363 le32_to_cpu(mpi_reply->IOCLogInfo)));
3364 } else {
3365 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3366 ioc->name, __FILE__, __LINE__, __func__);
3367 }
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05303368 return mpt3sas_check_for_pending_internal_cmds(ioc, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303369}
3370
3371/**
3372 * _scsih_tm_tr_volume_send - send target reset request for volumes
3373 * @ioc: per adapter object
3374 * @handle: device handle
3375 * Context: interrupt time.
3376 *
3377 * This is designed to send muliple task management request at the same
3378 * time to the fifo. If the fifo is full, we will append the request,
3379 * and process it in a future completion.
3380 */
3381static void
3382_scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3383{
3384 Mpi2SCSITaskManagementRequest_t *mpi_request;
3385 u16 smid;
3386 struct _tr_list *delayed_tr;
3387
3388 if (ioc->shost_recovery || ioc->remove_host ||
3389 ioc->pci_error_recovery) {
3390 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3391 "%s: host reset in progress!\n",
3392 __func__, ioc->name));
3393 return;
3394 }
3395
3396 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx);
3397 if (!smid) {
3398 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3399 if (!delayed_tr)
3400 return;
3401 INIT_LIST_HEAD(&delayed_tr->list);
3402 delayed_tr->handle = handle;
3403 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list);
3404 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3405 "DELAYED:tr:handle(0x%04x), (open)\n",
3406 ioc->name, handle));
3407 return;
3408 }
3409
3410 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3411 "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3412 ioc->name, handle, smid,
3413 ioc->tm_tr_volume_cb_idx));
3414 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3415 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3416 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3417 mpi_request->DevHandle = cpu_to_le16(handle);
3418 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
Suganath prabu Subramani03d1fb32016-01-28 12:07:06 +05303419 mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303420}
3421
3422/**
3423 * _scsih_tm_volume_tr_complete - target reset completion
3424 * @ioc: per adapter object
3425 * @smid: system request message index
3426 * @msix_index: MSIX table index supplied by the OS
3427 * @reply: reply message frame(lower 32bit addr)
3428 * Context: interrupt time.
3429 *
3430 * Return 1 meaning mf should be freed from _base_interrupt
3431 * 0 means the mf is freed from this function.
3432 */
3433static u8
3434_scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
3435 u8 msix_index, u32 reply)
3436{
3437 u16 handle;
3438 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
3439 Mpi2SCSITaskManagementReply_t *mpi_reply =
3440 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3441
3442 if (ioc->shost_recovery || ioc->remove_host ||
3443 ioc->pci_error_recovery) {
3444 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3445 "%s: host reset in progress!\n",
3446 __func__, ioc->name));
3447 return 1;
3448 }
3449 if (unlikely(!mpi_reply)) {
3450 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3451 ioc->name, __FILE__, __LINE__, __func__);
3452 return 1;
3453 }
3454
3455 mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
3456 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3457 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3458 dewtprintk(ioc, pr_err(MPT3SAS_FMT
3459 "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
3460 ioc->name, handle,
3461 le16_to_cpu(mpi_reply->DevHandle), smid));
3462 return 0;
3463 }
3464
3465 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3466 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3467 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3468 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3469 le32_to_cpu(mpi_reply->IOCLogInfo),
3470 le32_to_cpu(mpi_reply->TerminationCount)));
3471
3472 return _scsih_check_for_pending_tm(ioc, smid);
3473}
3474
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05303475/**
3476 * _scsih_issue_delayed_event_ack - issue delayed Event ACK messages
3477 * @ioc: per adapter object
3478 * @smid: system request message index
3479 * @event: Event ID
3480 * @event_context: used to track events uniquely
3481 *
3482 * Context - processed in interrupt context.
3483 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07003484static void
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05303485_scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event,
3486 u32 event_context)
3487{
3488 Mpi2EventAckRequest_t *ack_request;
3489 int i = smid - ioc->internal_smid;
3490 unsigned long flags;
3491
3492 /* Without releasing the smid just update the
3493 * call back index and reuse the same smid for
3494 * processing this delayed request
3495 */
3496 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
3497 ioc->internal_lookup[i].cb_idx = ioc->base_cb_idx;
3498 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
3499
3500 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3501 "EVENT ACK: event(0x%04x), smid(%d), cb(%d)\n",
3502 ioc->name, le16_to_cpu(event), smid,
3503 ioc->base_cb_idx));
3504 ack_request = mpt3sas_base_get_msg_frame(ioc, smid);
3505 memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
3506 ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
3507 ack_request->Event = event;
3508 ack_request->EventContext = event_context;
3509 ack_request->VF_ID = 0; /* TODO */
3510 ack_request->VP_ID = 0;
3511 mpt3sas_base_put_smid_default(ioc, smid);
3512}
3513
3514/**
3515 * _scsih_issue_delayed_sas_io_unit_ctrl - issue delayed
3516 * sas_io_unit_ctrl messages
3517 * @ioc: per adapter object
3518 * @smid: system request message index
3519 * @handle: device handle
3520 *
3521 * Context - processed in interrupt context.
3522 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07003523static void
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05303524_scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc,
3525 u16 smid, u16 handle)
3526 {
3527 Mpi2SasIoUnitControlRequest_t *mpi_request;
3528 u32 ioc_state;
3529 int i = smid - ioc->internal_smid;
3530 unsigned long flags;
3531
3532 if (ioc->remove_host) {
3533 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3534 "%s: host has been removed\n",
3535 __func__, ioc->name));
3536 return;
3537 } else if (ioc->pci_error_recovery) {
3538 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3539 "%s: host in pci error recovery\n",
3540 __func__, ioc->name));
3541 return;
3542 }
3543 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3544 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3545 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3546 "%s: host is not operational\n",
3547 __func__, ioc->name));
3548 return;
3549 }
3550
3551 /* Without releasing the smid just update the
3552 * call back index and reuse the same smid for
3553 * processing this delayed request
3554 */
3555 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
3556 ioc->internal_lookup[i].cb_idx = ioc->tm_sas_control_cb_idx;
3557 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
3558
3559 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3560 "sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3561 ioc->name, le16_to_cpu(handle), smid,
3562 ioc->tm_sas_control_cb_idx));
3563 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3564 memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
3565 mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
3566 mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
3567 mpi_request->DevHandle = handle;
3568 mpt3sas_base_put_smid_default(ioc, smid);
3569}
3570
3571/**
3572 * _scsih_check_for_pending_internal_cmds - check for pending internal messages
3573 * @ioc: per adapter object
3574 * @smid: system request message index
3575 *
3576 * Context: Executed in interrupt context
3577 *
3578 * This will check delayed internal messages list, and process the
3579 * next request.
3580 *
3581 * Return 1 meaning mf should be freed from _base_interrupt
3582 * 0 means the mf is freed from this function.
3583 */
3584u8
3585mpt3sas_check_for_pending_internal_cmds(struct MPT3SAS_ADAPTER *ioc, u16 smid)
3586{
3587 struct _sc_list *delayed_sc;
3588 struct _event_ack_list *delayed_event_ack;
3589
3590 if (!list_empty(&ioc->delayed_event_ack_list)) {
3591 delayed_event_ack = list_entry(ioc->delayed_event_ack_list.next,
3592 struct _event_ack_list, list);
3593 _scsih_issue_delayed_event_ack(ioc, smid,
3594 delayed_event_ack->Event, delayed_event_ack->EventContext);
3595 list_del(&delayed_event_ack->list);
3596 kfree(delayed_event_ack);
3597 return 0;
3598 }
3599
3600 if (!list_empty(&ioc->delayed_sc_list)) {
3601 delayed_sc = list_entry(ioc->delayed_sc_list.next,
3602 struct _sc_list, list);
3603 _scsih_issue_delayed_sas_io_unit_ctrl(ioc, smid,
3604 delayed_sc->handle);
3605 list_del(&delayed_sc->list);
3606 kfree(delayed_sc);
3607 return 0;
3608 }
3609 return 1;
3610}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303611
3612/**
3613 * _scsih_check_for_pending_tm - check for pending task management
3614 * @ioc: per adapter object
3615 * @smid: system request message index
3616 *
3617 * This will check delayed target reset list, and feed the
3618 * next reqeust.
3619 *
3620 * Return 1 meaning mf should be freed from _base_interrupt
3621 * 0 means the mf is freed from this function.
3622 */
3623static u8
3624_scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid)
3625{
3626 struct _tr_list *delayed_tr;
3627
3628 if (!list_empty(&ioc->delayed_tr_volume_list)) {
3629 delayed_tr = list_entry(ioc->delayed_tr_volume_list.next,
3630 struct _tr_list, list);
3631 mpt3sas_base_free_smid(ioc, smid);
3632 _scsih_tm_tr_volume_send(ioc, delayed_tr->handle);
3633 list_del(&delayed_tr->list);
3634 kfree(delayed_tr);
3635 return 0;
3636 }
3637
3638 if (!list_empty(&ioc->delayed_tr_list)) {
3639 delayed_tr = list_entry(ioc->delayed_tr_list.next,
3640 struct _tr_list, list);
3641 mpt3sas_base_free_smid(ioc, smid);
3642 _scsih_tm_tr_send(ioc, delayed_tr->handle);
3643 list_del(&delayed_tr->list);
3644 kfree(delayed_tr);
3645 return 0;
3646 }
3647
3648 return 1;
3649}
3650
3651/**
3652 * _scsih_check_topo_delete_events - sanity check on topo events
3653 * @ioc: per adapter object
3654 * @event_data: the event data payload
3655 *
3656 * This routine added to better handle cable breaker.
3657 *
3658 * This handles the case where driver receives multiple expander
3659 * add and delete events in a single shot. When there is a delete event
3660 * the routine will void any pending add events waiting in the event queue.
3661 *
3662 * Return nothing.
3663 */
3664static void
3665_scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc,
3666 Mpi2EventDataSasTopologyChangeList_t *event_data)
3667{
3668 struct fw_event_work *fw_event;
3669 Mpi2EventDataSasTopologyChangeList_t *local_event_data;
3670 u16 expander_handle;
3671 struct _sas_node *sas_expander;
3672 unsigned long flags;
3673 int i, reason_code;
3674 u16 handle;
3675
3676 for (i = 0 ; i < event_data->NumEntries; i++) {
3677 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3678 if (!handle)
3679 continue;
3680 reason_code = event_data->PHY[i].PhyStatus &
3681 MPI2_EVENT_SAS_TOPO_RC_MASK;
3682 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)
3683 _scsih_tm_tr_send(ioc, handle);
3684 }
3685
3686 expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
3687 if (expander_handle < ioc->sas_hba.num_phys) {
3688 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3689 return;
3690 }
3691 if (event_data->ExpStatus ==
3692 MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
3693 /* put expander attached devices into blocking state */
3694 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3695 sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
3696 expander_handle);
3697 _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
3698 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3699 do {
3700 handle = find_first_bit(ioc->blocking_handles,
3701 ioc->facts.MaxDevHandle);
3702 if (handle < ioc->facts.MaxDevHandle)
3703 _scsih_block_io_device(ioc, handle);
3704 } while (test_and_clear_bit(handle, ioc->blocking_handles));
3705 } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
3706 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3707
3708 if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
3709 return;
3710
3711 /* mark ignore flag for pending events */
3712 spin_lock_irqsave(&ioc->fw_event_lock, flags);
3713 list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
3714 if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
3715 fw_event->ignore)
3716 continue;
Joe Lawrence35b62362014-06-25 17:05:34 -04003717 local_event_data = (Mpi2EventDataSasTopologyChangeList_t *)
3718 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303719 if (local_event_data->ExpStatus ==
3720 MPI2_EVENT_SAS_TOPO_ES_ADDED ||
3721 local_event_data->ExpStatus ==
3722 MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
3723 if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
3724 expander_handle) {
3725 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3726 "setting ignoring flag\n", ioc->name));
3727 fw_event->ignore = 1;
3728 }
3729 }
3730 }
3731 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
3732}
3733
3734/**
3735 * _scsih_set_volume_delete_flag - setting volume delete flag
3736 * @ioc: per adapter object
3737 * @handle: device handle
3738 *
3739 * This returns nothing.
3740 */
3741static void
3742_scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3743{
3744 struct _raid_device *raid_device;
3745 struct MPT3SAS_TARGET *sas_target_priv_data;
3746 unsigned long flags;
3747
3748 spin_lock_irqsave(&ioc->raid_device_lock, flags);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303749 raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303750 if (raid_device && raid_device->starget &&
3751 raid_device->starget->hostdata) {
3752 sas_target_priv_data =
3753 raid_device->starget->hostdata;
3754 sas_target_priv_data->deleted = 1;
3755 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3756 "setting delete flag: handle(0x%04x), "
3757 "wwid(0x%016llx)\n", ioc->name, handle,
3758 (unsigned long long) raid_device->wwid));
3759 }
3760 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
3761}
3762
3763/**
3764 * _scsih_set_volume_handle_for_tr - set handle for target reset to volume
3765 * @handle: input handle
3766 * @a: handle for volume a
3767 * @b: handle for volume b
3768 *
3769 * IR firmware only supports two raid volumes. The purpose of this
3770 * routine is to set the volume handle in either a or b. When the given
3771 * input handle is non-zero, or when a and b have not been set before.
3772 */
3773static void
3774_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b)
3775{
3776 if (!handle || handle == *a || handle == *b)
3777 return;
3778 if (!*a)
3779 *a = handle;
3780 else if (!*b)
3781 *b = handle;
3782}
3783
3784/**
3785 * _scsih_check_ir_config_unhide_events - check for UNHIDE events
3786 * @ioc: per adapter object
3787 * @event_data: the event data payload
3788 * Context: interrupt time.
3789 *
3790 * This routine will send target reset to volume, followed by target
3791 * resets to the PDs. This is called when a PD has been removed, or
3792 * volume has been deleted or removed. When the target reset is sent
3793 * to volume, the PD target resets need to be queued to start upon
3794 * completion of the volume target reset.
3795 *
3796 * Return nothing.
3797 */
3798static void
3799_scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc,
3800 Mpi2EventDataIrConfigChangeList_t *event_data)
3801{
3802 Mpi2EventIrConfigElement_t *element;
3803 int i;
3804 u16 handle, volume_handle, a, b;
3805 struct _tr_list *delayed_tr;
3806
3807 a = 0;
3808 b = 0;
3809
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303810 if (ioc->is_warpdrive)
3811 return;
3812
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303813 /* Volume Resets for Deleted or Removed */
3814 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3815 for (i = 0; i < event_data->NumElements; i++, element++) {
3816 if (le32_to_cpu(event_data->Flags) &
3817 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3818 continue;
3819 if (element->ReasonCode ==
3820 MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED ||
3821 element->ReasonCode ==
3822 MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
3823 volume_handle = le16_to_cpu(element->VolDevHandle);
3824 _scsih_set_volume_delete_flag(ioc, volume_handle);
3825 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3826 }
3827 }
3828
3829 /* Volume Resets for UNHIDE events */
3830 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3831 for (i = 0; i < event_data->NumElements; i++, element++) {
3832 if (le32_to_cpu(event_data->Flags) &
3833 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3834 continue;
3835 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) {
3836 volume_handle = le16_to_cpu(element->VolDevHandle);
3837 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3838 }
3839 }
3840
3841 if (a)
3842 _scsih_tm_tr_volume_send(ioc, a);
3843 if (b)
3844 _scsih_tm_tr_volume_send(ioc, b);
3845
3846 /* PD target resets */
3847 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3848 for (i = 0; i < event_data->NumElements; i++, element++) {
3849 if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE)
3850 continue;
3851 handle = le16_to_cpu(element->PhysDiskDevHandle);
3852 volume_handle = le16_to_cpu(element->VolDevHandle);
3853 clear_bit(handle, ioc->pd_handles);
3854 if (!volume_handle)
3855 _scsih_tm_tr_send(ioc, handle);
3856 else if (volume_handle == a || volume_handle == b) {
3857 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3858 BUG_ON(!delayed_tr);
3859 INIT_LIST_HEAD(&delayed_tr->list);
3860 delayed_tr->handle = handle;
3861 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3862 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3863 "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name,
3864 handle));
3865 } else
3866 _scsih_tm_tr_send(ioc, handle);
3867 }
3868}
3869
3870
3871/**
3872 * _scsih_check_volume_delete_events - set delete flag for volumes
3873 * @ioc: per adapter object
3874 * @event_data: the event data payload
3875 * Context: interrupt time.
3876 *
3877 * This will handle the case when the cable connected to entire volume is
3878 * pulled. We will take care of setting the deleted flag so normal IO will
3879 * not be sent.
3880 *
3881 * Return nothing.
3882 */
3883static void
3884_scsih_check_volume_delete_events(struct MPT3SAS_ADAPTER *ioc,
3885 Mpi2EventDataIrVolume_t *event_data)
3886{
3887 u32 state;
3888
3889 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
3890 return;
3891 state = le32_to_cpu(event_data->NewValue);
3892 if (state == MPI2_RAID_VOL_STATE_MISSING || state ==
3893 MPI2_RAID_VOL_STATE_FAILED)
3894 _scsih_set_volume_delete_flag(ioc,
3895 le16_to_cpu(event_data->VolDevHandle));
3896}
3897
3898/**
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05303899 * _scsih_temp_threshold_events - display temperature threshold exceeded events
3900 * @ioc: per adapter object
3901 * @event_data: the temp threshold event data
3902 * Context: interrupt time.
3903 *
3904 * Return nothing.
3905 */
3906static void
3907_scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc,
3908 Mpi2EventDataTemperature_t *event_data)
3909{
3910 if (ioc->temp_sensors_count >= event_data->SensorNum) {
3911 pr_err(MPT3SAS_FMT "Temperature Threshold flags %s%s%s%s"
3912 " exceeded for Sensor: %d !!!\n", ioc->name,
3913 ((le16_to_cpu(event_data->Status) & 0x1) == 1) ? "0 " : " ",
3914 ((le16_to_cpu(event_data->Status) & 0x2) == 2) ? "1 " : " ",
3915 ((le16_to_cpu(event_data->Status) & 0x4) == 4) ? "2 " : " ",
3916 ((le16_to_cpu(event_data->Status) & 0x8) == 8) ? "3 " : " ",
3917 event_data->SensorNum);
3918 pr_err(MPT3SAS_FMT "Current Temp In Celsius: %d\n",
3919 ioc->name, event_data->CurrentTemperature);
3920 }
3921}
3922
James Bottomley16236802017-01-01 09:39:24 -08003923static int _scsih_set_satl_pending(struct scsi_cmnd *scmd, bool pending)
Suganath Prabu S7ff723a2016-11-17 16:15:58 +05303924{
James Bottomley16236802017-01-01 09:39:24 -08003925 struct MPT3SAS_DEVICE *priv = scmd->device->hostdata;
3926
3927 if (scmd->cmnd[0] != ATA_12 && scmd->cmnd[0] != ATA_16)
3928 return 0;
3929
3930 if (pending)
3931 return test_and_set_bit(0, &priv->ata_command_pending);
3932
3933 clear_bit(0, &priv->ata_command_pending);
3934 return 0;
Suganath Prabu S7ff723a2016-11-17 16:15:58 +05303935}
3936
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05303937/**
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303938 * _scsih_flush_running_cmds - completing outstanding commands.
3939 * @ioc: per adapter object
3940 *
3941 * The flushing out of all pending scmd commands following host reset,
3942 * where all IO is dropped to the floor.
3943 *
3944 * Return nothing.
3945 */
3946static void
3947_scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
3948{
3949 struct scsi_cmnd *scmd;
3950 u16 smid;
3951 u16 count = 0;
3952
3953 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
3954 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
3955 if (!scmd)
3956 continue;
3957 count++;
James Bottomley16236802017-01-01 09:39:24 -08003958 _scsih_set_satl_pending(scmd, false);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303959 mpt3sas_base_free_smid(ioc, smid);
3960 scsi_dma_unmap(scmd);
3961 if (ioc->pci_error_recovery)
3962 scmd->result = DID_NO_CONNECT << 16;
3963 else
3964 scmd->result = DID_RESET << 16;
3965 scmd->scsi_done(scmd);
3966 }
3967 dtmprintk(ioc, pr_info(MPT3SAS_FMT "completing %d cmds\n",
3968 ioc->name, count));
3969}
3970
3971/**
3972 * _scsih_setup_eedp - setup MPI request for EEDP transfer
3973 * @ioc: per adapter object
3974 * @scmd: pointer to scsi command object
3975 * @mpi_request: pointer to the SCSI_IO reqest message frame
3976 *
3977 * Supporting protection 1 and 3.
3978 *
3979 * Returns nothing
3980 */
3981static void
3982_scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
3983 Mpi2SCSIIORequest_t *mpi_request)
3984{
3985 u16 eedp_flags;
3986 unsigned char prot_op = scsi_get_prot_op(scmd);
3987 unsigned char prot_type = scsi_get_prot_type(scmd);
3988 Mpi25SCSIIORequest_t *mpi_request_3v =
3989 (Mpi25SCSIIORequest_t *)mpi_request;
3990
3991 if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
3992 return;
3993
3994 if (prot_op == SCSI_PROT_READ_STRIP)
3995 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
3996 else if (prot_op == SCSI_PROT_WRITE_INSERT)
3997 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
3998 else
3999 return;
4000
4001 switch (prot_type) {
4002 case SCSI_PROT_DIF_TYPE1:
4003 case SCSI_PROT_DIF_TYPE2:
4004
4005 /*
4006 * enable ref/guard checking
4007 * auto increment ref tag
4008 */
4009 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
4010 MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
4011 MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
4012 mpi_request->CDB.EEDP32.PrimaryReferenceTag =
Chaitra P B648512cc2016-05-06 14:29:28 +05304013 cpu_to_be32(scsi_prot_ref_tag(scmd));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304014 break;
4015
4016 case SCSI_PROT_DIF_TYPE3:
4017
4018 /*
4019 * enable guard checking
4020 */
4021 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
4022
4023 break;
4024 }
4025
4026 mpi_request_3v->EEDPBlockSize =
4027 cpu_to_le16(scmd->device->sector_size);
4028 mpi_request->EEDPFlags = cpu_to_le16(eedp_flags);
4029}
4030
4031/**
4032 * _scsih_eedp_error_handling - return sense code for EEDP errors
4033 * @scmd: pointer to scsi command object
4034 * @ioc_status: ioc status
4035 *
4036 * Returns nothing
4037 */
4038static void
4039_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
4040{
4041 u8 ascq;
4042
4043 switch (ioc_status) {
4044 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4045 ascq = 0x01;
4046 break;
4047 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4048 ascq = 0x02;
4049 break;
4050 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4051 ascq = 0x03;
4052 break;
4053 default:
4054 ascq = 0x00;
4055 break;
4056 }
4057 scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10,
4058 ascq);
4059 scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) |
4060 SAM_STAT_CHECK_CONDITION;
4061}
4062
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304063/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05304064 * scsih_qcmd - main scsi request entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304065 * @scmd: pointer to scsi command object
4066 * @done: function pointer to be invoked on completion
4067 *
4068 * The callback index is set inside `ioc->scsi_io_cb_idx`.
4069 *
4070 * Returns 0 on success. If there's a failure, return either:
4071 * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
4072 * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
4073 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07004074static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05304075scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304076{
Matthew Wilcoxd8bfbd82014-03-27 16:40:31 -04004077 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304078 struct MPT3SAS_DEVICE *sas_device_priv_data;
4079 struct MPT3SAS_TARGET *sas_target_priv_data;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304080 struct _raid_device *raid_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304081 Mpi2SCSIIORequest_t *mpi_request;
4082 u32 mpi_control;
4083 u16 smid;
4084 u16 handle;
4085
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304086 if (ioc->logging_level & MPT_DEBUG_SCSI)
4087 scsi_print_command(scmd);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304088
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304089 sas_device_priv_data = scmd->device->hostdata;
4090 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
4091 scmd->result = DID_NO_CONNECT << 16;
4092 scmd->scsi_done(scmd);
4093 return 0;
4094 }
4095
Suganath Prabuf8c80f62018-10-31 18:53:36 +05304096 if (!(_scsih_allow_scmd_to_device(ioc, scmd))) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304097 scmd->result = DID_NO_CONNECT << 16;
4098 scmd->scsi_done(scmd);
4099 return 0;
4100 }
4101
4102 sas_target_priv_data = sas_device_priv_data->sas_target;
4103
4104 /* invalid device handle */
4105 handle = sas_target_priv_data->handle;
4106 if (handle == MPT3SAS_INVALID_DEVICE_HANDLE) {
4107 scmd->result = DID_NO_CONNECT << 16;
4108 scmd->scsi_done(scmd);
4109 return 0;
4110 }
4111
4112
4113 /* host recovery or link resets sent via IOCTLs */
4114 if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
4115 return SCSI_MLQUEUE_HOST_BUSY;
4116
4117 /* device has been deleted */
4118 else if (sas_target_priv_data->deleted) {
4119 scmd->result = DID_NO_CONNECT << 16;
4120 scmd->scsi_done(scmd);
4121 return 0;
4122 /* device busy with task managment */
4123 } else if (sas_target_priv_data->tm_busy ||
4124 sas_device_priv_data->block)
4125 return SCSI_MLQUEUE_DEVICE_BUSY;
4126
Chaitra P B388f0c82017-12-27 23:09:11 -08004127 /*
4128 * Bug work around for firmware SATL handling. The loop
4129 * is based on atomic operations and ensures consistency
4130 * since we're lockless at this point
4131 */
4132 do {
4133 if (test_bit(0, &sas_device_priv_data->ata_command_pending)) {
4134 scmd->result = SAM_STAT_BUSY;
4135 scmd->scsi_done(scmd);
4136 return 0;
4137 }
4138 } while (_scsih_set_satl_pending(scmd, true));
4139
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304140 if (scmd->sc_data_direction == DMA_FROM_DEVICE)
4141 mpi_control = MPI2_SCSIIO_CONTROL_READ;
4142 else if (scmd->sc_data_direction == DMA_TO_DEVICE)
4143 mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
4144 else
4145 mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
4146
4147 /* set tags */
Christoph Hellwig609aa222014-10-30 11:54:58 +01004148 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304149
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304150 /* Make sure Device is not raid volume.
4151 * We do not expose raid functionality to upper layer for warpdrive.
4152 */
4153 if (!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev)
Sreekanth Reddy15de0de2015-11-12 23:40:37 +05304154 && sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304155 mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
4156
4157 smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
4158 if (!smid) {
4159 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
4160 ioc->name, __func__);
Chaitra P B388f0c82017-12-27 23:09:11 -08004161 _scsih_set_satl_pending(scmd, false);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304162 goto out;
4163 }
4164 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
4165 memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
4166 _scsih_setup_eedp(ioc, scmd, mpi_request);
4167
4168 if (scmd->cmd_len == 32)
4169 mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
4170 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
4171 if (sas_device_priv_data->sas_target->flags &
4172 MPT_TARGET_FLAGS_RAID_COMPONENT)
4173 mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
4174 else
4175 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
4176 mpi_request->DevHandle = cpu_to_le16(handle);
4177 mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
4178 mpi_request->Control = cpu_to_le32(mpi_control);
4179 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
4180 mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
4181 mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
4182 mpi_request->SenseBufferLowAddress =
4183 mpt3sas_base_get_sense_buffer_dma(ioc, smid);
4184 mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
4185 int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
4186 mpi_request->LUN);
4187 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
4188
4189 if (mpi_request->DataLength) {
4190 if (ioc->build_sg_scmd(ioc, scmd, smid)) {
4191 mpt3sas_base_free_smid(ioc, smid);
Chaitra P B388f0c82017-12-27 23:09:11 -08004192 _scsih_set_satl_pending(scmd, false);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304193 goto out;
4194 }
4195 } else
4196 ioc->build_zero_len_sge(ioc, &mpi_request->SGL);
4197
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304198 raid_device = sas_target_priv_data->raid_device;
4199 if (raid_device && raid_device->direct_io_enabled)
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05304200 mpt3sas_setup_direct_io(ioc, scmd, raid_device, mpi_request,
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304201 smid);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304202
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304203 if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) {
4204 if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
4205 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len |
4206 MPI25_SCSIIO_IOFLAGS_FAST_PATH);
4207 mpt3sas_base_put_smid_fast_path(ioc, smid, handle);
4208 } else
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304209 mpt3sas_base_put_smid_scsi_io(ioc, smid,
4210 le16_to_cpu(mpi_request->DevHandle));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304211 } else
4212 mpt3sas_base_put_smid_default(ioc, smid);
4213 return 0;
4214
4215 out:
4216 return SCSI_MLQUEUE_HOST_BUSY;
4217}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304218
4219/**
4220 * _scsih_normalize_sense - normalize descriptor and fixed format sense data
4221 * @sense_buffer: sense data returned by target
4222 * @data: normalized skey/asc/ascq
4223 *
4224 * Return nothing.
4225 */
4226static void
4227_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
4228{
4229 if ((sense_buffer[0] & 0x7F) >= 0x72) {
4230 /* descriptor format */
4231 data->skey = sense_buffer[1] & 0x0F;
4232 data->asc = sense_buffer[2];
4233 data->ascq = sense_buffer[3];
4234 } else {
4235 /* fixed format */
4236 data->skey = sense_buffer[2] & 0x0F;
4237 data->asc = sense_buffer[12];
4238 data->ascq = sense_buffer[13];
4239 }
4240}
4241
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304242/**
4243 * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
4244 * @ioc: per adapter object
4245 * @scmd: pointer to scsi command object
4246 * @mpi_reply: reply mf payload returned from firmware
4247 *
4248 * scsi_status - SCSI Status code returned from target device
4249 * scsi_state - state info associated with SCSI_IO determined by ioc
4250 * ioc_status - ioc supplied status info
4251 *
4252 * Return nothing.
4253 */
4254static void
4255_scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
4256 Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
4257{
4258 u32 response_info;
4259 u8 *response_bytes;
4260 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
4261 MPI2_IOCSTATUS_MASK;
4262 u8 scsi_state = mpi_reply->SCSIState;
4263 u8 scsi_status = mpi_reply->SCSIStatus;
4264 char *desc_ioc_state = NULL;
4265 char *desc_scsi_status = NULL;
4266 char *desc_scsi_state = ioc->tmp_string;
4267 u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
4268 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304269 struct scsi_target *starget = scmd->device->sdev_target;
4270 struct MPT3SAS_TARGET *priv_target = starget->hostdata;
4271 char *device_str = NULL;
4272
4273 if (!priv_target)
4274 return;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304275 if (ioc->hide_ir_msg)
4276 device_str = "WarpDrive";
4277 else
4278 device_str = "volume";
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304279
4280 if (log_info == 0x31170000)
4281 return;
4282
4283 switch (ioc_status) {
4284 case MPI2_IOCSTATUS_SUCCESS:
4285 desc_ioc_state = "success";
4286 break;
4287 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4288 desc_ioc_state = "invalid function";
4289 break;
4290 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4291 desc_ioc_state = "scsi recovered error";
4292 break;
4293 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
4294 desc_ioc_state = "scsi invalid dev handle";
4295 break;
4296 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4297 desc_ioc_state = "scsi device not there";
4298 break;
4299 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4300 desc_ioc_state = "scsi data overrun";
4301 break;
4302 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4303 desc_ioc_state = "scsi data underrun";
4304 break;
4305 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4306 desc_ioc_state = "scsi io data error";
4307 break;
4308 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4309 desc_ioc_state = "scsi protocol error";
4310 break;
4311 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4312 desc_ioc_state = "scsi task terminated";
4313 break;
4314 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4315 desc_ioc_state = "scsi residual mismatch";
4316 break;
4317 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4318 desc_ioc_state = "scsi task mgmt failed";
4319 break;
4320 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4321 desc_ioc_state = "scsi ioc terminated";
4322 break;
4323 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4324 desc_ioc_state = "scsi ext terminated";
4325 break;
4326 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4327 desc_ioc_state = "eedp guard error";
4328 break;
4329 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4330 desc_ioc_state = "eedp ref tag error";
4331 break;
4332 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4333 desc_ioc_state = "eedp app tag error";
4334 break;
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05304335 case MPI2_IOCSTATUS_INSUFFICIENT_POWER:
4336 desc_ioc_state = "insufficient power";
4337 break;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304338 default:
4339 desc_ioc_state = "unknown";
4340 break;
4341 }
4342
4343 switch (scsi_status) {
4344 case MPI2_SCSI_STATUS_GOOD:
4345 desc_scsi_status = "good";
4346 break;
4347 case MPI2_SCSI_STATUS_CHECK_CONDITION:
4348 desc_scsi_status = "check condition";
4349 break;
4350 case MPI2_SCSI_STATUS_CONDITION_MET:
4351 desc_scsi_status = "condition met";
4352 break;
4353 case MPI2_SCSI_STATUS_BUSY:
4354 desc_scsi_status = "busy";
4355 break;
4356 case MPI2_SCSI_STATUS_INTERMEDIATE:
4357 desc_scsi_status = "intermediate";
4358 break;
4359 case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
4360 desc_scsi_status = "intermediate condmet";
4361 break;
4362 case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
4363 desc_scsi_status = "reservation conflict";
4364 break;
4365 case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
4366 desc_scsi_status = "command terminated";
4367 break;
4368 case MPI2_SCSI_STATUS_TASK_SET_FULL:
4369 desc_scsi_status = "task set full";
4370 break;
4371 case MPI2_SCSI_STATUS_ACA_ACTIVE:
4372 desc_scsi_status = "aca active";
4373 break;
4374 case MPI2_SCSI_STATUS_TASK_ABORTED:
4375 desc_scsi_status = "task aborted";
4376 break;
4377 default:
4378 desc_scsi_status = "unknown";
4379 break;
4380 }
4381
4382 desc_scsi_state[0] = '\0';
4383 if (!scsi_state)
4384 desc_scsi_state = " ";
4385 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4386 strcat(desc_scsi_state, "response info ");
4387 if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4388 strcat(desc_scsi_state, "state terminated ");
4389 if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
4390 strcat(desc_scsi_state, "no status ");
4391 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
4392 strcat(desc_scsi_state, "autosense failed ");
4393 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
4394 strcat(desc_scsi_state, "autosense valid ");
4395
4396 scsi_print_command(scmd);
4397
4398 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
4399 pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
4400 device_str, (unsigned long long)priv_target->sas_address);
4401 } else {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304402 sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304403 if (sas_device) {
4404 pr_warn(MPT3SAS_FMT
4405 "\tsas_address(0x%016llx), phy(%d)\n",
4406 ioc->name, (unsigned long long)
4407 sas_device->sas_address, sas_device->phy);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304408 if (sas_device->enclosure_handle != 0)
4409 pr_warn(MPT3SAS_FMT
4410 "\tenclosure_logical_id(0x%016llx),"
4411 "slot(%d)\n", ioc->name,
4412 (unsigned long long)
4413 sas_device->enclosure_logical_id,
4414 sas_device->slot);
4415 if (sas_device->connector_name[0])
4416 pr_warn(MPT3SAS_FMT
4417 "\tenclosure level(0x%04x),"
4418 " connector name( %s)\n", ioc->name,
4419 sas_device->enclosure_level,
4420 sas_device->connector_name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304421
4422 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304423 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304424 }
4425
4426 pr_warn(MPT3SAS_FMT
4427 "\thandle(0x%04x), ioc_status(%s)(0x%04x), smid(%d)\n",
4428 ioc->name, le16_to_cpu(mpi_reply->DevHandle),
4429 desc_ioc_state, ioc_status, smid);
4430 pr_warn(MPT3SAS_FMT
4431 "\trequest_len(%d), underflow(%d), resid(%d)\n",
4432 ioc->name, scsi_bufflen(scmd), scmd->underflow,
4433 scsi_get_resid(scmd));
4434 pr_warn(MPT3SAS_FMT
4435 "\ttag(%d), transfer_count(%d), sc->result(0x%08x)\n",
4436 ioc->name, le16_to_cpu(mpi_reply->TaskTag),
4437 le32_to_cpu(mpi_reply->TransferCount), scmd->result);
4438 pr_warn(MPT3SAS_FMT
4439 "\tscsi_status(%s)(0x%02x), scsi_state(%s)(0x%02x)\n",
4440 ioc->name, desc_scsi_status,
4441 scsi_status, desc_scsi_state, scsi_state);
4442
4443 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4444 struct sense_info data;
4445 _scsih_normalize_sense(scmd->sense_buffer, &data);
4446 pr_warn(MPT3SAS_FMT
4447 "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n",
4448 ioc->name, data.skey,
4449 data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
4450 }
4451
4452 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
4453 response_info = le32_to_cpu(mpi_reply->ResponseInfo);
4454 response_bytes = (u8 *)&response_info;
4455 _scsih_response_code(ioc, response_bytes[0]);
4456 }
4457}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304458
4459/**
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304460 * _scsih_turn_on_pfa_led - illuminate PFA LED
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304461 * @ioc: per adapter object
4462 * @handle: device handle
4463 * Context: process
4464 *
4465 * Return nothing.
4466 */
4467static void
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304468_scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304469{
4470 Mpi2SepReply_t mpi_reply;
4471 Mpi2SepRequest_t mpi_request;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304472 struct _sas_device *sas_device;
4473
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304474 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304475 if (!sas_device)
4476 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304477
4478 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
4479 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
4480 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
4481 mpi_request.SlotStatus =
4482 cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
4483 mpi_request.DevHandle = cpu_to_le16(handle);
4484 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
4485 if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
4486 &mpi_request)) != 0) {
4487 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
4488 __FILE__, __LINE__, __func__);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304489 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304490 }
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304491 sas_device->pfa_led_on = 1;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304492
4493 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
4494 dewtprintk(ioc, pr_info(MPT3SAS_FMT
4495 "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
4496 ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
4497 le32_to_cpu(mpi_reply.IOCLogInfo)));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304498 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304499 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304500out:
4501 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304502}
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304503
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304504/**
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304505 * _scsih_turn_off_pfa_led - turn off Fault LED
4506 * @ioc: per adapter object
4507 * @sas_device: sas device whose PFA LED has to turned off
4508 * Context: process
4509 *
4510 * Return nothing.
4511 */
4512static void
4513_scsih_turn_off_pfa_led(struct MPT3SAS_ADAPTER *ioc,
4514 struct _sas_device *sas_device)
4515{
4516 Mpi2SepReply_t mpi_reply;
4517 Mpi2SepRequest_t mpi_request;
4518
4519 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
4520 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
4521 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
4522 mpi_request.SlotStatus = 0;
4523 mpi_request.Slot = cpu_to_le16(sas_device->slot);
4524 mpi_request.DevHandle = 0;
4525 mpi_request.EnclosureHandle = cpu_to_le16(sas_device->enclosure_handle);
4526 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
4527 if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
4528 &mpi_request)) != 0) {
4529 printk(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
4530 __FILE__, __LINE__, __func__);
4531 return;
4532 }
4533
4534 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
4535 dewtprintk(ioc, printk(MPT3SAS_FMT
4536 "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
4537 ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
4538 le32_to_cpu(mpi_reply.IOCLogInfo)));
4539 return;
4540 }
4541}
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304542
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304543/**
4544 * _scsih_send_event_to_turn_on_pfa_led - fire delayed event
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304545 * @ioc: per adapter object
4546 * @handle: device handle
4547 * Context: interrupt.
4548 *
4549 * Return nothing.
4550 */
4551static void
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304552_scsih_send_event_to_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304553{
4554 struct fw_event_work *fw_event;
4555
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05304556 fw_event = alloc_fw_event_work(0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304557 if (!fw_event)
4558 return;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304559 fw_event->event = MPT3SAS_TURN_ON_PFA_LED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304560 fw_event->device_handle = handle;
4561 fw_event->ioc = ioc;
4562 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05304563 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304564}
4565
4566/**
4567 * _scsih_smart_predicted_fault - process smart errors
4568 * @ioc: per adapter object
4569 * @handle: device handle
4570 * Context: interrupt.
4571 *
4572 * Return nothing.
4573 */
4574static void
4575_scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
4576{
4577 struct scsi_target *starget;
4578 struct MPT3SAS_TARGET *sas_target_priv_data;
4579 Mpi2EventNotificationReply_t *event_reply;
4580 Mpi2EventDataSasDeviceStatusChange_t *event_data;
4581 struct _sas_device *sas_device;
4582 ssize_t sz;
4583 unsigned long flags;
4584
4585 /* only handle non-raid devices */
4586 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304587 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
4588 if (!sas_device)
4589 goto out_unlock;
4590
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304591 starget = sas_device->starget;
4592 sas_target_priv_data = starget->hostdata;
4593
4594 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304595 ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)))
4596 goto out_unlock;
4597
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304598 if (sas_device->enclosure_handle != 0)
4599 starget_printk(KERN_INFO, starget, "predicted fault, "
4600 "enclosure logical id(0x%016llx), slot(%d)\n",
4601 (unsigned long long)sas_device->enclosure_logical_id,
4602 sas_device->slot);
4603 if (sas_device->connector_name[0] != '\0')
4604 starget_printk(KERN_WARNING, starget, "predicted fault, "
4605 "enclosure level(0x%04x), connector name( %s)\n",
4606 sas_device->enclosure_level,
4607 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304608 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4609
4610 if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304611 _scsih_send_event_to_turn_on_pfa_led(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304612
4613 /* insert into event log */
4614 sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
4615 sizeof(Mpi2EventDataSasDeviceStatusChange_t);
4616 event_reply = kzalloc(sz, GFP_KERNEL);
4617 if (!event_reply) {
4618 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4619 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304620 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304621 }
4622
4623 event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
4624 event_reply->Event =
4625 cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
4626 event_reply->MsgLength = sz/4;
4627 event_reply->EventDataLength =
4628 cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
4629 event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
4630 event_reply->EventData;
4631 event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
4632 event_data->ASC = 0x5D;
4633 event_data->DevHandle = cpu_to_le16(handle);
4634 event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
4635 mpt3sas_ctl_add_to_event_log(ioc, event_reply);
4636 kfree(event_reply);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304637out:
4638 if (sas_device)
4639 sas_device_put(sas_device);
4640 return;
4641
4642out_unlock:
4643 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4644 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304645}
4646
4647/**
4648 * _scsih_io_done - scsi request callback
4649 * @ioc: per adapter object
4650 * @smid: system request message index
4651 * @msix_index: MSIX table index supplied by the OS
4652 * @reply: reply message frame(lower 32bit addr)
4653 *
4654 * Callback handler when using _scsih_qcmd.
4655 *
4656 * Return 1 meaning mf should be freed from _base_interrupt
4657 * 0 means the mf is freed from this function.
4658 */
4659static u8
4660_scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4661{
4662 Mpi2SCSIIORequest_t *mpi_request;
4663 Mpi2SCSIIOReply_t *mpi_reply;
4664 struct scsi_cmnd *scmd;
4665 u16 ioc_status;
4666 u32 xfer_cnt;
4667 u8 scsi_state;
4668 u8 scsi_status;
4669 u32 log_info;
4670 struct MPT3SAS_DEVICE *sas_device_priv_data;
4671 u32 response_code = 0;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304672 unsigned long flags;
Ram Pai9869fb42017-01-26 16:37:01 -02004673 unsigned int sector_sz;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304674
4675 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
4676 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
4677 if (scmd == NULL)
4678 return 1;
4679
James Bottomley16236802017-01-01 09:39:24 -08004680 _scsih_set_satl_pending(scmd, false);
Andrey Grodzovsky18f60842016-11-10 09:35:27 -05004681
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304682 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
4683
4684 if (mpi_reply == NULL) {
4685 scmd->result = DID_OK << 16;
4686 goto out;
4687 }
4688
4689 sas_device_priv_data = scmd->device->hostdata;
4690 if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
4691 sas_device_priv_data->sas_target->deleted) {
4692 scmd->result = DID_NO_CONNECT << 16;
4693 goto out;
4694 }
4695 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
4696
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304697 /*
4698 * WARPDRIVE: If direct_io is set then it is directIO,
4699 * the failed direct I/O should be redirected to volume
4700 */
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05304701 if (mpt3sas_scsi_direct_io_get(ioc, smid) &&
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304702 ((ioc_status & MPI2_IOCSTATUS_MASK)
4703 != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
4704 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
4705 ioc->scsi_lookup[smid - 1].scmd = scmd;
4706 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05304707 mpt3sas_scsi_direct_io_set(ioc, smid, 0);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304708 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
4709 mpi_request->DevHandle =
4710 cpu_to_le16(sas_device_priv_data->sas_target->handle);
4711 mpt3sas_base_put_smid_scsi_io(ioc, smid,
4712 sas_device_priv_data->sas_target->handle);
4713 return 0;
4714 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304715 /* turning off TLR */
4716 scsi_state = mpi_reply->SCSIState;
4717 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4718 response_code =
4719 le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
4720 if (!sas_device_priv_data->tlr_snoop_check) {
4721 sas_device_priv_data->tlr_snoop_check++;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304722 if (!ioc->is_warpdrive &&
4723 !scsih_is_raid(&scmd->device->sdev_gendev) &&
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05304724 sas_is_tlr_enabled(scmd->device) &&
4725 response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) {
4726 sas_disable_tlr(scmd->device);
4727 sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n");
4728 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304729 }
4730
4731 xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
Ram Pai9869fb42017-01-26 16:37:01 -02004732
4733 /* In case of bogus fw or device, we could end up having
4734 * unaligned partial completion. We can force alignment here,
4735 * then scsi-ml does not need to handle this misbehavior.
4736 */
4737 sector_sz = scmd->device->sector_size;
4738 if (unlikely(scmd->request->cmd_type == REQ_TYPE_FS && sector_sz &&
4739 xfer_cnt % sector_sz)) {
4740 sdev_printk(KERN_INFO, scmd->device,
4741 "unaligned partial completion avoided (xfer_cnt=%u, sector_sz=%u)\n",
4742 xfer_cnt, sector_sz);
4743 xfer_cnt = round_down(xfer_cnt, sector_sz);
4744 }
4745
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304746 scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
4747 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
4748 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
4749 else
4750 log_info = 0;
4751 ioc_status &= MPI2_IOCSTATUS_MASK;
4752 scsi_status = mpi_reply->SCSIStatus;
4753
4754 if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
4755 (scsi_status == MPI2_SCSI_STATUS_BUSY ||
4756 scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
4757 scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
4758 ioc_status = MPI2_IOCSTATUS_SUCCESS;
4759 }
4760
4761 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4762 struct sense_info data;
4763 const void *sense_data = mpt3sas_base_get_sense_buffer(ioc,
4764 smid);
4765 u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
4766 le32_to_cpu(mpi_reply->SenseCount));
4767 memcpy(scmd->sense_buffer, sense_data, sz);
4768 _scsih_normalize_sense(scmd->sense_buffer, &data);
4769 /* failure prediction threshold exceeded */
4770 if (data.asc == 0x5D)
4771 _scsih_smart_predicted_fault(ioc,
4772 le16_to_cpu(mpi_reply->DevHandle));
4773 mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304774
Johannes Thumshirn0d667f72016-08-03 15:00:18 +02004775 if ((ioc->logging_level & MPT_DEBUG_REPLY) &&
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304776 ((scmd->sense_buffer[2] == UNIT_ATTENTION) ||
4777 (scmd->sense_buffer[2] == MEDIUM_ERROR) ||
4778 (scmd->sense_buffer[2] == HARDWARE_ERROR)))
4779 _scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304780 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304781 switch (ioc_status) {
4782 case MPI2_IOCSTATUS_BUSY:
4783 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
4784 scmd->result = SAM_STAT_BUSY;
4785 break;
4786
4787 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4788 scmd->result = DID_NO_CONNECT << 16;
4789 break;
4790
4791 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4792 if (sas_device_priv_data->block) {
4793 scmd->result = DID_TRANSPORT_DISRUPTED << 16;
4794 goto out;
4795 }
4796 if (log_info == 0x31110630) {
4797 if (scmd->retries > 2) {
4798 scmd->result = DID_NO_CONNECT << 16;
4799 scsi_device_set_state(scmd->device,
4800 SDEV_OFFLINE);
4801 } else {
4802 scmd->result = DID_SOFT_ERROR << 16;
4803 scmd->device->expecting_cc_ua = 1;
4804 }
4805 break;
Sreekanth Reddy3898f082015-06-30 12:25:00 +05304806 } else if (log_info == VIRTUAL_IO_FAILED_RETRY) {
4807 scmd->result = DID_RESET << 16;
4808 break;
Sreekanth Reddyb40eeea2017-10-10 18:41:18 +05304809 } else if ((scmd->device->channel == RAID_CHANNEL) &&
4810 (scsi_state == (MPI2_SCSI_STATE_TERMINATED |
4811 MPI2_SCSI_STATE_NO_SCSI_STATUS))) {
4812 scmd->result = DID_RESET << 16;
4813 break;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304814 }
4815 scmd->result = DID_SOFT_ERROR << 16;
4816 break;
4817 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4818 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4819 scmd->result = DID_RESET << 16;
4820 break;
4821
4822 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4823 if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
4824 scmd->result = DID_SOFT_ERROR << 16;
4825 else
4826 scmd->result = (DID_OK << 16) | scsi_status;
4827 break;
4828
4829 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4830 scmd->result = (DID_OK << 16) | scsi_status;
4831
4832 if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
4833 break;
4834
4835 if (xfer_cnt < scmd->underflow) {
4836 if (scsi_status == SAM_STAT_BUSY)
4837 scmd->result = SAM_STAT_BUSY;
4838 else
4839 scmd->result = DID_SOFT_ERROR << 16;
4840 } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4841 MPI2_SCSI_STATE_NO_SCSI_STATUS))
4842 scmd->result = DID_SOFT_ERROR << 16;
4843 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4844 scmd->result = DID_RESET << 16;
4845 else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
4846 mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
4847 mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
4848 scmd->result = (DRIVER_SENSE << 24) |
4849 SAM_STAT_CHECK_CONDITION;
4850 scmd->sense_buffer[0] = 0x70;
4851 scmd->sense_buffer[2] = ILLEGAL_REQUEST;
4852 scmd->sense_buffer[12] = 0x20;
4853 scmd->sense_buffer[13] = 0;
4854 }
4855 break;
4856
4857 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4858 scsi_set_resid(scmd, 0);
4859 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4860 case MPI2_IOCSTATUS_SUCCESS:
4861 scmd->result = (DID_OK << 16) | scsi_status;
4862 if (response_code ==
4863 MPI2_SCSITASKMGMT_RSP_INVALID_FRAME ||
4864 (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4865 MPI2_SCSI_STATE_NO_SCSI_STATUS)))
4866 scmd->result = DID_SOFT_ERROR << 16;
4867 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4868 scmd->result = DID_RESET << 16;
4869 break;
4870
4871 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4872 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4873 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4874 _scsih_eedp_error_handling(scmd, ioc_status);
4875 break;
4876
4877 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4878 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4879 case MPI2_IOCSTATUS_INVALID_SGL:
4880 case MPI2_IOCSTATUS_INTERNAL_ERROR:
4881 case MPI2_IOCSTATUS_INVALID_FIELD:
4882 case MPI2_IOCSTATUS_INVALID_STATE:
4883 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4884 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05304885 case MPI2_IOCSTATUS_INSUFFICIENT_POWER:
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304886 default:
4887 scmd->result = DID_SOFT_ERROR << 16;
4888 break;
4889
4890 }
4891
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304892 if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
4893 _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304894
4895 out:
4896
4897 scsi_dma_unmap(scmd);
4898
4899 scmd->scsi_done(scmd);
4900 return 1;
4901}
4902
4903/**
4904 * _scsih_sas_host_refresh - refreshing sas host object contents
4905 * @ioc: per adapter object
4906 * Context: user
4907 *
4908 * During port enable, fw will send topology events for every device. Its
4909 * possible that the handles may change from the previous setting, so this
4910 * code keeping handles updating if changed.
4911 *
4912 * Return nothing.
4913 */
4914static void
4915_scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
4916{
4917 u16 sz;
4918 u16 ioc_status;
4919 int i;
4920 Mpi2ConfigReply_t mpi_reply;
4921 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4922 u16 attached_handle;
4923 u8 link_rate;
4924
4925 dtmprintk(ioc, pr_info(MPT3SAS_FMT
4926 "updating handles for sas_host(0x%016llx)\n",
4927 ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
4928
4929 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
4930 * sizeof(Mpi2SasIOUnit0PhyData_t));
4931 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4932 if (!sas_iounit_pg0) {
4933 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4934 ioc->name, __FILE__, __LINE__, __func__);
4935 return;
4936 }
4937
4938 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4939 sas_iounit_pg0, sz)) != 0)
4940 goto out;
4941 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
4942 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
4943 goto out;
4944 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
4945 link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
4946 if (i == 0)
4947 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4948 PhyData[0].ControllerDevHandle);
4949 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4950 attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
4951 AttachedDevHandle);
4952 if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
4953 link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
4954 mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
4955 attached_handle, i, link_rate);
4956 }
4957 out:
4958 kfree(sas_iounit_pg0);
4959}
4960
4961/**
4962 * _scsih_sas_host_add - create sas host object
4963 * @ioc: per adapter object
4964 *
4965 * Creating host side data object, stored in ioc->sas_hba
4966 *
4967 * Return nothing.
4968 */
4969static void
4970_scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
4971{
4972 int i;
4973 Mpi2ConfigReply_t mpi_reply;
4974 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4975 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
4976 Mpi2SasPhyPage0_t phy_pg0;
4977 Mpi2SasDevicePage0_t sas_device_pg0;
4978 Mpi2SasEnclosurePage0_t enclosure_pg0;
4979 u16 ioc_status;
4980 u16 sz;
4981 u8 device_missing_delay;
Joe Lawrence87aa95d2016-05-25 15:14:28 -04004982 u8 num_phys;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304983
Joe Lawrence87aa95d2016-05-25 15:14:28 -04004984 mpt3sas_config_get_number_hba_phys(ioc, &num_phys);
4985 if (!num_phys) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304986 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4987 ioc->name, __FILE__, __LINE__, __func__);
4988 return;
4989 }
Joe Lawrence87aa95d2016-05-25 15:14:28 -04004990 ioc->sas_hba.phy = kcalloc(num_phys,
4991 sizeof(struct _sas_phy), GFP_KERNEL);
4992 if (!ioc->sas_hba.phy) {
4993 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4994 ioc->name, __FILE__, __LINE__, __func__);
4995 goto out;
4996 }
4997 ioc->sas_hba.num_phys = num_phys;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304998
4999 /* sas_iounit page 0 */
5000 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
5001 sizeof(Mpi2SasIOUnit0PhyData_t));
5002 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
5003 if (!sas_iounit_pg0) {
5004 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5005 ioc->name, __FILE__, __LINE__, __func__);
5006 return;
5007 }
5008 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
5009 sas_iounit_pg0, sz))) {
5010 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5011 ioc->name, __FILE__, __LINE__, __func__);
5012 goto out;
5013 }
5014 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5015 MPI2_IOCSTATUS_MASK;
5016 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5017 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5018 ioc->name, __FILE__, __LINE__, __func__);
5019 goto out;
5020 }
5021
5022 /* sas_iounit page 1 */
5023 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
5024 sizeof(Mpi2SasIOUnit1PhyData_t));
5025 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
5026 if (!sas_iounit_pg1) {
5027 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5028 ioc->name, __FILE__, __LINE__, __func__);
5029 goto out;
5030 }
5031 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
5032 sas_iounit_pg1, sz))) {
5033 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5034 ioc->name, __FILE__, __LINE__, __func__);
5035 goto out;
5036 }
5037 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5038 MPI2_IOCSTATUS_MASK;
5039 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5040 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5041 ioc->name, __FILE__, __LINE__, __func__);
5042 goto out;
5043 }
5044
5045 ioc->io_missing_delay =
5046 sas_iounit_pg1->IODeviceMissingDelay;
5047 device_missing_delay =
5048 sas_iounit_pg1->ReportDeviceMissingDelay;
5049 if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
5050 ioc->device_missing_delay = (device_missing_delay &
5051 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
5052 else
5053 ioc->device_missing_delay = device_missing_delay &
5054 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
5055
5056 ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305057 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
5058 if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
5059 i))) {
5060 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5061 ioc->name, __FILE__, __LINE__, __func__);
5062 goto out;
5063 }
5064 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5065 MPI2_IOCSTATUS_MASK;
5066 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5067 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5068 ioc->name, __FILE__, __LINE__, __func__);
5069 goto out;
5070 }
5071
5072 if (i == 0)
5073 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
5074 PhyData[0].ControllerDevHandle);
5075 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
5076 ioc->sas_hba.phy[i].phy_id = i;
5077 mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
5078 phy_pg0, ioc->sas_hba.parent_dev);
5079 }
5080 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5081 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
5082 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5083 ioc->name, __FILE__, __LINE__, __func__);
5084 goto out;
5085 }
5086 ioc->sas_hba.enclosure_handle =
5087 le16_to_cpu(sas_device_pg0.EnclosureHandle);
5088 ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
5089 pr_info(MPT3SAS_FMT
5090 "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
5091 ioc->name, ioc->sas_hba.handle,
5092 (unsigned long long) ioc->sas_hba.sas_address,
5093 ioc->sas_hba.num_phys) ;
5094
5095 if (ioc->sas_hba.enclosure_handle) {
5096 if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
5097 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
5098 ioc->sas_hba.enclosure_handle)))
5099 ioc->sas_hba.enclosure_logical_id =
5100 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
5101 }
5102
5103 out:
5104 kfree(sas_iounit_pg1);
5105 kfree(sas_iounit_pg0);
5106}
5107
5108/**
5109 * _scsih_expander_add - creating expander object
5110 * @ioc: per adapter object
5111 * @handle: expander handle
5112 *
5113 * Creating expander object, stored in ioc->sas_expander_list.
5114 *
5115 * Return 0 for success, else error.
5116 */
5117static int
5118_scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
5119{
5120 struct _sas_node *sas_expander;
5121 Mpi2ConfigReply_t mpi_reply;
5122 Mpi2ExpanderPage0_t expander_pg0;
5123 Mpi2ExpanderPage1_t expander_pg1;
5124 Mpi2SasEnclosurePage0_t enclosure_pg0;
5125 u32 ioc_status;
5126 u16 parent_handle;
5127 u64 sas_address, sas_address_parent = 0;
5128 int i;
5129 unsigned long flags;
5130 struct _sas_port *mpt3sas_port = NULL;
5131
5132 int rc = 0;
5133
5134 if (!handle)
5135 return -1;
5136
5137 if (ioc->shost_recovery || ioc->pci_error_recovery)
5138 return -1;
5139
5140 if ((mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
5141 MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
5142 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5143 ioc->name, __FILE__, __LINE__, __func__);
5144 return -1;
5145 }
5146
5147 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5148 MPI2_IOCSTATUS_MASK;
5149 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5150 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5151 ioc->name, __FILE__, __LINE__, __func__);
5152 return -1;
5153 }
5154
5155 /* handle out of order topology events */
5156 parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
5157 if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
5158 != 0) {
5159 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5160 ioc->name, __FILE__, __LINE__, __func__);
5161 return -1;
5162 }
5163 if (sas_address_parent != ioc->sas_hba.sas_address) {
5164 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5165 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
5166 sas_address_parent);
5167 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5168 if (!sas_expander) {
5169 rc = _scsih_expander_add(ioc, parent_handle);
5170 if (rc != 0)
5171 return rc;
5172 }
5173 }
5174
5175 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5176 sas_address = le64_to_cpu(expander_pg0.SASAddress);
5177 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
5178 sas_address);
5179 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5180
5181 if (sas_expander)
5182 return 0;
5183
5184 sas_expander = kzalloc(sizeof(struct _sas_node),
5185 GFP_KERNEL);
5186 if (!sas_expander) {
5187 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5188 ioc->name, __FILE__, __LINE__, __func__);
5189 return -1;
5190 }
5191
5192 sas_expander->handle = handle;
5193 sas_expander->num_phys = expander_pg0.NumPhys;
5194 sas_expander->sas_address_parent = sas_address_parent;
5195 sas_expander->sas_address = sas_address;
5196
5197 pr_info(MPT3SAS_FMT "expander_add: handle(0x%04x)," \
5198 " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
5199 handle, parent_handle, (unsigned long long)
5200 sas_expander->sas_address, sas_expander->num_phys);
5201
5202 if (!sas_expander->num_phys)
5203 goto out_fail;
5204 sas_expander->phy = kcalloc(sas_expander->num_phys,
5205 sizeof(struct _sas_phy), GFP_KERNEL);
5206 if (!sas_expander->phy) {
5207 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5208 ioc->name, __FILE__, __LINE__, __func__);
5209 rc = -1;
5210 goto out_fail;
5211 }
5212
5213 INIT_LIST_HEAD(&sas_expander->sas_port_list);
5214 mpt3sas_port = mpt3sas_transport_port_add(ioc, handle,
5215 sas_address_parent);
5216 if (!mpt3sas_port) {
5217 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5218 ioc->name, __FILE__, __LINE__, __func__);
5219 rc = -1;
5220 goto out_fail;
5221 }
5222 sas_expander->parent_dev = &mpt3sas_port->rphy->dev;
5223
5224 for (i = 0 ; i < sas_expander->num_phys ; i++) {
5225 if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
5226 &expander_pg1, i, handle))) {
5227 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5228 ioc->name, __FILE__, __LINE__, __func__);
5229 rc = -1;
5230 goto out_fail;
5231 }
5232 sas_expander->phy[i].handle = handle;
5233 sas_expander->phy[i].phy_id = i;
5234
5235 if ((mpt3sas_transport_add_expander_phy(ioc,
5236 &sas_expander->phy[i], expander_pg1,
5237 sas_expander->parent_dev))) {
5238 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5239 ioc->name, __FILE__, __LINE__, __func__);
5240 rc = -1;
5241 goto out_fail;
5242 }
5243 }
5244
5245 if (sas_expander->enclosure_handle) {
5246 if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
5247 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
5248 sas_expander->enclosure_handle)))
5249 sas_expander->enclosure_logical_id =
5250 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
5251 }
5252
5253 _scsih_expander_node_add(ioc, sas_expander);
5254 return 0;
5255
5256 out_fail:
5257
5258 if (mpt3sas_port)
5259 mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
5260 sas_address_parent);
5261 kfree(sas_expander);
5262 return rc;
5263}
5264
5265/**
5266 * mpt3sas_expander_remove - removing expander object
5267 * @ioc: per adapter object
5268 * @sas_address: expander sas_address
5269 *
5270 * Return nothing.
5271 */
5272void
5273mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
5274{
5275 struct _sas_node *sas_expander;
5276 unsigned long flags;
5277
5278 if (ioc->shost_recovery)
5279 return;
5280
5281 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5282 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
5283 sas_address);
5284 if (sas_expander)
5285 list_del(&sas_expander->list);
5286 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5287 if (sas_expander)
5288 _scsih_expander_node_remove(ioc, sas_expander);
5289}
5290
5291/**
5292 * _scsih_done - internal SCSI_IO callback handler.
5293 * @ioc: per adapter object
5294 * @smid: system request message index
5295 * @msix_index: MSIX table index supplied by the OS
5296 * @reply: reply message frame(lower 32bit addr)
5297 *
5298 * Callback handler when sending internal generated SCSI_IO.
5299 * The callback index passed is `ioc->scsih_cb_idx`
5300 *
5301 * Return 1 meaning mf should be freed from _base_interrupt
5302 * 0 means the mf is freed from this function.
5303 */
5304static u8
5305_scsih_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
5306{
5307 MPI2DefaultReply_t *mpi_reply;
5308
5309 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
5310 if (ioc->scsih_cmds.status == MPT3_CMD_NOT_USED)
5311 return 1;
5312 if (ioc->scsih_cmds.smid != smid)
5313 return 1;
5314 ioc->scsih_cmds.status |= MPT3_CMD_COMPLETE;
5315 if (mpi_reply) {
5316 memcpy(ioc->scsih_cmds.reply, mpi_reply,
5317 mpi_reply->MsgLength*4);
5318 ioc->scsih_cmds.status |= MPT3_CMD_REPLY_VALID;
5319 }
5320 ioc->scsih_cmds.status &= ~MPT3_CMD_PENDING;
5321 complete(&ioc->scsih_cmds.done);
5322 return 1;
5323}
5324
5325
5326
5327
5328#define MPT3_MAX_LUNS (255)
5329
5330
5331/**
5332 * _scsih_check_access_status - check access flags
5333 * @ioc: per adapter object
5334 * @sas_address: sas address
5335 * @handle: sas device handle
5336 * @access_flags: errors returned during discovery of the device
5337 *
5338 * Return 0 for success, else failure
5339 */
5340static u8
5341_scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
5342 u16 handle, u8 access_status)
5343{
5344 u8 rc = 1;
5345 char *desc = NULL;
5346
5347 switch (access_status) {
5348 case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS:
5349 case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION:
5350 rc = 0;
5351 break;
5352 case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED:
5353 desc = "sata capability failed";
5354 break;
5355 case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT:
5356 desc = "sata affiliation conflict";
5357 break;
5358 case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE:
5359 desc = "route not addressable";
5360 break;
5361 case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE:
5362 desc = "smp error not addressable";
5363 break;
5364 case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED:
5365 desc = "device blocked";
5366 break;
5367 case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED:
5368 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN:
5369 case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT:
5370 case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG:
5371 case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION:
5372 case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER:
5373 case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN:
5374 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN:
5375 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN:
5376 case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION:
5377 case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE:
5378 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX:
5379 desc = "sata initialization failed";
5380 break;
5381 default:
5382 desc = "unknown";
5383 break;
5384 }
5385
5386 if (!rc)
5387 return 0;
5388
5389 pr_err(MPT3SAS_FMT
5390 "discovery errors(%s): sas_address(0x%016llx), handle(0x%04x)\n",
5391 ioc->name, desc, (unsigned long long)sas_address, handle);
5392 return rc;
5393}
5394
5395/**
5396 * _scsih_check_device - checking device responsiveness
5397 * @ioc: per adapter object
5398 * @parent_sas_address: sas address of parent expander or sas host
5399 * @handle: attached device handle
5400 * @phy_numberv: phy number
5401 * @link_rate: new link rate
5402 *
5403 * Returns nothing.
5404 */
5405static void
5406_scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
5407 u64 parent_sas_address, u16 handle, u8 phy_number, u8 link_rate)
5408{
5409 Mpi2ConfigReply_t mpi_reply;
5410 Mpi2SasDevicePage0_t sas_device_pg0;
5411 struct _sas_device *sas_device;
5412 u32 ioc_status;
5413 unsigned long flags;
5414 u64 sas_address;
5415 struct scsi_target *starget;
5416 struct MPT3SAS_TARGET *sas_target_priv_data;
5417 u32 device_info;
5418
5419
5420 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5421 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
5422 return;
5423
5424 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
5425 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
5426 return;
5427
5428 /* wide port handling ~ we need only handle device once for the phy that
5429 * is matched in sas device page zero
5430 */
5431 if (phy_number != sas_device_pg0.PhyNum)
5432 return;
5433
5434 /* check if this is end device */
5435 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5436 if (!(_scsih_is_end_device(device_info)))
5437 return;
5438
5439 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5440 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305441 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305442 sas_address);
5443
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305444 if (!sas_device)
5445 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305446
5447 if (unlikely(sas_device->handle != handle)) {
5448 starget = sas_device->starget;
5449 sas_target_priv_data = starget->hostdata;
5450 starget_printk(KERN_INFO, starget,
5451 "handle changed from(0x%04x) to (0x%04x)!!!\n",
5452 sas_device->handle, handle);
5453 sas_target_priv_data->handle = handle;
5454 sas_device->handle = handle;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305455 if (sas_device_pg0.Flags &
5456 MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
5457 sas_device->enclosure_level =
5458 le16_to_cpu(sas_device_pg0.EnclosureLevel);
Calvin Owens310c8e42016-07-27 21:45:51 -07005459 memcpy(sas_device->connector_name,
5460 sas_device_pg0.ConnectorName, 4);
5461 sas_device->connector_name[4] = '\0';
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305462 } else {
5463 sas_device->enclosure_level = 0;
5464 sas_device->connector_name[0] = '\0';
5465 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305466 }
5467
5468 /* check if device is present */
5469 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5470 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5471 pr_err(MPT3SAS_FMT
5472 "device is not present handle(0x%04x), flags!!!\n",
5473 ioc->name, handle);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305474 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305475 }
5476
5477 /* check if there were any issues with discovery */
5478 if (_scsih_check_access_status(ioc, sas_address, handle,
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305479 sas_device_pg0.AccessStatus))
5480 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305481
5482 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5483 _scsih_ublock_io_device(ioc, sas_address);
5484
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305485 if (sas_device)
5486 sas_device_put(sas_device);
5487 return;
5488
5489out_unlock:
5490 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5491 if (sas_device)
5492 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305493}
5494
5495/**
5496 * _scsih_add_device - creating sas device object
5497 * @ioc: per adapter object
5498 * @handle: sas device handle
5499 * @phy_num: phy number end device attached to
5500 * @is_pd: is this hidden raid component
5501 *
5502 * Creating end device object, stored in ioc->sas_device_list.
5503 *
5504 * Returns 0 for success, non-zero for failure.
5505 */
5506static int
5507_scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
5508 u8 is_pd)
5509{
5510 Mpi2ConfigReply_t mpi_reply;
5511 Mpi2SasDevicePage0_t sas_device_pg0;
5512 Mpi2SasEnclosurePage0_t enclosure_pg0;
5513 struct _sas_device *sas_device;
5514 u32 ioc_status;
5515 u64 sas_address;
5516 u32 device_info;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305517
5518 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5519 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
5520 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5521 ioc->name, __FILE__, __LINE__, __func__);
5522 return -1;
5523 }
5524
5525 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5526 MPI2_IOCSTATUS_MASK;
5527 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5528 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5529 ioc->name, __FILE__, __LINE__, __func__);
5530 return -1;
5531 }
5532
5533 /* check if this is end device */
5534 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5535 if (!(_scsih_is_end_device(device_info)))
5536 return -1;
5537 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
5538
5539 /* check if device is present */
5540 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5541 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5542 pr_err(MPT3SAS_FMT "device is not present handle(0x04%x)!!!\n",
5543 ioc->name, handle);
5544 return -1;
5545 }
5546
5547 /* check if there were any issues with discovery */
5548 if (_scsih_check_access_status(ioc, sas_address, handle,
5549 sas_device_pg0.AccessStatus))
5550 return -1;
5551
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305552 sas_device = mpt3sas_get_sdev_by_addr(ioc,
5553 sas_address);
5554 if (sas_device) {
5555 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305556 return -1;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305557 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305558
5559 sas_device = kzalloc(sizeof(struct _sas_device),
5560 GFP_KERNEL);
5561 if (!sas_device) {
5562 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5563 ioc->name, __FILE__, __LINE__, __func__);
5564 return 0;
5565 }
5566
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305567 kref_init(&sas_device->refcount);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305568 sas_device->handle = handle;
5569 if (_scsih_get_sas_address(ioc,
5570 le16_to_cpu(sas_device_pg0.ParentDevHandle),
5571 &sas_device->sas_address_parent) != 0)
5572 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5573 ioc->name, __FILE__, __LINE__, __func__);
5574 sas_device->enclosure_handle =
5575 le16_to_cpu(sas_device_pg0.EnclosureHandle);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305576 if (sas_device->enclosure_handle != 0)
5577 sas_device->slot =
5578 le16_to_cpu(sas_device_pg0.Slot);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305579 sas_device->device_info = device_info;
5580 sas_device->sas_address = sas_address;
5581 sas_device->phy = sas_device_pg0.PhyNum;
5582 sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) &
5583 MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
5584
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305585 if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
5586 sas_device->enclosure_level =
5587 le16_to_cpu(sas_device_pg0.EnclosureLevel);
Calvin Owens310c8e42016-07-27 21:45:51 -07005588 memcpy(sas_device->connector_name,
5589 sas_device_pg0.ConnectorName, 4);
5590 sas_device->connector_name[4] = '\0';
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305591 } else {
5592 sas_device->enclosure_level = 0;
5593 sas_device->connector_name[0] = '\0';
5594 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305595 /* get enclosure_logical_id */
5596 if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0(
5597 ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
5598 sas_device->enclosure_handle)))
5599 sas_device->enclosure_logical_id =
5600 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
5601
5602 /* get device name */
5603 sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
5604
5605 if (ioc->wait_for_discovery_to_complete)
5606 _scsih_sas_device_init_add(ioc, sas_device);
5607 else
5608 _scsih_sas_device_add(ioc, sas_device);
5609
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305610 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305611 return 0;
5612}
5613
5614/**
5615 * _scsih_remove_device - removing sas device object
5616 * @ioc: per adapter object
5617 * @sas_device_delete: the sas_device object
5618 *
5619 * Return nothing.
5620 */
5621static void
5622_scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
5623 struct _sas_device *sas_device)
5624{
5625 struct MPT3SAS_TARGET *sas_target_priv_data;
5626
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05305627 if ((ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) &&
5628 (sas_device->pfa_led_on)) {
5629 _scsih_turn_off_pfa_led(ioc, sas_device);
5630 sas_device->pfa_led_on = 0;
5631 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305632 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5633 "%s: enter: handle(0x%04x), sas_addr(0x%016llx)\n",
5634 ioc->name, __func__,
5635 sas_device->handle, (unsigned long long)
5636 sas_device->sas_address));
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305637 if (sas_device->enclosure_handle != 0)
5638 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5639 "%s: enter: enclosure logical id(0x%016llx), slot(%d)\n",
5640 ioc->name, __func__,
5641 (unsigned long long)sas_device->enclosure_logical_id,
5642 sas_device->slot));
5643 if (sas_device->connector_name[0] != '\0')
5644 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5645 "%s: enter: enclosure level(0x%04x), connector name( %s)\n",
5646 ioc->name, __func__,
5647 sas_device->enclosure_level,
5648 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305649
5650 if (sas_device->starget && sas_device->starget->hostdata) {
5651 sas_target_priv_data = sas_device->starget->hostdata;
5652 sas_target_priv_data->deleted = 1;
5653 _scsih_ublock_io_device(ioc, sas_device->sas_address);
5654 sas_target_priv_data->handle =
5655 MPT3SAS_INVALID_DEVICE_HANDLE;
5656 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05305657
5658 if (!ioc->hide_drives)
5659 mpt3sas_transport_port_remove(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305660 sas_device->sas_address,
5661 sas_device->sas_address_parent);
5662
5663 pr_info(MPT3SAS_FMT
5664 "removing handle(0x%04x), sas_addr(0x%016llx)\n",
5665 ioc->name, sas_device->handle,
5666 (unsigned long long) sas_device->sas_address);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305667 if (sas_device->enclosure_handle != 0)
5668 pr_info(MPT3SAS_FMT
5669 "removing : enclosure logical id(0x%016llx), slot(%d)\n",
5670 ioc->name,
5671 (unsigned long long)sas_device->enclosure_logical_id,
5672 sas_device->slot);
5673 if (sas_device->connector_name[0] != '\0')
5674 pr_info(MPT3SAS_FMT
5675 "removing enclosure level(0x%04x), connector name( %s)\n",
5676 ioc->name, sas_device->enclosure_level,
5677 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305678
5679 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5680 "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n",
5681 ioc->name, __func__,
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305682 sas_device->handle, (unsigned long long)
5683 sas_device->sas_address));
5684 if (sas_device->enclosure_handle != 0)
5685 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5686 "%s: exit: enclosure logical id(0x%016llx), slot(%d)\n",
5687 ioc->name, __func__,
5688 (unsigned long long)sas_device->enclosure_logical_id,
5689 sas_device->slot));
5690 if (sas_device->connector_name[0] != '\0')
5691 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5692 "%s: exit: enclosure level(0x%04x), connector name(%s)\n",
5693 ioc->name, __func__, sas_device->enclosure_level,
5694 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305695}
5696
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305697/**
5698 * _scsih_sas_topology_change_event_debug - debug for topology event
5699 * @ioc: per adapter object
5700 * @event_data: event data payload
5701 * Context: user.
5702 */
5703static void
5704_scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5705 Mpi2EventDataSasTopologyChangeList_t *event_data)
5706{
5707 int i;
5708 u16 handle;
5709 u16 reason_code;
5710 u8 phy_number;
5711 char *status_str = NULL;
5712 u8 link_rate, prev_link_rate;
5713
5714 switch (event_data->ExpStatus) {
5715 case MPI2_EVENT_SAS_TOPO_ES_ADDED:
5716 status_str = "add";
5717 break;
5718 case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
5719 status_str = "remove";
5720 break;
5721 case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
5722 case 0:
5723 status_str = "responding";
5724 break;
5725 case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
5726 status_str = "remove delay";
5727 break;
5728 default:
5729 status_str = "unknown status";
5730 break;
5731 }
5732 pr_info(MPT3SAS_FMT "sas topology change: (%s)\n",
5733 ioc->name, status_str);
5734 pr_info("\thandle(0x%04x), enclosure_handle(0x%04x) " \
5735 "start_phy(%02d), count(%d)\n",
5736 le16_to_cpu(event_data->ExpanderDevHandle),
5737 le16_to_cpu(event_data->EnclosureHandle),
5738 event_data->StartPhyNum, event_data->NumEntries);
5739 for (i = 0; i < event_data->NumEntries; i++) {
5740 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5741 if (!handle)
5742 continue;
5743 phy_number = event_data->StartPhyNum + i;
5744 reason_code = event_data->PHY[i].PhyStatus &
5745 MPI2_EVENT_SAS_TOPO_RC_MASK;
5746 switch (reason_code) {
5747 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
5748 status_str = "target add";
5749 break;
5750 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
5751 status_str = "target remove";
5752 break;
5753 case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
5754 status_str = "delay target remove";
5755 break;
5756 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
5757 status_str = "link rate change";
5758 break;
5759 case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
5760 status_str = "target responding";
5761 break;
5762 default:
5763 status_str = "unknown";
5764 break;
5765 }
5766 link_rate = event_data->PHY[i].LinkRate >> 4;
5767 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
5768 pr_info("\tphy(%02d), attached_handle(0x%04x): %s:" \
5769 " link rate: new(0x%02x), old(0x%02x)\n", phy_number,
5770 handle, status_str, link_rate, prev_link_rate);
5771
5772 }
5773}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305774
5775/**
5776 * _scsih_sas_topology_change_event - handle topology changes
5777 * @ioc: per adapter object
5778 * @fw_event: The fw_event_work object
5779 * Context: user.
5780 *
5781 */
5782static int
5783_scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
5784 struct fw_event_work *fw_event)
5785{
5786 int i;
5787 u16 parent_handle, handle;
5788 u16 reason_code;
5789 u8 phy_number, max_phys;
5790 struct _sas_node *sas_expander;
5791 u64 sas_address;
5792 unsigned long flags;
5793 u8 link_rate, prev_link_rate;
Joe Lawrence35b62362014-06-25 17:05:34 -04005794 Mpi2EventDataSasTopologyChangeList_t *event_data =
5795 (Mpi2EventDataSasTopologyChangeList_t *)
5796 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305797
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305798 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5799 _scsih_sas_topology_change_event_debug(ioc, event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305800
5801 if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
5802 return 0;
5803
5804 if (!ioc->sas_hba.num_phys)
5805 _scsih_sas_host_add(ioc);
5806 else
5807 _scsih_sas_host_refresh(ioc);
5808
5809 if (fw_event->ignore) {
5810 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5811 "ignoring expander event\n", ioc->name));
5812 return 0;
5813 }
5814
5815 parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
5816
5817 /* handle expander add */
5818 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
5819 if (_scsih_expander_add(ioc, parent_handle) != 0)
5820 return 0;
5821
5822 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5823 sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
5824 parent_handle);
5825 if (sas_expander) {
5826 sas_address = sas_expander->sas_address;
5827 max_phys = sas_expander->num_phys;
5828 } else if (parent_handle < ioc->sas_hba.num_phys) {
5829 sas_address = ioc->sas_hba.sas_address;
5830 max_phys = ioc->sas_hba.num_phys;
5831 } else {
5832 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5833 return 0;
5834 }
5835 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5836
5837 /* handle siblings events */
5838 for (i = 0; i < event_data->NumEntries; i++) {
5839 if (fw_event->ignore) {
5840 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5841 "ignoring expander event\n", ioc->name));
5842 return 0;
5843 }
5844 if (ioc->remove_host || ioc->pci_error_recovery)
5845 return 0;
5846 phy_number = event_data->StartPhyNum + i;
5847 if (phy_number >= max_phys)
5848 continue;
5849 reason_code = event_data->PHY[i].PhyStatus &
5850 MPI2_EVENT_SAS_TOPO_RC_MASK;
5851 if ((event_data->PHY[i].PhyStatus &
5852 MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
5853 MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
5854 continue;
5855 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5856 if (!handle)
5857 continue;
5858 link_rate = event_data->PHY[i].LinkRate >> 4;
5859 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
5860 switch (reason_code) {
5861 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
5862
5863 if (ioc->shost_recovery)
5864 break;
5865
5866 if (link_rate == prev_link_rate)
5867 break;
5868
5869 mpt3sas_transport_update_links(ioc, sas_address,
5870 handle, phy_number, link_rate);
5871
5872 if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
5873 break;
5874
5875 _scsih_check_device(ioc, sas_address, handle,
5876 phy_number, link_rate);
5877
5878
5879 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
5880
5881 if (ioc->shost_recovery)
5882 break;
5883
5884 mpt3sas_transport_update_links(ioc, sas_address,
5885 handle, phy_number, link_rate);
5886
5887 _scsih_add_device(ioc, handle, phy_number, 0);
5888
5889 break;
5890 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
5891
5892 _scsih_device_remove_by_handle(ioc, handle);
5893 break;
5894 }
5895 }
5896
5897 /* handle expander removal */
5898 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
5899 sas_expander)
5900 mpt3sas_expander_remove(ioc, sas_address);
5901
5902 return 0;
5903}
5904
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305905/**
5906 * _scsih_sas_device_status_change_event_debug - debug for device event
5907 * @event_data: event data payload
5908 * Context: user.
5909 *
5910 * Return nothing.
5911 */
5912static void
5913_scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5914 Mpi2EventDataSasDeviceStatusChange_t *event_data)
5915{
5916 char *reason_str = NULL;
5917
5918 switch (event_data->ReasonCode) {
5919 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5920 reason_str = "smart data";
5921 break;
5922 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
5923 reason_str = "unsupported device discovered";
5924 break;
5925 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
5926 reason_str = "internal device reset";
5927 break;
5928 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
5929 reason_str = "internal task abort";
5930 break;
5931 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
5932 reason_str = "internal task abort set";
5933 break;
5934 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
5935 reason_str = "internal clear task set";
5936 break;
5937 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
5938 reason_str = "internal query task";
5939 break;
5940 case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
5941 reason_str = "sata init failure";
5942 break;
5943 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
5944 reason_str = "internal device reset complete";
5945 break;
5946 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
5947 reason_str = "internal task abort complete";
5948 break;
5949 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
5950 reason_str = "internal async notification";
5951 break;
5952 case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY:
5953 reason_str = "expander reduced functionality";
5954 break;
5955 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY:
5956 reason_str = "expander reduced functionality complete";
5957 break;
5958 default:
5959 reason_str = "unknown reason";
5960 break;
5961 }
5962 pr_info(MPT3SAS_FMT "device status change: (%s)\n"
5963 "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
5964 ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
5965 (unsigned long long)le64_to_cpu(event_data->SASAddress),
5966 le16_to_cpu(event_data->TaskTag));
5967 if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
5968 pr_info(MPT3SAS_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
5969 event_data->ASC, event_data->ASCQ);
5970 pr_info("\n");
5971}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305972
5973/**
5974 * _scsih_sas_device_status_change_event - handle device status change
5975 * @ioc: per adapter object
5976 * @fw_event: The fw_event_work object
5977 * Context: user.
5978 *
5979 * Return nothing.
5980 */
5981static void
5982_scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
5983 struct fw_event_work *fw_event)
5984{
5985 struct MPT3SAS_TARGET *target_priv_data;
5986 struct _sas_device *sas_device;
5987 u64 sas_address;
5988 unsigned long flags;
5989 Mpi2EventDataSasDeviceStatusChange_t *event_data =
Joe Lawrence35b62362014-06-25 17:05:34 -04005990 (Mpi2EventDataSasDeviceStatusChange_t *)
5991 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305992
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305993 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5994 _scsih_sas_device_status_change_event_debug(ioc,
5995 event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305996
5997 /* In MPI Revision K (0xC), the internal device reset complete was
5998 * implemented, so avoid setting tm_busy flag for older firmware.
5999 */
6000 if ((ioc->facts.HeaderVersion >> 8) < 0xC)
6001 return;
6002
6003 if (event_data->ReasonCode !=
6004 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
6005 event_data->ReasonCode !=
6006 MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)
6007 return;
6008
6009 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6010 sas_address = le64_to_cpu(event_data->SASAddress);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306011 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306012 sas_address);
6013
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306014 if (!sas_device || !sas_device->starget)
6015 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306016
6017 target_priv_data = sas_device->starget->hostdata;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306018 if (!target_priv_data)
6019 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306020
6021 if (event_data->ReasonCode ==
6022 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
6023 target_priv_data->tm_busy = 1;
6024 else
6025 target_priv_data->tm_busy = 0;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306026
6027out:
6028 if (sas_device)
6029 sas_device_put(sas_device);
6030
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306031 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306032
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306033}
6034
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306035/**
6036 * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure
6037 * event
6038 * @ioc: per adapter object
6039 * @event_data: event data payload
6040 * Context: user.
6041 *
6042 * Return nothing.
6043 */
6044static void
6045_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
6046 Mpi2EventDataSasEnclDevStatusChange_t *event_data)
6047{
6048 char *reason_str = NULL;
6049
6050 switch (event_data->ReasonCode) {
6051 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
6052 reason_str = "enclosure add";
6053 break;
6054 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
6055 reason_str = "enclosure remove";
6056 break;
6057 default:
6058 reason_str = "unknown reason";
6059 break;
6060 }
6061
6062 pr_info(MPT3SAS_FMT "enclosure status change: (%s)\n"
6063 "\thandle(0x%04x), enclosure logical id(0x%016llx)"
6064 " number slots(%d)\n", ioc->name, reason_str,
6065 le16_to_cpu(event_data->EnclosureHandle),
6066 (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
6067 le16_to_cpu(event_data->StartSlot));
6068}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306069
6070/**
6071 * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
6072 * @ioc: per adapter object
6073 * @fw_event: The fw_event_work object
6074 * Context: user.
6075 *
6076 * Return nothing.
6077 */
6078static void
6079_scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
6080 struct fw_event_work *fw_event)
6081{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306082 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
6083 _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
Joe Lawrence35b62362014-06-25 17:05:34 -04006084 (Mpi2EventDataSasEnclDevStatusChange_t *)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306085 fw_event->event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306086}
6087
6088/**
6089 * _scsih_sas_broadcast_primitive_event - handle broadcast events
6090 * @ioc: per adapter object
6091 * @fw_event: The fw_event_work object
6092 * Context: user.
6093 *
6094 * Return nothing.
6095 */
6096static void
6097_scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
6098 struct fw_event_work *fw_event)
6099{
6100 struct scsi_cmnd *scmd;
6101 struct scsi_device *sdev;
6102 u16 smid, handle;
6103 u32 lun;
6104 struct MPT3SAS_DEVICE *sas_device_priv_data;
6105 u32 termination_count;
6106 u32 query_count;
6107 Mpi2SCSITaskManagementReply_t *mpi_reply;
Joe Lawrence35b62362014-06-25 17:05:34 -04006108 Mpi2EventDataSasBroadcastPrimitive_t *event_data =
6109 (Mpi2EventDataSasBroadcastPrimitive_t *)
6110 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306111 u16 ioc_status;
6112 unsigned long flags;
6113 int r;
6114 u8 max_retries = 0;
6115 u8 task_abort_retries;
6116
6117 mutex_lock(&ioc->tm_cmds.mutex);
6118 pr_info(MPT3SAS_FMT
6119 "%s: enter: phy number(%d), width(%d)\n",
6120 ioc->name, __func__, event_data->PhyNum,
6121 event_data->PortWidth);
6122
6123 _scsih_block_io_all_device(ioc);
6124
6125 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6126 mpi_reply = ioc->tm_cmds.reply;
6127 broadcast_aen_retry:
6128
6129 /* sanity checks for retrying this loop */
6130 if (max_retries++ == 5) {
6131 dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: giving up\n",
6132 ioc->name, __func__));
6133 goto out;
6134 } else if (max_retries > 1)
6135 dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: %d retry\n",
6136 ioc->name, __func__, max_retries - 1));
6137
6138 termination_count = 0;
6139 query_count = 0;
6140 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
6141 if (ioc->shost_recovery)
6142 goto out;
6143 scmd = _scsih_scsi_lookup_get(ioc, smid);
6144 if (!scmd)
6145 continue;
6146 sdev = scmd->device;
6147 sas_device_priv_data = sdev->hostdata;
6148 if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
6149 continue;
6150 /* skip hidden raid components */
6151 if (sas_device_priv_data->sas_target->flags &
6152 MPT_TARGET_FLAGS_RAID_COMPONENT)
6153 continue;
6154 /* skip volumes */
6155 if (sas_device_priv_data->sas_target->flags &
6156 MPT_TARGET_FLAGS_VOLUME)
6157 continue;
6158
6159 handle = sas_device_priv_data->sas_target->handle;
6160 lun = sas_device_priv_data->lun;
6161 query_count++;
6162
6163 if (ioc->shost_recovery)
6164 goto out;
6165
6166 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
6167 r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
Calvin Owens96902832016-07-28 21:38:20 -07006168 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306169 if (r == FAILED) {
6170 sdev_printk(KERN_WARNING, sdev,
6171 "mpt3sas_scsih_issue_tm: FAILED when sending "
6172 "QUERY_TASK: scmd(%p)\n", scmd);
6173 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6174 goto broadcast_aen_retry;
6175 }
6176 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
6177 & MPI2_IOCSTATUS_MASK;
6178 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6179 sdev_printk(KERN_WARNING, sdev,
6180 "query task: FAILED with IOCSTATUS(0x%04x), scmd(%p)\n",
6181 ioc_status, scmd);
6182 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6183 goto broadcast_aen_retry;
6184 }
6185
6186 /* see if IO is still owned by IOC and target */
6187 if (mpi_reply->ResponseCode ==
6188 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
6189 mpi_reply->ResponseCode ==
6190 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
6191 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6192 continue;
6193 }
6194 task_abort_retries = 0;
6195 tm_retry:
6196 if (task_abort_retries++ == 60) {
6197 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6198 "%s: ABORT_TASK: giving up\n", ioc->name,
6199 __func__));
6200 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6201 goto broadcast_aen_retry;
6202 }
6203
6204 if (ioc->shost_recovery)
6205 goto out_no_lock;
6206
6207 r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
Calvin Owens96902832016-07-28 21:38:20 -07006208 sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid,
6209 30);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306210 if (r == FAILED) {
6211 sdev_printk(KERN_WARNING, sdev,
6212 "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : "
6213 "scmd(%p)\n", scmd);
6214 goto tm_retry;
6215 }
6216
6217 if (task_abort_retries > 1)
6218 sdev_printk(KERN_WARNING, sdev,
6219 "mpt3sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
6220 " scmd(%p)\n",
6221 task_abort_retries - 1, scmd);
6222
6223 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
6224 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6225 }
6226
6227 if (ioc->broadcast_aen_pending) {
6228 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6229 "%s: loop back due to pending AEN\n",
6230 ioc->name, __func__));
6231 ioc->broadcast_aen_pending = 0;
6232 goto broadcast_aen_retry;
6233 }
6234
6235 out:
6236 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
6237 out_no_lock:
6238
6239 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6240 "%s - exit, query_count = %d termination_count = %d\n",
6241 ioc->name, __func__, query_count, termination_count));
6242
6243 ioc->broadcast_aen_busy = 0;
6244 if (!ioc->shost_recovery)
6245 _scsih_ublock_io_all_device(ioc);
6246 mutex_unlock(&ioc->tm_cmds.mutex);
6247}
6248
6249/**
6250 * _scsih_sas_discovery_event - handle discovery events
6251 * @ioc: per adapter object
6252 * @fw_event: The fw_event_work object
6253 * Context: user.
6254 *
6255 * Return nothing.
6256 */
6257static void
6258_scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
6259 struct fw_event_work *fw_event)
6260{
Joe Lawrence35b62362014-06-25 17:05:34 -04006261 Mpi2EventDataSasDiscovery_t *event_data =
6262 (Mpi2EventDataSasDiscovery_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306263
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306264 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
6265 pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name,
6266 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
6267 "start" : "stop");
Sreekanth Reddyaf009412015-11-11 17:30:23 +05306268 if (event_data->DiscoveryStatus)
6269 pr_info("discovery_status(0x%08x)",
6270 le32_to_cpu(event_data->DiscoveryStatus));
6271 pr_info("\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306272 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306273
6274 if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
6275 !ioc->sas_hba.num_phys) {
6276 if (disable_discovery > 0 && ioc->shost_recovery) {
6277 /* Wait for the reset to complete */
6278 while (ioc->shost_recovery)
6279 ssleep(1);
6280 }
6281 _scsih_sas_host_add(ioc);
6282 }
6283}
6284
6285/**
6286 * _scsih_ir_fastpath - turn on fastpath for IR physdisk
6287 * @ioc: per adapter object
6288 * @handle: device handle for physical disk
6289 * @phys_disk_num: physical disk number
6290 *
6291 * Return 0 for success, else failure.
6292 */
6293static int
6294_scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
6295{
6296 Mpi2RaidActionRequest_t *mpi_request;
6297 Mpi2RaidActionReply_t *mpi_reply;
6298 u16 smid;
6299 u8 issue_reset = 0;
6300 int rc = 0;
6301 u16 ioc_status;
6302 u32 log_info;
6303
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05306304 if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
6305 return rc;
6306
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306307 mutex_lock(&ioc->scsih_cmds.mutex);
6308
6309 if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
6310 pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
6311 ioc->name, __func__);
6312 rc = -EAGAIN;
6313 goto out;
6314 }
6315 ioc->scsih_cmds.status = MPT3_CMD_PENDING;
6316
6317 smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
6318 if (!smid) {
6319 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
6320 ioc->name, __func__);
6321 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
6322 rc = -EAGAIN;
6323 goto out;
6324 }
6325
6326 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
6327 ioc->scsih_cmds.smid = smid;
6328 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
6329
6330 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
6331 mpi_request->Action = MPI2_RAID_ACTION_PHYSDISK_HIDDEN;
6332 mpi_request->PhysDiskNum = phys_disk_num;
6333
6334 dewtprintk(ioc, pr_info(MPT3SAS_FMT "IR RAID_ACTION: turning fast "\
6335 "path on for handle(0x%04x), phys_disk_num (0x%02x)\n", ioc->name,
6336 handle, phys_disk_num));
6337
6338 init_completion(&ioc->scsih_cmds.done);
6339 mpt3sas_base_put_smid_default(ioc, smid);
6340 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
6341
6342 if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
6343 pr_err(MPT3SAS_FMT "%s: timeout\n",
6344 ioc->name, __func__);
6345 if (!(ioc->scsih_cmds.status & MPT3_CMD_RESET))
6346 issue_reset = 1;
6347 rc = -EFAULT;
6348 goto out;
6349 }
6350
6351 if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
6352
6353 mpi_reply = ioc->scsih_cmds.reply;
6354 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
6355 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
6356 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
6357 else
6358 log_info = 0;
6359 ioc_status &= MPI2_IOCSTATUS_MASK;
6360 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6361 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6362 "IR RAID_ACTION: failed: ioc_status(0x%04x), "
6363 "loginfo(0x%08x)!!!\n", ioc->name, ioc_status,
6364 log_info));
6365 rc = -EFAULT;
6366 } else
6367 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6368 "IR RAID_ACTION: completed successfully\n",
6369 ioc->name));
6370 }
6371
6372 out:
6373 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
6374 mutex_unlock(&ioc->scsih_cmds.mutex);
6375
6376 if (issue_reset)
Calvin Owens98c56ad2016-07-28 21:38:21 -07006377 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306378 return rc;
6379}
6380
6381/**
6382 * _scsih_reprobe_lun - reprobing lun
6383 * @sdev: scsi device struct
6384 * @no_uld_attach: sdev->no_uld_attach flag setting
6385 *
6386 **/
6387static void
6388_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
6389{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306390 sdev->no_uld_attach = no_uld_attach ? 1 : 0;
6391 sdev_printk(KERN_INFO, sdev, "%s raid component\n",
6392 sdev->no_uld_attach ? "hidding" : "exposing");
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07006393 WARN_ON(scsi_device_reprobe(sdev));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306394}
6395
6396/**
6397 * _scsih_sas_volume_add - add new volume
6398 * @ioc: per adapter object
6399 * @element: IR config element data
6400 * Context: user.
6401 *
6402 * Return nothing.
6403 */
6404static void
6405_scsih_sas_volume_add(struct MPT3SAS_ADAPTER *ioc,
6406 Mpi2EventIrConfigElement_t *element)
6407{
6408 struct _raid_device *raid_device;
6409 unsigned long flags;
6410 u64 wwid;
6411 u16 handle = le16_to_cpu(element->VolDevHandle);
6412 int rc;
6413
6414 mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
6415 if (!wwid) {
6416 pr_err(MPT3SAS_FMT
6417 "failure at %s:%d/%s()!\n", ioc->name,
6418 __FILE__, __LINE__, __func__);
6419 return;
6420 }
6421
6422 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6423 raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
6424 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6425
6426 if (raid_device)
6427 return;
6428
6429 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6430 if (!raid_device) {
6431 pr_err(MPT3SAS_FMT
6432 "failure at %s:%d/%s()!\n", ioc->name,
6433 __FILE__, __LINE__, __func__);
6434 return;
6435 }
6436
6437 raid_device->id = ioc->sas_id++;
6438 raid_device->channel = RAID_CHANNEL;
6439 raid_device->handle = handle;
6440 raid_device->wwid = wwid;
6441 _scsih_raid_device_add(ioc, raid_device);
6442 if (!ioc->wait_for_discovery_to_complete) {
6443 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6444 raid_device->id, 0);
6445 if (rc)
6446 _scsih_raid_device_remove(ioc, raid_device);
6447 } else {
6448 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6449 _scsih_determine_boot_device(ioc, raid_device, 1);
6450 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6451 }
6452}
6453
6454/**
6455 * _scsih_sas_volume_delete - delete volume
6456 * @ioc: per adapter object
6457 * @handle: volume device handle
6458 * Context: user.
6459 *
6460 * Return nothing.
6461 */
6462static void
6463_scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle)
6464{
6465 struct _raid_device *raid_device;
6466 unsigned long flags;
6467 struct MPT3SAS_TARGET *sas_target_priv_data;
6468 struct scsi_target *starget = NULL;
6469
6470 spin_lock_irqsave(&ioc->raid_device_lock, flags);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05306471 raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306472 if (raid_device) {
6473 if (raid_device->starget) {
6474 starget = raid_device->starget;
6475 sas_target_priv_data = starget->hostdata;
6476 sas_target_priv_data->deleted = 1;
6477 }
6478 pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
6479 ioc->name, raid_device->handle,
6480 (unsigned long long) raid_device->wwid);
6481 list_del(&raid_device->list);
6482 kfree(raid_device);
6483 }
6484 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6485 if (starget)
6486 scsi_remove_target(&starget->dev);
6487}
6488
6489/**
6490 * _scsih_sas_pd_expose - expose pd component to /dev/sdX
6491 * @ioc: per adapter object
6492 * @element: IR config element data
6493 * Context: user.
6494 *
6495 * Return nothing.
6496 */
6497static void
6498_scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc,
6499 Mpi2EventIrConfigElement_t *element)
6500{
6501 struct _sas_device *sas_device;
6502 struct scsi_target *starget = NULL;
6503 struct MPT3SAS_TARGET *sas_target_priv_data;
6504 unsigned long flags;
6505 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6506
6507 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306508 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306509 if (sas_device) {
6510 sas_device->volume_handle = 0;
6511 sas_device->volume_wwid = 0;
6512 clear_bit(handle, ioc->pd_handles);
6513 if (sas_device->starget && sas_device->starget->hostdata) {
6514 starget = sas_device->starget;
6515 sas_target_priv_data = starget->hostdata;
6516 sas_target_priv_data->flags &=
6517 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
6518 }
6519 }
6520 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6521 if (!sas_device)
6522 return;
6523
6524 /* exposing raid component */
6525 if (starget)
6526 starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306527
6528 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306529}
6530
6531/**
6532 * _scsih_sas_pd_hide - hide pd component from /dev/sdX
6533 * @ioc: per adapter object
6534 * @element: IR config element data
6535 * Context: user.
6536 *
6537 * Return nothing.
6538 */
6539static void
6540_scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc,
6541 Mpi2EventIrConfigElement_t *element)
6542{
6543 struct _sas_device *sas_device;
6544 struct scsi_target *starget = NULL;
6545 struct MPT3SAS_TARGET *sas_target_priv_data;
6546 unsigned long flags;
6547 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6548 u16 volume_handle = 0;
6549 u64 volume_wwid = 0;
6550
6551 mpt3sas_config_get_volume_handle(ioc, handle, &volume_handle);
6552 if (volume_handle)
6553 mpt3sas_config_get_volume_wwid(ioc, volume_handle,
6554 &volume_wwid);
6555
6556 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306557 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306558 if (sas_device) {
6559 set_bit(handle, ioc->pd_handles);
6560 if (sas_device->starget && sas_device->starget->hostdata) {
6561 starget = sas_device->starget;
6562 sas_target_priv_data = starget->hostdata;
6563 sas_target_priv_data->flags |=
6564 MPT_TARGET_FLAGS_RAID_COMPONENT;
6565 sas_device->volume_handle = volume_handle;
6566 sas_device->volume_wwid = volume_wwid;
6567 }
6568 }
6569 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6570 if (!sas_device)
6571 return;
6572
6573 /* hiding raid component */
6574 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05306575
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306576 if (starget)
6577 starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306578
6579 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306580}
6581
6582/**
6583 * _scsih_sas_pd_delete - delete pd component
6584 * @ioc: per adapter object
6585 * @element: IR config element data
6586 * Context: user.
6587 *
6588 * Return nothing.
6589 */
6590static void
6591_scsih_sas_pd_delete(struct MPT3SAS_ADAPTER *ioc,
6592 Mpi2EventIrConfigElement_t *element)
6593{
6594 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6595
6596 _scsih_device_remove_by_handle(ioc, handle);
6597}
6598
6599/**
6600 * _scsih_sas_pd_add - remove pd component
6601 * @ioc: per adapter object
6602 * @element: IR config element data
6603 * Context: user.
6604 *
6605 * Return nothing.
6606 */
6607static void
6608_scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
6609 Mpi2EventIrConfigElement_t *element)
6610{
6611 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306612 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6613 Mpi2ConfigReply_t mpi_reply;
6614 Mpi2SasDevicePage0_t sas_device_pg0;
6615 u32 ioc_status;
6616 u64 sas_address;
6617 u16 parent_handle;
6618
6619 set_bit(handle, ioc->pd_handles);
6620
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306621 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306622 if (sas_device) {
6623 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306624 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306625 return;
6626 }
6627
6628 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
6629 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
6630 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6631 ioc->name, __FILE__, __LINE__, __func__);
6632 return;
6633 }
6634
6635 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6636 MPI2_IOCSTATUS_MASK;
6637 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6638 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6639 ioc->name, __FILE__, __LINE__, __func__);
6640 return;
6641 }
6642
6643 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6644 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6645 mpt3sas_transport_update_links(ioc, sas_address, handle,
6646 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
6647
6648 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
6649 _scsih_add_device(ioc, handle, 0, 1);
6650}
6651
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306652/**
6653 * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
6654 * @ioc: per adapter object
6655 * @event_data: event data payload
6656 * Context: user.
6657 *
6658 * Return nothing.
6659 */
6660static void
6661_scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
6662 Mpi2EventDataIrConfigChangeList_t *event_data)
6663{
6664 Mpi2EventIrConfigElement_t *element;
6665 u8 element_type;
6666 int i;
6667 char *reason_str = NULL, *element_str = NULL;
6668
6669 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6670
6671 pr_info(MPT3SAS_FMT "raid config change: (%s), elements(%d)\n",
6672 ioc->name, (le32_to_cpu(event_data->Flags) &
6673 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
6674 "foreign" : "native", event_data->NumElements);
6675 for (i = 0; i < event_data->NumElements; i++, element++) {
6676 switch (element->ReasonCode) {
6677 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6678 reason_str = "add";
6679 break;
6680 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6681 reason_str = "remove";
6682 break;
6683 case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
6684 reason_str = "no change";
6685 break;
6686 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6687 reason_str = "hide";
6688 break;
6689 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
6690 reason_str = "unhide";
6691 break;
6692 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6693 reason_str = "volume_created";
6694 break;
6695 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6696 reason_str = "volume_deleted";
6697 break;
6698 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6699 reason_str = "pd_created";
6700 break;
6701 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
6702 reason_str = "pd_deleted";
6703 break;
6704 default:
6705 reason_str = "unknown reason";
6706 break;
6707 }
6708 element_type = le16_to_cpu(element->ElementFlags) &
6709 MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
6710 switch (element_type) {
6711 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
6712 element_str = "volume";
6713 break;
6714 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
6715 element_str = "phys disk";
6716 break;
6717 case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
6718 element_str = "hot spare";
6719 break;
6720 default:
6721 element_str = "unknown element";
6722 break;
6723 }
6724 pr_info("\t(%s:%s), vol handle(0x%04x), " \
6725 "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
6726 reason_str, le16_to_cpu(element->VolDevHandle),
6727 le16_to_cpu(element->PhysDiskDevHandle),
6728 element->PhysDiskNum);
6729 }
6730}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306731
6732/**
6733 * _scsih_sas_ir_config_change_event - handle ir configuration change events
6734 * @ioc: per adapter object
6735 * @fw_event: The fw_event_work object
6736 * Context: user.
6737 *
6738 * Return nothing.
6739 */
6740static void
6741_scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
6742 struct fw_event_work *fw_event)
6743{
6744 Mpi2EventIrConfigElement_t *element;
6745 int i;
6746 u8 foreign_config;
Joe Lawrence35b62362014-06-25 17:05:34 -04006747 Mpi2EventDataIrConfigChangeList_t *event_data =
6748 (Mpi2EventDataIrConfigChangeList_t *)
6749 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306750
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306751 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
6752 (!ioc->hide_ir_msg))
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306753 _scsih_sas_ir_config_change_event_debug(ioc, event_data);
6754
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306755 foreign_config = (le32_to_cpu(event_data->Flags) &
6756 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
6757
6758 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05306759 if (ioc->shost_recovery &&
6760 ioc->hba_mpi_version_belonged != MPI2_VERSION) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306761 for (i = 0; i < event_data->NumElements; i++, element++) {
6762 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE)
6763 _scsih_ir_fastpath(ioc,
6764 le16_to_cpu(element->PhysDiskDevHandle),
6765 element->PhysDiskNum);
6766 }
6767 return;
6768 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306769
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306770 for (i = 0; i < event_data->NumElements; i++, element++) {
6771
6772 switch (element->ReasonCode) {
6773 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6774 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6775 if (!foreign_config)
6776 _scsih_sas_volume_add(ioc, element);
6777 break;
6778 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6779 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6780 if (!foreign_config)
6781 _scsih_sas_volume_delete(ioc,
6782 le16_to_cpu(element->VolDevHandle));
6783 break;
6784 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306785 if (!ioc->is_warpdrive)
6786 _scsih_sas_pd_hide(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306787 break;
6788 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306789 if (!ioc->is_warpdrive)
6790 _scsih_sas_pd_expose(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306791 break;
6792 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306793 if (!ioc->is_warpdrive)
6794 _scsih_sas_pd_add(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306795 break;
6796 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306797 if (!ioc->is_warpdrive)
6798 _scsih_sas_pd_delete(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306799 break;
6800 }
6801 }
6802}
6803
6804/**
6805 * _scsih_sas_ir_volume_event - IR volume event
6806 * @ioc: per adapter object
6807 * @fw_event: The fw_event_work object
6808 * Context: user.
6809 *
6810 * Return nothing.
6811 */
6812static void
6813_scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
6814 struct fw_event_work *fw_event)
6815{
6816 u64 wwid;
6817 unsigned long flags;
6818 struct _raid_device *raid_device;
6819 u16 handle;
6820 u32 state;
6821 int rc;
Joe Lawrence35b62362014-06-25 17:05:34 -04006822 Mpi2EventDataIrVolume_t *event_data =
6823 (Mpi2EventDataIrVolume_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306824
6825 if (ioc->shost_recovery)
6826 return;
6827
6828 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
6829 return;
6830
6831 handle = le16_to_cpu(event_data->VolDevHandle);
6832 state = le32_to_cpu(event_data->NewValue);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306833 if (!ioc->hide_ir_msg)
6834 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6835 "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
6836 ioc->name, __func__, handle,
6837 le32_to_cpu(event_data->PreviousValue), state));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306838 switch (state) {
6839 case MPI2_RAID_VOL_STATE_MISSING:
6840 case MPI2_RAID_VOL_STATE_FAILED:
6841 _scsih_sas_volume_delete(ioc, handle);
6842 break;
6843
6844 case MPI2_RAID_VOL_STATE_ONLINE:
6845 case MPI2_RAID_VOL_STATE_DEGRADED:
6846 case MPI2_RAID_VOL_STATE_OPTIMAL:
6847
6848 spin_lock_irqsave(&ioc->raid_device_lock, flags);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05306849 raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306850 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6851
6852 if (raid_device)
6853 break;
6854
6855 mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
6856 if (!wwid) {
6857 pr_err(MPT3SAS_FMT
6858 "failure at %s:%d/%s()!\n", ioc->name,
6859 __FILE__, __LINE__, __func__);
6860 break;
6861 }
6862
6863 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6864 if (!raid_device) {
6865 pr_err(MPT3SAS_FMT
6866 "failure at %s:%d/%s()!\n", ioc->name,
6867 __FILE__, __LINE__, __func__);
6868 break;
6869 }
6870
6871 raid_device->id = ioc->sas_id++;
6872 raid_device->channel = RAID_CHANNEL;
6873 raid_device->handle = handle;
6874 raid_device->wwid = wwid;
6875 _scsih_raid_device_add(ioc, raid_device);
6876 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6877 raid_device->id, 0);
6878 if (rc)
6879 _scsih_raid_device_remove(ioc, raid_device);
6880 break;
6881
6882 case MPI2_RAID_VOL_STATE_INITIALIZING:
6883 default:
6884 break;
6885 }
6886}
6887
6888/**
6889 * _scsih_sas_ir_physical_disk_event - PD event
6890 * @ioc: per adapter object
6891 * @fw_event: The fw_event_work object
6892 * Context: user.
6893 *
6894 * Return nothing.
6895 */
6896static void
6897_scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
6898 struct fw_event_work *fw_event)
6899{
6900 u16 handle, parent_handle;
6901 u32 state;
6902 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306903 Mpi2ConfigReply_t mpi_reply;
6904 Mpi2SasDevicePage0_t sas_device_pg0;
6905 u32 ioc_status;
Joe Lawrence35b62362014-06-25 17:05:34 -04006906 Mpi2EventDataIrPhysicalDisk_t *event_data =
6907 (Mpi2EventDataIrPhysicalDisk_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306908 u64 sas_address;
6909
6910 if (ioc->shost_recovery)
6911 return;
6912
6913 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
6914 return;
6915
6916 handle = le16_to_cpu(event_data->PhysDiskDevHandle);
6917 state = le32_to_cpu(event_data->NewValue);
6918
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306919 if (!ioc->hide_ir_msg)
6920 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6921 "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
6922 ioc->name, __func__, handle,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306923 le32_to_cpu(event_data->PreviousValue), state));
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306924
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306925 switch (state) {
6926 case MPI2_RAID_PD_STATE_ONLINE:
6927 case MPI2_RAID_PD_STATE_DEGRADED:
6928 case MPI2_RAID_PD_STATE_REBUILDING:
6929 case MPI2_RAID_PD_STATE_OPTIMAL:
6930 case MPI2_RAID_PD_STATE_HOT_SPARE:
6931
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306932 if (!ioc->is_warpdrive)
6933 set_bit(handle, ioc->pd_handles);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306934
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306935 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
6936 if (sas_device) {
6937 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306938 return;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306939 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306940
6941 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6942 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
6943 handle))) {
6944 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6945 ioc->name, __FILE__, __LINE__, __func__);
6946 return;
6947 }
6948
6949 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6950 MPI2_IOCSTATUS_MASK;
6951 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6952 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6953 ioc->name, __FILE__, __LINE__, __func__);
6954 return;
6955 }
6956
6957 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6958 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6959 mpt3sas_transport_update_links(ioc, sas_address, handle,
6960 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
6961
6962 _scsih_add_device(ioc, handle, 0, 1);
6963
6964 break;
6965
6966 case MPI2_RAID_PD_STATE_OFFLINE:
6967 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
6968 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
6969 default:
6970 break;
6971 }
6972}
6973
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306974/**
6975 * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
6976 * @ioc: per adapter object
6977 * @event_data: event data payload
6978 * Context: user.
6979 *
6980 * Return nothing.
6981 */
6982static void
6983_scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc,
6984 Mpi2EventDataIrOperationStatus_t *event_data)
6985{
6986 char *reason_str = NULL;
6987
6988 switch (event_data->RAIDOperation) {
6989 case MPI2_EVENT_IR_RAIDOP_RESYNC:
6990 reason_str = "resync";
6991 break;
6992 case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
6993 reason_str = "online capacity expansion";
6994 break;
6995 case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
6996 reason_str = "consistency check";
6997 break;
6998 case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT:
6999 reason_str = "background init";
7000 break;
7001 case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT:
7002 reason_str = "make data consistent";
7003 break;
7004 }
7005
7006 if (!reason_str)
7007 return;
7008
7009 pr_info(MPT3SAS_FMT "raid operational status: (%s)" \
7010 "\thandle(0x%04x), percent complete(%d)\n",
7011 ioc->name, reason_str,
7012 le16_to_cpu(event_data->VolDevHandle),
7013 event_data->PercentComplete);
7014}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307015
7016/**
7017 * _scsih_sas_ir_operation_status_event - handle RAID operation events
7018 * @ioc: per adapter object
7019 * @fw_event: The fw_event_work object
7020 * Context: user.
7021 *
7022 * Return nothing.
7023 */
7024static void
7025_scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
7026 struct fw_event_work *fw_event)
7027{
Joe Lawrence35b62362014-06-25 17:05:34 -04007028 Mpi2EventDataIrOperationStatus_t *event_data =
7029 (Mpi2EventDataIrOperationStatus_t *)
7030 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307031 static struct _raid_device *raid_device;
7032 unsigned long flags;
7033 u16 handle;
7034
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307035 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
7036 (!ioc->hide_ir_msg))
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307037 _scsih_sas_ir_operation_status_event_debug(ioc,
7038 event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307039
7040 /* code added for raid transport support */
7041 if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
7042
7043 spin_lock_irqsave(&ioc->raid_device_lock, flags);
7044 handle = le16_to_cpu(event_data->VolDevHandle);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05307045 raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307046 if (raid_device)
7047 raid_device->percent_complete =
7048 event_data->PercentComplete;
7049 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7050 }
7051}
7052
7053/**
7054 * _scsih_prep_device_scan - initialize parameters prior to device scan
7055 * @ioc: per adapter object
7056 *
7057 * Set the deleted flag prior to device scan. If the device is found during
7058 * the scan, then we clear the deleted flag.
7059 */
7060static void
7061_scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc)
7062{
7063 struct MPT3SAS_DEVICE *sas_device_priv_data;
7064 struct scsi_device *sdev;
7065
7066 shost_for_each_device(sdev, ioc->shost) {
7067 sas_device_priv_data = sdev->hostdata;
7068 if (sas_device_priv_data && sas_device_priv_data->sas_target)
7069 sas_device_priv_data->sas_target->deleted = 1;
7070 }
7071}
7072
7073/**
7074 * _scsih_mark_responding_sas_device - mark a sas_devices as responding
7075 * @ioc: per adapter object
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307076 * @sas_device_pg0: SAS Device page 0
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307077 *
7078 * After host reset, find out whether devices are still responding.
7079 * Used in _scsih_remove_unresponsive_sas_devices.
7080 *
7081 * Return nothing.
7082 */
7083static void
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307084_scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc,
7085Mpi2SasDevicePage0_t *sas_device_pg0)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307086{
7087 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
7088 struct scsi_target *starget;
7089 struct _sas_device *sas_device;
7090 unsigned long flags;
7091
7092 spin_lock_irqsave(&ioc->sas_device_lock, flags);
7093 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307094 if ((sas_device->sas_address == sas_device_pg0->SASAddress) &&
7095 (sas_device->slot == sas_device_pg0->Slot)) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307096 sas_device->responding = 1;
7097 starget = sas_device->starget;
7098 if (starget && starget->hostdata) {
7099 sas_target_priv_data = starget->hostdata;
7100 sas_target_priv_data->tm_busy = 0;
7101 sas_target_priv_data->deleted = 0;
7102 } else
7103 sas_target_priv_data = NULL;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307104 if (starget) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307105 starget_printk(KERN_INFO, starget,
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307106 "handle(0x%04x), sas_addr(0x%016llx)\n",
7107 sas_device_pg0->DevHandle,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307108 (unsigned long long)
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307109 sas_device->sas_address);
7110
7111 if (sas_device->enclosure_handle != 0)
7112 starget_printk(KERN_INFO, starget,
7113 "enclosure logical id(0x%016llx),"
7114 " slot(%d)\n",
7115 (unsigned long long)
7116 sas_device->enclosure_logical_id,
7117 sas_device->slot);
7118 }
7119 if (sas_device_pg0->Flags &
7120 MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
7121 sas_device->enclosure_level =
7122 le16_to_cpu(sas_device_pg0->EnclosureLevel);
7123 memcpy(&sas_device->connector_name[0],
7124 &sas_device_pg0->ConnectorName[0], 4);
7125 } else {
7126 sas_device->enclosure_level = 0;
7127 sas_device->connector_name[0] = '\0';
7128 }
7129
7130 if (sas_device->handle == sas_device_pg0->DevHandle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307131 goto out;
7132 pr_info("\thandle changed from(0x%04x)!!!\n",
7133 sas_device->handle);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307134 sas_device->handle = sas_device_pg0->DevHandle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307135 if (sas_target_priv_data)
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307136 sas_target_priv_data->handle =
7137 sas_device_pg0->DevHandle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307138 goto out;
7139 }
7140 }
7141 out:
7142 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
7143}
7144
7145/**
7146 * _scsih_search_responding_sas_devices -
7147 * @ioc: per adapter object
7148 *
7149 * After host reset, find out whether devices are still responding.
7150 * If not remove.
7151 *
7152 * Return nothing.
7153 */
7154static void
7155_scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
7156{
7157 Mpi2SasDevicePage0_t sas_device_pg0;
7158 Mpi2ConfigReply_t mpi_reply;
7159 u16 ioc_status;
7160 u16 handle;
7161 u32 device_info;
7162
7163 pr_info(MPT3SAS_FMT "search for end-devices: start\n", ioc->name);
7164
7165 if (list_empty(&ioc->sas_device_list))
7166 goto out;
7167
7168 handle = 0xFFFF;
7169 while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7170 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
7171 handle))) {
7172 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7173 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307174 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307175 break;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307176 handle = sas_device_pg0.DevHandle =
7177 le16_to_cpu(sas_device_pg0.DevHandle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307178 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
7179 if (!(_scsih_is_end_device(device_info)))
7180 continue;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307181 sas_device_pg0.SASAddress =
7182 le64_to_cpu(sas_device_pg0.SASAddress);
7183 sas_device_pg0.Slot = le16_to_cpu(sas_device_pg0.Slot);
7184 _scsih_mark_responding_sas_device(ioc, &sas_device_pg0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307185 }
7186
7187 out:
7188 pr_info(MPT3SAS_FMT "search for end-devices: complete\n",
7189 ioc->name);
7190}
7191
7192/**
7193 * _scsih_mark_responding_raid_device - mark a raid_device as responding
7194 * @ioc: per adapter object
7195 * @wwid: world wide identifier for raid volume
7196 * @handle: device handle
7197 *
7198 * After host reset, find out whether devices are still responding.
7199 * Used in _scsih_remove_unresponsive_raid_devices.
7200 *
7201 * Return nothing.
7202 */
7203static void
7204_scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
7205 u16 handle)
7206{
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307207 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307208 struct scsi_target *starget;
7209 struct _raid_device *raid_device;
7210 unsigned long flags;
7211
7212 spin_lock_irqsave(&ioc->raid_device_lock, flags);
7213 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
7214 if (raid_device->wwid == wwid && raid_device->starget) {
7215 starget = raid_device->starget;
7216 if (starget && starget->hostdata) {
7217 sas_target_priv_data = starget->hostdata;
7218 sas_target_priv_data->deleted = 0;
7219 } else
7220 sas_target_priv_data = NULL;
7221 raid_device->responding = 1;
7222 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7223 starget_printk(KERN_INFO, raid_device->starget,
7224 "handle(0x%04x), wwid(0x%016llx)\n", handle,
7225 (unsigned long long)raid_device->wwid);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307226
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307227 /*
7228 * WARPDRIVE: The handles of the PDs might have changed
7229 * across the host reset so re-initialize the
7230 * required data for Direct IO
7231 */
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05307232 mpt3sas_init_warpdrive_properties(ioc, raid_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307233 spin_lock_irqsave(&ioc->raid_device_lock, flags);
7234 if (raid_device->handle == handle) {
7235 spin_unlock_irqrestore(&ioc->raid_device_lock,
7236 flags);
7237 return;
7238 }
7239 pr_info("\thandle changed from(0x%04x)!!!\n",
7240 raid_device->handle);
7241 raid_device->handle = handle;
7242 if (sas_target_priv_data)
7243 sas_target_priv_data->handle = handle;
7244 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7245 return;
7246 }
7247 }
7248 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7249}
7250
7251/**
7252 * _scsih_search_responding_raid_devices -
7253 * @ioc: per adapter object
7254 *
7255 * After host reset, find out whether devices are still responding.
7256 * If not remove.
7257 *
7258 * Return nothing.
7259 */
7260static void
7261_scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
7262{
7263 Mpi2RaidVolPage1_t volume_pg1;
7264 Mpi2RaidVolPage0_t volume_pg0;
7265 Mpi2RaidPhysDiskPage0_t pd_pg0;
7266 Mpi2ConfigReply_t mpi_reply;
7267 u16 ioc_status;
7268 u16 handle;
7269 u8 phys_disk_num;
7270
7271 if (!ioc->ir_firmware)
7272 return;
7273
7274 pr_info(MPT3SAS_FMT "search for raid volumes: start\n",
7275 ioc->name);
7276
7277 if (list_empty(&ioc->raid_device_list))
7278 goto out;
7279
7280 handle = 0xFFFF;
7281 while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
7282 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
7283 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7284 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307285 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307286 break;
7287 handle = le16_to_cpu(volume_pg1.DevHandle);
7288
7289 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
7290 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
7291 sizeof(Mpi2RaidVolPage0_t)))
7292 continue;
7293
7294 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
7295 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
7296 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED)
7297 _scsih_mark_responding_raid_device(ioc,
7298 le64_to_cpu(volume_pg1.WWID), handle);
7299 }
7300
7301 /* refresh the pd_handles */
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307302 if (!ioc->is_warpdrive) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307303 phys_disk_num = 0xFF;
7304 memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
7305 while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
7306 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
7307 phys_disk_num))) {
7308 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7309 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307310 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307311 break;
7312 phys_disk_num = pd_pg0.PhysDiskNum;
7313 handle = le16_to_cpu(pd_pg0.DevHandle);
7314 set_bit(handle, ioc->pd_handles);
7315 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307316 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307317 out:
7318 pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n",
7319 ioc->name);
7320}
7321
7322/**
7323 * _scsih_mark_responding_expander - mark a expander as responding
7324 * @ioc: per adapter object
7325 * @sas_address: sas address
7326 * @handle:
7327 *
7328 * After host reset, find out whether devices are still responding.
7329 * Used in _scsih_remove_unresponsive_expanders.
7330 *
7331 * Return nothing.
7332 */
7333static void
7334_scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
7335 u16 handle)
7336{
7337 struct _sas_node *sas_expander;
7338 unsigned long flags;
7339 int i;
7340
7341 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7342 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
7343 if (sas_expander->sas_address != sas_address)
7344 continue;
7345 sas_expander->responding = 1;
7346 if (sas_expander->handle == handle)
7347 goto out;
7348 pr_info("\texpander(0x%016llx): handle changed" \
7349 " from(0x%04x) to (0x%04x)!!!\n",
7350 (unsigned long long)sas_expander->sas_address,
7351 sas_expander->handle, handle);
7352 sas_expander->handle = handle;
7353 for (i = 0 ; i < sas_expander->num_phys ; i++)
7354 sas_expander->phy[i].handle = handle;
7355 goto out;
7356 }
7357 out:
7358 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7359}
7360
7361/**
7362 * _scsih_search_responding_expanders -
7363 * @ioc: per adapter object
7364 *
7365 * After host reset, find out whether devices are still responding.
7366 * If not remove.
7367 *
7368 * Return nothing.
7369 */
7370static void
7371_scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
7372{
7373 Mpi2ExpanderPage0_t expander_pg0;
7374 Mpi2ConfigReply_t mpi_reply;
7375 u16 ioc_status;
7376 u64 sas_address;
7377 u16 handle;
7378
7379 pr_info(MPT3SAS_FMT "search for expanders: start\n", ioc->name);
7380
7381 if (list_empty(&ioc->sas_expander_list))
7382 goto out;
7383
7384 handle = 0xFFFF;
7385 while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
7386 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
7387
7388 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7389 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307390 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307391 break;
7392
7393 handle = le16_to_cpu(expander_pg0.DevHandle);
7394 sas_address = le64_to_cpu(expander_pg0.SASAddress);
7395 pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n",
7396 handle,
7397 (unsigned long long)sas_address);
7398 _scsih_mark_responding_expander(ioc, sas_address, handle);
7399 }
7400
7401 out:
7402 pr_info(MPT3SAS_FMT "search for expanders: complete\n", ioc->name);
7403}
7404
7405/**
7406 * _scsih_remove_unresponding_sas_devices - removing unresponding devices
7407 * @ioc: per adapter object
7408 *
7409 * Return nothing.
7410 */
7411static void
7412_scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
7413{
7414 struct _sas_device *sas_device, *sas_device_next;
7415 struct _sas_node *sas_expander, *sas_expander_next;
7416 struct _raid_device *raid_device, *raid_device_next;
7417 struct list_head tmp_list;
7418 unsigned long flags;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307419 LIST_HEAD(head);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307420
7421 pr_info(MPT3SAS_FMT "removing unresponding devices: start\n",
7422 ioc->name);
7423
7424 /* removing unresponding end devices */
7425 pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n",
7426 ioc->name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307427 /*
7428 * Iterate, pulling off devices marked as non-responding. We become the
7429 * owner for the reference the list had on any object we prune.
7430 */
7431 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307432 list_for_each_entry_safe(sas_device, sas_device_next,
7433 &ioc->sas_device_list, list) {
7434 if (!sas_device->responding)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307435 list_move_tail(&sas_device->list, &head);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307436 else
7437 sas_device->responding = 0;
7438 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307439 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
7440
7441 /*
7442 * Now, uninitialize and remove the unresponding devices we pruned.
7443 */
7444 list_for_each_entry_safe(sas_device, sas_device_next, &head, list) {
7445 _scsih_remove_device(ioc, sas_device);
7446 list_del_init(&sas_device->list);
7447 sas_device_put(sas_device);
7448 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307449
7450 /* removing unresponding volumes */
7451 if (ioc->ir_firmware) {
7452 pr_info(MPT3SAS_FMT "removing unresponding devices: volumes\n",
7453 ioc->name);
7454 list_for_each_entry_safe(raid_device, raid_device_next,
7455 &ioc->raid_device_list, list) {
7456 if (!raid_device->responding)
7457 _scsih_sas_volume_delete(ioc,
7458 raid_device->handle);
7459 else
7460 raid_device->responding = 0;
7461 }
7462 }
7463
7464 /* removing unresponding expanders */
7465 pr_info(MPT3SAS_FMT "removing unresponding devices: expanders\n",
7466 ioc->name);
7467 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7468 INIT_LIST_HEAD(&tmp_list);
7469 list_for_each_entry_safe(sas_expander, sas_expander_next,
7470 &ioc->sas_expander_list, list) {
7471 if (!sas_expander->responding)
7472 list_move_tail(&sas_expander->list, &tmp_list);
7473 else
7474 sas_expander->responding = 0;
7475 }
7476 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7477 list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
7478 list) {
7479 list_del(&sas_expander->list);
7480 _scsih_expander_node_remove(ioc, sas_expander);
7481 }
7482
7483 pr_info(MPT3SAS_FMT "removing unresponding devices: complete\n",
7484 ioc->name);
7485
7486 /* unblock devices */
7487 _scsih_ublock_io_all_device(ioc);
7488}
7489
7490static void
7491_scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc,
7492 struct _sas_node *sas_expander, u16 handle)
7493{
7494 Mpi2ExpanderPage1_t expander_pg1;
7495 Mpi2ConfigReply_t mpi_reply;
7496 int i;
7497
7498 for (i = 0 ; i < sas_expander->num_phys ; i++) {
7499 if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
7500 &expander_pg1, i, handle))) {
7501 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7502 ioc->name, __FILE__, __LINE__, __func__);
7503 return;
7504 }
7505
7506 mpt3sas_transport_update_links(ioc, sas_expander->sas_address,
7507 le16_to_cpu(expander_pg1.AttachedDevHandle), i,
7508 expander_pg1.NegotiatedLinkRate >> 4);
7509 }
7510}
7511
7512/**
7513 * _scsih_scan_for_devices_after_reset - scan for devices after host reset
7514 * @ioc: per adapter object
7515 *
7516 * Return nothing.
7517 */
7518static void
7519_scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
7520{
7521 Mpi2ExpanderPage0_t expander_pg0;
7522 Mpi2SasDevicePage0_t sas_device_pg0;
7523 Mpi2RaidVolPage1_t volume_pg1;
7524 Mpi2RaidVolPage0_t volume_pg0;
7525 Mpi2RaidPhysDiskPage0_t pd_pg0;
7526 Mpi2EventIrConfigElement_t element;
7527 Mpi2ConfigReply_t mpi_reply;
7528 u8 phys_disk_num;
7529 u16 ioc_status;
7530 u16 handle, parent_handle;
7531 u64 sas_address;
7532 struct _sas_device *sas_device;
7533 struct _sas_node *expander_device;
7534 static struct _raid_device *raid_device;
7535 u8 retry_count;
7536 unsigned long flags;
7537
7538 pr_info(MPT3SAS_FMT "scan devices: start\n", ioc->name);
7539
7540 _scsih_sas_host_refresh(ioc);
7541
7542 pr_info(MPT3SAS_FMT "\tscan devices: expanders start\n", ioc->name);
7543
7544 /* expanders */
7545 handle = 0xFFFF;
7546 while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
7547 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
7548 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7549 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307550 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7551 pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \
7552 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7553 ioc->name, ioc_status,
7554 le32_to_cpu(mpi_reply.IOCLogInfo));
7555 break;
7556 }
7557 handle = le16_to_cpu(expander_pg0.DevHandle);
7558 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7559 expander_device = mpt3sas_scsih_expander_find_by_sas_address(
7560 ioc, le64_to_cpu(expander_pg0.SASAddress));
7561 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7562 if (expander_device)
7563 _scsih_refresh_expander_links(ioc, expander_device,
7564 handle);
7565 else {
7566 pr_info(MPT3SAS_FMT "\tBEFORE adding expander: " \
7567 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7568 handle, (unsigned long long)
7569 le64_to_cpu(expander_pg0.SASAddress));
7570 _scsih_expander_add(ioc, handle);
7571 pr_info(MPT3SAS_FMT "\tAFTER adding expander: " \
7572 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7573 handle, (unsigned long long)
7574 le64_to_cpu(expander_pg0.SASAddress));
7575 }
7576 }
7577
7578 pr_info(MPT3SAS_FMT "\tscan devices: expanders complete\n",
7579 ioc->name);
7580
7581 if (!ioc->ir_firmware)
7582 goto skip_to_sas;
7583
7584 pr_info(MPT3SAS_FMT "\tscan devices: phys disk start\n", ioc->name);
7585
7586 /* phys disk */
7587 phys_disk_num = 0xFF;
7588 while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
7589 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
7590 phys_disk_num))) {
7591 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7592 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307593 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7594 pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\
7595 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7596 ioc->name, ioc_status,
7597 le32_to_cpu(mpi_reply.IOCLogInfo));
7598 break;
7599 }
7600 phys_disk_num = pd_pg0.PhysDiskNum;
7601 handle = le16_to_cpu(pd_pg0.DevHandle);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307602 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
7603 if (sas_device) {
7604 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307605 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307606 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307607 if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7608 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
7609 handle) != 0)
7610 continue;
7611 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7612 MPI2_IOCSTATUS_MASK;
7613 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7614 pr_info(MPT3SAS_FMT "\tbreak from phys disk scan " \
7615 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7616 ioc->name, ioc_status,
7617 le32_to_cpu(mpi_reply.IOCLogInfo));
7618 break;
7619 }
7620 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7621 if (!_scsih_get_sas_address(ioc, parent_handle,
7622 &sas_address)) {
7623 pr_info(MPT3SAS_FMT "\tBEFORE adding phys disk: " \
7624 " handle (0x%04x), sas_addr(0x%016llx)\n",
7625 ioc->name, handle, (unsigned long long)
7626 le64_to_cpu(sas_device_pg0.SASAddress));
7627 mpt3sas_transport_update_links(ioc, sas_address,
7628 handle, sas_device_pg0.PhyNum,
7629 MPI2_SAS_NEG_LINK_RATE_1_5);
7630 set_bit(handle, ioc->pd_handles);
7631 retry_count = 0;
7632 /* This will retry adding the end device.
7633 * _scsih_add_device() will decide on retries and
7634 * return "1" when it should be retried
7635 */
7636 while (_scsih_add_device(ioc, handle, retry_count++,
7637 1)) {
7638 ssleep(1);
7639 }
7640 pr_info(MPT3SAS_FMT "\tAFTER adding phys disk: " \
7641 " handle (0x%04x), sas_addr(0x%016llx)\n",
7642 ioc->name, handle, (unsigned long long)
7643 le64_to_cpu(sas_device_pg0.SASAddress));
7644 }
7645 }
7646
7647 pr_info(MPT3SAS_FMT "\tscan devices: phys disk complete\n",
7648 ioc->name);
7649
7650 pr_info(MPT3SAS_FMT "\tscan devices: volumes start\n", ioc->name);
7651
7652 /* volumes */
7653 handle = 0xFFFF;
7654 while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
7655 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
7656 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7657 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307658 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7659 pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
7660 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7661 ioc->name, ioc_status,
7662 le32_to_cpu(mpi_reply.IOCLogInfo));
7663 break;
7664 }
7665 handle = le16_to_cpu(volume_pg1.DevHandle);
7666 spin_lock_irqsave(&ioc->raid_device_lock, flags);
7667 raid_device = _scsih_raid_device_find_by_wwid(ioc,
7668 le64_to_cpu(volume_pg1.WWID));
7669 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7670 if (raid_device)
7671 continue;
7672 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
7673 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
7674 sizeof(Mpi2RaidVolPage0_t)))
7675 continue;
7676 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7677 MPI2_IOCSTATUS_MASK;
7678 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7679 pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
7680 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7681 ioc->name, ioc_status,
7682 le32_to_cpu(mpi_reply.IOCLogInfo));
7683 break;
7684 }
7685 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
7686 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
7687 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
7688 memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
7689 element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
7690 element.VolDevHandle = volume_pg1.DevHandle;
7691 pr_info(MPT3SAS_FMT
7692 "\tBEFORE adding volume: handle (0x%04x)\n",
7693 ioc->name, volume_pg1.DevHandle);
7694 _scsih_sas_volume_add(ioc, &element);
7695 pr_info(MPT3SAS_FMT
7696 "\tAFTER adding volume: handle (0x%04x)\n",
7697 ioc->name, volume_pg1.DevHandle);
7698 }
7699 }
7700
7701 pr_info(MPT3SAS_FMT "\tscan devices: volumes complete\n",
7702 ioc->name);
7703
7704 skip_to_sas:
7705
7706 pr_info(MPT3SAS_FMT "\tscan devices: end devices start\n",
7707 ioc->name);
7708
7709 /* sas devices */
7710 handle = 0xFFFF;
7711 while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7712 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
7713 handle))) {
7714 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7715 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307716 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7717 pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\
7718 " ioc_status(0x%04x), loginfo(0x%08x)\n",
7719 ioc->name, ioc_status,
7720 le32_to_cpu(mpi_reply.IOCLogInfo));
7721 break;
7722 }
7723 handle = le16_to_cpu(sas_device_pg0.DevHandle);
7724 if (!(_scsih_is_end_device(
7725 le32_to_cpu(sas_device_pg0.DeviceInfo))))
7726 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307727 sas_device = mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307728 le64_to_cpu(sas_device_pg0.SASAddress));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307729 if (sas_device) {
7730 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307731 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307732 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307733 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7734 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
7735 pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \
7736 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7737 handle, (unsigned long long)
7738 le64_to_cpu(sas_device_pg0.SASAddress));
7739 mpt3sas_transport_update_links(ioc, sas_address, handle,
7740 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
7741 retry_count = 0;
7742 /* This will retry adding the end device.
7743 * _scsih_add_device() will decide on retries and
7744 * return "1" when it should be retried
7745 */
7746 while (_scsih_add_device(ioc, handle, retry_count++,
7747 0)) {
7748 ssleep(1);
7749 }
7750 pr_info(MPT3SAS_FMT "\tAFTER adding end device: " \
7751 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7752 handle, (unsigned long long)
7753 le64_to_cpu(sas_device_pg0.SASAddress));
7754 }
7755 }
7756 pr_info(MPT3SAS_FMT "\tscan devices: end devices complete\n",
7757 ioc->name);
7758
7759 pr_info(MPT3SAS_FMT "scan devices: complete\n", ioc->name);
7760}
7761/**
7762 * mpt3sas_scsih_reset_handler - reset callback handler (for scsih)
7763 * @ioc: per adapter object
7764 * @reset_phase: phase
7765 *
7766 * The handler for doing any required cleanup or initialization.
7767 *
7768 * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET,
7769 * MPT3_IOC_DONE_RESET
7770 *
7771 * Return nothing.
7772 */
7773void
7774mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
7775{
7776 switch (reset_phase) {
7777 case MPT3_IOC_PRE_RESET:
7778 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7779 "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__));
7780 break;
7781 case MPT3_IOC_AFTER_RESET:
7782 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7783 "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__));
7784 if (ioc->scsih_cmds.status & MPT3_CMD_PENDING) {
7785 ioc->scsih_cmds.status |= MPT3_CMD_RESET;
7786 mpt3sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
7787 complete(&ioc->scsih_cmds.done);
7788 }
7789 if (ioc->tm_cmds.status & MPT3_CMD_PENDING) {
7790 ioc->tm_cmds.status |= MPT3_CMD_RESET;
7791 mpt3sas_base_free_smid(ioc, ioc->tm_cmds.smid);
7792 complete(&ioc->tm_cmds.done);
7793 }
7794
7795 _scsih_fw_event_cleanup_queue(ioc);
7796 _scsih_flush_running_cmds(ioc);
7797 break;
7798 case MPT3_IOC_DONE_RESET:
7799 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7800 "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__));
7801 if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
7802 !ioc->sas_hba.num_phys)) {
7803 _scsih_prep_device_scan(ioc);
7804 _scsih_search_responding_sas_devices(ioc);
7805 _scsih_search_responding_raid_devices(ioc);
7806 _scsih_search_responding_expanders(ioc);
7807 _scsih_error_recovery_delete_devices(ioc);
7808 }
7809 break;
7810 }
7811}
7812
7813/**
7814 * _mpt3sas_fw_work - delayed task for processing firmware events
7815 * @ioc: per adapter object
7816 * @fw_event: The fw_event_work object
7817 * Context: user.
7818 *
7819 * Return nothing.
7820 */
7821static void
7822_mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
7823{
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307824 _scsih_fw_event_del_from_list(ioc, fw_event);
7825
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307826 /* the queue is being flushed so ignore this event */
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307827 if (ioc->remove_host || ioc->pci_error_recovery) {
7828 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307829 return;
7830 }
7831
7832 switch (fw_event->event) {
7833 case MPT3SAS_PROCESS_TRIGGER_DIAG:
Joe Lawrence35b62362014-06-25 17:05:34 -04007834 mpt3sas_process_trigger_data(ioc,
7835 (struct SL_WH_TRIGGERS_EVENT_DATA_T *)
7836 fw_event->event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307837 break;
7838 case MPT3SAS_REMOVE_UNRESPONDING_DEVICES:
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307839 while (scsi_host_in_recovery(ioc->shost) ||
7840 ioc->shost_recovery) {
7841 /*
7842 * If we're unloading, bail. Otherwise, this can become
7843 * an infinite loop.
7844 */
7845 if (ioc->remove_host)
7846 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307847 ssleep(1);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307848 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307849 _scsih_remove_unresponding_sas_devices(ioc);
7850 _scsih_scan_for_devices_after_reset(ioc);
7851 break;
7852 case MPT3SAS_PORT_ENABLE_COMPLETE:
7853 ioc->start_scan = 0;
7854 if (missing_delay[0] != -1 && missing_delay[1] != -1)
7855 mpt3sas_base_update_missing_delay(ioc, missing_delay[0],
7856 missing_delay[1]);
7857 dewtprintk(ioc, pr_info(MPT3SAS_FMT
7858 "port enable: complete from worker thread\n",
7859 ioc->name));
7860 break;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05307861 case MPT3SAS_TURN_ON_PFA_LED:
7862 _scsih_turn_on_pfa_led(ioc, fw_event->device_handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307863 break;
7864 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7865 _scsih_sas_topology_change_event(ioc, fw_event);
7866 break;
7867 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7868 _scsih_sas_device_status_change_event(ioc, fw_event);
7869 break;
7870 case MPI2_EVENT_SAS_DISCOVERY:
7871 _scsih_sas_discovery_event(ioc, fw_event);
7872 break;
7873 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7874 _scsih_sas_broadcast_primitive_event(ioc, fw_event);
7875 break;
7876 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7877 _scsih_sas_enclosure_dev_status_change_event(ioc,
7878 fw_event);
7879 break;
7880 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7881 _scsih_sas_ir_config_change_event(ioc, fw_event);
7882 break;
7883 case MPI2_EVENT_IR_VOLUME:
7884 _scsih_sas_ir_volume_event(ioc, fw_event);
7885 break;
7886 case MPI2_EVENT_IR_PHYSICAL_DISK:
7887 _scsih_sas_ir_physical_disk_event(ioc, fw_event);
7888 break;
7889 case MPI2_EVENT_IR_OPERATION_STATUS:
7890 _scsih_sas_ir_operation_status_event(ioc, fw_event);
7891 break;
7892 }
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307893out:
7894 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307895}
7896
7897/**
7898 * _firmware_event_work
7899 * @ioc: per adapter object
7900 * @work: The fw_event_work object
7901 * Context: user.
7902 *
7903 * wrappers for the work thread handling firmware events
7904 *
7905 * Return nothing.
7906 */
7907
7908static void
7909_firmware_event_work(struct work_struct *work)
7910{
7911 struct fw_event_work *fw_event = container_of(work,
7912 struct fw_event_work, work);
7913
7914 _mpt3sas_fw_work(fw_event->ioc, fw_event);
7915}
7916
7917/**
7918 * mpt3sas_scsih_event_callback - firmware event handler (called at ISR time)
7919 * @ioc: per adapter object
7920 * @msix_index: MSIX table index supplied by the OS
7921 * @reply: reply message frame(lower 32bit addr)
7922 * Context: interrupt.
7923 *
7924 * This function merely adds a new work task into ioc->firmware_event_thread.
7925 * The tasks are worked from _firmware_event_work in user context.
7926 *
7927 * Return 1 meaning mf should be freed from _base_interrupt
7928 * 0 means the mf is freed from this function.
7929 */
7930u8
7931mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
7932 u32 reply)
7933{
7934 struct fw_event_work *fw_event;
7935 Mpi2EventNotificationReply_t *mpi_reply;
7936 u16 event;
7937 u16 sz;
Chaitra P Ba470a512016-05-06 14:29:27 +05307938 Mpi26EventDataActiveCableExcept_t *ActiveCableEventData;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307939
7940 /* events turned off due to host reset or driver unloading */
7941 if (ioc->remove_host || ioc->pci_error_recovery)
7942 return 1;
7943
7944 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
7945
7946 if (unlikely(!mpi_reply)) {
7947 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
7948 ioc->name, __FILE__, __LINE__, __func__);
7949 return 1;
7950 }
7951
7952 event = le16_to_cpu(mpi_reply->Event);
7953
7954 if (event != MPI2_EVENT_LOG_ENTRY_ADDED)
7955 mpt3sas_trigger_event(ioc, event, 0);
7956
7957 switch (event) {
7958 /* handle these */
7959 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7960 {
7961 Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
7962 (Mpi2EventDataSasBroadcastPrimitive_t *)
7963 mpi_reply->EventData;
7964
7965 if (baen_data->Primitive !=
7966 MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
7967 return 1;
7968
7969 if (ioc->broadcast_aen_busy) {
7970 ioc->broadcast_aen_pending++;
7971 return 1;
7972 } else
7973 ioc->broadcast_aen_busy = 1;
7974 break;
7975 }
7976
7977 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7978 _scsih_check_topo_delete_events(ioc,
7979 (Mpi2EventDataSasTopologyChangeList_t *)
7980 mpi_reply->EventData);
7981 break;
7982 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7983 _scsih_check_ir_config_unhide_events(ioc,
7984 (Mpi2EventDataIrConfigChangeList_t *)
7985 mpi_reply->EventData);
7986 break;
7987 case MPI2_EVENT_IR_VOLUME:
7988 _scsih_check_volume_delete_events(ioc,
7989 (Mpi2EventDataIrVolume_t *)
7990 mpi_reply->EventData);
7991 break;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307992 case MPI2_EVENT_LOG_ENTRY_ADDED:
7993 {
7994 Mpi2EventDataLogEntryAdded_t *log_entry;
7995 u32 *log_code;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307996
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307997 if (!ioc->is_warpdrive)
7998 break;
7999
8000 log_entry = (Mpi2EventDataLogEntryAdded_t *)
8001 mpi_reply->EventData;
8002 log_code = (u32 *)log_entry->LogData;
8003
8004 if (le16_to_cpu(log_entry->LogEntryQualifier)
8005 != MPT2_WARPDRIVE_LOGENTRY)
8006 break;
8007
8008 switch (le32_to_cpu(*log_code)) {
8009 case MPT2_WARPDRIVE_LC_SSDT:
8010 pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
8011 "IO Throttling has occurred in the WarpDrive "
8012 "subsystem. Check WarpDrive documentation for "
8013 "additional details.\n", ioc->name);
8014 break;
8015 case MPT2_WARPDRIVE_LC_SSDLW:
8016 pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
8017 "Program/Erase Cycles for the WarpDrive subsystem "
8018 "in degraded range. Check WarpDrive documentation "
8019 "for additional details.\n", ioc->name);
8020 break;
8021 case MPT2_WARPDRIVE_LC_SSDLF:
8022 pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
8023 "There are no Program/Erase Cycles for the "
8024 "WarpDrive subsystem. The storage device will be "
8025 "in read-only mode. Check WarpDrive documentation "
8026 "for additional details.\n", ioc->name);
8027 break;
8028 case MPT2_WARPDRIVE_LC_BRMF:
8029 pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
8030 "The Backup Rail Monitor has failed on the "
8031 "WarpDrive subsystem. Check WarpDrive "
8032 "documentation for additional details.\n",
8033 ioc->name);
8034 break;
8035 }
8036
8037 break;
8038 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308039 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
8040 case MPI2_EVENT_IR_OPERATION_STATUS:
8041 case MPI2_EVENT_SAS_DISCOVERY:
8042 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
8043 case MPI2_EVENT_IR_PHYSICAL_DISK:
8044 break;
8045
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05308046 case MPI2_EVENT_TEMP_THRESHOLD:
8047 _scsih_temp_threshold_events(ioc,
8048 (Mpi2EventDataTemperature_t *)
8049 mpi_reply->EventData);
8050 break;
Chaitra P Ba470a512016-05-06 14:29:27 +05308051 case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION:
8052 ActiveCableEventData =
8053 (Mpi26EventDataActiveCableExcept_t *) mpi_reply->EventData;
8054 if (ActiveCableEventData->ReasonCode ==
Dan Carpenter7ebd67e2016-05-12 23:37:38 +03008055 MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) {
Chaitra P Ba470a512016-05-06 14:29:27 +05308056 pr_info(MPT3SAS_FMT "Currently an active cable with ReceptacleID %d",
8057 ioc->name, ActiveCableEventData->ReceptacleID);
8058 pr_info("cannot be powered and devices connected to this active cable");
8059 pr_info("will not be seen. This active cable");
8060 pr_info("requires %d mW of power",
8061 ActiveCableEventData->ActiveCablePowerRequirement);
Dan Carpenter7ebd67e2016-05-12 23:37:38 +03008062 }
Chaitra P Ba470a512016-05-06 14:29:27 +05308063 break;
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05308064
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308065 default: /* ignore the rest */
8066 return 1;
8067 }
8068
Joe Lawrence35b62362014-06-25 17:05:34 -04008069 sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05308070 fw_event = alloc_fw_event_work(sz);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308071 if (!fw_event) {
8072 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8073 ioc->name, __FILE__, __LINE__, __func__);
8074 return 1;
8075 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308076
8077 memcpy(fw_event->event_data, mpi_reply->EventData, sz);
8078 fw_event->ioc = ioc;
8079 fw_event->VF_ID = mpi_reply->VF_ID;
8080 fw_event->VP_ID = mpi_reply->VP_ID;
8081 fw_event->event = event;
8082 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05308083 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308084 return 1;
8085}
8086
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308087/**
8088 * _scsih_expander_node_remove - removing expander device from list.
8089 * @ioc: per adapter object
8090 * @sas_expander: the sas_device object
8091 * Context: Calling function should acquire ioc->sas_node_lock.
8092 *
8093 * Removing object and freeing associated memory from the
8094 * ioc->sas_expander_list.
8095 *
8096 * Return nothing.
8097 */
8098static void
8099_scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
8100 struct _sas_node *sas_expander)
8101{
8102 struct _sas_port *mpt3sas_port, *next;
8103
8104 /* remove sibling ports attached to this expander */
8105 list_for_each_entry_safe(mpt3sas_port, next,
8106 &sas_expander->sas_port_list, port_list) {
8107 if (ioc->shost_recovery)
8108 return;
8109 if (mpt3sas_port->remote_identify.device_type ==
8110 SAS_END_DEVICE)
8111 mpt3sas_device_remove_by_sas_address(ioc,
8112 mpt3sas_port->remote_identify.sas_address);
8113 else if (mpt3sas_port->remote_identify.device_type ==
8114 SAS_EDGE_EXPANDER_DEVICE ||
8115 mpt3sas_port->remote_identify.device_type ==
8116 SAS_FANOUT_EXPANDER_DEVICE)
8117 mpt3sas_expander_remove(ioc,
8118 mpt3sas_port->remote_identify.sas_address);
8119 }
8120
8121 mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
8122 sas_expander->sas_address_parent);
8123
8124 pr_info(MPT3SAS_FMT
8125 "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n",
8126 ioc->name,
8127 sas_expander->handle, (unsigned long long)
8128 sas_expander->sas_address);
8129
8130 kfree(sas_expander->phy);
8131 kfree(sas_expander);
8132}
8133
8134/**
8135 * _scsih_ir_shutdown - IR shutdown notification
8136 * @ioc: per adapter object
8137 *
8138 * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
8139 * the host system is shutting down.
8140 *
8141 * Return nothing.
8142 */
8143static void
8144_scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
8145{
8146 Mpi2RaidActionRequest_t *mpi_request;
8147 Mpi2RaidActionReply_t *mpi_reply;
8148 u16 smid;
8149
8150 /* is IR firmware build loaded ? */
8151 if (!ioc->ir_firmware)
8152 return;
8153
8154 /* are there any volumes ? */
8155 if (list_empty(&ioc->raid_device_list))
8156 return;
8157
8158 mutex_lock(&ioc->scsih_cmds.mutex);
8159
8160 if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
8161 pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
8162 ioc->name, __func__);
8163 goto out;
8164 }
8165 ioc->scsih_cmds.status = MPT3_CMD_PENDING;
8166
8167 smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
8168 if (!smid) {
8169 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
8170 ioc->name, __func__);
8171 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
8172 goto out;
8173 }
8174
8175 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
8176 ioc->scsih_cmds.smid = smid;
8177 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
8178
8179 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
8180 mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
8181
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308182 if (!ioc->hide_ir_msg)
8183 pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308184 init_completion(&ioc->scsih_cmds.done);
8185 mpt3sas_base_put_smid_default(ioc, smid);
8186 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
8187
8188 if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
8189 pr_err(MPT3SAS_FMT "%s: timeout\n",
8190 ioc->name, __func__);
8191 goto out;
8192 }
8193
8194 if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
8195 mpi_reply = ioc->scsih_cmds.reply;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308196 if (!ioc->hide_ir_msg)
8197 pr_info(MPT3SAS_FMT "IR shutdown "
8198 "(complete): ioc_status(0x%04x), loginfo(0x%08x)\n",
8199 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
8200 le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308201 }
8202
8203 out:
8204 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
8205 mutex_unlock(&ioc->scsih_cmds.mutex);
8206}
8207
8208/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308209 * scsih_remove - detach and remove add host
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308210 * @pdev: PCI device struct
8211 *
8212 * Routine called when unloading the driver.
8213 * Return nothing.
8214 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008215static void scsih_remove(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308216{
8217 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8218 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8219 struct _sas_port *mpt3sas_port, *next_port;
8220 struct _raid_device *raid_device, *next;
8221 struct MPT3SAS_TARGET *sas_target_priv_data;
8222 struct workqueue_struct *wq;
8223 unsigned long flags;
8224
8225 ioc->remove_host = 1;
8226 _scsih_fw_event_cleanup_queue(ioc);
8227
8228 spin_lock_irqsave(&ioc->fw_event_lock, flags);
8229 wq = ioc->firmware_event_thread;
8230 ioc->firmware_event_thread = NULL;
8231 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
8232 if (wq)
8233 destroy_workqueue(wq);
8234
8235 /* release all the volumes */
8236 _scsih_ir_shutdown(ioc);
8237 list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
8238 list) {
8239 if (raid_device->starget) {
8240 sas_target_priv_data =
8241 raid_device->starget->hostdata;
8242 sas_target_priv_data->deleted = 1;
8243 scsi_remove_target(&raid_device->starget->dev);
8244 }
8245 pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
8246 ioc->name, raid_device->handle,
8247 (unsigned long long) raid_device->wwid);
8248 _scsih_raid_device_remove(ioc, raid_device);
8249 }
8250
8251 /* free ports attached to the sas_host */
8252 list_for_each_entry_safe(mpt3sas_port, next_port,
8253 &ioc->sas_hba.sas_port_list, port_list) {
8254 if (mpt3sas_port->remote_identify.device_type ==
8255 SAS_END_DEVICE)
8256 mpt3sas_device_remove_by_sas_address(ioc,
8257 mpt3sas_port->remote_identify.sas_address);
8258 else if (mpt3sas_port->remote_identify.device_type ==
8259 SAS_EDGE_EXPANDER_DEVICE ||
8260 mpt3sas_port->remote_identify.device_type ==
8261 SAS_FANOUT_EXPANDER_DEVICE)
8262 mpt3sas_expander_remove(ioc,
8263 mpt3sas_port->remote_identify.sas_address);
8264 }
8265
8266 /* free phys attached to the sas_host */
8267 if (ioc->sas_hba.num_phys) {
8268 kfree(ioc->sas_hba.phy);
8269 ioc->sas_hba.phy = NULL;
8270 ioc->sas_hba.num_phys = 0;
8271 }
8272
8273 sas_remove_host(shost);
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308274 scsi_remove_host(shost);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308275 mpt3sas_base_detach(ioc);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308276 spin_lock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308277 list_del(&ioc->list);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308278 spin_unlock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308279 scsi_host_put(shost);
8280}
8281
8282/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308283 * scsih_shutdown - routine call during system shutdown
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308284 * @pdev: PCI device struct
8285 *
8286 * Return nothing.
8287 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008288static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308289scsih_shutdown(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308290{
8291 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8292 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8293 struct workqueue_struct *wq;
8294 unsigned long flags;
8295
8296 ioc->remove_host = 1;
8297 _scsih_fw_event_cleanup_queue(ioc);
8298
8299 spin_lock_irqsave(&ioc->fw_event_lock, flags);
8300 wq = ioc->firmware_event_thread;
8301 ioc->firmware_event_thread = NULL;
8302 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
8303 if (wq)
8304 destroy_workqueue(wq);
8305
8306 _scsih_ir_shutdown(ioc);
8307 mpt3sas_base_detach(ioc);
8308}
8309
8310
8311/**
8312 * _scsih_probe_boot_devices - reports 1st device
8313 * @ioc: per adapter object
8314 *
8315 * If specified in bios page 2, this routine reports the 1st
8316 * device scsi-ml or sas transport for persistent boot device
8317 * purposes. Please refer to function _scsih_determine_boot_device()
8318 */
8319static void
8320_scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
8321{
8322 u8 is_raid;
8323 void *device;
8324 struct _sas_device *sas_device;
8325 struct _raid_device *raid_device;
8326 u16 handle;
8327 u64 sas_address_parent;
8328 u64 sas_address;
8329 unsigned long flags;
8330 int rc;
8331
8332 /* no Bios, return immediately */
8333 if (!ioc->bios_pg3.BiosVersion)
8334 return;
8335
8336 device = NULL;
8337 is_raid = 0;
8338 if (ioc->req_boot_device.device) {
8339 device = ioc->req_boot_device.device;
8340 is_raid = ioc->req_boot_device.is_raid;
8341 } else if (ioc->req_alt_boot_device.device) {
8342 device = ioc->req_alt_boot_device.device;
8343 is_raid = ioc->req_alt_boot_device.is_raid;
8344 } else if (ioc->current_boot_device.device) {
8345 device = ioc->current_boot_device.device;
8346 is_raid = ioc->current_boot_device.is_raid;
8347 }
8348
8349 if (!device)
8350 return;
8351
8352 if (is_raid) {
8353 raid_device = device;
8354 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
8355 raid_device->id, 0);
8356 if (rc)
8357 _scsih_raid_device_remove(ioc, raid_device);
8358 } else {
8359 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8360 sas_device = device;
8361 handle = sas_device->handle;
8362 sas_address_parent = sas_device->sas_address_parent;
8363 sas_address = sas_device->sas_address;
8364 list_move_tail(&sas_device->list, &ioc->sas_device_list);
8365 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8366
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308367 if (ioc->hide_drives)
8368 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308369 if (!mpt3sas_transport_port_add(ioc, handle,
8370 sas_address_parent)) {
8371 _scsih_sas_device_remove(ioc, sas_device);
8372 } else if (!sas_device->starget) {
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308373 if (!ioc->is_driver_loading) {
8374 mpt3sas_transport_port_remove(ioc,
8375 sas_address,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308376 sas_address_parent);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308377 _scsih_sas_device_remove(ioc, sas_device);
8378 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308379 }
8380 }
8381}
8382
8383/**
8384 * _scsih_probe_raid - reporting raid volumes to scsi-ml
8385 * @ioc: per adapter object
8386 *
8387 * Called during initial loading of the driver.
8388 */
8389static void
8390_scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc)
8391{
8392 struct _raid_device *raid_device, *raid_next;
8393 int rc;
8394
8395 list_for_each_entry_safe(raid_device, raid_next,
8396 &ioc->raid_device_list, list) {
8397 if (raid_device->starget)
8398 continue;
8399 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
8400 raid_device->id, 0);
8401 if (rc)
8402 _scsih_raid_device_remove(ioc, raid_device);
8403 }
8404}
8405
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308406static struct _sas_device *get_next_sas_device(struct MPT3SAS_ADAPTER *ioc)
8407{
8408 struct _sas_device *sas_device = NULL;
8409 unsigned long flags;
8410
8411 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8412 if (!list_empty(&ioc->sas_device_init_list)) {
8413 sas_device = list_first_entry(&ioc->sas_device_init_list,
8414 struct _sas_device, list);
8415 sas_device_get(sas_device);
8416 }
8417 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8418
8419 return sas_device;
8420}
8421
8422static void sas_device_make_active(struct MPT3SAS_ADAPTER *ioc,
8423 struct _sas_device *sas_device)
8424{
8425 unsigned long flags;
8426
8427 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8428
8429 /*
8430 * Since we dropped the lock during the call to port_add(), we need to
8431 * be careful here that somebody else didn't move or delete this item
8432 * while we were busy with other things.
8433 *
8434 * If it was on the list, we need a put() for the reference the list
8435 * had. Either way, we need a get() for the destination list.
8436 */
8437 if (!list_empty(&sas_device->list)) {
8438 list_del_init(&sas_device->list);
8439 sas_device_put(sas_device);
8440 }
8441
8442 sas_device_get(sas_device);
8443 list_add_tail(&sas_device->list, &ioc->sas_device_list);
8444
8445 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8446}
8447
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308448/**
8449 * _scsih_probe_sas - reporting sas devices to sas transport
8450 * @ioc: per adapter object
8451 *
8452 * Called during initial loading of the driver.
8453 */
8454static void
8455_scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
8456{
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308457 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308458
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308459 if (ioc->hide_drives)
8460 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308461
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308462 while ((sas_device = get_next_sas_device(ioc))) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308463 if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
8464 sas_device->sas_address_parent)) {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308465 _scsih_sas_device_remove(ioc, sas_device);
8466 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308467 continue;
8468 } else if (!sas_device->starget) {
8469 /*
8470 * When asyn scanning is enabled, its not possible to
8471 * remove devices while scanning is turned on due to an
8472 * oops in scsi_sysfs_add_sdev()->add_device()->
8473 * sysfs_addrm_start()
8474 */
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308475 if (!ioc->is_driver_loading) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308476 mpt3sas_transport_port_remove(ioc,
8477 sas_device->sas_address,
8478 sas_device->sas_address_parent);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308479 _scsih_sas_device_remove(ioc, sas_device);
8480 sas_device_put(sas_device);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308481 continue;
8482 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308483 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308484 sas_device_make_active(ioc, sas_device);
8485 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308486 }
8487}
8488
8489/**
8490 * _scsih_probe_devices - probing for devices
8491 * @ioc: per adapter object
8492 *
8493 * Called during initial loading of the driver.
8494 */
8495static void
8496_scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc)
8497{
8498 u16 volume_mapping_flags;
8499
8500 if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
8501 return; /* return when IOC doesn't support initiator mode */
8502
8503 _scsih_probe_boot_devices(ioc);
8504
8505 if (ioc->ir_firmware) {
8506 volume_mapping_flags =
8507 le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
8508 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
8509 if (volume_mapping_flags ==
8510 MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
8511 _scsih_probe_raid(ioc);
8512 _scsih_probe_sas(ioc);
8513 } else {
8514 _scsih_probe_sas(ioc);
8515 _scsih_probe_raid(ioc);
8516 }
8517 } else
8518 _scsih_probe_sas(ioc);
8519}
8520
8521/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308522 * scsih_scan_start - scsi lld callback for .scan_start
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308523 * @shost: SCSI host pointer
8524 *
8525 * The shost has the ability to discover targets on its own instead
8526 * of scanning the entire bus. In our implemention, we will kick off
8527 * firmware discovery.
8528 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008529static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308530scsih_scan_start(struct Scsi_Host *shost)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308531{
8532 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8533 int rc;
8534 if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
8535 mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable);
8536
8537 if (disable_discovery > 0)
8538 return;
8539
8540 ioc->start_scan = 1;
8541 rc = mpt3sas_port_enable(ioc);
8542
8543 if (rc != 0)
8544 pr_info(MPT3SAS_FMT "port enable: FAILED\n", ioc->name);
8545}
8546
8547/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308548 * scsih_scan_finished - scsi lld callback for .scan_finished
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308549 * @shost: SCSI host pointer
8550 * @time: elapsed time of the scan in jiffies
8551 *
8552 * This function will be called periodicallyn until it returns 1 with the
8553 * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
8554 * we wait for firmware discovery to complete, then return 1.
8555 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008556static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308557scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308558{
8559 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8560
8561 if (disable_discovery > 0) {
8562 ioc->is_driver_loading = 0;
8563 ioc->wait_for_discovery_to_complete = 0;
8564 return 1;
8565 }
8566
8567 if (time >= (300 * HZ)) {
8568 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
8569 pr_info(MPT3SAS_FMT
8570 "port enable: FAILED with timeout (timeout=300s)\n",
8571 ioc->name);
8572 ioc->is_driver_loading = 0;
8573 return 1;
8574 }
8575
8576 if (ioc->start_scan)
8577 return 0;
8578
8579 if (ioc->start_scan_failed) {
8580 pr_info(MPT3SAS_FMT
8581 "port enable: FAILED with (ioc_status=0x%08x)\n",
8582 ioc->name, ioc->start_scan_failed);
8583 ioc->is_driver_loading = 0;
8584 ioc->wait_for_discovery_to_complete = 0;
8585 ioc->remove_host = 1;
8586 return 1;
8587 }
8588
8589 pr_info(MPT3SAS_FMT "port enable: SUCCESS\n", ioc->name);
8590 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
8591
8592 if (ioc->wait_for_discovery_to_complete) {
8593 ioc->wait_for_discovery_to_complete = 0;
8594 _scsih_probe_devices(ioc);
8595 }
8596 mpt3sas_base_start_watchdog(ioc);
8597 ioc->is_driver_loading = 0;
8598 return 1;
8599}
8600
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308601/* shost template for SAS 2.0 HBA devices */
8602static struct scsi_host_template mpt2sas_driver_template = {
8603 .module = THIS_MODULE,
8604 .name = "Fusion MPT SAS Host",
8605 .proc_name = MPT2SAS_DRIVER_NAME,
8606 .queuecommand = scsih_qcmd,
8607 .target_alloc = scsih_target_alloc,
8608 .slave_alloc = scsih_slave_alloc,
8609 .slave_configure = scsih_slave_configure,
8610 .target_destroy = scsih_target_destroy,
8611 .slave_destroy = scsih_slave_destroy,
8612 .scan_finished = scsih_scan_finished,
8613 .scan_start = scsih_scan_start,
8614 .change_queue_depth = scsih_change_queue_depth,
8615 .eh_abort_handler = scsih_abort,
8616 .eh_device_reset_handler = scsih_dev_reset,
8617 .eh_target_reset_handler = scsih_target_reset,
8618 .eh_host_reset_handler = scsih_host_reset,
8619 .bios_param = scsih_bios_param,
8620 .can_queue = 1,
8621 .this_id = -1,
8622 .sg_tablesize = MPT2SAS_SG_DEPTH,
8623 .max_sectors = 32767,
8624 .cmd_per_lun = 7,
8625 .use_clustering = ENABLE_CLUSTERING,
8626 .shost_attrs = mpt3sas_host_attrs,
8627 .sdev_attrs = mpt3sas_dev_attrs,
8628 .track_queue_depth = 1,
8629};
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308630
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308631/* raid transport support for SAS 2.0 HBA devices */
8632static struct raid_function_template mpt2sas_raid_functions = {
8633 .cookie = &mpt2sas_driver_template,
8634 .is_raid = scsih_is_raid,
8635 .get_resync = scsih_get_resync,
8636 .get_state = scsih_get_state,
8637};
8638
8639/* shost template for SAS 3.0 HBA devices */
8640static struct scsi_host_template mpt3sas_driver_template = {
8641 .module = THIS_MODULE,
8642 .name = "Fusion MPT SAS Host",
8643 .proc_name = MPT3SAS_DRIVER_NAME,
8644 .queuecommand = scsih_qcmd,
8645 .target_alloc = scsih_target_alloc,
8646 .slave_alloc = scsih_slave_alloc,
8647 .slave_configure = scsih_slave_configure,
8648 .target_destroy = scsih_target_destroy,
8649 .slave_destroy = scsih_slave_destroy,
8650 .scan_finished = scsih_scan_finished,
8651 .scan_start = scsih_scan_start,
8652 .change_queue_depth = scsih_change_queue_depth,
8653 .eh_abort_handler = scsih_abort,
8654 .eh_device_reset_handler = scsih_dev_reset,
8655 .eh_target_reset_handler = scsih_target_reset,
8656 .eh_host_reset_handler = scsih_host_reset,
8657 .bios_param = scsih_bios_param,
8658 .can_queue = 1,
8659 .this_id = -1,
8660 .sg_tablesize = MPT3SAS_SG_DEPTH,
8661 .max_sectors = 32767,
8662 .cmd_per_lun = 7,
8663 .use_clustering = ENABLE_CLUSTERING,
8664 .shost_attrs = mpt3sas_host_attrs,
8665 .sdev_attrs = mpt3sas_dev_attrs,
8666 .track_queue_depth = 1,
8667};
8668
8669/* raid transport support for SAS 3.0 HBA devices */
8670static struct raid_function_template mpt3sas_raid_functions = {
8671 .cookie = &mpt3sas_driver_template,
8672 .is_raid = scsih_is_raid,
8673 .get_resync = scsih_get_resync,
8674 .get_state = scsih_get_state,
8675};
8676
8677/**
8678 * _scsih_determine_hba_mpi_version - determine in which MPI version class
8679 * this device belongs to.
8680 * @pdev: PCI device struct
8681 *
8682 * return MPI2_VERSION for SAS 2.0 HBA devices,
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05308683 * MPI25_VERSION for SAS 3.0 HBA devices, and
8684 * MPI26 VERSION for Cutlass & Invader SAS 3.0 HBA devices
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308685 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008686static u16
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308687_scsih_determine_hba_mpi_version(struct pci_dev *pdev)
8688{
8689
8690 switch (pdev->device) {
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308691 case MPI2_MFGPAGE_DEVID_SSS6200:
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308692 case MPI2_MFGPAGE_DEVID_SAS2004:
8693 case MPI2_MFGPAGE_DEVID_SAS2008:
8694 case MPI2_MFGPAGE_DEVID_SAS2108_1:
8695 case MPI2_MFGPAGE_DEVID_SAS2108_2:
8696 case MPI2_MFGPAGE_DEVID_SAS2108_3:
8697 case MPI2_MFGPAGE_DEVID_SAS2116_1:
8698 case MPI2_MFGPAGE_DEVID_SAS2116_2:
8699 case MPI2_MFGPAGE_DEVID_SAS2208_1:
8700 case MPI2_MFGPAGE_DEVID_SAS2208_2:
8701 case MPI2_MFGPAGE_DEVID_SAS2208_3:
8702 case MPI2_MFGPAGE_DEVID_SAS2208_4:
8703 case MPI2_MFGPAGE_DEVID_SAS2208_5:
8704 case MPI2_MFGPAGE_DEVID_SAS2208_6:
8705 case MPI2_MFGPAGE_DEVID_SAS2308_1:
8706 case MPI2_MFGPAGE_DEVID_SAS2308_2:
8707 case MPI2_MFGPAGE_DEVID_SAS2308_3:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308708 return MPI2_VERSION;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308709 case MPI25_MFGPAGE_DEVID_SAS3004:
8710 case MPI25_MFGPAGE_DEVID_SAS3008:
8711 case MPI25_MFGPAGE_DEVID_SAS3108_1:
8712 case MPI25_MFGPAGE_DEVID_SAS3108_2:
8713 case MPI25_MFGPAGE_DEVID_SAS3108_5:
8714 case MPI25_MFGPAGE_DEVID_SAS3108_6:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308715 return MPI25_VERSION;
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05308716 case MPI26_MFGPAGE_DEVID_SAS3216:
8717 case MPI26_MFGPAGE_DEVID_SAS3224:
8718 case MPI26_MFGPAGE_DEVID_SAS3316_1:
8719 case MPI26_MFGPAGE_DEVID_SAS3316_2:
8720 case MPI26_MFGPAGE_DEVID_SAS3316_3:
8721 case MPI26_MFGPAGE_DEVID_SAS3316_4:
8722 case MPI26_MFGPAGE_DEVID_SAS3324_1:
8723 case MPI26_MFGPAGE_DEVID_SAS3324_2:
8724 case MPI26_MFGPAGE_DEVID_SAS3324_3:
8725 case MPI26_MFGPAGE_DEVID_SAS3324_4:
8726 return MPI26_VERSION;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308727 }
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308728 return 0;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308729}
8730
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308731/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308732 * _scsih_probe - attach and add scsi host
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308733 * @pdev: PCI device struct
8734 * @id: pci device id
8735 *
8736 * Returns 0 success, anything else error.
8737 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008738static int
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308739_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308740{
8741 struct MPT3SAS_ADAPTER *ioc;
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308742 struct Scsi_Host *shost = NULL;
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308743 int rv;
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308744 u16 hba_mpi_version;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308745
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308746 /* Determine in which MPI version class this pci device belongs */
8747 hba_mpi_version = _scsih_determine_hba_mpi_version(pdev);
8748 if (hba_mpi_version == 0)
8749 return -ENODEV;
8750
8751 /* Enumerate only SAS 2.0 HBA's if hbas_to_enumerate is one,
8752 * for other generation HBA's return with -ENODEV
8753 */
8754 if ((hbas_to_enumerate == 1) && (hba_mpi_version != MPI2_VERSION))
8755 return -ENODEV;
8756
8757 /* Enumerate only SAS 3.0 HBA's if hbas_to_enumerate is two,
8758 * for other generation HBA's return with -ENODEV
8759 */
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05308760 if ((hbas_to_enumerate == 2) && (!(hba_mpi_version == MPI25_VERSION
8761 || hba_mpi_version == MPI26_VERSION)))
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308762 return -ENODEV;
8763
8764 switch (hba_mpi_version) {
8765 case MPI2_VERSION:
ojabb5d5f282016-12-28 11:05:24 +00008766 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
8767 PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308768 /* Use mpt2sas driver host template for SAS 2.0 HBA's */
8769 shost = scsi_host_alloc(&mpt2sas_driver_template,
8770 sizeof(struct MPT3SAS_ADAPTER));
8771 if (!shost)
8772 return -ENODEV;
8773 ioc = shost_priv(shost);
8774 memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
8775 ioc->hba_mpi_version_belonged = hba_mpi_version;
8776 ioc->id = mpt2_ids++;
8777 sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME);
8778 if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) {
8779 ioc->is_warpdrive = 1;
8780 ioc->hide_ir_msg = 1;
8781 } else
8782 ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
8783 break;
8784 case MPI25_VERSION:
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05308785 case MPI26_VERSION:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308786 /* Use mpt3sas driver host template for SAS 3.0 HBA's */
8787 shost = scsi_host_alloc(&mpt3sas_driver_template,
8788 sizeof(struct MPT3SAS_ADAPTER));
8789 if (!shost)
8790 return -ENODEV;
8791 ioc = shost_priv(shost);
8792 memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
8793 ioc->hba_mpi_version_belonged = hba_mpi_version;
8794 ioc->id = mpt3_ids++;
8795 sprintf(ioc->driver_name, "%s", MPT3SAS_DRIVER_NAME);
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05308796 if ((ioc->hba_mpi_version_belonged == MPI25_VERSION &&
8797 pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION) ||
8798 (ioc->hba_mpi_version_belonged == MPI26_VERSION))
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308799 ioc->msix96_vector = 1;
8800 break;
8801 default:
8802 return -ENODEV;
8803 }
8804
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308805 INIT_LIST_HEAD(&ioc->list);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308806 spin_lock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308807 list_add_tail(&ioc->list, &mpt3sas_ioc_list);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308808 spin_unlock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308809 ioc->shost = shost;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308810 ioc->pdev = pdev;
8811 ioc->scsi_io_cb_idx = scsi_io_cb_idx;
8812 ioc->tm_cb_idx = tm_cb_idx;
8813 ioc->ctl_cb_idx = ctl_cb_idx;
8814 ioc->base_cb_idx = base_cb_idx;
8815 ioc->port_enable_cb_idx = port_enable_cb_idx;
8816 ioc->transport_cb_idx = transport_cb_idx;
8817 ioc->scsih_cb_idx = scsih_cb_idx;
8818 ioc->config_cb_idx = config_cb_idx;
8819 ioc->tm_tr_cb_idx = tm_tr_cb_idx;
8820 ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx;
8821 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
8822 ioc->logging_level = logging_level;
8823 ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
8824 /* misc semaphores and spin locks */
8825 mutex_init(&ioc->reset_in_progress_mutex);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308826 /* initializing pci_access_mutex lock */
8827 mutex_init(&ioc->pci_access_mutex);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308828 spin_lock_init(&ioc->ioc_reset_in_progress_lock);
8829 spin_lock_init(&ioc->scsi_lookup_lock);
8830 spin_lock_init(&ioc->sas_device_lock);
8831 spin_lock_init(&ioc->sas_node_lock);
8832 spin_lock_init(&ioc->fw_event_lock);
8833 spin_lock_init(&ioc->raid_device_lock);
8834 spin_lock_init(&ioc->diag_trigger_lock);
8835
8836 INIT_LIST_HEAD(&ioc->sas_device_list);
8837 INIT_LIST_HEAD(&ioc->sas_device_init_list);
8838 INIT_LIST_HEAD(&ioc->sas_expander_list);
8839 INIT_LIST_HEAD(&ioc->fw_event_list);
8840 INIT_LIST_HEAD(&ioc->raid_device_list);
8841 INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
8842 INIT_LIST_HEAD(&ioc->delayed_tr_list);
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05308843 INIT_LIST_HEAD(&ioc->delayed_sc_list);
8844 INIT_LIST_HEAD(&ioc->delayed_event_ack_list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308845 INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
Joe Lawrencecf9bd21a2013-08-08 16:45:39 -04008846 INIT_LIST_HEAD(&ioc->reply_queue_list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308847
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308848 sprintf(ioc->name, "%s_cm%d", ioc->driver_name, ioc->id);
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308849
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308850 /* init shost parameters */
8851 shost->max_cmd_len = 32;
8852 shost->max_lun = max_lun;
8853 shost->transportt = mpt3sas_transport_template;
8854 shost->unique_id = ioc->id;
8855
8856 if (max_sectors != 0xFFFF) {
8857 if (max_sectors < 64) {
8858 shost->max_sectors = 64;
8859 pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
8860 "for max_sectors, range is 64 to 32767. Assigning "
8861 "value of 64.\n", ioc->name, max_sectors);
8862 } else if (max_sectors > 32767) {
8863 shost->max_sectors = 32767;
8864 pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
8865 "for max_sectors, range is 64 to 32767. Assigning "
8866 "default value of 32767.\n", ioc->name,
8867 max_sectors);
8868 } else {
8869 shost->max_sectors = max_sectors & 0xFFFE;
8870 pr_info(MPT3SAS_FMT
8871 "The max_sectors value is set to %d\n",
8872 ioc->name, shost->max_sectors);
8873 }
8874 }
8875
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308876 /* register EEDP capabilities with SCSI layer */
8877 if (prot_mask > 0)
8878 scsi_host_set_prot(shost, prot_mask);
8879 else
8880 scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
8881 | SHOST_DIF_TYPE2_PROTECTION
8882 | SHOST_DIF_TYPE3_PROTECTION);
8883
8884 scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
8885
8886 /* event thread */
8887 snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308888 "fw_event_%s%d", ioc->driver_name, ioc->id);
Sreekanth Reddybdff7852015-06-30 12:25:03 +05308889 ioc->firmware_event_thread = alloc_ordered_workqueue(
Hannes Reinecke4a8907d2018-02-26 15:26:01 +01008890 ioc->firmware_event_name, 0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308891 if (!ioc->firmware_event_thread) {
8892 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8893 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308894 rv = -ENODEV;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308895 goto out_thread_fail;
8896 }
8897
8898 ioc->is_driver_loading = 1;
8899 if ((mpt3sas_base_attach(ioc))) {
8900 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8901 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308902 rv = -ENODEV;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308903 goto out_attach_fail;
8904 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308905
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308906 if (ioc->is_warpdrive) {
8907 if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
8908 ioc->hide_drives = 0;
8909 else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS)
8910 ioc->hide_drives = 1;
8911 else {
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308912 if (mpt3sas_get_num_volumes(ioc))
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308913 ioc->hide_drives = 1;
8914 else
8915 ioc->hide_drives = 0;
8916 }
8917 } else
8918 ioc->hide_drives = 0;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308919
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308920 rv = scsi_add_host(shost, &pdev->dev);
8921 if (rv) {
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308922 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8923 ioc->name, __FILE__, __LINE__, __func__);
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308924 goto out_add_shost_fail;
8925 }
8926
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308927 scsi_scan_host(shost);
8928 return 0;
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308929out_add_shost_fail:
8930 mpt3sas_base_detach(ioc);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308931 out_attach_fail:
8932 destroy_workqueue(ioc->firmware_event_thread);
8933 out_thread_fail:
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308934 spin_lock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308935 list_del(&ioc->list);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308936 spin_unlock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308937 scsi_host_put(shost);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308938 return rv;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308939}
8940
8941#ifdef CONFIG_PM
8942/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308943 * scsih_suspend - power management suspend main entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308944 * @pdev: PCI device struct
8945 * @state: PM state change to (usually PCI_D3)
8946 *
8947 * Returns 0 success, anything else error.
8948 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008949static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308950scsih_suspend(struct pci_dev *pdev, pm_message_t state)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308951{
8952 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8953 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8954 pci_power_t device_state;
8955
8956 mpt3sas_base_stop_watchdog(ioc);
8957 flush_scheduled_work();
8958 scsi_block_requests(shost);
8959 device_state = pci_choose_state(pdev, state);
8960 pr_info(MPT3SAS_FMT
8961 "pdev=0x%p, slot=%s, entering operating state [D%d]\n",
8962 ioc->name, pdev, pci_name(pdev), device_state);
8963
8964 pci_save_state(pdev);
8965 mpt3sas_base_free_resources(ioc);
8966 pci_set_power_state(pdev, device_state);
8967 return 0;
8968}
8969
8970/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308971 * scsih_resume - power management resume main entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308972 * @pdev: PCI device struct
8973 *
8974 * Returns 0 success, anything else error.
8975 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008976static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308977scsih_resume(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308978{
8979 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8980 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8981 pci_power_t device_state = pdev->current_state;
8982 int r;
8983
8984 pr_info(MPT3SAS_FMT
8985 "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
8986 ioc->name, pdev, pci_name(pdev), device_state);
8987
8988 pci_set_power_state(pdev, PCI_D0);
8989 pci_enable_wake(pdev, PCI_D0, 0);
8990 pci_restore_state(pdev);
8991 ioc->pdev = pdev;
8992 r = mpt3sas_base_map_resources(ioc);
8993 if (r)
8994 return r;
8995
Calvin Owens98c56ad2016-07-28 21:38:21 -07008996 mpt3sas_base_hard_reset_handler(ioc, SOFT_RESET);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308997 scsi_unblock_requests(shost);
8998 mpt3sas_base_start_watchdog(ioc);
8999 return 0;
9000}
9001#endif /* CONFIG_PM */
9002
9003/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309004 * scsih_pci_error_detected - Called when a PCI error is detected.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309005 * @pdev: PCI device struct
9006 * @state: PCI channel state
9007 *
9008 * Description: Called when a PCI error is detected.
9009 *
9010 * Return value:
9011 * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
9012 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009013static pci_ers_result_t
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309014scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309015{
9016 struct Scsi_Host *shost = pci_get_drvdata(pdev);
9017 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
9018
9019 pr_info(MPT3SAS_FMT "PCI error: detected callback, state(%d)!!\n",
9020 ioc->name, state);
9021
9022 switch (state) {
9023 case pci_channel_io_normal:
9024 return PCI_ERS_RESULT_CAN_RECOVER;
9025 case pci_channel_io_frozen:
9026 /* Fatal error, prepare for slot reset */
9027 ioc->pci_error_recovery = 1;
9028 scsi_block_requests(ioc->shost);
9029 mpt3sas_base_stop_watchdog(ioc);
9030 mpt3sas_base_free_resources(ioc);
9031 return PCI_ERS_RESULT_NEED_RESET;
9032 case pci_channel_io_perm_failure:
9033 /* Permanent error, prepare for device removal */
9034 ioc->pci_error_recovery = 1;
9035 mpt3sas_base_stop_watchdog(ioc);
9036 _scsih_flush_running_cmds(ioc);
9037 return PCI_ERS_RESULT_DISCONNECT;
9038 }
9039 return PCI_ERS_RESULT_NEED_RESET;
9040}
9041
9042/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309043 * scsih_pci_slot_reset - Called when PCI slot has been reset.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309044 * @pdev: PCI device struct
9045 *
9046 * Description: This routine is called by the pci error recovery
9047 * code after the PCI slot has been reset, just before we
9048 * should resume normal operations.
9049 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009050static pci_ers_result_t
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309051scsih_pci_slot_reset(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309052{
9053 struct Scsi_Host *shost = pci_get_drvdata(pdev);
9054 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
9055 int rc;
9056
9057 pr_info(MPT3SAS_FMT "PCI error: slot reset callback!!\n",
9058 ioc->name);
9059
9060 ioc->pci_error_recovery = 0;
9061 ioc->pdev = pdev;
9062 pci_restore_state(pdev);
9063 rc = mpt3sas_base_map_resources(ioc);
9064 if (rc)
9065 return PCI_ERS_RESULT_DISCONNECT;
9066
Calvin Owens98c56ad2016-07-28 21:38:21 -07009067 rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309068
9069 pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name,
9070 (rc == 0) ? "success" : "failed");
9071
9072 if (!rc)
9073 return PCI_ERS_RESULT_RECOVERED;
9074 else
9075 return PCI_ERS_RESULT_DISCONNECT;
9076}
9077
9078/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309079 * scsih_pci_resume() - resume normal ops after PCI reset
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309080 * @pdev: pointer to PCI device
9081 *
9082 * Called when the error recovery driver tells us that its
9083 * OK to resume normal operation. Use completion to allow
9084 * halted scsi ops to resume.
9085 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009086static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309087scsih_pci_resume(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309088{
9089 struct Scsi_Host *shost = pci_get_drvdata(pdev);
9090 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
9091
9092 pr_info(MPT3SAS_FMT "PCI error: resume callback!!\n", ioc->name);
9093
9094 pci_cleanup_aer_uncorrect_error_status(pdev);
9095 mpt3sas_base_start_watchdog(ioc);
9096 scsi_unblock_requests(ioc->shost);
9097}
9098
9099/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309100 * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309101 * @pdev: pointer to PCI device
9102 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009103static pci_ers_result_t
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309104scsih_pci_mmio_enabled(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309105{
9106 struct Scsi_Host *shost = pci_get_drvdata(pdev);
9107 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
9108
9109 pr_info(MPT3SAS_FMT "PCI error: mmio enabled callback!!\n",
9110 ioc->name);
9111
9112 /* TODO - dump whatever for debugging purposes */
9113
Kefeng Wang83c3d342016-07-12 17:43:25 +08009114 /* This called only if scsih_pci_error_detected returns
9115 * PCI_ERS_RESULT_CAN_RECOVER. Read/write to the device still
9116 * works, no need to reset slot.
9117 */
9118 return PCI_ERS_RESULT_RECOVERED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309119}
9120
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05309121/*
9122 * The pci device ids are defined in mpi/mpi2_cnfg.h.
9123 */
9124static const struct pci_device_id mpt3sas_pci_table[] = {
9125 /* Spitfire ~ 2004 */
9126 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
9127 PCI_ANY_ID, PCI_ANY_ID },
9128 /* Falcon ~ 2008 */
9129 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
9130 PCI_ANY_ID, PCI_ANY_ID },
9131 /* Liberator ~ 2108 */
9132 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
9133 PCI_ANY_ID, PCI_ANY_ID },
9134 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
9135 PCI_ANY_ID, PCI_ANY_ID },
9136 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
9137 PCI_ANY_ID, PCI_ANY_ID },
9138 /* Meteor ~ 2116 */
9139 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
9140 PCI_ANY_ID, PCI_ANY_ID },
9141 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
9142 PCI_ANY_ID, PCI_ANY_ID },
9143 /* Thunderbolt ~ 2208 */
9144 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
9145 PCI_ANY_ID, PCI_ANY_ID },
9146 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
9147 PCI_ANY_ID, PCI_ANY_ID },
9148 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
9149 PCI_ANY_ID, PCI_ANY_ID },
9150 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
9151 PCI_ANY_ID, PCI_ANY_ID },
9152 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
9153 PCI_ANY_ID, PCI_ANY_ID },
9154 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
9155 PCI_ANY_ID, PCI_ANY_ID },
9156 /* Mustang ~ 2308 */
9157 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1,
9158 PCI_ANY_ID, PCI_ANY_ID },
9159 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
9160 PCI_ANY_ID, PCI_ANY_ID },
9161 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
9162 PCI_ANY_ID, PCI_ANY_ID },
9163 /* SSS6200 */
9164 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
9165 PCI_ANY_ID, PCI_ANY_ID },
9166 /* Fury ~ 3004 and 3008 */
9167 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
9168 PCI_ANY_ID, PCI_ANY_ID },
9169 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
9170 PCI_ANY_ID, PCI_ANY_ID },
9171 /* Invader ~ 3108 */
9172 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
9173 PCI_ANY_ID, PCI_ANY_ID },
9174 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
9175 PCI_ANY_ID, PCI_ANY_ID },
9176 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
9177 PCI_ANY_ID, PCI_ANY_ID },
9178 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
9179 PCI_ANY_ID, PCI_ANY_ID },
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05309180 /* Cutlass ~ 3216 and 3224 */
9181 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3216,
9182 PCI_ANY_ID, PCI_ANY_ID },
9183 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3224,
9184 PCI_ANY_ID, PCI_ANY_ID },
9185 /* Intruder ~ 3316 and 3324 */
9186 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_1,
9187 PCI_ANY_ID, PCI_ANY_ID },
9188 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_2,
9189 PCI_ANY_ID, PCI_ANY_ID },
9190 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_3,
9191 PCI_ANY_ID, PCI_ANY_ID },
9192 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_4,
9193 PCI_ANY_ID, PCI_ANY_ID },
9194 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_1,
9195 PCI_ANY_ID, PCI_ANY_ID },
9196 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_2,
9197 PCI_ANY_ID, PCI_ANY_ID },
9198 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_3,
9199 PCI_ANY_ID, PCI_ANY_ID },
9200 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_4,
9201 PCI_ANY_ID, PCI_ANY_ID },
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05309202 {0} /* Terminating entry */
9203};
9204MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table);
9205
9206static struct pci_error_handlers _mpt3sas_err_handler = {
9207 .error_detected = scsih_pci_error_detected,
9208 .mmio_enabled = scsih_pci_mmio_enabled,
9209 .slot_reset = scsih_pci_slot_reset,
9210 .resume = scsih_pci_resume,
9211};
9212
9213static struct pci_driver mpt3sas_driver = {
9214 .name = MPT3SAS_DRIVER_NAME,
9215 .id_table = mpt3sas_pci_table,
9216 .probe = _scsih_probe,
9217 .remove = scsih_remove,
9218 .shutdown = scsih_shutdown,
9219 .err_handler = &_mpt3sas_err_handler,
9220#ifdef CONFIG_PM
9221 .suspend = scsih_suspend,
9222 .resume = scsih_resume,
9223#endif
9224};
9225
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309226/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309227 * scsih_init - main entry point for this driver.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309228 *
9229 * Returns 0 success, anything else error.
9230 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009231static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309232scsih_init(void)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309233{
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05309234 mpt2_ids = 0;
9235 mpt3_ids = 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309236
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309237 mpt3sas_base_initialize_callback_handler();
9238
9239 /* queuecommand callback hander */
9240 scsi_io_cb_idx = mpt3sas_base_register_callback_handler(_scsih_io_done);
9241
9242 /* task managment callback handler */
9243 tm_cb_idx = mpt3sas_base_register_callback_handler(_scsih_tm_done);
9244
9245 /* base internal commands callback handler */
9246 base_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_base_done);
9247 port_enable_cb_idx = mpt3sas_base_register_callback_handler(
9248 mpt3sas_port_enable_done);
9249
9250 /* transport internal commands callback handler */
9251 transport_cb_idx = mpt3sas_base_register_callback_handler(
9252 mpt3sas_transport_done);
9253
9254 /* scsih internal commands callback handler */
9255 scsih_cb_idx = mpt3sas_base_register_callback_handler(_scsih_done);
9256
9257 /* configuration page API internal commands callback handler */
9258 config_cb_idx = mpt3sas_base_register_callback_handler(
9259 mpt3sas_config_done);
9260
9261 /* ctl module callback handler */
9262 ctl_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_ctl_done);
9263
9264 tm_tr_cb_idx = mpt3sas_base_register_callback_handler(
9265 _scsih_tm_tr_complete);
9266
9267 tm_tr_volume_cb_idx = mpt3sas_base_register_callback_handler(
9268 _scsih_tm_volume_tr_complete);
9269
9270 tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
9271 _scsih_sas_control_complete);
9272
Sreekanth Reddy7497392a2015-11-11 17:30:19 +05309273 return 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309274}
9275
9276/**
Sreekanth Reddy7497392a2015-11-11 17:30:19 +05309277 * scsih_exit - exit point for this driver (when it is a module).
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309278 *
9279 * Returns 0 success, anything else error.
9280 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009281static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309282scsih_exit(void)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309283{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309284
9285 mpt3sas_base_release_callback_handler(scsi_io_cb_idx);
9286 mpt3sas_base_release_callback_handler(tm_cb_idx);
9287 mpt3sas_base_release_callback_handler(base_cb_idx);
9288 mpt3sas_base_release_callback_handler(port_enable_cb_idx);
9289 mpt3sas_base_release_callback_handler(transport_cb_idx);
9290 mpt3sas_base_release_callback_handler(scsih_cb_idx);
9291 mpt3sas_base_release_callback_handler(config_cb_idx);
9292 mpt3sas_base_release_callback_handler(ctl_cb_idx);
9293
9294 mpt3sas_base_release_callback_handler(tm_tr_cb_idx);
9295 mpt3sas_base_release_callback_handler(tm_tr_volume_cb_idx);
9296 mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx);
9297
9298/* raid transport support */
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05309299 if (hbas_to_enumerate != 1)
9300 raid_class_release(mpt3sas_raid_template);
9301 if (hbas_to_enumerate != 2)
9302 raid_class_release(mpt2sas_raid_template);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309303 sas_release_transport(mpt3sas_transport_template);
9304}
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05309305
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05309306/**
9307 * _mpt3sas_init - main entry point for this driver.
9308 *
9309 * Returns 0 success, anything else error.
9310 */
9311static int __init
9312_mpt3sas_init(void)
9313{
9314 int error;
9315
9316 pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME,
9317 MPT3SAS_DRIVER_VERSION);
9318
9319 mpt3sas_transport_template =
9320 sas_attach_transport(&mpt3sas_transport_functions);
9321 if (!mpt3sas_transport_template)
9322 return -ENODEV;
9323
9324 /* No need attach mpt3sas raid functions template
9325 * if hbas_to_enumarate value is one.
9326 */
9327 if (hbas_to_enumerate != 1) {
9328 mpt3sas_raid_template =
9329 raid_class_attach(&mpt3sas_raid_functions);
9330 if (!mpt3sas_raid_template) {
9331 sas_release_transport(mpt3sas_transport_template);
9332 return -ENODEV;
9333 }
9334 }
9335
9336 /* No need to attach mpt2sas raid functions template
9337 * if hbas_to_enumarate value is two
9338 */
9339 if (hbas_to_enumerate != 2) {
9340 mpt2sas_raid_template =
9341 raid_class_attach(&mpt2sas_raid_functions);
9342 if (!mpt2sas_raid_template) {
9343 sas_release_transport(mpt3sas_transport_template);
9344 return -ENODEV;
9345 }
9346 }
9347
9348 error = scsih_init();
9349 if (error) {
9350 scsih_exit();
9351 return error;
9352 }
9353
9354 mpt3sas_ctl_init(hbas_to_enumerate);
9355
9356 error = pci_register_driver(&mpt3sas_driver);
9357 if (error)
9358 scsih_exit();
9359
9360 return error;
9361}
9362
9363/**
9364 * _mpt3sas_exit - exit point for this driver (when it is a module).
9365 *
9366 */
9367static void __exit
9368_mpt3sas_exit(void)
9369{
9370 pr_info("mpt3sas version %s unloading\n",
9371 MPT3SAS_DRIVER_VERSION);
9372
9373 pci_unregister_driver(&mpt3sas_driver);
9374
9375 mpt3sas_ctl_exit(hbas_to_enumerate);
9376
9377 scsih_exit();
9378}
9379
9380module_init(_mpt3sas_init);
9381module_exit(_mpt3sas_exit);