blob: 468acab04d3dca9ebbeca8aaf892ed9f024dad69 [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
3300
3301/**
3302 * _scsih_sas_control_complete - completion routine
3303 * @ioc: per adapter object
3304 * @smid: system request message index
3305 * @msix_index: MSIX table index supplied by the OS
3306 * @reply: reply message frame(lower 32bit addr)
3307 * Context: interrupt time.
3308 *
3309 * This is the sas iounit control completion routine.
3310 * This code is part of the code to initiate the device removal
3311 * handshake protocol with controller firmware.
3312 *
3313 * Return 1 meaning mf should be freed from _base_interrupt
3314 * 0 means the mf is freed from this function.
3315 */
3316static u8
3317_scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
3318 u8 msix_index, u32 reply)
3319{
3320 Mpi2SasIoUnitControlReply_t *mpi_reply =
3321 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3322
3323 if (likely(mpi_reply)) {
3324 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3325 "sc_complete:handle(0x%04x), (open) "
3326 "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
3327 ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
3328 le16_to_cpu(mpi_reply->IOCStatus),
3329 le32_to_cpu(mpi_reply->IOCLogInfo)));
3330 } else {
3331 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3332 ioc->name, __FILE__, __LINE__, __func__);
3333 }
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05303334 return mpt3sas_check_for_pending_internal_cmds(ioc, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303335}
3336
3337/**
3338 * _scsih_tm_tr_volume_send - send target reset request for volumes
3339 * @ioc: per adapter object
3340 * @handle: device handle
3341 * Context: interrupt time.
3342 *
3343 * This is designed to send muliple task management request at the same
3344 * time to the fifo. If the fifo is full, we will append the request,
3345 * and process it in a future completion.
3346 */
3347static void
3348_scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3349{
3350 Mpi2SCSITaskManagementRequest_t *mpi_request;
3351 u16 smid;
3352 struct _tr_list *delayed_tr;
3353
3354 if (ioc->shost_recovery || ioc->remove_host ||
3355 ioc->pci_error_recovery) {
3356 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3357 "%s: host reset in progress!\n",
3358 __func__, ioc->name));
3359 return;
3360 }
3361
3362 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx);
3363 if (!smid) {
3364 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3365 if (!delayed_tr)
3366 return;
3367 INIT_LIST_HEAD(&delayed_tr->list);
3368 delayed_tr->handle = handle;
3369 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list);
3370 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3371 "DELAYED:tr:handle(0x%04x), (open)\n",
3372 ioc->name, handle));
3373 return;
3374 }
3375
3376 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3377 "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3378 ioc->name, handle, smid,
3379 ioc->tm_tr_volume_cb_idx));
3380 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3381 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3382 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3383 mpi_request->DevHandle = cpu_to_le16(handle);
3384 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
Suganath prabu Subramani03d1fb32016-01-28 12:07:06 +05303385 mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303386}
3387
3388/**
3389 * _scsih_tm_volume_tr_complete - target reset completion
3390 * @ioc: per adapter object
3391 * @smid: system request message index
3392 * @msix_index: MSIX table index supplied by the OS
3393 * @reply: reply message frame(lower 32bit addr)
3394 * Context: interrupt time.
3395 *
3396 * Return 1 meaning mf should be freed from _base_interrupt
3397 * 0 means the mf is freed from this function.
3398 */
3399static u8
3400_scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
3401 u8 msix_index, u32 reply)
3402{
3403 u16 handle;
3404 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
3405 Mpi2SCSITaskManagementReply_t *mpi_reply =
3406 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3407
3408 if (ioc->shost_recovery || ioc->remove_host ||
3409 ioc->pci_error_recovery) {
3410 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3411 "%s: host reset in progress!\n",
3412 __func__, ioc->name));
3413 return 1;
3414 }
3415 if (unlikely(!mpi_reply)) {
3416 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3417 ioc->name, __FILE__, __LINE__, __func__);
3418 return 1;
3419 }
3420
3421 mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
3422 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3423 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3424 dewtprintk(ioc, pr_err(MPT3SAS_FMT
3425 "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
3426 ioc->name, handle,
3427 le16_to_cpu(mpi_reply->DevHandle), smid));
3428 return 0;
3429 }
3430
3431 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3432 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3433 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3434 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3435 le32_to_cpu(mpi_reply->IOCLogInfo),
3436 le32_to_cpu(mpi_reply->TerminationCount)));
3437
3438 return _scsih_check_for_pending_tm(ioc, smid);
3439}
3440
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05303441/**
3442 * _scsih_issue_delayed_event_ack - issue delayed Event ACK messages
3443 * @ioc: per adapter object
3444 * @smid: system request message index
3445 * @event: Event ID
3446 * @event_context: used to track events uniquely
3447 *
3448 * Context - processed in interrupt context.
3449 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07003450static void
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05303451_scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event,
3452 u32 event_context)
3453{
3454 Mpi2EventAckRequest_t *ack_request;
3455 int i = smid - ioc->internal_smid;
3456 unsigned long flags;
3457
3458 /* Without releasing the smid just update the
3459 * call back index and reuse the same smid for
3460 * processing this delayed request
3461 */
3462 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
3463 ioc->internal_lookup[i].cb_idx = ioc->base_cb_idx;
3464 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
3465
3466 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3467 "EVENT ACK: event(0x%04x), smid(%d), cb(%d)\n",
3468 ioc->name, le16_to_cpu(event), smid,
3469 ioc->base_cb_idx));
3470 ack_request = mpt3sas_base_get_msg_frame(ioc, smid);
3471 memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
3472 ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
3473 ack_request->Event = event;
3474 ack_request->EventContext = event_context;
3475 ack_request->VF_ID = 0; /* TODO */
3476 ack_request->VP_ID = 0;
3477 mpt3sas_base_put_smid_default(ioc, smid);
3478}
3479
3480/**
3481 * _scsih_issue_delayed_sas_io_unit_ctrl - issue delayed
3482 * sas_io_unit_ctrl messages
3483 * @ioc: per adapter object
3484 * @smid: system request message index
3485 * @handle: device handle
3486 *
3487 * Context - processed in interrupt context.
3488 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07003489static void
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05303490_scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc,
3491 u16 smid, u16 handle)
3492 {
3493 Mpi2SasIoUnitControlRequest_t *mpi_request;
3494 u32 ioc_state;
3495 int i = smid - ioc->internal_smid;
3496 unsigned long flags;
3497
3498 if (ioc->remove_host) {
3499 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3500 "%s: host has been removed\n",
3501 __func__, ioc->name));
3502 return;
3503 } else if (ioc->pci_error_recovery) {
3504 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3505 "%s: host in pci error recovery\n",
3506 __func__, ioc->name));
3507 return;
3508 }
3509 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3510 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3511 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3512 "%s: host is not operational\n",
3513 __func__, ioc->name));
3514 return;
3515 }
3516
3517 /* Without releasing the smid just update the
3518 * call back index and reuse the same smid for
3519 * processing this delayed request
3520 */
3521 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
3522 ioc->internal_lookup[i].cb_idx = ioc->tm_sas_control_cb_idx;
3523 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
3524
3525 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3526 "sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3527 ioc->name, le16_to_cpu(handle), smid,
3528 ioc->tm_sas_control_cb_idx));
3529 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3530 memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
3531 mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
3532 mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
3533 mpi_request->DevHandle = handle;
3534 mpt3sas_base_put_smid_default(ioc, smid);
3535}
3536
3537/**
3538 * _scsih_check_for_pending_internal_cmds - check for pending internal messages
3539 * @ioc: per adapter object
3540 * @smid: system request message index
3541 *
3542 * Context: Executed in interrupt context
3543 *
3544 * This will check delayed internal messages list, and process the
3545 * next request.
3546 *
3547 * Return 1 meaning mf should be freed from _base_interrupt
3548 * 0 means the mf is freed from this function.
3549 */
3550u8
3551mpt3sas_check_for_pending_internal_cmds(struct MPT3SAS_ADAPTER *ioc, u16 smid)
3552{
3553 struct _sc_list *delayed_sc;
3554 struct _event_ack_list *delayed_event_ack;
3555
3556 if (!list_empty(&ioc->delayed_event_ack_list)) {
3557 delayed_event_ack = list_entry(ioc->delayed_event_ack_list.next,
3558 struct _event_ack_list, list);
3559 _scsih_issue_delayed_event_ack(ioc, smid,
3560 delayed_event_ack->Event, delayed_event_ack->EventContext);
3561 list_del(&delayed_event_ack->list);
3562 kfree(delayed_event_ack);
3563 return 0;
3564 }
3565
3566 if (!list_empty(&ioc->delayed_sc_list)) {
3567 delayed_sc = list_entry(ioc->delayed_sc_list.next,
3568 struct _sc_list, list);
3569 _scsih_issue_delayed_sas_io_unit_ctrl(ioc, smid,
3570 delayed_sc->handle);
3571 list_del(&delayed_sc->list);
3572 kfree(delayed_sc);
3573 return 0;
3574 }
3575 return 1;
3576}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303577
3578/**
3579 * _scsih_check_for_pending_tm - check for pending task management
3580 * @ioc: per adapter object
3581 * @smid: system request message index
3582 *
3583 * This will check delayed target reset list, and feed the
3584 * next reqeust.
3585 *
3586 * Return 1 meaning mf should be freed from _base_interrupt
3587 * 0 means the mf is freed from this function.
3588 */
3589static u8
3590_scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid)
3591{
3592 struct _tr_list *delayed_tr;
3593
3594 if (!list_empty(&ioc->delayed_tr_volume_list)) {
3595 delayed_tr = list_entry(ioc->delayed_tr_volume_list.next,
3596 struct _tr_list, list);
3597 mpt3sas_base_free_smid(ioc, smid);
3598 _scsih_tm_tr_volume_send(ioc, delayed_tr->handle);
3599 list_del(&delayed_tr->list);
3600 kfree(delayed_tr);
3601 return 0;
3602 }
3603
3604 if (!list_empty(&ioc->delayed_tr_list)) {
3605 delayed_tr = list_entry(ioc->delayed_tr_list.next,
3606 struct _tr_list, list);
3607 mpt3sas_base_free_smid(ioc, smid);
3608 _scsih_tm_tr_send(ioc, delayed_tr->handle);
3609 list_del(&delayed_tr->list);
3610 kfree(delayed_tr);
3611 return 0;
3612 }
3613
3614 return 1;
3615}
3616
3617/**
3618 * _scsih_check_topo_delete_events - sanity check on topo events
3619 * @ioc: per adapter object
3620 * @event_data: the event data payload
3621 *
3622 * This routine added to better handle cable breaker.
3623 *
3624 * This handles the case where driver receives multiple expander
3625 * add and delete events in a single shot. When there is a delete event
3626 * the routine will void any pending add events waiting in the event queue.
3627 *
3628 * Return nothing.
3629 */
3630static void
3631_scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc,
3632 Mpi2EventDataSasTopologyChangeList_t *event_data)
3633{
3634 struct fw_event_work *fw_event;
3635 Mpi2EventDataSasTopologyChangeList_t *local_event_data;
3636 u16 expander_handle;
3637 struct _sas_node *sas_expander;
3638 unsigned long flags;
3639 int i, reason_code;
3640 u16 handle;
3641
3642 for (i = 0 ; i < event_data->NumEntries; i++) {
3643 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3644 if (!handle)
3645 continue;
3646 reason_code = event_data->PHY[i].PhyStatus &
3647 MPI2_EVENT_SAS_TOPO_RC_MASK;
3648 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)
3649 _scsih_tm_tr_send(ioc, handle);
3650 }
3651
3652 expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
3653 if (expander_handle < ioc->sas_hba.num_phys) {
3654 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3655 return;
3656 }
3657 if (event_data->ExpStatus ==
3658 MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
3659 /* put expander attached devices into blocking state */
3660 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3661 sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
3662 expander_handle);
3663 _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
3664 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3665 do {
3666 handle = find_first_bit(ioc->blocking_handles,
3667 ioc->facts.MaxDevHandle);
3668 if (handle < ioc->facts.MaxDevHandle)
3669 _scsih_block_io_device(ioc, handle);
3670 } while (test_and_clear_bit(handle, ioc->blocking_handles));
3671 } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
3672 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3673
3674 if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
3675 return;
3676
3677 /* mark ignore flag for pending events */
3678 spin_lock_irqsave(&ioc->fw_event_lock, flags);
3679 list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
3680 if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
3681 fw_event->ignore)
3682 continue;
Joe Lawrence35b62362014-06-25 17:05:34 -04003683 local_event_data = (Mpi2EventDataSasTopologyChangeList_t *)
3684 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303685 if (local_event_data->ExpStatus ==
3686 MPI2_EVENT_SAS_TOPO_ES_ADDED ||
3687 local_event_data->ExpStatus ==
3688 MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
3689 if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
3690 expander_handle) {
3691 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3692 "setting ignoring flag\n", ioc->name));
3693 fw_event->ignore = 1;
3694 }
3695 }
3696 }
3697 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
3698}
3699
3700/**
3701 * _scsih_set_volume_delete_flag - setting volume delete flag
3702 * @ioc: per adapter object
3703 * @handle: device handle
3704 *
3705 * This returns nothing.
3706 */
3707static void
3708_scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3709{
3710 struct _raid_device *raid_device;
3711 struct MPT3SAS_TARGET *sas_target_priv_data;
3712 unsigned long flags;
3713
3714 spin_lock_irqsave(&ioc->raid_device_lock, flags);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05303715 raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303716 if (raid_device && raid_device->starget &&
3717 raid_device->starget->hostdata) {
3718 sas_target_priv_data =
3719 raid_device->starget->hostdata;
3720 sas_target_priv_data->deleted = 1;
3721 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3722 "setting delete flag: handle(0x%04x), "
3723 "wwid(0x%016llx)\n", ioc->name, handle,
3724 (unsigned long long) raid_device->wwid));
3725 }
3726 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
3727}
3728
3729/**
3730 * _scsih_set_volume_handle_for_tr - set handle for target reset to volume
3731 * @handle: input handle
3732 * @a: handle for volume a
3733 * @b: handle for volume b
3734 *
3735 * IR firmware only supports two raid volumes. The purpose of this
3736 * routine is to set the volume handle in either a or b. When the given
3737 * input handle is non-zero, or when a and b have not been set before.
3738 */
3739static void
3740_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b)
3741{
3742 if (!handle || handle == *a || handle == *b)
3743 return;
3744 if (!*a)
3745 *a = handle;
3746 else if (!*b)
3747 *b = handle;
3748}
3749
3750/**
3751 * _scsih_check_ir_config_unhide_events - check for UNHIDE events
3752 * @ioc: per adapter object
3753 * @event_data: the event data payload
3754 * Context: interrupt time.
3755 *
3756 * This routine will send target reset to volume, followed by target
3757 * resets to the PDs. This is called when a PD has been removed, or
3758 * volume has been deleted or removed. When the target reset is sent
3759 * to volume, the PD target resets need to be queued to start upon
3760 * completion of the volume target reset.
3761 *
3762 * Return nothing.
3763 */
3764static void
3765_scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc,
3766 Mpi2EventDataIrConfigChangeList_t *event_data)
3767{
3768 Mpi2EventIrConfigElement_t *element;
3769 int i;
3770 u16 handle, volume_handle, a, b;
3771 struct _tr_list *delayed_tr;
3772
3773 a = 0;
3774 b = 0;
3775
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303776 if (ioc->is_warpdrive)
3777 return;
3778
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303779 /* Volume Resets for Deleted or Removed */
3780 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3781 for (i = 0; i < event_data->NumElements; i++, element++) {
3782 if (le32_to_cpu(event_data->Flags) &
3783 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3784 continue;
3785 if (element->ReasonCode ==
3786 MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED ||
3787 element->ReasonCode ==
3788 MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
3789 volume_handle = le16_to_cpu(element->VolDevHandle);
3790 _scsih_set_volume_delete_flag(ioc, volume_handle);
3791 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3792 }
3793 }
3794
3795 /* Volume Resets for UNHIDE events */
3796 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3797 for (i = 0; i < event_data->NumElements; i++, element++) {
3798 if (le32_to_cpu(event_data->Flags) &
3799 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3800 continue;
3801 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) {
3802 volume_handle = le16_to_cpu(element->VolDevHandle);
3803 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3804 }
3805 }
3806
3807 if (a)
3808 _scsih_tm_tr_volume_send(ioc, a);
3809 if (b)
3810 _scsih_tm_tr_volume_send(ioc, b);
3811
3812 /* PD target resets */
3813 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3814 for (i = 0; i < event_data->NumElements; i++, element++) {
3815 if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE)
3816 continue;
3817 handle = le16_to_cpu(element->PhysDiskDevHandle);
3818 volume_handle = le16_to_cpu(element->VolDevHandle);
3819 clear_bit(handle, ioc->pd_handles);
3820 if (!volume_handle)
3821 _scsih_tm_tr_send(ioc, handle);
3822 else if (volume_handle == a || volume_handle == b) {
3823 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3824 BUG_ON(!delayed_tr);
3825 INIT_LIST_HEAD(&delayed_tr->list);
3826 delayed_tr->handle = handle;
3827 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3828 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3829 "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name,
3830 handle));
3831 } else
3832 _scsih_tm_tr_send(ioc, handle);
3833 }
3834}
3835
3836
3837/**
3838 * _scsih_check_volume_delete_events - set delete flag for volumes
3839 * @ioc: per adapter object
3840 * @event_data: the event data payload
3841 * Context: interrupt time.
3842 *
3843 * This will handle the case when the cable connected to entire volume is
3844 * pulled. We will take care of setting the deleted flag so normal IO will
3845 * not be sent.
3846 *
3847 * Return nothing.
3848 */
3849static void
3850_scsih_check_volume_delete_events(struct MPT3SAS_ADAPTER *ioc,
3851 Mpi2EventDataIrVolume_t *event_data)
3852{
3853 u32 state;
3854
3855 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
3856 return;
3857 state = le32_to_cpu(event_data->NewValue);
3858 if (state == MPI2_RAID_VOL_STATE_MISSING || state ==
3859 MPI2_RAID_VOL_STATE_FAILED)
3860 _scsih_set_volume_delete_flag(ioc,
3861 le16_to_cpu(event_data->VolDevHandle));
3862}
3863
3864/**
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05303865 * _scsih_temp_threshold_events - display temperature threshold exceeded events
3866 * @ioc: per adapter object
3867 * @event_data: the temp threshold event data
3868 * Context: interrupt time.
3869 *
3870 * Return nothing.
3871 */
3872static void
3873_scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc,
3874 Mpi2EventDataTemperature_t *event_data)
3875{
3876 if (ioc->temp_sensors_count >= event_data->SensorNum) {
3877 pr_err(MPT3SAS_FMT "Temperature Threshold flags %s%s%s%s"
3878 " exceeded for Sensor: %d !!!\n", ioc->name,
3879 ((le16_to_cpu(event_data->Status) & 0x1) == 1) ? "0 " : " ",
3880 ((le16_to_cpu(event_data->Status) & 0x2) == 2) ? "1 " : " ",
3881 ((le16_to_cpu(event_data->Status) & 0x4) == 4) ? "2 " : " ",
3882 ((le16_to_cpu(event_data->Status) & 0x8) == 8) ? "3 " : " ",
3883 event_data->SensorNum);
3884 pr_err(MPT3SAS_FMT "Current Temp In Celsius: %d\n",
3885 ioc->name, event_data->CurrentTemperature);
3886 }
3887}
3888
James Bottomley16236802017-01-01 09:39:24 -08003889static int _scsih_set_satl_pending(struct scsi_cmnd *scmd, bool pending)
Suganath Prabu S7ff723a2016-11-17 16:15:58 +05303890{
James Bottomley16236802017-01-01 09:39:24 -08003891 struct MPT3SAS_DEVICE *priv = scmd->device->hostdata;
3892
3893 if (scmd->cmnd[0] != ATA_12 && scmd->cmnd[0] != ATA_16)
3894 return 0;
3895
3896 if (pending)
3897 return test_and_set_bit(0, &priv->ata_command_pending);
3898
3899 clear_bit(0, &priv->ata_command_pending);
3900 return 0;
Suganath Prabu S7ff723a2016-11-17 16:15:58 +05303901}
3902
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05303903/**
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303904 * _scsih_flush_running_cmds - completing outstanding commands.
3905 * @ioc: per adapter object
3906 *
3907 * The flushing out of all pending scmd commands following host reset,
3908 * where all IO is dropped to the floor.
3909 *
3910 * Return nothing.
3911 */
3912static void
3913_scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
3914{
3915 struct scsi_cmnd *scmd;
3916 u16 smid;
3917 u16 count = 0;
3918
3919 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
3920 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
3921 if (!scmd)
3922 continue;
3923 count++;
James Bottomley16236802017-01-01 09:39:24 -08003924 _scsih_set_satl_pending(scmd, false);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303925 mpt3sas_base_free_smid(ioc, smid);
3926 scsi_dma_unmap(scmd);
3927 if (ioc->pci_error_recovery)
3928 scmd->result = DID_NO_CONNECT << 16;
3929 else
3930 scmd->result = DID_RESET << 16;
3931 scmd->scsi_done(scmd);
3932 }
3933 dtmprintk(ioc, pr_info(MPT3SAS_FMT "completing %d cmds\n",
3934 ioc->name, count));
3935}
3936
3937/**
3938 * _scsih_setup_eedp - setup MPI request for EEDP transfer
3939 * @ioc: per adapter object
3940 * @scmd: pointer to scsi command object
3941 * @mpi_request: pointer to the SCSI_IO reqest message frame
3942 *
3943 * Supporting protection 1 and 3.
3944 *
3945 * Returns nothing
3946 */
3947static void
3948_scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
3949 Mpi2SCSIIORequest_t *mpi_request)
3950{
3951 u16 eedp_flags;
3952 unsigned char prot_op = scsi_get_prot_op(scmd);
3953 unsigned char prot_type = scsi_get_prot_type(scmd);
3954 Mpi25SCSIIORequest_t *mpi_request_3v =
3955 (Mpi25SCSIIORequest_t *)mpi_request;
3956
3957 if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
3958 return;
3959
3960 if (prot_op == SCSI_PROT_READ_STRIP)
3961 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
3962 else if (prot_op == SCSI_PROT_WRITE_INSERT)
3963 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
3964 else
3965 return;
3966
3967 switch (prot_type) {
3968 case SCSI_PROT_DIF_TYPE1:
3969 case SCSI_PROT_DIF_TYPE2:
3970
3971 /*
3972 * enable ref/guard checking
3973 * auto increment ref tag
3974 */
3975 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
3976 MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
3977 MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
3978 mpi_request->CDB.EEDP32.PrimaryReferenceTag =
Chaitra P B648512cc2016-05-06 14:29:28 +05303979 cpu_to_be32(scsi_prot_ref_tag(scmd));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303980 break;
3981
3982 case SCSI_PROT_DIF_TYPE3:
3983
3984 /*
3985 * enable guard checking
3986 */
3987 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
3988
3989 break;
3990 }
3991
3992 mpi_request_3v->EEDPBlockSize =
3993 cpu_to_le16(scmd->device->sector_size);
3994 mpi_request->EEDPFlags = cpu_to_le16(eedp_flags);
3995}
3996
3997/**
3998 * _scsih_eedp_error_handling - return sense code for EEDP errors
3999 * @scmd: pointer to scsi command object
4000 * @ioc_status: ioc status
4001 *
4002 * Returns nothing
4003 */
4004static void
4005_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
4006{
4007 u8 ascq;
4008
4009 switch (ioc_status) {
4010 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4011 ascq = 0x01;
4012 break;
4013 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4014 ascq = 0x02;
4015 break;
4016 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4017 ascq = 0x03;
4018 break;
4019 default:
4020 ascq = 0x00;
4021 break;
4022 }
4023 scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10,
4024 ascq);
4025 scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) |
4026 SAM_STAT_CHECK_CONDITION;
4027}
4028
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304029/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05304030 * scsih_qcmd - main scsi request entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304031 * @scmd: pointer to scsi command object
4032 * @done: function pointer to be invoked on completion
4033 *
4034 * The callback index is set inside `ioc->scsi_io_cb_idx`.
4035 *
4036 * Returns 0 on success. If there's a failure, return either:
4037 * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
4038 * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
4039 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07004040static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05304041scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304042{
Matthew Wilcoxd8bfbd82014-03-27 16:40:31 -04004043 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304044 struct MPT3SAS_DEVICE *sas_device_priv_data;
4045 struct MPT3SAS_TARGET *sas_target_priv_data;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304046 struct _raid_device *raid_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304047 Mpi2SCSIIORequest_t *mpi_request;
4048 u32 mpi_control;
4049 u16 smid;
4050 u16 handle;
4051
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304052 if (ioc->logging_level & MPT_DEBUG_SCSI)
4053 scsi_print_command(scmd);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304054
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304055 sas_device_priv_data = scmd->device->hostdata;
4056 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
4057 scmd->result = DID_NO_CONNECT << 16;
4058 scmd->scsi_done(scmd);
4059 return 0;
4060 }
4061
4062 if (ioc->pci_error_recovery || ioc->remove_host) {
4063 scmd->result = DID_NO_CONNECT << 16;
4064 scmd->scsi_done(scmd);
4065 return 0;
4066 }
4067
James Bottomley16236802017-01-01 09:39:24 -08004068 /*
4069 * Bug work around for firmware SATL handling. The loop
4070 * is based on atomic operations and ensures consistency
4071 * since we're lockless at this point
4072 */
4073 do {
4074 if (test_bit(0, &sas_device_priv_data->ata_command_pending)) {
4075 scmd->result = SAM_STAT_BUSY;
4076 scmd->scsi_done(scmd);
4077 return 0;
4078 }
4079 } while (_scsih_set_satl_pending(scmd, true));
4080
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304081 sas_target_priv_data = sas_device_priv_data->sas_target;
4082
4083 /* invalid device handle */
4084 handle = sas_target_priv_data->handle;
4085 if (handle == MPT3SAS_INVALID_DEVICE_HANDLE) {
4086 scmd->result = DID_NO_CONNECT << 16;
4087 scmd->scsi_done(scmd);
4088 return 0;
4089 }
4090
4091
4092 /* host recovery or link resets sent via IOCTLs */
4093 if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
4094 return SCSI_MLQUEUE_HOST_BUSY;
4095
4096 /* device has been deleted */
4097 else if (sas_target_priv_data->deleted) {
4098 scmd->result = DID_NO_CONNECT << 16;
4099 scmd->scsi_done(scmd);
4100 return 0;
4101 /* device busy with task managment */
4102 } else if (sas_target_priv_data->tm_busy ||
4103 sas_device_priv_data->block)
4104 return SCSI_MLQUEUE_DEVICE_BUSY;
4105
4106 if (scmd->sc_data_direction == DMA_FROM_DEVICE)
4107 mpi_control = MPI2_SCSIIO_CONTROL_READ;
4108 else if (scmd->sc_data_direction == DMA_TO_DEVICE)
4109 mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
4110 else
4111 mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
4112
4113 /* set tags */
Christoph Hellwig609aa222014-10-30 11:54:58 +01004114 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304115
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304116 /* Make sure Device is not raid volume.
4117 * We do not expose raid functionality to upper layer for warpdrive.
4118 */
4119 if (!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev)
Sreekanth Reddy15de0de2015-11-12 23:40:37 +05304120 && sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304121 mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
4122
4123 smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
4124 if (!smid) {
4125 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
4126 ioc->name, __func__);
4127 goto out;
4128 }
4129 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
4130 memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
4131 _scsih_setup_eedp(ioc, scmd, mpi_request);
4132
4133 if (scmd->cmd_len == 32)
4134 mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
4135 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
4136 if (sas_device_priv_data->sas_target->flags &
4137 MPT_TARGET_FLAGS_RAID_COMPONENT)
4138 mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
4139 else
4140 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
4141 mpi_request->DevHandle = cpu_to_le16(handle);
4142 mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
4143 mpi_request->Control = cpu_to_le32(mpi_control);
4144 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
4145 mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
4146 mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
4147 mpi_request->SenseBufferLowAddress =
4148 mpt3sas_base_get_sense_buffer_dma(ioc, smid);
4149 mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
4150 int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
4151 mpi_request->LUN);
4152 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
4153
4154 if (mpi_request->DataLength) {
4155 if (ioc->build_sg_scmd(ioc, scmd, smid)) {
4156 mpt3sas_base_free_smid(ioc, smid);
4157 goto out;
4158 }
4159 } else
4160 ioc->build_zero_len_sge(ioc, &mpi_request->SGL);
4161
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304162 raid_device = sas_target_priv_data->raid_device;
4163 if (raid_device && raid_device->direct_io_enabled)
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05304164 mpt3sas_setup_direct_io(ioc, scmd, raid_device, mpi_request,
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304165 smid);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304166
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304167 if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) {
4168 if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
4169 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len |
4170 MPI25_SCSIIO_IOFLAGS_FAST_PATH);
4171 mpt3sas_base_put_smid_fast_path(ioc, smid, handle);
4172 } else
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304173 mpt3sas_base_put_smid_scsi_io(ioc, smid,
4174 le16_to_cpu(mpi_request->DevHandle));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304175 } else
4176 mpt3sas_base_put_smid_default(ioc, smid);
4177 return 0;
4178
4179 out:
4180 return SCSI_MLQUEUE_HOST_BUSY;
4181}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304182
4183/**
4184 * _scsih_normalize_sense - normalize descriptor and fixed format sense data
4185 * @sense_buffer: sense data returned by target
4186 * @data: normalized skey/asc/ascq
4187 *
4188 * Return nothing.
4189 */
4190static void
4191_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
4192{
4193 if ((sense_buffer[0] & 0x7F) >= 0x72) {
4194 /* descriptor format */
4195 data->skey = sense_buffer[1] & 0x0F;
4196 data->asc = sense_buffer[2];
4197 data->ascq = sense_buffer[3];
4198 } else {
4199 /* fixed format */
4200 data->skey = sense_buffer[2] & 0x0F;
4201 data->asc = sense_buffer[12];
4202 data->ascq = sense_buffer[13];
4203 }
4204}
4205
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304206/**
4207 * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
4208 * @ioc: per adapter object
4209 * @scmd: pointer to scsi command object
4210 * @mpi_reply: reply mf payload returned from firmware
4211 *
4212 * scsi_status - SCSI Status code returned from target device
4213 * scsi_state - state info associated with SCSI_IO determined by ioc
4214 * ioc_status - ioc supplied status info
4215 *
4216 * Return nothing.
4217 */
4218static void
4219_scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
4220 Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
4221{
4222 u32 response_info;
4223 u8 *response_bytes;
4224 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
4225 MPI2_IOCSTATUS_MASK;
4226 u8 scsi_state = mpi_reply->SCSIState;
4227 u8 scsi_status = mpi_reply->SCSIStatus;
4228 char *desc_ioc_state = NULL;
4229 char *desc_scsi_status = NULL;
4230 char *desc_scsi_state = ioc->tmp_string;
4231 u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
4232 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304233 struct scsi_target *starget = scmd->device->sdev_target;
4234 struct MPT3SAS_TARGET *priv_target = starget->hostdata;
4235 char *device_str = NULL;
4236
4237 if (!priv_target)
4238 return;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304239 if (ioc->hide_ir_msg)
4240 device_str = "WarpDrive";
4241 else
4242 device_str = "volume";
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304243
4244 if (log_info == 0x31170000)
4245 return;
4246
4247 switch (ioc_status) {
4248 case MPI2_IOCSTATUS_SUCCESS:
4249 desc_ioc_state = "success";
4250 break;
4251 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4252 desc_ioc_state = "invalid function";
4253 break;
4254 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4255 desc_ioc_state = "scsi recovered error";
4256 break;
4257 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
4258 desc_ioc_state = "scsi invalid dev handle";
4259 break;
4260 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4261 desc_ioc_state = "scsi device not there";
4262 break;
4263 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4264 desc_ioc_state = "scsi data overrun";
4265 break;
4266 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4267 desc_ioc_state = "scsi data underrun";
4268 break;
4269 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4270 desc_ioc_state = "scsi io data error";
4271 break;
4272 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4273 desc_ioc_state = "scsi protocol error";
4274 break;
4275 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4276 desc_ioc_state = "scsi task terminated";
4277 break;
4278 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4279 desc_ioc_state = "scsi residual mismatch";
4280 break;
4281 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4282 desc_ioc_state = "scsi task mgmt failed";
4283 break;
4284 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4285 desc_ioc_state = "scsi ioc terminated";
4286 break;
4287 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4288 desc_ioc_state = "scsi ext terminated";
4289 break;
4290 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4291 desc_ioc_state = "eedp guard error";
4292 break;
4293 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4294 desc_ioc_state = "eedp ref tag error";
4295 break;
4296 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4297 desc_ioc_state = "eedp app tag error";
4298 break;
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05304299 case MPI2_IOCSTATUS_INSUFFICIENT_POWER:
4300 desc_ioc_state = "insufficient power";
4301 break;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304302 default:
4303 desc_ioc_state = "unknown";
4304 break;
4305 }
4306
4307 switch (scsi_status) {
4308 case MPI2_SCSI_STATUS_GOOD:
4309 desc_scsi_status = "good";
4310 break;
4311 case MPI2_SCSI_STATUS_CHECK_CONDITION:
4312 desc_scsi_status = "check condition";
4313 break;
4314 case MPI2_SCSI_STATUS_CONDITION_MET:
4315 desc_scsi_status = "condition met";
4316 break;
4317 case MPI2_SCSI_STATUS_BUSY:
4318 desc_scsi_status = "busy";
4319 break;
4320 case MPI2_SCSI_STATUS_INTERMEDIATE:
4321 desc_scsi_status = "intermediate";
4322 break;
4323 case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
4324 desc_scsi_status = "intermediate condmet";
4325 break;
4326 case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
4327 desc_scsi_status = "reservation conflict";
4328 break;
4329 case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
4330 desc_scsi_status = "command terminated";
4331 break;
4332 case MPI2_SCSI_STATUS_TASK_SET_FULL:
4333 desc_scsi_status = "task set full";
4334 break;
4335 case MPI2_SCSI_STATUS_ACA_ACTIVE:
4336 desc_scsi_status = "aca active";
4337 break;
4338 case MPI2_SCSI_STATUS_TASK_ABORTED:
4339 desc_scsi_status = "task aborted";
4340 break;
4341 default:
4342 desc_scsi_status = "unknown";
4343 break;
4344 }
4345
4346 desc_scsi_state[0] = '\0';
4347 if (!scsi_state)
4348 desc_scsi_state = " ";
4349 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4350 strcat(desc_scsi_state, "response info ");
4351 if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4352 strcat(desc_scsi_state, "state terminated ");
4353 if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
4354 strcat(desc_scsi_state, "no status ");
4355 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
4356 strcat(desc_scsi_state, "autosense failed ");
4357 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
4358 strcat(desc_scsi_state, "autosense valid ");
4359
4360 scsi_print_command(scmd);
4361
4362 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
4363 pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
4364 device_str, (unsigned long long)priv_target->sas_address);
4365 } else {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304366 sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304367 if (sas_device) {
4368 pr_warn(MPT3SAS_FMT
4369 "\tsas_address(0x%016llx), phy(%d)\n",
4370 ioc->name, (unsigned long long)
4371 sas_device->sas_address, sas_device->phy);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304372 if (sas_device->enclosure_handle != 0)
4373 pr_warn(MPT3SAS_FMT
4374 "\tenclosure_logical_id(0x%016llx),"
4375 "slot(%d)\n", ioc->name,
4376 (unsigned long long)
4377 sas_device->enclosure_logical_id,
4378 sas_device->slot);
4379 if (sas_device->connector_name[0])
4380 pr_warn(MPT3SAS_FMT
4381 "\tenclosure level(0x%04x),"
4382 " connector name( %s)\n", ioc->name,
4383 sas_device->enclosure_level,
4384 sas_device->connector_name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304385
4386 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304387 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304388 }
4389
4390 pr_warn(MPT3SAS_FMT
4391 "\thandle(0x%04x), ioc_status(%s)(0x%04x), smid(%d)\n",
4392 ioc->name, le16_to_cpu(mpi_reply->DevHandle),
4393 desc_ioc_state, ioc_status, smid);
4394 pr_warn(MPT3SAS_FMT
4395 "\trequest_len(%d), underflow(%d), resid(%d)\n",
4396 ioc->name, scsi_bufflen(scmd), scmd->underflow,
4397 scsi_get_resid(scmd));
4398 pr_warn(MPT3SAS_FMT
4399 "\ttag(%d), transfer_count(%d), sc->result(0x%08x)\n",
4400 ioc->name, le16_to_cpu(mpi_reply->TaskTag),
4401 le32_to_cpu(mpi_reply->TransferCount), scmd->result);
4402 pr_warn(MPT3SAS_FMT
4403 "\tscsi_status(%s)(0x%02x), scsi_state(%s)(0x%02x)\n",
4404 ioc->name, desc_scsi_status,
4405 scsi_status, desc_scsi_state, scsi_state);
4406
4407 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4408 struct sense_info data;
4409 _scsih_normalize_sense(scmd->sense_buffer, &data);
4410 pr_warn(MPT3SAS_FMT
4411 "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n",
4412 ioc->name, data.skey,
4413 data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
4414 }
4415
4416 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
4417 response_info = le32_to_cpu(mpi_reply->ResponseInfo);
4418 response_bytes = (u8 *)&response_info;
4419 _scsih_response_code(ioc, response_bytes[0]);
4420 }
4421}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304422
4423/**
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304424 * _scsih_turn_on_pfa_led - illuminate PFA LED
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304425 * @ioc: per adapter object
4426 * @handle: device handle
4427 * Context: process
4428 *
4429 * Return nothing.
4430 */
4431static void
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304432_scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304433{
4434 Mpi2SepReply_t mpi_reply;
4435 Mpi2SepRequest_t mpi_request;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304436 struct _sas_device *sas_device;
4437
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304438 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304439 if (!sas_device)
4440 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304441
4442 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
4443 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
4444 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
4445 mpi_request.SlotStatus =
4446 cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
4447 mpi_request.DevHandle = cpu_to_le16(handle);
4448 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
4449 if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
4450 &mpi_request)) != 0) {
4451 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
4452 __FILE__, __LINE__, __func__);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304453 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304454 }
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304455 sas_device->pfa_led_on = 1;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304456
4457 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
4458 dewtprintk(ioc, pr_info(MPT3SAS_FMT
4459 "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
4460 ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
4461 le32_to_cpu(mpi_reply.IOCLogInfo)));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304462 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304463 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304464out:
4465 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304466}
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304467
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304468/**
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304469 * _scsih_turn_off_pfa_led - turn off Fault LED
4470 * @ioc: per adapter object
4471 * @sas_device: sas device whose PFA LED has to turned off
4472 * Context: process
4473 *
4474 * Return nothing.
4475 */
4476static void
4477_scsih_turn_off_pfa_led(struct MPT3SAS_ADAPTER *ioc,
4478 struct _sas_device *sas_device)
4479{
4480 Mpi2SepReply_t mpi_reply;
4481 Mpi2SepRequest_t mpi_request;
4482
4483 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
4484 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
4485 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
4486 mpi_request.SlotStatus = 0;
4487 mpi_request.Slot = cpu_to_le16(sas_device->slot);
4488 mpi_request.DevHandle = 0;
4489 mpi_request.EnclosureHandle = cpu_to_le16(sas_device->enclosure_handle);
4490 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
4491 if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
4492 &mpi_request)) != 0) {
4493 printk(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
4494 __FILE__, __LINE__, __func__);
4495 return;
4496 }
4497
4498 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
4499 dewtprintk(ioc, printk(MPT3SAS_FMT
4500 "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
4501 ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
4502 le32_to_cpu(mpi_reply.IOCLogInfo)));
4503 return;
4504 }
4505}
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304506
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304507/**
4508 * _scsih_send_event_to_turn_on_pfa_led - fire delayed event
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304509 * @ioc: per adapter object
4510 * @handle: device handle
4511 * Context: interrupt.
4512 *
4513 * Return nothing.
4514 */
4515static void
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304516_scsih_send_event_to_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304517{
4518 struct fw_event_work *fw_event;
4519
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05304520 fw_event = alloc_fw_event_work(0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304521 if (!fw_event)
4522 return;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304523 fw_event->event = MPT3SAS_TURN_ON_PFA_LED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304524 fw_event->device_handle = handle;
4525 fw_event->ioc = ioc;
4526 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05304527 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304528}
4529
4530/**
4531 * _scsih_smart_predicted_fault - process smart errors
4532 * @ioc: per adapter object
4533 * @handle: device handle
4534 * Context: interrupt.
4535 *
4536 * Return nothing.
4537 */
4538static void
4539_scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
4540{
4541 struct scsi_target *starget;
4542 struct MPT3SAS_TARGET *sas_target_priv_data;
4543 Mpi2EventNotificationReply_t *event_reply;
4544 Mpi2EventDataSasDeviceStatusChange_t *event_data;
4545 struct _sas_device *sas_device;
4546 ssize_t sz;
4547 unsigned long flags;
4548
4549 /* only handle non-raid devices */
4550 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304551 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
4552 if (!sas_device)
4553 goto out_unlock;
4554
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304555 starget = sas_device->starget;
4556 sas_target_priv_data = starget->hostdata;
4557
4558 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304559 ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)))
4560 goto out_unlock;
4561
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304562 if (sas_device->enclosure_handle != 0)
4563 starget_printk(KERN_INFO, starget, "predicted fault, "
4564 "enclosure logical id(0x%016llx), slot(%d)\n",
4565 (unsigned long long)sas_device->enclosure_logical_id,
4566 sas_device->slot);
4567 if (sas_device->connector_name[0] != '\0')
4568 starget_printk(KERN_WARNING, starget, "predicted fault, "
4569 "enclosure level(0x%04x), connector name( %s)\n",
4570 sas_device->enclosure_level,
4571 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304572 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4573
4574 if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304575 _scsih_send_event_to_turn_on_pfa_led(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304576
4577 /* insert into event log */
4578 sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
4579 sizeof(Mpi2EventDataSasDeviceStatusChange_t);
4580 event_reply = kzalloc(sz, GFP_KERNEL);
4581 if (!event_reply) {
4582 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4583 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304584 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304585 }
4586
4587 event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
4588 event_reply->Event =
4589 cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
4590 event_reply->MsgLength = sz/4;
4591 event_reply->EventDataLength =
4592 cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
4593 event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
4594 event_reply->EventData;
4595 event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
4596 event_data->ASC = 0x5D;
4597 event_data->DevHandle = cpu_to_le16(handle);
4598 event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
4599 mpt3sas_ctl_add_to_event_log(ioc, event_reply);
4600 kfree(event_reply);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304601out:
4602 if (sas_device)
4603 sas_device_put(sas_device);
4604 return;
4605
4606out_unlock:
4607 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4608 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304609}
4610
4611/**
4612 * _scsih_io_done - scsi request callback
4613 * @ioc: per adapter object
4614 * @smid: system request message index
4615 * @msix_index: MSIX table index supplied by the OS
4616 * @reply: reply message frame(lower 32bit addr)
4617 *
4618 * Callback handler when using _scsih_qcmd.
4619 *
4620 * Return 1 meaning mf should be freed from _base_interrupt
4621 * 0 means the mf is freed from this function.
4622 */
4623static u8
4624_scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4625{
4626 Mpi2SCSIIORequest_t *mpi_request;
4627 Mpi2SCSIIOReply_t *mpi_reply;
4628 struct scsi_cmnd *scmd;
4629 u16 ioc_status;
4630 u32 xfer_cnt;
4631 u8 scsi_state;
4632 u8 scsi_status;
4633 u32 log_info;
4634 struct MPT3SAS_DEVICE *sas_device_priv_data;
4635 u32 response_code = 0;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304636 unsigned long flags;
Ram Pai9869fb42017-01-26 16:37:01 -02004637 unsigned int sector_sz;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304638
4639 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
4640 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
4641 if (scmd == NULL)
4642 return 1;
4643
James Bottomley16236802017-01-01 09:39:24 -08004644 _scsih_set_satl_pending(scmd, false);
Andrey Grodzovsky18f60842016-11-10 09:35:27 -05004645
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304646 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
4647
4648 if (mpi_reply == NULL) {
4649 scmd->result = DID_OK << 16;
4650 goto out;
4651 }
4652
4653 sas_device_priv_data = scmd->device->hostdata;
4654 if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
4655 sas_device_priv_data->sas_target->deleted) {
4656 scmd->result = DID_NO_CONNECT << 16;
4657 goto out;
4658 }
4659 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
4660
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304661 /*
4662 * WARPDRIVE: If direct_io is set then it is directIO,
4663 * the failed direct I/O should be redirected to volume
4664 */
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05304665 if (mpt3sas_scsi_direct_io_get(ioc, smid) &&
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304666 ((ioc_status & MPI2_IOCSTATUS_MASK)
4667 != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
4668 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
4669 ioc->scsi_lookup[smid - 1].scmd = scmd;
4670 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05304671 mpt3sas_scsi_direct_io_set(ioc, smid, 0);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304672 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
4673 mpi_request->DevHandle =
4674 cpu_to_le16(sas_device_priv_data->sas_target->handle);
4675 mpt3sas_base_put_smid_scsi_io(ioc, smid,
4676 sas_device_priv_data->sas_target->handle);
4677 return 0;
4678 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304679 /* turning off TLR */
4680 scsi_state = mpi_reply->SCSIState;
4681 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4682 response_code =
4683 le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
4684 if (!sas_device_priv_data->tlr_snoop_check) {
4685 sas_device_priv_data->tlr_snoop_check++;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304686 if (!ioc->is_warpdrive &&
4687 !scsih_is_raid(&scmd->device->sdev_gendev) &&
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05304688 sas_is_tlr_enabled(scmd->device) &&
4689 response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) {
4690 sas_disable_tlr(scmd->device);
4691 sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n");
4692 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304693 }
4694
4695 xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
Ram Pai9869fb42017-01-26 16:37:01 -02004696
4697 /* In case of bogus fw or device, we could end up having
4698 * unaligned partial completion. We can force alignment here,
4699 * then scsi-ml does not need to handle this misbehavior.
4700 */
4701 sector_sz = scmd->device->sector_size;
4702 if (unlikely(scmd->request->cmd_type == REQ_TYPE_FS && sector_sz &&
4703 xfer_cnt % sector_sz)) {
4704 sdev_printk(KERN_INFO, scmd->device,
4705 "unaligned partial completion avoided (xfer_cnt=%u, sector_sz=%u)\n",
4706 xfer_cnt, sector_sz);
4707 xfer_cnt = round_down(xfer_cnt, sector_sz);
4708 }
4709
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304710 scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
4711 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
4712 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
4713 else
4714 log_info = 0;
4715 ioc_status &= MPI2_IOCSTATUS_MASK;
4716 scsi_status = mpi_reply->SCSIStatus;
4717
4718 if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
4719 (scsi_status == MPI2_SCSI_STATUS_BUSY ||
4720 scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
4721 scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
4722 ioc_status = MPI2_IOCSTATUS_SUCCESS;
4723 }
4724
4725 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4726 struct sense_info data;
4727 const void *sense_data = mpt3sas_base_get_sense_buffer(ioc,
4728 smid);
4729 u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
4730 le32_to_cpu(mpi_reply->SenseCount));
4731 memcpy(scmd->sense_buffer, sense_data, sz);
4732 _scsih_normalize_sense(scmd->sense_buffer, &data);
4733 /* failure prediction threshold exceeded */
4734 if (data.asc == 0x5D)
4735 _scsih_smart_predicted_fault(ioc,
4736 le16_to_cpu(mpi_reply->DevHandle));
4737 mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304738
Johannes Thumshirn0d667f72016-08-03 15:00:18 +02004739 if ((ioc->logging_level & MPT_DEBUG_REPLY) &&
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304740 ((scmd->sense_buffer[2] == UNIT_ATTENTION) ||
4741 (scmd->sense_buffer[2] == MEDIUM_ERROR) ||
4742 (scmd->sense_buffer[2] == HARDWARE_ERROR)))
4743 _scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304744 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304745 switch (ioc_status) {
4746 case MPI2_IOCSTATUS_BUSY:
4747 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
4748 scmd->result = SAM_STAT_BUSY;
4749 break;
4750
4751 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4752 scmd->result = DID_NO_CONNECT << 16;
4753 break;
4754
4755 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4756 if (sas_device_priv_data->block) {
4757 scmd->result = DID_TRANSPORT_DISRUPTED << 16;
4758 goto out;
4759 }
4760 if (log_info == 0x31110630) {
4761 if (scmd->retries > 2) {
4762 scmd->result = DID_NO_CONNECT << 16;
4763 scsi_device_set_state(scmd->device,
4764 SDEV_OFFLINE);
4765 } else {
4766 scmd->result = DID_SOFT_ERROR << 16;
4767 scmd->device->expecting_cc_ua = 1;
4768 }
4769 break;
Sreekanth Reddy3898f082015-06-30 12:25:00 +05304770 } else if (log_info == VIRTUAL_IO_FAILED_RETRY) {
4771 scmd->result = DID_RESET << 16;
4772 break;
Sreekanth Reddyb40eeea2017-10-10 18:41:18 +05304773 } else if ((scmd->device->channel == RAID_CHANNEL) &&
4774 (scsi_state == (MPI2_SCSI_STATE_TERMINATED |
4775 MPI2_SCSI_STATE_NO_SCSI_STATUS))) {
4776 scmd->result = DID_RESET << 16;
4777 break;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304778 }
4779 scmd->result = DID_SOFT_ERROR << 16;
4780 break;
4781 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4782 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4783 scmd->result = DID_RESET << 16;
4784 break;
4785
4786 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4787 if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
4788 scmd->result = DID_SOFT_ERROR << 16;
4789 else
4790 scmd->result = (DID_OK << 16) | scsi_status;
4791 break;
4792
4793 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4794 scmd->result = (DID_OK << 16) | scsi_status;
4795
4796 if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
4797 break;
4798
4799 if (xfer_cnt < scmd->underflow) {
4800 if (scsi_status == SAM_STAT_BUSY)
4801 scmd->result = SAM_STAT_BUSY;
4802 else
4803 scmd->result = DID_SOFT_ERROR << 16;
4804 } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4805 MPI2_SCSI_STATE_NO_SCSI_STATUS))
4806 scmd->result = DID_SOFT_ERROR << 16;
4807 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4808 scmd->result = DID_RESET << 16;
4809 else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
4810 mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
4811 mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
4812 scmd->result = (DRIVER_SENSE << 24) |
4813 SAM_STAT_CHECK_CONDITION;
4814 scmd->sense_buffer[0] = 0x70;
4815 scmd->sense_buffer[2] = ILLEGAL_REQUEST;
4816 scmd->sense_buffer[12] = 0x20;
4817 scmd->sense_buffer[13] = 0;
4818 }
4819 break;
4820
4821 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4822 scsi_set_resid(scmd, 0);
4823 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4824 case MPI2_IOCSTATUS_SUCCESS:
4825 scmd->result = (DID_OK << 16) | scsi_status;
4826 if (response_code ==
4827 MPI2_SCSITASKMGMT_RSP_INVALID_FRAME ||
4828 (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4829 MPI2_SCSI_STATE_NO_SCSI_STATUS)))
4830 scmd->result = DID_SOFT_ERROR << 16;
4831 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4832 scmd->result = DID_RESET << 16;
4833 break;
4834
4835 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4836 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4837 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4838 _scsih_eedp_error_handling(scmd, ioc_status);
4839 break;
4840
4841 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4842 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4843 case MPI2_IOCSTATUS_INVALID_SGL:
4844 case MPI2_IOCSTATUS_INTERNAL_ERROR:
4845 case MPI2_IOCSTATUS_INVALID_FIELD:
4846 case MPI2_IOCSTATUS_INVALID_STATE:
4847 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4848 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05304849 case MPI2_IOCSTATUS_INSUFFICIENT_POWER:
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304850 default:
4851 scmd->result = DID_SOFT_ERROR << 16;
4852 break;
4853
4854 }
4855
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304856 if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
4857 _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304858
4859 out:
4860
4861 scsi_dma_unmap(scmd);
4862
4863 scmd->scsi_done(scmd);
4864 return 1;
4865}
4866
4867/**
4868 * _scsih_sas_host_refresh - refreshing sas host object contents
4869 * @ioc: per adapter object
4870 * Context: user
4871 *
4872 * During port enable, fw will send topology events for every device. Its
4873 * possible that the handles may change from the previous setting, so this
4874 * code keeping handles updating if changed.
4875 *
4876 * Return nothing.
4877 */
4878static void
4879_scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
4880{
4881 u16 sz;
4882 u16 ioc_status;
4883 int i;
4884 Mpi2ConfigReply_t mpi_reply;
4885 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4886 u16 attached_handle;
4887 u8 link_rate;
4888
4889 dtmprintk(ioc, pr_info(MPT3SAS_FMT
4890 "updating handles for sas_host(0x%016llx)\n",
4891 ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
4892
4893 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
4894 * sizeof(Mpi2SasIOUnit0PhyData_t));
4895 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4896 if (!sas_iounit_pg0) {
4897 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4898 ioc->name, __FILE__, __LINE__, __func__);
4899 return;
4900 }
4901
4902 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4903 sas_iounit_pg0, sz)) != 0)
4904 goto out;
4905 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
4906 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
4907 goto out;
4908 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
4909 link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
4910 if (i == 0)
4911 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4912 PhyData[0].ControllerDevHandle);
4913 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4914 attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
4915 AttachedDevHandle);
4916 if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
4917 link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
4918 mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
4919 attached_handle, i, link_rate);
4920 }
4921 out:
4922 kfree(sas_iounit_pg0);
4923}
4924
4925/**
4926 * _scsih_sas_host_add - create sas host object
4927 * @ioc: per adapter object
4928 *
4929 * Creating host side data object, stored in ioc->sas_hba
4930 *
4931 * Return nothing.
4932 */
4933static void
4934_scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
4935{
4936 int i;
4937 Mpi2ConfigReply_t mpi_reply;
4938 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4939 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
4940 Mpi2SasPhyPage0_t phy_pg0;
4941 Mpi2SasDevicePage0_t sas_device_pg0;
4942 Mpi2SasEnclosurePage0_t enclosure_pg0;
4943 u16 ioc_status;
4944 u16 sz;
4945 u8 device_missing_delay;
Joe Lawrence87aa95d2016-05-25 15:14:28 -04004946 u8 num_phys;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304947
Joe Lawrence87aa95d2016-05-25 15:14:28 -04004948 mpt3sas_config_get_number_hba_phys(ioc, &num_phys);
4949 if (!num_phys) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304950 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4951 ioc->name, __FILE__, __LINE__, __func__);
4952 return;
4953 }
Joe Lawrence87aa95d2016-05-25 15:14:28 -04004954 ioc->sas_hba.phy = kcalloc(num_phys,
4955 sizeof(struct _sas_phy), GFP_KERNEL);
4956 if (!ioc->sas_hba.phy) {
4957 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4958 ioc->name, __FILE__, __LINE__, __func__);
4959 goto out;
4960 }
4961 ioc->sas_hba.num_phys = num_phys;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304962
4963 /* sas_iounit page 0 */
4964 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
4965 sizeof(Mpi2SasIOUnit0PhyData_t));
4966 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4967 if (!sas_iounit_pg0) {
4968 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4969 ioc->name, __FILE__, __LINE__, __func__);
4970 return;
4971 }
4972 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4973 sas_iounit_pg0, sz))) {
4974 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4975 ioc->name, __FILE__, __LINE__, __func__);
4976 goto out;
4977 }
4978 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4979 MPI2_IOCSTATUS_MASK;
4980 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4981 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4982 ioc->name, __FILE__, __LINE__, __func__);
4983 goto out;
4984 }
4985
4986 /* sas_iounit page 1 */
4987 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
4988 sizeof(Mpi2SasIOUnit1PhyData_t));
4989 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
4990 if (!sas_iounit_pg1) {
4991 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4992 ioc->name, __FILE__, __LINE__, __func__);
4993 goto out;
4994 }
4995 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
4996 sas_iounit_pg1, sz))) {
4997 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4998 ioc->name, __FILE__, __LINE__, __func__);
4999 goto out;
5000 }
5001 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5002 MPI2_IOCSTATUS_MASK;
5003 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5004 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5005 ioc->name, __FILE__, __LINE__, __func__);
5006 goto out;
5007 }
5008
5009 ioc->io_missing_delay =
5010 sas_iounit_pg1->IODeviceMissingDelay;
5011 device_missing_delay =
5012 sas_iounit_pg1->ReportDeviceMissingDelay;
5013 if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
5014 ioc->device_missing_delay = (device_missing_delay &
5015 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
5016 else
5017 ioc->device_missing_delay = device_missing_delay &
5018 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
5019
5020 ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305021 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
5022 if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
5023 i))) {
5024 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5025 ioc->name, __FILE__, __LINE__, __func__);
5026 goto out;
5027 }
5028 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5029 MPI2_IOCSTATUS_MASK;
5030 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5031 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5032 ioc->name, __FILE__, __LINE__, __func__);
5033 goto out;
5034 }
5035
5036 if (i == 0)
5037 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
5038 PhyData[0].ControllerDevHandle);
5039 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
5040 ioc->sas_hba.phy[i].phy_id = i;
5041 mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
5042 phy_pg0, ioc->sas_hba.parent_dev);
5043 }
5044 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5045 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
5046 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5047 ioc->name, __FILE__, __LINE__, __func__);
5048 goto out;
5049 }
5050 ioc->sas_hba.enclosure_handle =
5051 le16_to_cpu(sas_device_pg0.EnclosureHandle);
5052 ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
5053 pr_info(MPT3SAS_FMT
5054 "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
5055 ioc->name, ioc->sas_hba.handle,
5056 (unsigned long long) ioc->sas_hba.sas_address,
5057 ioc->sas_hba.num_phys) ;
5058
5059 if (ioc->sas_hba.enclosure_handle) {
5060 if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
5061 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
5062 ioc->sas_hba.enclosure_handle)))
5063 ioc->sas_hba.enclosure_logical_id =
5064 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
5065 }
5066
5067 out:
5068 kfree(sas_iounit_pg1);
5069 kfree(sas_iounit_pg0);
5070}
5071
5072/**
5073 * _scsih_expander_add - creating expander object
5074 * @ioc: per adapter object
5075 * @handle: expander handle
5076 *
5077 * Creating expander object, stored in ioc->sas_expander_list.
5078 *
5079 * Return 0 for success, else error.
5080 */
5081static int
5082_scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
5083{
5084 struct _sas_node *sas_expander;
5085 Mpi2ConfigReply_t mpi_reply;
5086 Mpi2ExpanderPage0_t expander_pg0;
5087 Mpi2ExpanderPage1_t expander_pg1;
5088 Mpi2SasEnclosurePage0_t enclosure_pg0;
5089 u32 ioc_status;
5090 u16 parent_handle;
5091 u64 sas_address, sas_address_parent = 0;
5092 int i;
5093 unsigned long flags;
5094 struct _sas_port *mpt3sas_port = NULL;
5095
5096 int rc = 0;
5097
5098 if (!handle)
5099 return -1;
5100
5101 if (ioc->shost_recovery || ioc->pci_error_recovery)
5102 return -1;
5103
5104 if ((mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
5105 MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
5106 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5107 ioc->name, __FILE__, __LINE__, __func__);
5108 return -1;
5109 }
5110
5111 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5112 MPI2_IOCSTATUS_MASK;
5113 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5114 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5115 ioc->name, __FILE__, __LINE__, __func__);
5116 return -1;
5117 }
5118
5119 /* handle out of order topology events */
5120 parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
5121 if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
5122 != 0) {
5123 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5124 ioc->name, __FILE__, __LINE__, __func__);
5125 return -1;
5126 }
5127 if (sas_address_parent != ioc->sas_hba.sas_address) {
5128 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5129 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
5130 sas_address_parent);
5131 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5132 if (!sas_expander) {
5133 rc = _scsih_expander_add(ioc, parent_handle);
5134 if (rc != 0)
5135 return rc;
5136 }
5137 }
5138
5139 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5140 sas_address = le64_to_cpu(expander_pg0.SASAddress);
5141 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
5142 sas_address);
5143 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5144
5145 if (sas_expander)
5146 return 0;
5147
5148 sas_expander = kzalloc(sizeof(struct _sas_node),
5149 GFP_KERNEL);
5150 if (!sas_expander) {
5151 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5152 ioc->name, __FILE__, __LINE__, __func__);
5153 return -1;
5154 }
5155
5156 sas_expander->handle = handle;
5157 sas_expander->num_phys = expander_pg0.NumPhys;
5158 sas_expander->sas_address_parent = sas_address_parent;
5159 sas_expander->sas_address = sas_address;
5160
5161 pr_info(MPT3SAS_FMT "expander_add: handle(0x%04x)," \
5162 " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
5163 handle, parent_handle, (unsigned long long)
5164 sas_expander->sas_address, sas_expander->num_phys);
5165
5166 if (!sas_expander->num_phys)
5167 goto out_fail;
5168 sas_expander->phy = kcalloc(sas_expander->num_phys,
5169 sizeof(struct _sas_phy), GFP_KERNEL);
5170 if (!sas_expander->phy) {
5171 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5172 ioc->name, __FILE__, __LINE__, __func__);
5173 rc = -1;
5174 goto out_fail;
5175 }
5176
5177 INIT_LIST_HEAD(&sas_expander->sas_port_list);
5178 mpt3sas_port = mpt3sas_transport_port_add(ioc, handle,
5179 sas_address_parent);
5180 if (!mpt3sas_port) {
5181 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5182 ioc->name, __FILE__, __LINE__, __func__);
5183 rc = -1;
5184 goto out_fail;
5185 }
5186 sas_expander->parent_dev = &mpt3sas_port->rphy->dev;
5187
5188 for (i = 0 ; i < sas_expander->num_phys ; i++) {
5189 if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
5190 &expander_pg1, i, handle))) {
5191 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5192 ioc->name, __FILE__, __LINE__, __func__);
5193 rc = -1;
5194 goto out_fail;
5195 }
5196 sas_expander->phy[i].handle = handle;
5197 sas_expander->phy[i].phy_id = i;
5198
5199 if ((mpt3sas_transport_add_expander_phy(ioc,
5200 &sas_expander->phy[i], expander_pg1,
5201 sas_expander->parent_dev))) {
5202 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5203 ioc->name, __FILE__, __LINE__, __func__);
5204 rc = -1;
5205 goto out_fail;
5206 }
5207 }
5208
5209 if (sas_expander->enclosure_handle) {
5210 if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
5211 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
5212 sas_expander->enclosure_handle)))
5213 sas_expander->enclosure_logical_id =
5214 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
5215 }
5216
5217 _scsih_expander_node_add(ioc, sas_expander);
5218 return 0;
5219
5220 out_fail:
5221
5222 if (mpt3sas_port)
5223 mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
5224 sas_address_parent);
5225 kfree(sas_expander);
5226 return rc;
5227}
5228
5229/**
5230 * mpt3sas_expander_remove - removing expander object
5231 * @ioc: per adapter object
5232 * @sas_address: expander sas_address
5233 *
5234 * Return nothing.
5235 */
5236void
5237mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
5238{
5239 struct _sas_node *sas_expander;
5240 unsigned long flags;
5241
5242 if (ioc->shost_recovery)
5243 return;
5244
5245 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5246 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
5247 sas_address);
5248 if (sas_expander)
5249 list_del(&sas_expander->list);
5250 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5251 if (sas_expander)
5252 _scsih_expander_node_remove(ioc, sas_expander);
5253}
5254
5255/**
5256 * _scsih_done - internal SCSI_IO callback handler.
5257 * @ioc: per adapter object
5258 * @smid: system request message index
5259 * @msix_index: MSIX table index supplied by the OS
5260 * @reply: reply message frame(lower 32bit addr)
5261 *
5262 * Callback handler when sending internal generated SCSI_IO.
5263 * The callback index passed is `ioc->scsih_cb_idx`
5264 *
5265 * Return 1 meaning mf should be freed from _base_interrupt
5266 * 0 means the mf is freed from this function.
5267 */
5268static u8
5269_scsih_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
5270{
5271 MPI2DefaultReply_t *mpi_reply;
5272
5273 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
5274 if (ioc->scsih_cmds.status == MPT3_CMD_NOT_USED)
5275 return 1;
5276 if (ioc->scsih_cmds.smid != smid)
5277 return 1;
5278 ioc->scsih_cmds.status |= MPT3_CMD_COMPLETE;
5279 if (mpi_reply) {
5280 memcpy(ioc->scsih_cmds.reply, mpi_reply,
5281 mpi_reply->MsgLength*4);
5282 ioc->scsih_cmds.status |= MPT3_CMD_REPLY_VALID;
5283 }
5284 ioc->scsih_cmds.status &= ~MPT3_CMD_PENDING;
5285 complete(&ioc->scsih_cmds.done);
5286 return 1;
5287}
5288
5289
5290
5291
5292#define MPT3_MAX_LUNS (255)
5293
5294
5295/**
5296 * _scsih_check_access_status - check access flags
5297 * @ioc: per adapter object
5298 * @sas_address: sas address
5299 * @handle: sas device handle
5300 * @access_flags: errors returned during discovery of the device
5301 *
5302 * Return 0 for success, else failure
5303 */
5304static u8
5305_scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
5306 u16 handle, u8 access_status)
5307{
5308 u8 rc = 1;
5309 char *desc = NULL;
5310
5311 switch (access_status) {
5312 case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS:
5313 case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION:
5314 rc = 0;
5315 break;
5316 case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED:
5317 desc = "sata capability failed";
5318 break;
5319 case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT:
5320 desc = "sata affiliation conflict";
5321 break;
5322 case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE:
5323 desc = "route not addressable";
5324 break;
5325 case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE:
5326 desc = "smp error not addressable";
5327 break;
5328 case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED:
5329 desc = "device blocked";
5330 break;
5331 case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED:
5332 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN:
5333 case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT:
5334 case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG:
5335 case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION:
5336 case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER:
5337 case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN:
5338 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN:
5339 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN:
5340 case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION:
5341 case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE:
5342 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX:
5343 desc = "sata initialization failed";
5344 break;
5345 default:
5346 desc = "unknown";
5347 break;
5348 }
5349
5350 if (!rc)
5351 return 0;
5352
5353 pr_err(MPT3SAS_FMT
5354 "discovery errors(%s): sas_address(0x%016llx), handle(0x%04x)\n",
5355 ioc->name, desc, (unsigned long long)sas_address, handle);
5356 return rc;
5357}
5358
5359/**
5360 * _scsih_check_device - checking device responsiveness
5361 * @ioc: per adapter object
5362 * @parent_sas_address: sas address of parent expander or sas host
5363 * @handle: attached device handle
5364 * @phy_numberv: phy number
5365 * @link_rate: new link rate
5366 *
5367 * Returns nothing.
5368 */
5369static void
5370_scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
5371 u64 parent_sas_address, u16 handle, u8 phy_number, u8 link_rate)
5372{
5373 Mpi2ConfigReply_t mpi_reply;
5374 Mpi2SasDevicePage0_t sas_device_pg0;
5375 struct _sas_device *sas_device;
5376 u32 ioc_status;
5377 unsigned long flags;
5378 u64 sas_address;
5379 struct scsi_target *starget;
5380 struct MPT3SAS_TARGET *sas_target_priv_data;
5381 u32 device_info;
5382
5383
5384 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5385 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
5386 return;
5387
5388 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
5389 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
5390 return;
5391
5392 /* wide port handling ~ we need only handle device once for the phy that
5393 * is matched in sas device page zero
5394 */
5395 if (phy_number != sas_device_pg0.PhyNum)
5396 return;
5397
5398 /* check if this is end device */
5399 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5400 if (!(_scsih_is_end_device(device_info)))
5401 return;
5402
5403 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5404 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305405 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305406 sas_address);
5407
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305408 if (!sas_device)
5409 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305410
5411 if (unlikely(sas_device->handle != handle)) {
5412 starget = sas_device->starget;
5413 sas_target_priv_data = starget->hostdata;
5414 starget_printk(KERN_INFO, starget,
5415 "handle changed from(0x%04x) to (0x%04x)!!!\n",
5416 sas_device->handle, handle);
5417 sas_target_priv_data->handle = handle;
5418 sas_device->handle = handle;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305419 if (sas_device_pg0.Flags &
5420 MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
5421 sas_device->enclosure_level =
5422 le16_to_cpu(sas_device_pg0.EnclosureLevel);
Calvin Owens310c8e42016-07-27 21:45:51 -07005423 memcpy(sas_device->connector_name,
5424 sas_device_pg0.ConnectorName, 4);
5425 sas_device->connector_name[4] = '\0';
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305426 } else {
5427 sas_device->enclosure_level = 0;
5428 sas_device->connector_name[0] = '\0';
5429 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305430 }
5431
5432 /* check if device is present */
5433 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5434 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5435 pr_err(MPT3SAS_FMT
5436 "device is not present handle(0x%04x), flags!!!\n",
5437 ioc->name, handle);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305438 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305439 }
5440
5441 /* check if there were any issues with discovery */
5442 if (_scsih_check_access_status(ioc, sas_address, handle,
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305443 sas_device_pg0.AccessStatus))
5444 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305445
5446 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5447 _scsih_ublock_io_device(ioc, sas_address);
5448
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305449 if (sas_device)
5450 sas_device_put(sas_device);
5451 return;
5452
5453out_unlock:
5454 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5455 if (sas_device)
5456 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305457}
5458
5459/**
5460 * _scsih_add_device - creating sas device object
5461 * @ioc: per adapter object
5462 * @handle: sas device handle
5463 * @phy_num: phy number end device attached to
5464 * @is_pd: is this hidden raid component
5465 *
5466 * Creating end device object, stored in ioc->sas_device_list.
5467 *
5468 * Returns 0 for success, non-zero for failure.
5469 */
5470static int
5471_scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
5472 u8 is_pd)
5473{
5474 Mpi2ConfigReply_t mpi_reply;
5475 Mpi2SasDevicePage0_t sas_device_pg0;
5476 Mpi2SasEnclosurePage0_t enclosure_pg0;
5477 struct _sas_device *sas_device;
5478 u32 ioc_status;
5479 u64 sas_address;
5480 u32 device_info;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305481
5482 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5483 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
5484 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5485 ioc->name, __FILE__, __LINE__, __func__);
5486 return -1;
5487 }
5488
5489 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5490 MPI2_IOCSTATUS_MASK;
5491 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5492 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5493 ioc->name, __FILE__, __LINE__, __func__);
5494 return -1;
5495 }
5496
5497 /* check if this is end device */
5498 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5499 if (!(_scsih_is_end_device(device_info)))
5500 return -1;
5501 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
5502
5503 /* check if device is present */
5504 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5505 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5506 pr_err(MPT3SAS_FMT "device is not present handle(0x04%x)!!!\n",
5507 ioc->name, handle);
5508 return -1;
5509 }
5510
5511 /* check if there were any issues with discovery */
5512 if (_scsih_check_access_status(ioc, sas_address, handle,
5513 sas_device_pg0.AccessStatus))
5514 return -1;
5515
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305516 sas_device = mpt3sas_get_sdev_by_addr(ioc,
5517 sas_address);
5518 if (sas_device) {
5519 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305520 return -1;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305521 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305522
5523 sas_device = kzalloc(sizeof(struct _sas_device),
5524 GFP_KERNEL);
5525 if (!sas_device) {
5526 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5527 ioc->name, __FILE__, __LINE__, __func__);
5528 return 0;
5529 }
5530
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305531 kref_init(&sas_device->refcount);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305532 sas_device->handle = handle;
5533 if (_scsih_get_sas_address(ioc,
5534 le16_to_cpu(sas_device_pg0.ParentDevHandle),
5535 &sas_device->sas_address_parent) != 0)
5536 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5537 ioc->name, __FILE__, __LINE__, __func__);
5538 sas_device->enclosure_handle =
5539 le16_to_cpu(sas_device_pg0.EnclosureHandle);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305540 if (sas_device->enclosure_handle != 0)
5541 sas_device->slot =
5542 le16_to_cpu(sas_device_pg0.Slot);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305543 sas_device->device_info = device_info;
5544 sas_device->sas_address = sas_address;
5545 sas_device->phy = sas_device_pg0.PhyNum;
5546 sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) &
5547 MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
5548
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305549 if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
5550 sas_device->enclosure_level =
5551 le16_to_cpu(sas_device_pg0.EnclosureLevel);
Calvin Owens310c8e42016-07-27 21:45:51 -07005552 memcpy(sas_device->connector_name,
5553 sas_device_pg0.ConnectorName, 4);
5554 sas_device->connector_name[4] = '\0';
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305555 } else {
5556 sas_device->enclosure_level = 0;
5557 sas_device->connector_name[0] = '\0';
5558 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305559 /* get enclosure_logical_id */
5560 if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0(
5561 ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
5562 sas_device->enclosure_handle)))
5563 sas_device->enclosure_logical_id =
5564 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
5565
5566 /* get device name */
5567 sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
5568
5569 if (ioc->wait_for_discovery_to_complete)
5570 _scsih_sas_device_init_add(ioc, sas_device);
5571 else
5572 _scsih_sas_device_add(ioc, sas_device);
5573
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305574 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305575 return 0;
5576}
5577
5578/**
5579 * _scsih_remove_device - removing sas device object
5580 * @ioc: per adapter object
5581 * @sas_device_delete: the sas_device object
5582 *
5583 * Return nothing.
5584 */
5585static void
5586_scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
5587 struct _sas_device *sas_device)
5588{
5589 struct MPT3SAS_TARGET *sas_target_priv_data;
5590
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05305591 if ((ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) &&
5592 (sas_device->pfa_led_on)) {
5593 _scsih_turn_off_pfa_led(ioc, sas_device);
5594 sas_device->pfa_led_on = 0;
5595 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305596 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5597 "%s: enter: handle(0x%04x), sas_addr(0x%016llx)\n",
5598 ioc->name, __func__,
5599 sas_device->handle, (unsigned long long)
5600 sas_device->sas_address));
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305601 if (sas_device->enclosure_handle != 0)
5602 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5603 "%s: enter: enclosure logical id(0x%016llx), slot(%d)\n",
5604 ioc->name, __func__,
5605 (unsigned long long)sas_device->enclosure_logical_id,
5606 sas_device->slot));
5607 if (sas_device->connector_name[0] != '\0')
5608 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5609 "%s: enter: enclosure level(0x%04x), connector name( %s)\n",
5610 ioc->name, __func__,
5611 sas_device->enclosure_level,
5612 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305613
5614 if (sas_device->starget && sas_device->starget->hostdata) {
5615 sas_target_priv_data = sas_device->starget->hostdata;
5616 sas_target_priv_data->deleted = 1;
5617 _scsih_ublock_io_device(ioc, sas_device->sas_address);
5618 sas_target_priv_data->handle =
5619 MPT3SAS_INVALID_DEVICE_HANDLE;
5620 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05305621
5622 if (!ioc->hide_drives)
5623 mpt3sas_transport_port_remove(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305624 sas_device->sas_address,
5625 sas_device->sas_address_parent);
5626
5627 pr_info(MPT3SAS_FMT
5628 "removing handle(0x%04x), sas_addr(0x%016llx)\n",
5629 ioc->name, sas_device->handle,
5630 (unsigned long long) sas_device->sas_address);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305631 if (sas_device->enclosure_handle != 0)
5632 pr_info(MPT3SAS_FMT
5633 "removing : enclosure logical id(0x%016llx), slot(%d)\n",
5634 ioc->name,
5635 (unsigned long long)sas_device->enclosure_logical_id,
5636 sas_device->slot);
5637 if (sas_device->connector_name[0] != '\0')
5638 pr_info(MPT3SAS_FMT
5639 "removing enclosure level(0x%04x), connector name( %s)\n",
5640 ioc->name, sas_device->enclosure_level,
5641 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305642
5643 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5644 "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n",
5645 ioc->name, __func__,
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305646 sas_device->handle, (unsigned long long)
5647 sas_device->sas_address));
5648 if (sas_device->enclosure_handle != 0)
5649 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5650 "%s: exit: enclosure logical id(0x%016llx), slot(%d)\n",
5651 ioc->name, __func__,
5652 (unsigned long long)sas_device->enclosure_logical_id,
5653 sas_device->slot));
5654 if (sas_device->connector_name[0] != '\0')
5655 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5656 "%s: exit: enclosure level(0x%04x), connector name(%s)\n",
5657 ioc->name, __func__, sas_device->enclosure_level,
5658 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305659}
5660
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305661/**
5662 * _scsih_sas_topology_change_event_debug - debug for topology event
5663 * @ioc: per adapter object
5664 * @event_data: event data payload
5665 * Context: user.
5666 */
5667static void
5668_scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5669 Mpi2EventDataSasTopologyChangeList_t *event_data)
5670{
5671 int i;
5672 u16 handle;
5673 u16 reason_code;
5674 u8 phy_number;
5675 char *status_str = NULL;
5676 u8 link_rate, prev_link_rate;
5677
5678 switch (event_data->ExpStatus) {
5679 case MPI2_EVENT_SAS_TOPO_ES_ADDED:
5680 status_str = "add";
5681 break;
5682 case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
5683 status_str = "remove";
5684 break;
5685 case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
5686 case 0:
5687 status_str = "responding";
5688 break;
5689 case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
5690 status_str = "remove delay";
5691 break;
5692 default:
5693 status_str = "unknown status";
5694 break;
5695 }
5696 pr_info(MPT3SAS_FMT "sas topology change: (%s)\n",
5697 ioc->name, status_str);
5698 pr_info("\thandle(0x%04x), enclosure_handle(0x%04x) " \
5699 "start_phy(%02d), count(%d)\n",
5700 le16_to_cpu(event_data->ExpanderDevHandle),
5701 le16_to_cpu(event_data->EnclosureHandle),
5702 event_data->StartPhyNum, event_data->NumEntries);
5703 for (i = 0; i < event_data->NumEntries; i++) {
5704 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5705 if (!handle)
5706 continue;
5707 phy_number = event_data->StartPhyNum + i;
5708 reason_code = event_data->PHY[i].PhyStatus &
5709 MPI2_EVENT_SAS_TOPO_RC_MASK;
5710 switch (reason_code) {
5711 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
5712 status_str = "target add";
5713 break;
5714 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
5715 status_str = "target remove";
5716 break;
5717 case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
5718 status_str = "delay target remove";
5719 break;
5720 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
5721 status_str = "link rate change";
5722 break;
5723 case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
5724 status_str = "target responding";
5725 break;
5726 default:
5727 status_str = "unknown";
5728 break;
5729 }
5730 link_rate = event_data->PHY[i].LinkRate >> 4;
5731 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
5732 pr_info("\tphy(%02d), attached_handle(0x%04x): %s:" \
5733 " link rate: new(0x%02x), old(0x%02x)\n", phy_number,
5734 handle, status_str, link_rate, prev_link_rate);
5735
5736 }
5737}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305738
5739/**
5740 * _scsih_sas_topology_change_event - handle topology changes
5741 * @ioc: per adapter object
5742 * @fw_event: The fw_event_work object
5743 * Context: user.
5744 *
5745 */
5746static int
5747_scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
5748 struct fw_event_work *fw_event)
5749{
5750 int i;
5751 u16 parent_handle, handle;
5752 u16 reason_code;
5753 u8 phy_number, max_phys;
5754 struct _sas_node *sas_expander;
5755 u64 sas_address;
5756 unsigned long flags;
5757 u8 link_rate, prev_link_rate;
Joe Lawrence35b62362014-06-25 17:05:34 -04005758 Mpi2EventDataSasTopologyChangeList_t *event_data =
5759 (Mpi2EventDataSasTopologyChangeList_t *)
5760 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305761
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305762 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5763 _scsih_sas_topology_change_event_debug(ioc, event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305764
5765 if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
5766 return 0;
5767
5768 if (!ioc->sas_hba.num_phys)
5769 _scsih_sas_host_add(ioc);
5770 else
5771 _scsih_sas_host_refresh(ioc);
5772
5773 if (fw_event->ignore) {
5774 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5775 "ignoring expander event\n", ioc->name));
5776 return 0;
5777 }
5778
5779 parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
5780
5781 /* handle expander add */
5782 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
5783 if (_scsih_expander_add(ioc, parent_handle) != 0)
5784 return 0;
5785
5786 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5787 sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
5788 parent_handle);
5789 if (sas_expander) {
5790 sas_address = sas_expander->sas_address;
5791 max_phys = sas_expander->num_phys;
5792 } else if (parent_handle < ioc->sas_hba.num_phys) {
5793 sas_address = ioc->sas_hba.sas_address;
5794 max_phys = ioc->sas_hba.num_phys;
5795 } else {
5796 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5797 return 0;
5798 }
5799 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5800
5801 /* handle siblings events */
5802 for (i = 0; i < event_data->NumEntries; i++) {
5803 if (fw_event->ignore) {
5804 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5805 "ignoring expander event\n", ioc->name));
5806 return 0;
5807 }
5808 if (ioc->remove_host || ioc->pci_error_recovery)
5809 return 0;
5810 phy_number = event_data->StartPhyNum + i;
5811 if (phy_number >= max_phys)
5812 continue;
5813 reason_code = event_data->PHY[i].PhyStatus &
5814 MPI2_EVENT_SAS_TOPO_RC_MASK;
5815 if ((event_data->PHY[i].PhyStatus &
5816 MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
5817 MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
5818 continue;
5819 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5820 if (!handle)
5821 continue;
5822 link_rate = event_data->PHY[i].LinkRate >> 4;
5823 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
5824 switch (reason_code) {
5825 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
5826
5827 if (ioc->shost_recovery)
5828 break;
5829
5830 if (link_rate == prev_link_rate)
5831 break;
5832
5833 mpt3sas_transport_update_links(ioc, sas_address,
5834 handle, phy_number, link_rate);
5835
5836 if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
5837 break;
5838
5839 _scsih_check_device(ioc, sas_address, handle,
5840 phy_number, link_rate);
5841
5842
5843 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
5844
5845 if (ioc->shost_recovery)
5846 break;
5847
5848 mpt3sas_transport_update_links(ioc, sas_address,
5849 handle, phy_number, link_rate);
5850
5851 _scsih_add_device(ioc, handle, phy_number, 0);
5852
5853 break;
5854 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
5855
5856 _scsih_device_remove_by_handle(ioc, handle);
5857 break;
5858 }
5859 }
5860
5861 /* handle expander removal */
5862 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
5863 sas_expander)
5864 mpt3sas_expander_remove(ioc, sas_address);
5865
5866 return 0;
5867}
5868
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305869/**
5870 * _scsih_sas_device_status_change_event_debug - debug for device event
5871 * @event_data: event data payload
5872 * Context: user.
5873 *
5874 * Return nothing.
5875 */
5876static void
5877_scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5878 Mpi2EventDataSasDeviceStatusChange_t *event_data)
5879{
5880 char *reason_str = NULL;
5881
5882 switch (event_data->ReasonCode) {
5883 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5884 reason_str = "smart data";
5885 break;
5886 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
5887 reason_str = "unsupported device discovered";
5888 break;
5889 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
5890 reason_str = "internal device reset";
5891 break;
5892 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
5893 reason_str = "internal task abort";
5894 break;
5895 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
5896 reason_str = "internal task abort set";
5897 break;
5898 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
5899 reason_str = "internal clear task set";
5900 break;
5901 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
5902 reason_str = "internal query task";
5903 break;
5904 case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
5905 reason_str = "sata init failure";
5906 break;
5907 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
5908 reason_str = "internal device reset complete";
5909 break;
5910 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
5911 reason_str = "internal task abort complete";
5912 break;
5913 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
5914 reason_str = "internal async notification";
5915 break;
5916 case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY:
5917 reason_str = "expander reduced functionality";
5918 break;
5919 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY:
5920 reason_str = "expander reduced functionality complete";
5921 break;
5922 default:
5923 reason_str = "unknown reason";
5924 break;
5925 }
5926 pr_info(MPT3SAS_FMT "device status change: (%s)\n"
5927 "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
5928 ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
5929 (unsigned long long)le64_to_cpu(event_data->SASAddress),
5930 le16_to_cpu(event_data->TaskTag));
5931 if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
5932 pr_info(MPT3SAS_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
5933 event_data->ASC, event_data->ASCQ);
5934 pr_info("\n");
5935}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305936
5937/**
5938 * _scsih_sas_device_status_change_event - handle device status change
5939 * @ioc: per adapter object
5940 * @fw_event: The fw_event_work object
5941 * Context: user.
5942 *
5943 * Return nothing.
5944 */
5945static void
5946_scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
5947 struct fw_event_work *fw_event)
5948{
5949 struct MPT3SAS_TARGET *target_priv_data;
5950 struct _sas_device *sas_device;
5951 u64 sas_address;
5952 unsigned long flags;
5953 Mpi2EventDataSasDeviceStatusChange_t *event_data =
Joe Lawrence35b62362014-06-25 17:05:34 -04005954 (Mpi2EventDataSasDeviceStatusChange_t *)
5955 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305956
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305957 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5958 _scsih_sas_device_status_change_event_debug(ioc,
5959 event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305960
5961 /* In MPI Revision K (0xC), the internal device reset complete was
5962 * implemented, so avoid setting tm_busy flag for older firmware.
5963 */
5964 if ((ioc->facts.HeaderVersion >> 8) < 0xC)
5965 return;
5966
5967 if (event_data->ReasonCode !=
5968 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
5969 event_data->ReasonCode !=
5970 MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)
5971 return;
5972
5973 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5974 sas_address = le64_to_cpu(event_data->SASAddress);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305975 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305976 sas_address);
5977
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305978 if (!sas_device || !sas_device->starget)
5979 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305980
5981 target_priv_data = sas_device->starget->hostdata;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305982 if (!target_priv_data)
5983 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305984
5985 if (event_data->ReasonCode ==
5986 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
5987 target_priv_data->tm_busy = 1;
5988 else
5989 target_priv_data->tm_busy = 0;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305990
5991out:
5992 if (sas_device)
5993 sas_device_put(sas_device);
5994
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305995 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305996
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305997}
5998
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305999/**
6000 * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure
6001 * event
6002 * @ioc: per adapter object
6003 * @event_data: event data payload
6004 * Context: user.
6005 *
6006 * Return nothing.
6007 */
6008static void
6009_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
6010 Mpi2EventDataSasEnclDevStatusChange_t *event_data)
6011{
6012 char *reason_str = NULL;
6013
6014 switch (event_data->ReasonCode) {
6015 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
6016 reason_str = "enclosure add";
6017 break;
6018 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
6019 reason_str = "enclosure remove";
6020 break;
6021 default:
6022 reason_str = "unknown reason";
6023 break;
6024 }
6025
6026 pr_info(MPT3SAS_FMT "enclosure status change: (%s)\n"
6027 "\thandle(0x%04x), enclosure logical id(0x%016llx)"
6028 " number slots(%d)\n", ioc->name, reason_str,
6029 le16_to_cpu(event_data->EnclosureHandle),
6030 (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
6031 le16_to_cpu(event_data->StartSlot));
6032}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306033
6034/**
6035 * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
6036 * @ioc: per adapter object
6037 * @fw_event: The fw_event_work object
6038 * Context: user.
6039 *
6040 * Return nothing.
6041 */
6042static void
6043_scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
6044 struct fw_event_work *fw_event)
6045{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306046 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
6047 _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
Joe Lawrence35b62362014-06-25 17:05:34 -04006048 (Mpi2EventDataSasEnclDevStatusChange_t *)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306049 fw_event->event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306050}
6051
6052/**
6053 * _scsih_sas_broadcast_primitive_event - handle broadcast events
6054 * @ioc: per adapter object
6055 * @fw_event: The fw_event_work object
6056 * Context: user.
6057 *
6058 * Return nothing.
6059 */
6060static void
6061_scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
6062 struct fw_event_work *fw_event)
6063{
6064 struct scsi_cmnd *scmd;
6065 struct scsi_device *sdev;
6066 u16 smid, handle;
6067 u32 lun;
6068 struct MPT3SAS_DEVICE *sas_device_priv_data;
6069 u32 termination_count;
6070 u32 query_count;
6071 Mpi2SCSITaskManagementReply_t *mpi_reply;
Joe Lawrence35b62362014-06-25 17:05:34 -04006072 Mpi2EventDataSasBroadcastPrimitive_t *event_data =
6073 (Mpi2EventDataSasBroadcastPrimitive_t *)
6074 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306075 u16 ioc_status;
6076 unsigned long flags;
6077 int r;
6078 u8 max_retries = 0;
6079 u8 task_abort_retries;
6080
6081 mutex_lock(&ioc->tm_cmds.mutex);
6082 pr_info(MPT3SAS_FMT
6083 "%s: enter: phy number(%d), width(%d)\n",
6084 ioc->name, __func__, event_data->PhyNum,
6085 event_data->PortWidth);
6086
6087 _scsih_block_io_all_device(ioc);
6088
6089 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6090 mpi_reply = ioc->tm_cmds.reply;
6091 broadcast_aen_retry:
6092
6093 /* sanity checks for retrying this loop */
6094 if (max_retries++ == 5) {
6095 dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: giving up\n",
6096 ioc->name, __func__));
6097 goto out;
6098 } else if (max_retries > 1)
6099 dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: %d retry\n",
6100 ioc->name, __func__, max_retries - 1));
6101
6102 termination_count = 0;
6103 query_count = 0;
6104 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
6105 if (ioc->shost_recovery)
6106 goto out;
6107 scmd = _scsih_scsi_lookup_get(ioc, smid);
6108 if (!scmd)
6109 continue;
6110 sdev = scmd->device;
6111 sas_device_priv_data = sdev->hostdata;
6112 if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
6113 continue;
6114 /* skip hidden raid components */
6115 if (sas_device_priv_data->sas_target->flags &
6116 MPT_TARGET_FLAGS_RAID_COMPONENT)
6117 continue;
6118 /* skip volumes */
6119 if (sas_device_priv_data->sas_target->flags &
6120 MPT_TARGET_FLAGS_VOLUME)
6121 continue;
6122
6123 handle = sas_device_priv_data->sas_target->handle;
6124 lun = sas_device_priv_data->lun;
6125 query_count++;
6126
6127 if (ioc->shost_recovery)
6128 goto out;
6129
6130 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
6131 r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
Calvin Owens96902832016-07-28 21:38:20 -07006132 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306133 if (r == FAILED) {
6134 sdev_printk(KERN_WARNING, sdev,
6135 "mpt3sas_scsih_issue_tm: FAILED when sending "
6136 "QUERY_TASK: scmd(%p)\n", scmd);
6137 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6138 goto broadcast_aen_retry;
6139 }
6140 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
6141 & MPI2_IOCSTATUS_MASK;
6142 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6143 sdev_printk(KERN_WARNING, sdev,
6144 "query task: FAILED with IOCSTATUS(0x%04x), scmd(%p)\n",
6145 ioc_status, scmd);
6146 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6147 goto broadcast_aen_retry;
6148 }
6149
6150 /* see if IO is still owned by IOC and target */
6151 if (mpi_reply->ResponseCode ==
6152 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
6153 mpi_reply->ResponseCode ==
6154 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
6155 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6156 continue;
6157 }
6158 task_abort_retries = 0;
6159 tm_retry:
6160 if (task_abort_retries++ == 60) {
6161 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6162 "%s: ABORT_TASK: giving up\n", ioc->name,
6163 __func__));
6164 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6165 goto broadcast_aen_retry;
6166 }
6167
6168 if (ioc->shost_recovery)
6169 goto out_no_lock;
6170
6171 r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
Calvin Owens96902832016-07-28 21:38:20 -07006172 sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid,
6173 30);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306174 if (r == FAILED) {
6175 sdev_printk(KERN_WARNING, sdev,
6176 "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : "
6177 "scmd(%p)\n", scmd);
6178 goto tm_retry;
6179 }
6180
6181 if (task_abort_retries > 1)
6182 sdev_printk(KERN_WARNING, sdev,
6183 "mpt3sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
6184 " scmd(%p)\n",
6185 task_abort_retries - 1, scmd);
6186
6187 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
6188 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
6189 }
6190
6191 if (ioc->broadcast_aen_pending) {
6192 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6193 "%s: loop back due to pending AEN\n",
6194 ioc->name, __func__));
6195 ioc->broadcast_aen_pending = 0;
6196 goto broadcast_aen_retry;
6197 }
6198
6199 out:
6200 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
6201 out_no_lock:
6202
6203 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6204 "%s - exit, query_count = %d termination_count = %d\n",
6205 ioc->name, __func__, query_count, termination_count));
6206
6207 ioc->broadcast_aen_busy = 0;
6208 if (!ioc->shost_recovery)
6209 _scsih_ublock_io_all_device(ioc);
6210 mutex_unlock(&ioc->tm_cmds.mutex);
6211}
6212
6213/**
6214 * _scsih_sas_discovery_event - handle discovery events
6215 * @ioc: per adapter object
6216 * @fw_event: The fw_event_work object
6217 * Context: user.
6218 *
6219 * Return nothing.
6220 */
6221static void
6222_scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
6223 struct fw_event_work *fw_event)
6224{
Joe Lawrence35b62362014-06-25 17:05:34 -04006225 Mpi2EventDataSasDiscovery_t *event_data =
6226 (Mpi2EventDataSasDiscovery_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306227
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306228 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
6229 pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name,
6230 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
6231 "start" : "stop");
Sreekanth Reddyaf009412015-11-11 17:30:23 +05306232 if (event_data->DiscoveryStatus)
6233 pr_info("discovery_status(0x%08x)",
6234 le32_to_cpu(event_data->DiscoveryStatus));
6235 pr_info("\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306236 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306237
6238 if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
6239 !ioc->sas_hba.num_phys) {
6240 if (disable_discovery > 0 && ioc->shost_recovery) {
6241 /* Wait for the reset to complete */
6242 while (ioc->shost_recovery)
6243 ssleep(1);
6244 }
6245 _scsih_sas_host_add(ioc);
6246 }
6247}
6248
6249/**
6250 * _scsih_ir_fastpath - turn on fastpath for IR physdisk
6251 * @ioc: per adapter object
6252 * @handle: device handle for physical disk
6253 * @phys_disk_num: physical disk number
6254 *
6255 * Return 0 for success, else failure.
6256 */
6257static int
6258_scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
6259{
6260 Mpi2RaidActionRequest_t *mpi_request;
6261 Mpi2RaidActionReply_t *mpi_reply;
6262 u16 smid;
6263 u8 issue_reset = 0;
6264 int rc = 0;
6265 u16 ioc_status;
6266 u32 log_info;
6267
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05306268 if (ioc->hba_mpi_version_belonged == MPI2_VERSION)
6269 return rc;
6270
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306271 mutex_lock(&ioc->scsih_cmds.mutex);
6272
6273 if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
6274 pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
6275 ioc->name, __func__);
6276 rc = -EAGAIN;
6277 goto out;
6278 }
6279 ioc->scsih_cmds.status = MPT3_CMD_PENDING;
6280
6281 smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
6282 if (!smid) {
6283 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
6284 ioc->name, __func__);
6285 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
6286 rc = -EAGAIN;
6287 goto out;
6288 }
6289
6290 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
6291 ioc->scsih_cmds.smid = smid;
6292 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
6293
6294 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
6295 mpi_request->Action = MPI2_RAID_ACTION_PHYSDISK_HIDDEN;
6296 mpi_request->PhysDiskNum = phys_disk_num;
6297
6298 dewtprintk(ioc, pr_info(MPT3SAS_FMT "IR RAID_ACTION: turning fast "\
6299 "path on for handle(0x%04x), phys_disk_num (0x%02x)\n", ioc->name,
6300 handle, phys_disk_num));
6301
6302 init_completion(&ioc->scsih_cmds.done);
6303 mpt3sas_base_put_smid_default(ioc, smid);
6304 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
6305
6306 if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
6307 pr_err(MPT3SAS_FMT "%s: timeout\n",
6308 ioc->name, __func__);
6309 if (!(ioc->scsih_cmds.status & MPT3_CMD_RESET))
6310 issue_reset = 1;
6311 rc = -EFAULT;
6312 goto out;
6313 }
6314
6315 if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
6316
6317 mpi_reply = ioc->scsih_cmds.reply;
6318 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
6319 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
6320 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
6321 else
6322 log_info = 0;
6323 ioc_status &= MPI2_IOCSTATUS_MASK;
6324 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6325 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6326 "IR RAID_ACTION: failed: ioc_status(0x%04x), "
6327 "loginfo(0x%08x)!!!\n", ioc->name, ioc_status,
6328 log_info));
6329 rc = -EFAULT;
6330 } else
6331 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6332 "IR RAID_ACTION: completed successfully\n",
6333 ioc->name));
6334 }
6335
6336 out:
6337 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
6338 mutex_unlock(&ioc->scsih_cmds.mutex);
6339
6340 if (issue_reset)
Calvin Owens98c56ad2016-07-28 21:38:21 -07006341 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306342 return rc;
6343}
6344
6345/**
6346 * _scsih_reprobe_lun - reprobing lun
6347 * @sdev: scsi device struct
6348 * @no_uld_attach: sdev->no_uld_attach flag setting
6349 *
6350 **/
6351static void
6352_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
6353{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306354 sdev->no_uld_attach = no_uld_attach ? 1 : 0;
6355 sdev_printk(KERN_INFO, sdev, "%s raid component\n",
6356 sdev->no_uld_attach ? "hidding" : "exposing");
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07006357 WARN_ON(scsi_device_reprobe(sdev));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306358}
6359
6360/**
6361 * _scsih_sas_volume_add - add new volume
6362 * @ioc: per adapter object
6363 * @element: IR config element data
6364 * Context: user.
6365 *
6366 * Return nothing.
6367 */
6368static void
6369_scsih_sas_volume_add(struct MPT3SAS_ADAPTER *ioc,
6370 Mpi2EventIrConfigElement_t *element)
6371{
6372 struct _raid_device *raid_device;
6373 unsigned long flags;
6374 u64 wwid;
6375 u16 handle = le16_to_cpu(element->VolDevHandle);
6376 int rc;
6377
6378 mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
6379 if (!wwid) {
6380 pr_err(MPT3SAS_FMT
6381 "failure at %s:%d/%s()!\n", ioc->name,
6382 __FILE__, __LINE__, __func__);
6383 return;
6384 }
6385
6386 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6387 raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
6388 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6389
6390 if (raid_device)
6391 return;
6392
6393 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6394 if (!raid_device) {
6395 pr_err(MPT3SAS_FMT
6396 "failure at %s:%d/%s()!\n", ioc->name,
6397 __FILE__, __LINE__, __func__);
6398 return;
6399 }
6400
6401 raid_device->id = ioc->sas_id++;
6402 raid_device->channel = RAID_CHANNEL;
6403 raid_device->handle = handle;
6404 raid_device->wwid = wwid;
6405 _scsih_raid_device_add(ioc, raid_device);
6406 if (!ioc->wait_for_discovery_to_complete) {
6407 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6408 raid_device->id, 0);
6409 if (rc)
6410 _scsih_raid_device_remove(ioc, raid_device);
6411 } else {
6412 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6413 _scsih_determine_boot_device(ioc, raid_device, 1);
6414 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6415 }
6416}
6417
6418/**
6419 * _scsih_sas_volume_delete - delete volume
6420 * @ioc: per adapter object
6421 * @handle: volume device handle
6422 * Context: user.
6423 *
6424 * Return nothing.
6425 */
6426static void
6427_scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle)
6428{
6429 struct _raid_device *raid_device;
6430 unsigned long flags;
6431 struct MPT3SAS_TARGET *sas_target_priv_data;
6432 struct scsi_target *starget = NULL;
6433
6434 spin_lock_irqsave(&ioc->raid_device_lock, flags);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05306435 raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306436 if (raid_device) {
6437 if (raid_device->starget) {
6438 starget = raid_device->starget;
6439 sas_target_priv_data = starget->hostdata;
6440 sas_target_priv_data->deleted = 1;
6441 }
6442 pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
6443 ioc->name, raid_device->handle,
6444 (unsigned long long) raid_device->wwid);
6445 list_del(&raid_device->list);
6446 kfree(raid_device);
6447 }
6448 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6449 if (starget)
6450 scsi_remove_target(&starget->dev);
6451}
6452
6453/**
6454 * _scsih_sas_pd_expose - expose pd component to /dev/sdX
6455 * @ioc: per adapter object
6456 * @element: IR config element data
6457 * Context: user.
6458 *
6459 * Return nothing.
6460 */
6461static void
6462_scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc,
6463 Mpi2EventIrConfigElement_t *element)
6464{
6465 struct _sas_device *sas_device;
6466 struct scsi_target *starget = NULL;
6467 struct MPT3SAS_TARGET *sas_target_priv_data;
6468 unsigned long flags;
6469 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6470
6471 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306472 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306473 if (sas_device) {
6474 sas_device->volume_handle = 0;
6475 sas_device->volume_wwid = 0;
6476 clear_bit(handle, ioc->pd_handles);
6477 if (sas_device->starget && sas_device->starget->hostdata) {
6478 starget = sas_device->starget;
6479 sas_target_priv_data = starget->hostdata;
6480 sas_target_priv_data->flags &=
6481 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
6482 }
6483 }
6484 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6485 if (!sas_device)
6486 return;
6487
6488 /* exposing raid component */
6489 if (starget)
6490 starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306491
6492 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306493}
6494
6495/**
6496 * _scsih_sas_pd_hide - hide pd component from /dev/sdX
6497 * @ioc: per adapter object
6498 * @element: IR config element data
6499 * Context: user.
6500 *
6501 * Return nothing.
6502 */
6503static void
6504_scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc,
6505 Mpi2EventIrConfigElement_t *element)
6506{
6507 struct _sas_device *sas_device;
6508 struct scsi_target *starget = NULL;
6509 struct MPT3SAS_TARGET *sas_target_priv_data;
6510 unsigned long flags;
6511 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6512 u16 volume_handle = 0;
6513 u64 volume_wwid = 0;
6514
6515 mpt3sas_config_get_volume_handle(ioc, handle, &volume_handle);
6516 if (volume_handle)
6517 mpt3sas_config_get_volume_wwid(ioc, volume_handle,
6518 &volume_wwid);
6519
6520 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306521 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306522 if (sas_device) {
6523 set_bit(handle, ioc->pd_handles);
6524 if (sas_device->starget && sas_device->starget->hostdata) {
6525 starget = sas_device->starget;
6526 sas_target_priv_data = starget->hostdata;
6527 sas_target_priv_data->flags |=
6528 MPT_TARGET_FLAGS_RAID_COMPONENT;
6529 sas_device->volume_handle = volume_handle;
6530 sas_device->volume_wwid = volume_wwid;
6531 }
6532 }
6533 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6534 if (!sas_device)
6535 return;
6536
6537 /* hiding raid component */
6538 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05306539
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306540 if (starget)
6541 starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306542
6543 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306544}
6545
6546/**
6547 * _scsih_sas_pd_delete - delete pd component
6548 * @ioc: per adapter object
6549 * @element: IR config element data
6550 * Context: user.
6551 *
6552 * Return nothing.
6553 */
6554static void
6555_scsih_sas_pd_delete(struct MPT3SAS_ADAPTER *ioc,
6556 Mpi2EventIrConfigElement_t *element)
6557{
6558 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6559
6560 _scsih_device_remove_by_handle(ioc, handle);
6561}
6562
6563/**
6564 * _scsih_sas_pd_add - remove pd component
6565 * @ioc: per adapter object
6566 * @element: IR config element data
6567 * Context: user.
6568 *
6569 * Return nothing.
6570 */
6571static void
6572_scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
6573 Mpi2EventIrConfigElement_t *element)
6574{
6575 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306576 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6577 Mpi2ConfigReply_t mpi_reply;
6578 Mpi2SasDevicePage0_t sas_device_pg0;
6579 u32 ioc_status;
6580 u64 sas_address;
6581 u16 parent_handle;
6582
6583 set_bit(handle, ioc->pd_handles);
6584
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306585 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306586 if (sas_device) {
6587 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306588 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306589 return;
6590 }
6591
6592 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
6593 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
6594 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6595 ioc->name, __FILE__, __LINE__, __func__);
6596 return;
6597 }
6598
6599 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6600 MPI2_IOCSTATUS_MASK;
6601 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6602 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6603 ioc->name, __FILE__, __LINE__, __func__);
6604 return;
6605 }
6606
6607 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6608 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6609 mpt3sas_transport_update_links(ioc, sas_address, handle,
6610 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
6611
6612 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
6613 _scsih_add_device(ioc, handle, 0, 1);
6614}
6615
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306616/**
6617 * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
6618 * @ioc: per adapter object
6619 * @event_data: event data payload
6620 * Context: user.
6621 *
6622 * Return nothing.
6623 */
6624static void
6625_scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
6626 Mpi2EventDataIrConfigChangeList_t *event_data)
6627{
6628 Mpi2EventIrConfigElement_t *element;
6629 u8 element_type;
6630 int i;
6631 char *reason_str = NULL, *element_str = NULL;
6632
6633 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6634
6635 pr_info(MPT3SAS_FMT "raid config change: (%s), elements(%d)\n",
6636 ioc->name, (le32_to_cpu(event_data->Flags) &
6637 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
6638 "foreign" : "native", event_data->NumElements);
6639 for (i = 0; i < event_data->NumElements; i++, element++) {
6640 switch (element->ReasonCode) {
6641 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6642 reason_str = "add";
6643 break;
6644 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6645 reason_str = "remove";
6646 break;
6647 case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
6648 reason_str = "no change";
6649 break;
6650 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6651 reason_str = "hide";
6652 break;
6653 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
6654 reason_str = "unhide";
6655 break;
6656 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6657 reason_str = "volume_created";
6658 break;
6659 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6660 reason_str = "volume_deleted";
6661 break;
6662 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6663 reason_str = "pd_created";
6664 break;
6665 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
6666 reason_str = "pd_deleted";
6667 break;
6668 default:
6669 reason_str = "unknown reason";
6670 break;
6671 }
6672 element_type = le16_to_cpu(element->ElementFlags) &
6673 MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
6674 switch (element_type) {
6675 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
6676 element_str = "volume";
6677 break;
6678 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
6679 element_str = "phys disk";
6680 break;
6681 case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
6682 element_str = "hot spare";
6683 break;
6684 default:
6685 element_str = "unknown element";
6686 break;
6687 }
6688 pr_info("\t(%s:%s), vol handle(0x%04x), " \
6689 "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
6690 reason_str, le16_to_cpu(element->VolDevHandle),
6691 le16_to_cpu(element->PhysDiskDevHandle),
6692 element->PhysDiskNum);
6693 }
6694}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306695
6696/**
6697 * _scsih_sas_ir_config_change_event - handle ir configuration change events
6698 * @ioc: per adapter object
6699 * @fw_event: The fw_event_work object
6700 * Context: user.
6701 *
6702 * Return nothing.
6703 */
6704static void
6705_scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
6706 struct fw_event_work *fw_event)
6707{
6708 Mpi2EventIrConfigElement_t *element;
6709 int i;
6710 u8 foreign_config;
Joe Lawrence35b62362014-06-25 17:05:34 -04006711 Mpi2EventDataIrConfigChangeList_t *event_data =
6712 (Mpi2EventDataIrConfigChangeList_t *)
6713 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306714
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306715 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
6716 (!ioc->hide_ir_msg))
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306717 _scsih_sas_ir_config_change_event_debug(ioc, event_data);
6718
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306719 foreign_config = (le32_to_cpu(event_data->Flags) &
6720 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
6721
6722 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05306723 if (ioc->shost_recovery &&
6724 ioc->hba_mpi_version_belonged != MPI2_VERSION) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306725 for (i = 0; i < event_data->NumElements; i++, element++) {
6726 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE)
6727 _scsih_ir_fastpath(ioc,
6728 le16_to_cpu(element->PhysDiskDevHandle),
6729 element->PhysDiskNum);
6730 }
6731 return;
6732 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306733
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306734 for (i = 0; i < event_data->NumElements; i++, element++) {
6735
6736 switch (element->ReasonCode) {
6737 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6738 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6739 if (!foreign_config)
6740 _scsih_sas_volume_add(ioc, element);
6741 break;
6742 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6743 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6744 if (!foreign_config)
6745 _scsih_sas_volume_delete(ioc,
6746 le16_to_cpu(element->VolDevHandle));
6747 break;
6748 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306749 if (!ioc->is_warpdrive)
6750 _scsih_sas_pd_hide(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306751 break;
6752 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306753 if (!ioc->is_warpdrive)
6754 _scsih_sas_pd_expose(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306755 break;
6756 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306757 if (!ioc->is_warpdrive)
6758 _scsih_sas_pd_add(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306759 break;
6760 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306761 if (!ioc->is_warpdrive)
6762 _scsih_sas_pd_delete(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306763 break;
6764 }
6765 }
6766}
6767
6768/**
6769 * _scsih_sas_ir_volume_event - IR volume event
6770 * @ioc: per adapter object
6771 * @fw_event: The fw_event_work object
6772 * Context: user.
6773 *
6774 * Return nothing.
6775 */
6776static void
6777_scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
6778 struct fw_event_work *fw_event)
6779{
6780 u64 wwid;
6781 unsigned long flags;
6782 struct _raid_device *raid_device;
6783 u16 handle;
6784 u32 state;
6785 int rc;
Joe Lawrence35b62362014-06-25 17:05:34 -04006786 Mpi2EventDataIrVolume_t *event_data =
6787 (Mpi2EventDataIrVolume_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306788
6789 if (ioc->shost_recovery)
6790 return;
6791
6792 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
6793 return;
6794
6795 handle = le16_to_cpu(event_data->VolDevHandle);
6796 state = le32_to_cpu(event_data->NewValue);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306797 if (!ioc->hide_ir_msg)
6798 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6799 "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
6800 ioc->name, __func__, handle,
6801 le32_to_cpu(event_data->PreviousValue), state));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306802 switch (state) {
6803 case MPI2_RAID_VOL_STATE_MISSING:
6804 case MPI2_RAID_VOL_STATE_FAILED:
6805 _scsih_sas_volume_delete(ioc, handle);
6806 break;
6807
6808 case MPI2_RAID_VOL_STATE_ONLINE:
6809 case MPI2_RAID_VOL_STATE_DEGRADED:
6810 case MPI2_RAID_VOL_STATE_OPTIMAL:
6811
6812 spin_lock_irqsave(&ioc->raid_device_lock, flags);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05306813 raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306814 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6815
6816 if (raid_device)
6817 break;
6818
6819 mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
6820 if (!wwid) {
6821 pr_err(MPT3SAS_FMT
6822 "failure at %s:%d/%s()!\n", ioc->name,
6823 __FILE__, __LINE__, __func__);
6824 break;
6825 }
6826
6827 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6828 if (!raid_device) {
6829 pr_err(MPT3SAS_FMT
6830 "failure at %s:%d/%s()!\n", ioc->name,
6831 __FILE__, __LINE__, __func__);
6832 break;
6833 }
6834
6835 raid_device->id = ioc->sas_id++;
6836 raid_device->channel = RAID_CHANNEL;
6837 raid_device->handle = handle;
6838 raid_device->wwid = wwid;
6839 _scsih_raid_device_add(ioc, raid_device);
6840 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6841 raid_device->id, 0);
6842 if (rc)
6843 _scsih_raid_device_remove(ioc, raid_device);
6844 break;
6845
6846 case MPI2_RAID_VOL_STATE_INITIALIZING:
6847 default:
6848 break;
6849 }
6850}
6851
6852/**
6853 * _scsih_sas_ir_physical_disk_event - PD event
6854 * @ioc: per adapter object
6855 * @fw_event: The fw_event_work object
6856 * Context: user.
6857 *
6858 * Return nothing.
6859 */
6860static void
6861_scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
6862 struct fw_event_work *fw_event)
6863{
6864 u16 handle, parent_handle;
6865 u32 state;
6866 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306867 Mpi2ConfigReply_t mpi_reply;
6868 Mpi2SasDevicePage0_t sas_device_pg0;
6869 u32 ioc_status;
Joe Lawrence35b62362014-06-25 17:05:34 -04006870 Mpi2EventDataIrPhysicalDisk_t *event_data =
6871 (Mpi2EventDataIrPhysicalDisk_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306872 u64 sas_address;
6873
6874 if (ioc->shost_recovery)
6875 return;
6876
6877 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
6878 return;
6879
6880 handle = le16_to_cpu(event_data->PhysDiskDevHandle);
6881 state = le32_to_cpu(event_data->NewValue);
6882
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306883 if (!ioc->hide_ir_msg)
6884 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6885 "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
6886 ioc->name, __func__, handle,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306887 le32_to_cpu(event_data->PreviousValue), state));
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306888
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306889 switch (state) {
6890 case MPI2_RAID_PD_STATE_ONLINE:
6891 case MPI2_RAID_PD_STATE_DEGRADED:
6892 case MPI2_RAID_PD_STATE_REBUILDING:
6893 case MPI2_RAID_PD_STATE_OPTIMAL:
6894 case MPI2_RAID_PD_STATE_HOT_SPARE:
6895
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306896 if (!ioc->is_warpdrive)
6897 set_bit(handle, ioc->pd_handles);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306898
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306899 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
6900 if (sas_device) {
6901 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306902 return;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306903 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306904
6905 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6906 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
6907 handle))) {
6908 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6909 ioc->name, __FILE__, __LINE__, __func__);
6910 return;
6911 }
6912
6913 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6914 MPI2_IOCSTATUS_MASK;
6915 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6916 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6917 ioc->name, __FILE__, __LINE__, __func__);
6918 return;
6919 }
6920
6921 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6922 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6923 mpt3sas_transport_update_links(ioc, sas_address, handle,
6924 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
6925
6926 _scsih_add_device(ioc, handle, 0, 1);
6927
6928 break;
6929
6930 case MPI2_RAID_PD_STATE_OFFLINE:
6931 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
6932 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
6933 default:
6934 break;
6935 }
6936}
6937
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306938/**
6939 * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
6940 * @ioc: per adapter object
6941 * @event_data: event data payload
6942 * Context: user.
6943 *
6944 * Return nothing.
6945 */
6946static void
6947_scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc,
6948 Mpi2EventDataIrOperationStatus_t *event_data)
6949{
6950 char *reason_str = NULL;
6951
6952 switch (event_data->RAIDOperation) {
6953 case MPI2_EVENT_IR_RAIDOP_RESYNC:
6954 reason_str = "resync";
6955 break;
6956 case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
6957 reason_str = "online capacity expansion";
6958 break;
6959 case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
6960 reason_str = "consistency check";
6961 break;
6962 case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT:
6963 reason_str = "background init";
6964 break;
6965 case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT:
6966 reason_str = "make data consistent";
6967 break;
6968 }
6969
6970 if (!reason_str)
6971 return;
6972
6973 pr_info(MPT3SAS_FMT "raid operational status: (%s)" \
6974 "\thandle(0x%04x), percent complete(%d)\n",
6975 ioc->name, reason_str,
6976 le16_to_cpu(event_data->VolDevHandle),
6977 event_data->PercentComplete);
6978}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306979
6980/**
6981 * _scsih_sas_ir_operation_status_event - handle RAID operation events
6982 * @ioc: per adapter object
6983 * @fw_event: The fw_event_work object
6984 * Context: user.
6985 *
6986 * Return nothing.
6987 */
6988static void
6989_scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
6990 struct fw_event_work *fw_event)
6991{
Joe Lawrence35b62362014-06-25 17:05:34 -04006992 Mpi2EventDataIrOperationStatus_t *event_data =
6993 (Mpi2EventDataIrOperationStatus_t *)
6994 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306995 static struct _raid_device *raid_device;
6996 unsigned long flags;
6997 u16 handle;
6998
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306999 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
7000 (!ioc->hide_ir_msg))
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307001 _scsih_sas_ir_operation_status_event_debug(ioc,
7002 event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307003
7004 /* code added for raid transport support */
7005 if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
7006
7007 spin_lock_irqsave(&ioc->raid_device_lock, flags);
7008 handle = le16_to_cpu(event_data->VolDevHandle);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05307009 raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307010 if (raid_device)
7011 raid_device->percent_complete =
7012 event_data->PercentComplete;
7013 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7014 }
7015}
7016
7017/**
7018 * _scsih_prep_device_scan - initialize parameters prior to device scan
7019 * @ioc: per adapter object
7020 *
7021 * Set the deleted flag prior to device scan. If the device is found during
7022 * the scan, then we clear the deleted flag.
7023 */
7024static void
7025_scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc)
7026{
7027 struct MPT3SAS_DEVICE *sas_device_priv_data;
7028 struct scsi_device *sdev;
7029
7030 shost_for_each_device(sdev, ioc->shost) {
7031 sas_device_priv_data = sdev->hostdata;
7032 if (sas_device_priv_data && sas_device_priv_data->sas_target)
7033 sas_device_priv_data->sas_target->deleted = 1;
7034 }
7035}
7036
7037/**
7038 * _scsih_mark_responding_sas_device - mark a sas_devices as responding
7039 * @ioc: per adapter object
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307040 * @sas_device_pg0: SAS Device page 0
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307041 *
7042 * After host reset, find out whether devices are still responding.
7043 * Used in _scsih_remove_unresponsive_sas_devices.
7044 *
7045 * Return nothing.
7046 */
7047static void
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307048_scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc,
7049Mpi2SasDevicePage0_t *sas_device_pg0)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307050{
7051 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
7052 struct scsi_target *starget;
7053 struct _sas_device *sas_device;
7054 unsigned long flags;
7055
7056 spin_lock_irqsave(&ioc->sas_device_lock, flags);
7057 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307058 if ((sas_device->sas_address == sas_device_pg0->SASAddress) &&
7059 (sas_device->slot == sas_device_pg0->Slot)) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307060 sas_device->responding = 1;
7061 starget = sas_device->starget;
7062 if (starget && starget->hostdata) {
7063 sas_target_priv_data = starget->hostdata;
7064 sas_target_priv_data->tm_busy = 0;
7065 sas_target_priv_data->deleted = 0;
7066 } else
7067 sas_target_priv_data = NULL;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307068 if (starget) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307069 starget_printk(KERN_INFO, starget,
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307070 "handle(0x%04x), sas_addr(0x%016llx)\n",
7071 sas_device_pg0->DevHandle,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307072 (unsigned long long)
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307073 sas_device->sas_address);
7074
7075 if (sas_device->enclosure_handle != 0)
7076 starget_printk(KERN_INFO, starget,
7077 "enclosure logical id(0x%016llx),"
7078 " slot(%d)\n",
7079 (unsigned long long)
7080 sas_device->enclosure_logical_id,
7081 sas_device->slot);
7082 }
7083 if (sas_device_pg0->Flags &
7084 MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
7085 sas_device->enclosure_level =
7086 le16_to_cpu(sas_device_pg0->EnclosureLevel);
7087 memcpy(&sas_device->connector_name[0],
7088 &sas_device_pg0->ConnectorName[0], 4);
7089 } else {
7090 sas_device->enclosure_level = 0;
7091 sas_device->connector_name[0] = '\0';
7092 }
7093
7094 if (sas_device->handle == sas_device_pg0->DevHandle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307095 goto out;
7096 pr_info("\thandle changed from(0x%04x)!!!\n",
7097 sas_device->handle);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307098 sas_device->handle = sas_device_pg0->DevHandle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307099 if (sas_target_priv_data)
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307100 sas_target_priv_data->handle =
7101 sas_device_pg0->DevHandle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307102 goto out;
7103 }
7104 }
7105 out:
7106 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
7107}
7108
7109/**
7110 * _scsih_search_responding_sas_devices -
7111 * @ioc: per adapter object
7112 *
7113 * After host reset, find out whether devices are still responding.
7114 * If not remove.
7115 *
7116 * Return nothing.
7117 */
7118static void
7119_scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
7120{
7121 Mpi2SasDevicePage0_t sas_device_pg0;
7122 Mpi2ConfigReply_t mpi_reply;
7123 u16 ioc_status;
7124 u16 handle;
7125 u32 device_info;
7126
7127 pr_info(MPT3SAS_FMT "search for end-devices: start\n", ioc->name);
7128
7129 if (list_empty(&ioc->sas_device_list))
7130 goto out;
7131
7132 handle = 0xFFFF;
7133 while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7134 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
7135 handle))) {
7136 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7137 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307138 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307139 break;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307140 handle = sas_device_pg0.DevHandle =
7141 le16_to_cpu(sas_device_pg0.DevHandle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307142 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
7143 if (!(_scsih_is_end_device(device_info)))
7144 continue;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05307145 sas_device_pg0.SASAddress =
7146 le64_to_cpu(sas_device_pg0.SASAddress);
7147 sas_device_pg0.Slot = le16_to_cpu(sas_device_pg0.Slot);
7148 _scsih_mark_responding_sas_device(ioc, &sas_device_pg0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307149 }
7150
7151 out:
7152 pr_info(MPT3SAS_FMT "search for end-devices: complete\n",
7153 ioc->name);
7154}
7155
7156/**
7157 * _scsih_mark_responding_raid_device - mark a raid_device as responding
7158 * @ioc: per adapter object
7159 * @wwid: world wide identifier for raid volume
7160 * @handle: device handle
7161 *
7162 * After host reset, find out whether devices are still responding.
7163 * Used in _scsih_remove_unresponsive_raid_devices.
7164 *
7165 * Return nothing.
7166 */
7167static void
7168_scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
7169 u16 handle)
7170{
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307171 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307172 struct scsi_target *starget;
7173 struct _raid_device *raid_device;
7174 unsigned long flags;
7175
7176 spin_lock_irqsave(&ioc->raid_device_lock, flags);
7177 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
7178 if (raid_device->wwid == wwid && raid_device->starget) {
7179 starget = raid_device->starget;
7180 if (starget && starget->hostdata) {
7181 sas_target_priv_data = starget->hostdata;
7182 sas_target_priv_data->deleted = 0;
7183 } else
7184 sas_target_priv_data = NULL;
7185 raid_device->responding = 1;
7186 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7187 starget_printk(KERN_INFO, raid_device->starget,
7188 "handle(0x%04x), wwid(0x%016llx)\n", handle,
7189 (unsigned long long)raid_device->wwid);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307190
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307191 /*
7192 * WARPDRIVE: The handles of the PDs might have changed
7193 * across the host reset so re-initialize the
7194 * required data for Direct IO
7195 */
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05307196 mpt3sas_init_warpdrive_properties(ioc, raid_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307197 spin_lock_irqsave(&ioc->raid_device_lock, flags);
7198 if (raid_device->handle == handle) {
7199 spin_unlock_irqrestore(&ioc->raid_device_lock,
7200 flags);
7201 return;
7202 }
7203 pr_info("\thandle changed from(0x%04x)!!!\n",
7204 raid_device->handle);
7205 raid_device->handle = handle;
7206 if (sas_target_priv_data)
7207 sas_target_priv_data->handle = handle;
7208 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7209 return;
7210 }
7211 }
7212 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7213}
7214
7215/**
7216 * _scsih_search_responding_raid_devices -
7217 * @ioc: per adapter object
7218 *
7219 * After host reset, find out whether devices are still responding.
7220 * If not remove.
7221 *
7222 * Return nothing.
7223 */
7224static void
7225_scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
7226{
7227 Mpi2RaidVolPage1_t volume_pg1;
7228 Mpi2RaidVolPage0_t volume_pg0;
7229 Mpi2RaidPhysDiskPage0_t pd_pg0;
7230 Mpi2ConfigReply_t mpi_reply;
7231 u16 ioc_status;
7232 u16 handle;
7233 u8 phys_disk_num;
7234
7235 if (!ioc->ir_firmware)
7236 return;
7237
7238 pr_info(MPT3SAS_FMT "search for raid volumes: start\n",
7239 ioc->name);
7240
7241 if (list_empty(&ioc->raid_device_list))
7242 goto out;
7243
7244 handle = 0xFFFF;
7245 while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
7246 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
7247 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7248 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307249 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307250 break;
7251 handle = le16_to_cpu(volume_pg1.DevHandle);
7252
7253 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
7254 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
7255 sizeof(Mpi2RaidVolPage0_t)))
7256 continue;
7257
7258 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
7259 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
7260 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED)
7261 _scsih_mark_responding_raid_device(ioc,
7262 le64_to_cpu(volume_pg1.WWID), handle);
7263 }
7264
7265 /* refresh the pd_handles */
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307266 if (!ioc->is_warpdrive) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307267 phys_disk_num = 0xFF;
7268 memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
7269 while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
7270 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
7271 phys_disk_num))) {
7272 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7273 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307274 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307275 break;
7276 phys_disk_num = pd_pg0.PhysDiskNum;
7277 handle = le16_to_cpu(pd_pg0.DevHandle);
7278 set_bit(handle, ioc->pd_handles);
7279 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307280 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307281 out:
7282 pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n",
7283 ioc->name);
7284}
7285
7286/**
7287 * _scsih_mark_responding_expander - mark a expander as responding
7288 * @ioc: per adapter object
7289 * @sas_address: sas address
7290 * @handle:
7291 *
7292 * After host reset, find out whether devices are still responding.
7293 * Used in _scsih_remove_unresponsive_expanders.
7294 *
7295 * Return nothing.
7296 */
7297static void
7298_scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
7299 u16 handle)
7300{
7301 struct _sas_node *sas_expander;
7302 unsigned long flags;
7303 int i;
7304
7305 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7306 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
7307 if (sas_expander->sas_address != sas_address)
7308 continue;
7309 sas_expander->responding = 1;
7310 if (sas_expander->handle == handle)
7311 goto out;
7312 pr_info("\texpander(0x%016llx): handle changed" \
7313 " from(0x%04x) to (0x%04x)!!!\n",
7314 (unsigned long long)sas_expander->sas_address,
7315 sas_expander->handle, handle);
7316 sas_expander->handle = handle;
7317 for (i = 0 ; i < sas_expander->num_phys ; i++)
7318 sas_expander->phy[i].handle = handle;
7319 goto out;
7320 }
7321 out:
7322 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7323}
7324
7325/**
7326 * _scsih_search_responding_expanders -
7327 * @ioc: per adapter object
7328 *
7329 * After host reset, find out whether devices are still responding.
7330 * If not remove.
7331 *
7332 * Return nothing.
7333 */
7334static void
7335_scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
7336{
7337 Mpi2ExpanderPage0_t expander_pg0;
7338 Mpi2ConfigReply_t mpi_reply;
7339 u16 ioc_status;
7340 u64 sas_address;
7341 u16 handle;
7342
7343 pr_info(MPT3SAS_FMT "search for expanders: start\n", ioc->name);
7344
7345 if (list_empty(&ioc->sas_expander_list))
7346 goto out;
7347
7348 handle = 0xFFFF;
7349 while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
7350 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
7351
7352 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7353 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307354 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307355 break;
7356
7357 handle = le16_to_cpu(expander_pg0.DevHandle);
7358 sas_address = le64_to_cpu(expander_pg0.SASAddress);
7359 pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n",
7360 handle,
7361 (unsigned long long)sas_address);
7362 _scsih_mark_responding_expander(ioc, sas_address, handle);
7363 }
7364
7365 out:
7366 pr_info(MPT3SAS_FMT "search for expanders: complete\n", ioc->name);
7367}
7368
7369/**
7370 * _scsih_remove_unresponding_sas_devices - removing unresponding devices
7371 * @ioc: per adapter object
7372 *
7373 * Return nothing.
7374 */
7375static void
7376_scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
7377{
7378 struct _sas_device *sas_device, *sas_device_next;
7379 struct _sas_node *sas_expander, *sas_expander_next;
7380 struct _raid_device *raid_device, *raid_device_next;
7381 struct list_head tmp_list;
7382 unsigned long flags;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307383 LIST_HEAD(head);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307384
7385 pr_info(MPT3SAS_FMT "removing unresponding devices: start\n",
7386 ioc->name);
7387
7388 /* removing unresponding end devices */
7389 pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n",
7390 ioc->name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307391 /*
7392 * Iterate, pulling off devices marked as non-responding. We become the
7393 * owner for the reference the list had on any object we prune.
7394 */
7395 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307396 list_for_each_entry_safe(sas_device, sas_device_next,
7397 &ioc->sas_device_list, list) {
7398 if (!sas_device->responding)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307399 list_move_tail(&sas_device->list, &head);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307400 else
7401 sas_device->responding = 0;
7402 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307403 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
7404
7405 /*
7406 * Now, uninitialize and remove the unresponding devices we pruned.
7407 */
7408 list_for_each_entry_safe(sas_device, sas_device_next, &head, list) {
7409 _scsih_remove_device(ioc, sas_device);
7410 list_del_init(&sas_device->list);
7411 sas_device_put(sas_device);
7412 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307413
7414 /* removing unresponding volumes */
7415 if (ioc->ir_firmware) {
7416 pr_info(MPT3SAS_FMT "removing unresponding devices: volumes\n",
7417 ioc->name);
7418 list_for_each_entry_safe(raid_device, raid_device_next,
7419 &ioc->raid_device_list, list) {
7420 if (!raid_device->responding)
7421 _scsih_sas_volume_delete(ioc,
7422 raid_device->handle);
7423 else
7424 raid_device->responding = 0;
7425 }
7426 }
7427
7428 /* removing unresponding expanders */
7429 pr_info(MPT3SAS_FMT "removing unresponding devices: expanders\n",
7430 ioc->name);
7431 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7432 INIT_LIST_HEAD(&tmp_list);
7433 list_for_each_entry_safe(sas_expander, sas_expander_next,
7434 &ioc->sas_expander_list, list) {
7435 if (!sas_expander->responding)
7436 list_move_tail(&sas_expander->list, &tmp_list);
7437 else
7438 sas_expander->responding = 0;
7439 }
7440 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7441 list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
7442 list) {
7443 list_del(&sas_expander->list);
7444 _scsih_expander_node_remove(ioc, sas_expander);
7445 }
7446
7447 pr_info(MPT3SAS_FMT "removing unresponding devices: complete\n",
7448 ioc->name);
7449
7450 /* unblock devices */
7451 _scsih_ublock_io_all_device(ioc);
7452}
7453
7454static void
7455_scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc,
7456 struct _sas_node *sas_expander, u16 handle)
7457{
7458 Mpi2ExpanderPage1_t expander_pg1;
7459 Mpi2ConfigReply_t mpi_reply;
7460 int i;
7461
7462 for (i = 0 ; i < sas_expander->num_phys ; i++) {
7463 if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
7464 &expander_pg1, i, handle))) {
7465 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7466 ioc->name, __FILE__, __LINE__, __func__);
7467 return;
7468 }
7469
7470 mpt3sas_transport_update_links(ioc, sas_expander->sas_address,
7471 le16_to_cpu(expander_pg1.AttachedDevHandle), i,
7472 expander_pg1.NegotiatedLinkRate >> 4);
7473 }
7474}
7475
7476/**
7477 * _scsih_scan_for_devices_after_reset - scan for devices after host reset
7478 * @ioc: per adapter object
7479 *
7480 * Return nothing.
7481 */
7482static void
7483_scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
7484{
7485 Mpi2ExpanderPage0_t expander_pg0;
7486 Mpi2SasDevicePage0_t sas_device_pg0;
7487 Mpi2RaidVolPage1_t volume_pg1;
7488 Mpi2RaidVolPage0_t volume_pg0;
7489 Mpi2RaidPhysDiskPage0_t pd_pg0;
7490 Mpi2EventIrConfigElement_t element;
7491 Mpi2ConfigReply_t mpi_reply;
7492 u8 phys_disk_num;
7493 u16 ioc_status;
7494 u16 handle, parent_handle;
7495 u64 sas_address;
7496 struct _sas_device *sas_device;
7497 struct _sas_node *expander_device;
7498 static struct _raid_device *raid_device;
7499 u8 retry_count;
7500 unsigned long flags;
7501
7502 pr_info(MPT3SAS_FMT "scan devices: start\n", ioc->name);
7503
7504 _scsih_sas_host_refresh(ioc);
7505
7506 pr_info(MPT3SAS_FMT "\tscan devices: expanders start\n", ioc->name);
7507
7508 /* expanders */
7509 handle = 0xFFFF;
7510 while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
7511 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
7512 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7513 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307514 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7515 pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \
7516 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7517 ioc->name, ioc_status,
7518 le32_to_cpu(mpi_reply.IOCLogInfo));
7519 break;
7520 }
7521 handle = le16_to_cpu(expander_pg0.DevHandle);
7522 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7523 expander_device = mpt3sas_scsih_expander_find_by_sas_address(
7524 ioc, le64_to_cpu(expander_pg0.SASAddress));
7525 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7526 if (expander_device)
7527 _scsih_refresh_expander_links(ioc, expander_device,
7528 handle);
7529 else {
7530 pr_info(MPT3SAS_FMT "\tBEFORE adding expander: " \
7531 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7532 handle, (unsigned long long)
7533 le64_to_cpu(expander_pg0.SASAddress));
7534 _scsih_expander_add(ioc, handle);
7535 pr_info(MPT3SAS_FMT "\tAFTER adding expander: " \
7536 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7537 handle, (unsigned long long)
7538 le64_to_cpu(expander_pg0.SASAddress));
7539 }
7540 }
7541
7542 pr_info(MPT3SAS_FMT "\tscan devices: expanders complete\n",
7543 ioc->name);
7544
7545 if (!ioc->ir_firmware)
7546 goto skip_to_sas;
7547
7548 pr_info(MPT3SAS_FMT "\tscan devices: phys disk start\n", ioc->name);
7549
7550 /* phys disk */
7551 phys_disk_num = 0xFF;
7552 while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
7553 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
7554 phys_disk_num))) {
7555 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7556 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307557 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7558 pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\
7559 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7560 ioc->name, ioc_status,
7561 le32_to_cpu(mpi_reply.IOCLogInfo));
7562 break;
7563 }
7564 phys_disk_num = pd_pg0.PhysDiskNum;
7565 handle = le16_to_cpu(pd_pg0.DevHandle);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307566 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
7567 if (sas_device) {
7568 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307569 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307570 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307571 if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7572 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
7573 handle) != 0)
7574 continue;
7575 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7576 MPI2_IOCSTATUS_MASK;
7577 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7578 pr_info(MPT3SAS_FMT "\tbreak from phys disk scan " \
7579 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7580 ioc->name, ioc_status,
7581 le32_to_cpu(mpi_reply.IOCLogInfo));
7582 break;
7583 }
7584 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7585 if (!_scsih_get_sas_address(ioc, parent_handle,
7586 &sas_address)) {
7587 pr_info(MPT3SAS_FMT "\tBEFORE adding phys disk: " \
7588 " handle (0x%04x), sas_addr(0x%016llx)\n",
7589 ioc->name, handle, (unsigned long long)
7590 le64_to_cpu(sas_device_pg0.SASAddress));
7591 mpt3sas_transport_update_links(ioc, sas_address,
7592 handle, sas_device_pg0.PhyNum,
7593 MPI2_SAS_NEG_LINK_RATE_1_5);
7594 set_bit(handle, ioc->pd_handles);
7595 retry_count = 0;
7596 /* This will retry adding the end device.
7597 * _scsih_add_device() will decide on retries and
7598 * return "1" when it should be retried
7599 */
7600 while (_scsih_add_device(ioc, handle, retry_count++,
7601 1)) {
7602 ssleep(1);
7603 }
7604 pr_info(MPT3SAS_FMT "\tAFTER adding phys disk: " \
7605 " handle (0x%04x), sas_addr(0x%016llx)\n",
7606 ioc->name, handle, (unsigned long long)
7607 le64_to_cpu(sas_device_pg0.SASAddress));
7608 }
7609 }
7610
7611 pr_info(MPT3SAS_FMT "\tscan devices: phys disk complete\n",
7612 ioc->name);
7613
7614 pr_info(MPT3SAS_FMT "\tscan devices: volumes start\n", ioc->name);
7615
7616 /* volumes */
7617 handle = 0xFFFF;
7618 while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
7619 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
7620 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7621 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307622 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7623 pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
7624 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7625 ioc->name, ioc_status,
7626 le32_to_cpu(mpi_reply.IOCLogInfo));
7627 break;
7628 }
7629 handle = le16_to_cpu(volume_pg1.DevHandle);
7630 spin_lock_irqsave(&ioc->raid_device_lock, flags);
7631 raid_device = _scsih_raid_device_find_by_wwid(ioc,
7632 le64_to_cpu(volume_pg1.WWID));
7633 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7634 if (raid_device)
7635 continue;
7636 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
7637 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
7638 sizeof(Mpi2RaidVolPage0_t)))
7639 continue;
7640 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7641 MPI2_IOCSTATUS_MASK;
7642 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7643 pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
7644 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7645 ioc->name, ioc_status,
7646 le32_to_cpu(mpi_reply.IOCLogInfo));
7647 break;
7648 }
7649 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
7650 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
7651 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
7652 memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
7653 element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
7654 element.VolDevHandle = volume_pg1.DevHandle;
7655 pr_info(MPT3SAS_FMT
7656 "\tBEFORE adding volume: handle (0x%04x)\n",
7657 ioc->name, volume_pg1.DevHandle);
7658 _scsih_sas_volume_add(ioc, &element);
7659 pr_info(MPT3SAS_FMT
7660 "\tAFTER adding volume: handle (0x%04x)\n",
7661 ioc->name, volume_pg1.DevHandle);
7662 }
7663 }
7664
7665 pr_info(MPT3SAS_FMT "\tscan devices: volumes complete\n",
7666 ioc->name);
7667
7668 skip_to_sas:
7669
7670 pr_info(MPT3SAS_FMT "\tscan devices: end devices start\n",
7671 ioc->name);
7672
7673 /* sas devices */
7674 handle = 0xFFFF;
7675 while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7676 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
7677 handle))) {
7678 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7679 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307680 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7681 pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\
7682 " ioc_status(0x%04x), loginfo(0x%08x)\n",
7683 ioc->name, ioc_status,
7684 le32_to_cpu(mpi_reply.IOCLogInfo));
7685 break;
7686 }
7687 handle = le16_to_cpu(sas_device_pg0.DevHandle);
7688 if (!(_scsih_is_end_device(
7689 le32_to_cpu(sas_device_pg0.DeviceInfo))))
7690 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307691 sas_device = mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307692 le64_to_cpu(sas_device_pg0.SASAddress));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307693 if (sas_device) {
7694 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307695 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307696 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307697 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7698 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
7699 pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \
7700 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7701 handle, (unsigned long long)
7702 le64_to_cpu(sas_device_pg0.SASAddress));
7703 mpt3sas_transport_update_links(ioc, sas_address, handle,
7704 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
7705 retry_count = 0;
7706 /* This will retry adding the end device.
7707 * _scsih_add_device() will decide on retries and
7708 * return "1" when it should be retried
7709 */
7710 while (_scsih_add_device(ioc, handle, retry_count++,
7711 0)) {
7712 ssleep(1);
7713 }
7714 pr_info(MPT3SAS_FMT "\tAFTER adding end device: " \
7715 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7716 handle, (unsigned long long)
7717 le64_to_cpu(sas_device_pg0.SASAddress));
7718 }
7719 }
7720 pr_info(MPT3SAS_FMT "\tscan devices: end devices complete\n",
7721 ioc->name);
7722
7723 pr_info(MPT3SAS_FMT "scan devices: complete\n", ioc->name);
7724}
7725/**
7726 * mpt3sas_scsih_reset_handler - reset callback handler (for scsih)
7727 * @ioc: per adapter object
7728 * @reset_phase: phase
7729 *
7730 * The handler for doing any required cleanup or initialization.
7731 *
7732 * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET,
7733 * MPT3_IOC_DONE_RESET
7734 *
7735 * Return nothing.
7736 */
7737void
7738mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
7739{
7740 switch (reset_phase) {
7741 case MPT3_IOC_PRE_RESET:
7742 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7743 "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__));
7744 break;
7745 case MPT3_IOC_AFTER_RESET:
7746 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7747 "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__));
7748 if (ioc->scsih_cmds.status & MPT3_CMD_PENDING) {
7749 ioc->scsih_cmds.status |= MPT3_CMD_RESET;
7750 mpt3sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
7751 complete(&ioc->scsih_cmds.done);
7752 }
7753 if (ioc->tm_cmds.status & MPT3_CMD_PENDING) {
7754 ioc->tm_cmds.status |= MPT3_CMD_RESET;
7755 mpt3sas_base_free_smid(ioc, ioc->tm_cmds.smid);
7756 complete(&ioc->tm_cmds.done);
7757 }
7758
7759 _scsih_fw_event_cleanup_queue(ioc);
7760 _scsih_flush_running_cmds(ioc);
7761 break;
7762 case MPT3_IOC_DONE_RESET:
7763 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7764 "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__));
7765 if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
7766 !ioc->sas_hba.num_phys)) {
7767 _scsih_prep_device_scan(ioc);
7768 _scsih_search_responding_sas_devices(ioc);
7769 _scsih_search_responding_raid_devices(ioc);
7770 _scsih_search_responding_expanders(ioc);
7771 _scsih_error_recovery_delete_devices(ioc);
7772 }
7773 break;
7774 }
7775}
7776
7777/**
7778 * _mpt3sas_fw_work - delayed task for processing firmware events
7779 * @ioc: per adapter object
7780 * @fw_event: The fw_event_work object
7781 * Context: user.
7782 *
7783 * Return nothing.
7784 */
7785static void
7786_mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
7787{
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307788 _scsih_fw_event_del_from_list(ioc, fw_event);
7789
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307790 /* the queue is being flushed so ignore this event */
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307791 if (ioc->remove_host || ioc->pci_error_recovery) {
7792 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307793 return;
7794 }
7795
7796 switch (fw_event->event) {
7797 case MPT3SAS_PROCESS_TRIGGER_DIAG:
Joe Lawrence35b62362014-06-25 17:05:34 -04007798 mpt3sas_process_trigger_data(ioc,
7799 (struct SL_WH_TRIGGERS_EVENT_DATA_T *)
7800 fw_event->event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307801 break;
7802 case MPT3SAS_REMOVE_UNRESPONDING_DEVICES:
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307803 while (scsi_host_in_recovery(ioc->shost) ||
7804 ioc->shost_recovery) {
7805 /*
7806 * If we're unloading, bail. Otherwise, this can become
7807 * an infinite loop.
7808 */
7809 if (ioc->remove_host)
7810 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307811 ssleep(1);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307812 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307813 _scsih_remove_unresponding_sas_devices(ioc);
7814 _scsih_scan_for_devices_after_reset(ioc);
7815 break;
7816 case MPT3SAS_PORT_ENABLE_COMPLETE:
7817 ioc->start_scan = 0;
7818 if (missing_delay[0] != -1 && missing_delay[1] != -1)
7819 mpt3sas_base_update_missing_delay(ioc, missing_delay[0],
7820 missing_delay[1]);
7821 dewtprintk(ioc, pr_info(MPT3SAS_FMT
7822 "port enable: complete from worker thread\n",
7823 ioc->name));
7824 break;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05307825 case MPT3SAS_TURN_ON_PFA_LED:
7826 _scsih_turn_on_pfa_led(ioc, fw_event->device_handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307827 break;
7828 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7829 _scsih_sas_topology_change_event(ioc, fw_event);
7830 break;
7831 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7832 _scsih_sas_device_status_change_event(ioc, fw_event);
7833 break;
7834 case MPI2_EVENT_SAS_DISCOVERY:
7835 _scsih_sas_discovery_event(ioc, fw_event);
7836 break;
7837 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7838 _scsih_sas_broadcast_primitive_event(ioc, fw_event);
7839 break;
7840 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7841 _scsih_sas_enclosure_dev_status_change_event(ioc,
7842 fw_event);
7843 break;
7844 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7845 _scsih_sas_ir_config_change_event(ioc, fw_event);
7846 break;
7847 case MPI2_EVENT_IR_VOLUME:
7848 _scsih_sas_ir_volume_event(ioc, fw_event);
7849 break;
7850 case MPI2_EVENT_IR_PHYSICAL_DISK:
7851 _scsih_sas_ir_physical_disk_event(ioc, fw_event);
7852 break;
7853 case MPI2_EVENT_IR_OPERATION_STATUS:
7854 _scsih_sas_ir_operation_status_event(ioc, fw_event);
7855 break;
7856 }
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307857out:
7858 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307859}
7860
7861/**
7862 * _firmware_event_work
7863 * @ioc: per adapter object
7864 * @work: The fw_event_work object
7865 * Context: user.
7866 *
7867 * wrappers for the work thread handling firmware events
7868 *
7869 * Return nothing.
7870 */
7871
7872static void
7873_firmware_event_work(struct work_struct *work)
7874{
7875 struct fw_event_work *fw_event = container_of(work,
7876 struct fw_event_work, work);
7877
7878 _mpt3sas_fw_work(fw_event->ioc, fw_event);
7879}
7880
7881/**
7882 * mpt3sas_scsih_event_callback - firmware event handler (called at ISR time)
7883 * @ioc: per adapter object
7884 * @msix_index: MSIX table index supplied by the OS
7885 * @reply: reply message frame(lower 32bit addr)
7886 * Context: interrupt.
7887 *
7888 * This function merely adds a new work task into ioc->firmware_event_thread.
7889 * The tasks are worked from _firmware_event_work in user context.
7890 *
7891 * Return 1 meaning mf should be freed from _base_interrupt
7892 * 0 means the mf is freed from this function.
7893 */
7894u8
7895mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
7896 u32 reply)
7897{
7898 struct fw_event_work *fw_event;
7899 Mpi2EventNotificationReply_t *mpi_reply;
7900 u16 event;
7901 u16 sz;
Chaitra P Ba470a512016-05-06 14:29:27 +05307902 Mpi26EventDataActiveCableExcept_t *ActiveCableEventData;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307903
7904 /* events turned off due to host reset or driver unloading */
7905 if (ioc->remove_host || ioc->pci_error_recovery)
7906 return 1;
7907
7908 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
7909
7910 if (unlikely(!mpi_reply)) {
7911 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
7912 ioc->name, __FILE__, __LINE__, __func__);
7913 return 1;
7914 }
7915
7916 event = le16_to_cpu(mpi_reply->Event);
7917
7918 if (event != MPI2_EVENT_LOG_ENTRY_ADDED)
7919 mpt3sas_trigger_event(ioc, event, 0);
7920
7921 switch (event) {
7922 /* handle these */
7923 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7924 {
7925 Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
7926 (Mpi2EventDataSasBroadcastPrimitive_t *)
7927 mpi_reply->EventData;
7928
7929 if (baen_data->Primitive !=
7930 MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
7931 return 1;
7932
7933 if (ioc->broadcast_aen_busy) {
7934 ioc->broadcast_aen_pending++;
7935 return 1;
7936 } else
7937 ioc->broadcast_aen_busy = 1;
7938 break;
7939 }
7940
7941 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7942 _scsih_check_topo_delete_events(ioc,
7943 (Mpi2EventDataSasTopologyChangeList_t *)
7944 mpi_reply->EventData);
7945 break;
7946 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7947 _scsih_check_ir_config_unhide_events(ioc,
7948 (Mpi2EventDataIrConfigChangeList_t *)
7949 mpi_reply->EventData);
7950 break;
7951 case MPI2_EVENT_IR_VOLUME:
7952 _scsih_check_volume_delete_events(ioc,
7953 (Mpi2EventDataIrVolume_t *)
7954 mpi_reply->EventData);
7955 break;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307956 case MPI2_EVENT_LOG_ENTRY_ADDED:
7957 {
7958 Mpi2EventDataLogEntryAdded_t *log_entry;
7959 u32 *log_code;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307960
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307961 if (!ioc->is_warpdrive)
7962 break;
7963
7964 log_entry = (Mpi2EventDataLogEntryAdded_t *)
7965 mpi_reply->EventData;
7966 log_code = (u32 *)log_entry->LogData;
7967
7968 if (le16_to_cpu(log_entry->LogEntryQualifier)
7969 != MPT2_WARPDRIVE_LOGENTRY)
7970 break;
7971
7972 switch (le32_to_cpu(*log_code)) {
7973 case MPT2_WARPDRIVE_LC_SSDT:
7974 pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
7975 "IO Throttling has occurred in the WarpDrive "
7976 "subsystem. Check WarpDrive documentation for "
7977 "additional details.\n", ioc->name);
7978 break;
7979 case MPT2_WARPDRIVE_LC_SSDLW:
7980 pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
7981 "Program/Erase Cycles for the WarpDrive subsystem "
7982 "in degraded range. Check WarpDrive documentation "
7983 "for additional details.\n", ioc->name);
7984 break;
7985 case MPT2_WARPDRIVE_LC_SSDLF:
7986 pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
7987 "There are no Program/Erase Cycles for the "
7988 "WarpDrive subsystem. The storage device will be "
7989 "in read-only mode. Check WarpDrive documentation "
7990 "for additional details.\n", ioc->name);
7991 break;
7992 case MPT2_WARPDRIVE_LC_BRMF:
7993 pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
7994 "The Backup Rail Monitor has failed on the "
7995 "WarpDrive subsystem. Check WarpDrive "
7996 "documentation for additional details.\n",
7997 ioc->name);
7998 break;
7999 }
8000
8001 break;
8002 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308003 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
8004 case MPI2_EVENT_IR_OPERATION_STATUS:
8005 case MPI2_EVENT_SAS_DISCOVERY:
8006 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
8007 case MPI2_EVENT_IR_PHYSICAL_DISK:
8008 break;
8009
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05308010 case MPI2_EVENT_TEMP_THRESHOLD:
8011 _scsih_temp_threshold_events(ioc,
8012 (Mpi2EventDataTemperature_t *)
8013 mpi_reply->EventData);
8014 break;
Chaitra P Ba470a512016-05-06 14:29:27 +05308015 case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION:
8016 ActiveCableEventData =
8017 (Mpi26EventDataActiveCableExcept_t *) mpi_reply->EventData;
8018 if (ActiveCableEventData->ReasonCode ==
Dan Carpenter7ebd67e2016-05-12 23:37:38 +03008019 MPI26_EVENT_ACTIVE_CABLE_INSUFFICIENT_POWER) {
Chaitra P Ba470a512016-05-06 14:29:27 +05308020 pr_info(MPT3SAS_FMT "Currently an active cable with ReceptacleID %d",
8021 ioc->name, ActiveCableEventData->ReceptacleID);
8022 pr_info("cannot be powered and devices connected to this active cable");
8023 pr_info("will not be seen. This active cable");
8024 pr_info("requires %d mW of power",
8025 ActiveCableEventData->ActiveCablePowerRequirement);
Dan Carpenter7ebd67e2016-05-12 23:37:38 +03008026 }
Chaitra P Ba470a512016-05-06 14:29:27 +05308027 break;
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05308028
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308029 default: /* ignore the rest */
8030 return 1;
8031 }
8032
Joe Lawrence35b62362014-06-25 17:05:34 -04008033 sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05308034 fw_event = alloc_fw_event_work(sz);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308035 if (!fw_event) {
8036 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8037 ioc->name, __FILE__, __LINE__, __func__);
8038 return 1;
8039 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308040
8041 memcpy(fw_event->event_data, mpi_reply->EventData, sz);
8042 fw_event->ioc = ioc;
8043 fw_event->VF_ID = mpi_reply->VF_ID;
8044 fw_event->VP_ID = mpi_reply->VP_ID;
8045 fw_event->event = event;
8046 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05308047 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308048 return 1;
8049}
8050
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308051/**
8052 * _scsih_expander_node_remove - removing expander device from list.
8053 * @ioc: per adapter object
8054 * @sas_expander: the sas_device object
8055 * Context: Calling function should acquire ioc->sas_node_lock.
8056 *
8057 * Removing object and freeing associated memory from the
8058 * ioc->sas_expander_list.
8059 *
8060 * Return nothing.
8061 */
8062static void
8063_scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
8064 struct _sas_node *sas_expander)
8065{
8066 struct _sas_port *mpt3sas_port, *next;
8067
8068 /* remove sibling ports attached to this expander */
8069 list_for_each_entry_safe(mpt3sas_port, next,
8070 &sas_expander->sas_port_list, port_list) {
8071 if (ioc->shost_recovery)
8072 return;
8073 if (mpt3sas_port->remote_identify.device_type ==
8074 SAS_END_DEVICE)
8075 mpt3sas_device_remove_by_sas_address(ioc,
8076 mpt3sas_port->remote_identify.sas_address);
8077 else if (mpt3sas_port->remote_identify.device_type ==
8078 SAS_EDGE_EXPANDER_DEVICE ||
8079 mpt3sas_port->remote_identify.device_type ==
8080 SAS_FANOUT_EXPANDER_DEVICE)
8081 mpt3sas_expander_remove(ioc,
8082 mpt3sas_port->remote_identify.sas_address);
8083 }
8084
8085 mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
8086 sas_expander->sas_address_parent);
8087
8088 pr_info(MPT3SAS_FMT
8089 "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n",
8090 ioc->name,
8091 sas_expander->handle, (unsigned long long)
8092 sas_expander->sas_address);
8093
8094 kfree(sas_expander->phy);
8095 kfree(sas_expander);
8096}
8097
8098/**
8099 * _scsih_ir_shutdown - IR shutdown notification
8100 * @ioc: per adapter object
8101 *
8102 * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
8103 * the host system is shutting down.
8104 *
8105 * Return nothing.
8106 */
8107static void
8108_scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
8109{
8110 Mpi2RaidActionRequest_t *mpi_request;
8111 Mpi2RaidActionReply_t *mpi_reply;
8112 u16 smid;
8113
8114 /* is IR firmware build loaded ? */
8115 if (!ioc->ir_firmware)
8116 return;
8117
8118 /* are there any volumes ? */
8119 if (list_empty(&ioc->raid_device_list))
8120 return;
8121
8122 mutex_lock(&ioc->scsih_cmds.mutex);
8123
8124 if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
8125 pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
8126 ioc->name, __func__);
8127 goto out;
8128 }
8129 ioc->scsih_cmds.status = MPT3_CMD_PENDING;
8130
8131 smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
8132 if (!smid) {
8133 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
8134 ioc->name, __func__);
8135 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
8136 goto out;
8137 }
8138
8139 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
8140 ioc->scsih_cmds.smid = smid;
8141 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
8142
8143 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
8144 mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
8145
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308146 if (!ioc->hide_ir_msg)
8147 pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308148 init_completion(&ioc->scsih_cmds.done);
8149 mpt3sas_base_put_smid_default(ioc, smid);
8150 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
8151
8152 if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
8153 pr_err(MPT3SAS_FMT "%s: timeout\n",
8154 ioc->name, __func__);
8155 goto out;
8156 }
8157
8158 if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
8159 mpi_reply = ioc->scsih_cmds.reply;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308160 if (!ioc->hide_ir_msg)
8161 pr_info(MPT3SAS_FMT "IR shutdown "
8162 "(complete): ioc_status(0x%04x), loginfo(0x%08x)\n",
8163 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
8164 le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308165 }
8166
8167 out:
8168 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
8169 mutex_unlock(&ioc->scsih_cmds.mutex);
8170}
8171
8172/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308173 * scsih_remove - detach and remove add host
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308174 * @pdev: PCI device struct
8175 *
8176 * Routine called when unloading the driver.
8177 * Return nothing.
8178 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008179static void scsih_remove(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308180{
8181 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8182 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8183 struct _sas_port *mpt3sas_port, *next_port;
8184 struct _raid_device *raid_device, *next;
8185 struct MPT3SAS_TARGET *sas_target_priv_data;
8186 struct workqueue_struct *wq;
8187 unsigned long flags;
8188
8189 ioc->remove_host = 1;
8190 _scsih_fw_event_cleanup_queue(ioc);
8191
8192 spin_lock_irqsave(&ioc->fw_event_lock, flags);
8193 wq = ioc->firmware_event_thread;
8194 ioc->firmware_event_thread = NULL;
8195 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
8196 if (wq)
8197 destroy_workqueue(wq);
8198
8199 /* release all the volumes */
8200 _scsih_ir_shutdown(ioc);
8201 list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
8202 list) {
8203 if (raid_device->starget) {
8204 sas_target_priv_data =
8205 raid_device->starget->hostdata;
8206 sas_target_priv_data->deleted = 1;
8207 scsi_remove_target(&raid_device->starget->dev);
8208 }
8209 pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
8210 ioc->name, raid_device->handle,
8211 (unsigned long long) raid_device->wwid);
8212 _scsih_raid_device_remove(ioc, raid_device);
8213 }
8214
8215 /* free ports attached to the sas_host */
8216 list_for_each_entry_safe(mpt3sas_port, next_port,
8217 &ioc->sas_hba.sas_port_list, port_list) {
8218 if (mpt3sas_port->remote_identify.device_type ==
8219 SAS_END_DEVICE)
8220 mpt3sas_device_remove_by_sas_address(ioc,
8221 mpt3sas_port->remote_identify.sas_address);
8222 else if (mpt3sas_port->remote_identify.device_type ==
8223 SAS_EDGE_EXPANDER_DEVICE ||
8224 mpt3sas_port->remote_identify.device_type ==
8225 SAS_FANOUT_EXPANDER_DEVICE)
8226 mpt3sas_expander_remove(ioc,
8227 mpt3sas_port->remote_identify.sas_address);
8228 }
8229
8230 /* free phys attached to the sas_host */
8231 if (ioc->sas_hba.num_phys) {
8232 kfree(ioc->sas_hba.phy);
8233 ioc->sas_hba.phy = NULL;
8234 ioc->sas_hba.num_phys = 0;
8235 }
8236
8237 sas_remove_host(shost);
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308238 scsi_remove_host(shost);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308239 mpt3sas_base_detach(ioc);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308240 spin_lock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308241 list_del(&ioc->list);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308242 spin_unlock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308243 scsi_host_put(shost);
8244}
8245
8246/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308247 * scsih_shutdown - routine call during system shutdown
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308248 * @pdev: PCI device struct
8249 *
8250 * Return nothing.
8251 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008252static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308253scsih_shutdown(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308254{
8255 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8256 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8257 struct workqueue_struct *wq;
8258 unsigned long flags;
8259
8260 ioc->remove_host = 1;
8261 _scsih_fw_event_cleanup_queue(ioc);
8262
8263 spin_lock_irqsave(&ioc->fw_event_lock, flags);
8264 wq = ioc->firmware_event_thread;
8265 ioc->firmware_event_thread = NULL;
8266 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
8267 if (wq)
8268 destroy_workqueue(wq);
8269
8270 _scsih_ir_shutdown(ioc);
8271 mpt3sas_base_detach(ioc);
8272}
8273
8274
8275/**
8276 * _scsih_probe_boot_devices - reports 1st device
8277 * @ioc: per adapter object
8278 *
8279 * If specified in bios page 2, this routine reports the 1st
8280 * device scsi-ml or sas transport for persistent boot device
8281 * purposes. Please refer to function _scsih_determine_boot_device()
8282 */
8283static void
8284_scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
8285{
8286 u8 is_raid;
8287 void *device;
8288 struct _sas_device *sas_device;
8289 struct _raid_device *raid_device;
8290 u16 handle;
8291 u64 sas_address_parent;
8292 u64 sas_address;
8293 unsigned long flags;
8294 int rc;
8295
8296 /* no Bios, return immediately */
8297 if (!ioc->bios_pg3.BiosVersion)
8298 return;
8299
8300 device = NULL;
8301 is_raid = 0;
8302 if (ioc->req_boot_device.device) {
8303 device = ioc->req_boot_device.device;
8304 is_raid = ioc->req_boot_device.is_raid;
8305 } else if (ioc->req_alt_boot_device.device) {
8306 device = ioc->req_alt_boot_device.device;
8307 is_raid = ioc->req_alt_boot_device.is_raid;
8308 } else if (ioc->current_boot_device.device) {
8309 device = ioc->current_boot_device.device;
8310 is_raid = ioc->current_boot_device.is_raid;
8311 }
8312
8313 if (!device)
8314 return;
8315
8316 if (is_raid) {
8317 raid_device = device;
8318 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
8319 raid_device->id, 0);
8320 if (rc)
8321 _scsih_raid_device_remove(ioc, raid_device);
8322 } else {
8323 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8324 sas_device = device;
8325 handle = sas_device->handle;
8326 sas_address_parent = sas_device->sas_address_parent;
8327 sas_address = sas_device->sas_address;
8328 list_move_tail(&sas_device->list, &ioc->sas_device_list);
8329 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8330
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308331 if (ioc->hide_drives)
8332 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308333 if (!mpt3sas_transport_port_add(ioc, handle,
8334 sas_address_parent)) {
8335 _scsih_sas_device_remove(ioc, sas_device);
8336 } else if (!sas_device->starget) {
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308337 if (!ioc->is_driver_loading) {
8338 mpt3sas_transport_port_remove(ioc,
8339 sas_address,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308340 sas_address_parent);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308341 _scsih_sas_device_remove(ioc, sas_device);
8342 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308343 }
8344 }
8345}
8346
8347/**
8348 * _scsih_probe_raid - reporting raid volumes to scsi-ml
8349 * @ioc: per adapter object
8350 *
8351 * Called during initial loading of the driver.
8352 */
8353static void
8354_scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc)
8355{
8356 struct _raid_device *raid_device, *raid_next;
8357 int rc;
8358
8359 list_for_each_entry_safe(raid_device, raid_next,
8360 &ioc->raid_device_list, list) {
8361 if (raid_device->starget)
8362 continue;
8363 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
8364 raid_device->id, 0);
8365 if (rc)
8366 _scsih_raid_device_remove(ioc, raid_device);
8367 }
8368}
8369
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308370static struct _sas_device *get_next_sas_device(struct MPT3SAS_ADAPTER *ioc)
8371{
8372 struct _sas_device *sas_device = NULL;
8373 unsigned long flags;
8374
8375 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8376 if (!list_empty(&ioc->sas_device_init_list)) {
8377 sas_device = list_first_entry(&ioc->sas_device_init_list,
8378 struct _sas_device, list);
8379 sas_device_get(sas_device);
8380 }
8381 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8382
8383 return sas_device;
8384}
8385
8386static void sas_device_make_active(struct MPT3SAS_ADAPTER *ioc,
8387 struct _sas_device *sas_device)
8388{
8389 unsigned long flags;
8390
8391 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8392
8393 /*
8394 * Since we dropped the lock during the call to port_add(), we need to
8395 * be careful here that somebody else didn't move or delete this item
8396 * while we were busy with other things.
8397 *
8398 * If it was on the list, we need a put() for the reference the list
8399 * had. Either way, we need a get() for the destination list.
8400 */
8401 if (!list_empty(&sas_device->list)) {
8402 list_del_init(&sas_device->list);
8403 sas_device_put(sas_device);
8404 }
8405
8406 sas_device_get(sas_device);
8407 list_add_tail(&sas_device->list, &ioc->sas_device_list);
8408
8409 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8410}
8411
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308412/**
8413 * _scsih_probe_sas - reporting sas devices to sas transport
8414 * @ioc: per adapter object
8415 *
8416 * Called during initial loading of the driver.
8417 */
8418static void
8419_scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
8420{
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308421 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308422
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308423 if (ioc->hide_drives)
8424 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308425
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308426 while ((sas_device = get_next_sas_device(ioc))) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308427 if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
8428 sas_device->sas_address_parent)) {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308429 _scsih_sas_device_remove(ioc, sas_device);
8430 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308431 continue;
8432 } else if (!sas_device->starget) {
8433 /*
8434 * When asyn scanning is enabled, its not possible to
8435 * remove devices while scanning is turned on due to an
8436 * oops in scsi_sysfs_add_sdev()->add_device()->
8437 * sysfs_addrm_start()
8438 */
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308439 if (!ioc->is_driver_loading) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308440 mpt3sas_transport_port_remove(ioc,
8441 sas_device->sas_address,
8442 sas_device->sas_address_parent);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308443 _scsih_sas_device_remove(ioc, sas_device);
8444 sas_device_put(sas_device);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308445 continue;
8446 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308447 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308448 sas_device_make_active(ioc, sas_device);
8449 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308450 }
8451}
8452
8453/**
8454 * _scsih_probe_devices - probing for devices
8455 * @ioc: per adapter object
8456 *
8457 * Called during initial loading of the driver.
8458 */
8459static void
8460_scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc)
8461{
8462 u16 volume_mapping_flags;
8463
8464 if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
8465 return; /* return when IOC doesn't support initiator mode */
8466
8467 _scsih_probe_boot_devices(ioc);
8468
8469 if (ioc->ir_firmware) {
8470 volume_mapping_flags =
8471 le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
8472 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
8473 if (volume_mapping_flags ==
8474 MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
8475 _scsih_probe_raid(ioc);
8476 _scsih_probe_sas(ioc);
8477 } else {
8478 _scsih_probe_sas(ioc);
8479 _scsih_probe_raid(ioc);
8480 }
8481 } else
8482 _scsih_probe_sas(ioc);
8483}
8484
8485/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308486 * scsih_scan_start - scsi lld callback for .scan_start
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308487 * @shost: SCSI host pointer
8488 *
8489 * The shost has the ability to discover targets on its own instead
8490 * of scanning the entire bus. In our implemention, we will kick off
8491 * firmware discovery.
8492 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008493static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308494scsih_scan_start(struct Scsi_Host *shost)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308495{
8496 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8497 int rc;
8498 if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
8499 mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable);
8500
8501 if (disable_discovery > 0)
8502 return;
8503
8504 ioc->start_scan = 1;
8505 rc = mpt3sas_port_enable(ioc);
8506
8507 if (rc != 0)
8508 pr_info(MPT3SAS_FMT "port enable: FAILED\n", ioc->name);
8509}
8510
8511/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308512 * scsih_scan_finished - scsi lld callback for .scan_finished
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308513 * @shost: SCSI host pointer
8514 * @time: elapsed time of the scan in jiffies
8515 *
8516 * This function will be called periodicallyn until it returns 1 with the
8517 * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
8518 * we wait for firmware discovery to complete, then return 1.
8519 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008520static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308521scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308522{
8523 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8524
8525 if (disable_discovery > 0) {
8526 ioc->is_driver_loading = 0;
8527 ioc->wait_for_discovery_to_complete = 0;
8528 return 1;
8529 }
8530
8531 if (time >= (300 * HZ)) {
8532 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
8533 pr_info(MPT3SAS_FMT
8534 "port enable: FAILED with timeout (timeout=300s)\n",
8535 ioc->name);
8536 ioc->is_driver_loading = 0;
8537 return 1;
8538 }
8539
8540 if (ioc->start_scan)
8541 return 0;
8542
8543 if (ioc->start_scan_failed) {
8544 pr_info(MPT3SAS_FMT
8545 "port enable: FAILED with (ioc_status=0x%08x)\n",
8546 ioc->name, ioc->start_scan_failed);
8547 ioc->is_driver_loading = 0;
8548 ioc->wait_for_discovery_to_complete = 0;
8549 ioc->remove_host = 1;
8550 return 1;
8551 }
8552
8553 pr_info(MPT3SAS_FMT "port enable: SUCCESS\n", ioc->name);
8554 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
8555
8556 if (ioc->wait_for_discovery_to_complete) {
8557 ioc->wait_for_discovery_to_complete = 0;
8558 _scsih_probe_devices(ioc);
8559 }
8560 mpt3sas_base_start_watchdog(ioc);
8561 ioc->is_driver_loading = 0;
8562 return 1;
8563}
8564
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308565/* shost template for SAS 2.0 HBA devices */
8566static struct scsi_host_template mpt2sas_driver_template = {
8567 .module = THIS_MODULE,
8568 .name = "Fusion MPT SAS Host",
8569 .proc_name = MPT2SAS_DRIVER_NAME,
8570 .queuecommand = scsih_qcmd,
8571 .target_alloc = scsih_target_alloc,
8572 .slave_alloc = scsih_slave_alloc,
8573 .slave_configure = scsih_slave_configure,
8574 .target_destroy = scsih_target_destroy,
8575 .slave_destroy = scsih_slave_destroy,
8576 .scan_finished = scsih_scan_finished,
8577 .scan_start = scsih_scan_start,
8578 .change_queue_depth = scsih_change_queue_depth,
8579 .eh_abort_handler = scsih_abort,
8580 .eh_device_reset_handler = scsih_dev_reset,
8581 .eh_target_reset_handler = scsih_target_reset,
8582 .eh_host_reset_handler = scsih_host_reset,
8583 .bios_param = scsih_bios_param,
8584 .can_queue = 1,
8585 .this_id = -1,
8586 .sg_tablesize = MPT2SAS_SG_DEPTH,
8587 .max_sectors = 32767,
8588 .cmd_per_lun = 7,
8589 .use_clustering = ENABLE_CLUSTERING,
8590 .shost_attrs = mpt3sas_host_attrs,
8591 .sdev_attrs = mpt3sas_dev_attrs,
8592 .track_queue_depth = 1,
8593};
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308594
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308595/* raid transport support for SAS 2.0 HBA devices */
8596static struct raid_function_template mpt2sas_raid_functions = {
8597 .cookie = &mpt2sas_driver_template,
8598 .is_raid = scsih_is_raid,
8599 .get_resync = scsih_get_resync,
8600 .get_state = scsih_get_state,
8601};
8602
8603/* shost template for SAS 3.0 HBA devices */
8604static struct scsi_host_template mpt3sas_driver_template = {
8605 .module = THIS_MODULE,
8606 .name = "Fusion MPT SAS Host",
8607 .proc_name = MPT3SAS_DRIVER_NAME,
8608 .queuecommand = scsih_qcmd,
8609 .target_alloc = scsih_target_alloc,
8610 .slave_alloc = scsih_slave_alloc,
8611 .slave_configure = scsih_slave_configure,
8612 .target_destroy = scsih_target_destroy,
8613 .slave_destroy = scsih_slave_destroy,
8614 .scan_finished = scsih_scan_finished,
8615 .scan_start = scsih_scan_start,
8616 .change_queue_depth = scsih_change_queue_depth,
8617 .eh_abort_handler = scsih_abort,
8618 .eh_device_reset_handler = scsih_dev_reset,
8619 .eh_target_reset_handler = scsih_target_reset,
8620 .eh_host_reset_handler = scsih_host_reset,
8621 .bios_param = scsih_bios_param,
8622 .can_queue = 1,
8623 .this_id = -1,
8624 .sg_tablesize = MPT3SAS_SG_DEPTH,
8625 .max_sectors = 32767,
8626 .cmd_per_lun = 7,
8627 .use_clustering = ENABLE_CLUSTERING,
8628 .shost_attrs = mpt3sas_host_attrs,
8629 .sdev_attrs = mpt3sas_dev_attrs,
8630 .track_queue_depth = 1,
8631};
8632
8633/* raid transport support for SAS 3.0 HBA devices */
8634static struct raid_function_template mpt3sas_raid_functions = {
8635 .cookie = &mpt3sas_driver_template,
8636 .is_raid = scsih_is_raid,
8637 .get_resync = scsih_get_resync,
8638 .get_state = scsih_get_state,
8639};
8640
8641/**
8642 * _scsih_determine_hba_mpi_version - determine in which MPI version class
8643 * this device belongs to.
8644 * @pdev: PCI device struct
8645 *
8646 * return MPI2_VERSION for SAS 2.0 HBA devices,
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05308647 * MPI25_VERSION for SAS 3.0 HBA devices, and
8648 * MPI26 VERSION for Cutlass & Invader SAS 3.0 HBA devices
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308649 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008650static u16
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308651_scsih_determine_hba_mpi_version(struct pci_dev *pdev)
8652{
8653
8654 switch (pdev->device) {
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308655 case MPI2_MFGPAGE_DEVID_SSS6200:
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308656 case MPI2_MFGPAGE_DEVID_SAS2004:
8657 case MPI2_MFGPAGE_DEVID_SAS2008:
8658 case MPI2_MFGPAGE_DEVID_SAS2108_1:
8659 case MPI2_MFGPAGE_DEVID_SAS2108_2:
8660 case MPI2_MFGPAGE_DEVID_SAS2108_3:
8661 case MPI2_MFGPAGE_DEVID_SAS2116_1:
8662 case MPI2_MFGPAGE_DEVID_SAS2116_2:
8663 case MPI2_MFGPAGE_DEVID_SAS2208_1:
8664 case MPI2_MFGPAGE_DEVID_SAS2208_2:
8665 case MPI2_MFGPAGE_DEVID_SAS2208_3:
8666 case MPI2_MFGPAGE_DEVID_SAS2208_4:
8667 case MPI2_MFGPAGE_DEVID_SAS2208_5:
8668 case MPI2_MFGPAGE_DEVID_SAS2208_6:
8669 case MPI2_MFGPAGE_DEVID_SAS2308_1:
8670 case MPI2_MFGPAGE_DEVID_SAS2308_2:
8671 case MPI2_MFGPAGE_DEVID_SAS2308_3:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308672 return MPI2_VERSION;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308673 case MPI25_MFGPAGE_DEVID_SAS3004:
8674 case MPI25_MFGPAGE_DEVID_SAS3008:
8675 case MPI25_MFGPAGE_DEVID_SAS3108_1:
8676 case MPI25_MFGPAGE_DEVID_SAS3108_2:
8677 case MPI25_MFGPAGE_DEVID_SAS3108_5:
8678 case MPI25_MFGPAGE_DEVID_SAS3108_6:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308679 return MPI25_VERSION;
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05308680 case MPI26_MFGPAGE_DEVID_SAS3216:
8681 case MPI26_MFGPAGE_DEVID_SAS3224:
8682 case MPI26_MFGPAGE_DEVID_SAS3316_1:
8683 case MPI26_MFGPAGE_DEVID_SAS3316_2:
8684 case MPI26_MFGPAGE_DEVID_SAS3316_3:
8685 case MPI26_MFGPAGE_DEVID_SAS3316_4:
8686 case MPI26_MFGPAGE_DEVID_SAS3324_1:
8687 case MPI26_MFGPAGE_DEVID_SAS3324_2:
8688 case MPI26_MFGPAGE_DEVID_SAS3324_3:
8689 case MPI26_MFGPAGE_DEVID_SAS3324_4:
8690 return MPI26_VERSION;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308691 }
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308692 return 0;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308693}
8694
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308695/**
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308696 * _scsih_probe - attach and add scsi host
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308697 * @pdev: PCI device struct
8698 * @id: pci device id
8699 *
8700 * Returns 0 success, anything else error.
8701 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008702static int
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308703_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308704{
8705 struct MPT3SAS_ADAPTER *ioc;
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308706 struct Scsi_Host *shost = NULL;
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308707 int rv;
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308708 u16 hba_mpi_version;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308709
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308710 /* Determine in which MPI version class this pci device belongs */
8711 hba_mpi_version = _scsih_determine_hba_mpi_version(pdev);
8712 if (hba_mpi_version == 0)
8713 return -ENODEV;
8714
8715 /* Enumerate only SAS 2.0 HBA's if hbas_to_enumerate is one,
8716 * for other generation HBA's return with -ENODEV
8717 */
8718 if ((hbas_to_enumerate == 1) && (hba_mpi_version != MPI2_VERSION))
8719 return -ENODEV;
8720
8721 /* Enumerate only SAS 3.0 HBA's if hbas_to_enumerate is two,
8722 * for other generation HBA's return with -ENODEV
8723 */
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05308724 if ((hbas_to_enumerate == 2) && (!(hba_mpi_version == MPI25_VERSION
8725 || hba_mpi_version == MPI26_VERSION)))
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308726 return -ENODEV;
8727
8728 switch (hba_mpi_version) {
8729 case MPI2_VERSION:
ojabb5d5f282016-12-28 11:05:24 +00008730 pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
8731 PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308732 /* Use mpt2sas driver host template for SAS 2.0 HBA's */
8733 shost = scsi_host_alloc(&mpt2sas_driver_template,
8734 sizeof(struct MPT3SAS_ADAPTER));
8735 if (!shost)
8736 return -ENODEV;
8737 ioc = shost_priv(shost);
8738 memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
8739 ioc->hba_mpi_version_belonged = hba_mpi_version;
8740 ioc->id = mpt2_ids++;
8741 sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME);
8742 if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) {
8743 ioc->is_warpdrive = 1;
8744 ioc->hide_ir_msg = 1;
8745 } else
8746 ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
8747 break;
8748 case MPI25_VERSION:
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05308749 case MPI26_VERSION:
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308750 /* Use mpt3sas driver host template for SAS 3.0 HBA's */
8751 shost = scsi_host_alloc(&mpt3sas_driver_template,
8752 sizeof(struct MPT3SAS_ADAPTER));
8753 if (!shost)
8754 return -ENODEV;
8755 ioc = shost_priv(shost);
8756 memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
8757 ioc->hba_mpi_version_belonged = hba_mpi_version;
8758 ioc->id = mpt3_ids++;
8759 sprintf(ioc->driver_name, "%s", MPT3SAS_DRIVER_NAME);
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05308760 if ((ioc->hba_mpi_version_belonged == MPI25_VERSION &&
8761 pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION) ||
8762 (ioc->hba_mpi_version_belonged == MPI26_VERSION))
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308763 ioc->msix96_vector = 1;
8764 break;
8765 default:
8766 return -ENODEV;
8767 }
8768
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308769 INIT_LIST_HEAD(&ioc->list);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308770 spin_lock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308771 list_add_tail(&ioc->list, &mpt3sas_ioc_list);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308772 spin_unlock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308773 ioc->shost = shost;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308774 ioc->pdev = pdev;
8775 ioc->scsi_io_cb_idx = scsi_io_cb_idx;
8776 ioc->tm_cb_idx = tm_cb_idx;
8777 ioc->ctl_cb_idx = ctl_cb_idx;
8778 ioc->base_cb_idx = base_cb_idx;
8779 ioc->port_enable_cb_idx = port_enable_cb_idx;
8780 ioc->transport_cb_idx = transport_cb_idx;
8781 ioc->scsih_cb_idx = scsih_cb_idx;
8782 ioc->config_cb_idx = config_cb_idx;
8783 ioc->tm_tr_cb_idx = tm_tr_cb_idx;
8784 ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx;
8785 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
8786 ioc->logging_level = logging_level;
8787 ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
8788 /* misc semaphores and spin locks */
8789 mutex_init(&ioc->reset_in_progress_mutex);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308790 /* initializing pci_access_mutex lock */
8791 mutex_init(&ioc->pci_access_mutex);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308792 spin_lock_init(&ioc->ioc_reset_in_progress_lock);
8793 spin_lock_init(&ioc->scsi_lookup_lock);
8794 spin_lock_init(&ioc->sas_device_lock);
8795 spin_lock_init(&ioc->sas_node_lock);
8796 spin_lock_init(&ioc->fw_event_lock);
8797 spin_lock_init(&ioc->raid_device_lock);
8798 spin_lock_init(&ioc->diag_trigger_lock);
8799
8800 INIT_LIST_HEAD(&ioc->sas_device_list);
8801 INIT_LIST_HEAD(&ioc->sas_device_init_list);
8802 INIT_LIST_HEAD(&ioc->sas_expander_list);
8803 INIT_LIST_HEAD(&ioc->fw_event_list);
8804 INIT_LIST_HEAD(&ioc->raid_device_list);
8805 INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
8806 INIT_LIST_HEAD(&ioc->delayed_tr_list);
Suganath prabu Subramanifd0331b2016-01-28 12:07:02 +05308807 INIT_LIST_HEAD(&ioc->delayed_sc_list);
8808 INIT_LIST_HEAD(&ioc->delayed_event_ack_list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308809 INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
Joe Lawrencecf9bd21a2013-08-08 16:45:39 -04008810 INIT_LIST_HEAD(&ioc->reply_queue_list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308811
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308812 sprintf(ioc->name, "%s_cm%d", ioc->driver_name, ioc->id);
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308813
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308814 /* init shost parameters */
8815 shost->max_cmd_len = 32;
8816 shost->max_lun = max_lun;
8817 shost->transportt = mpt3sas_transport_template;
8818 shost->unique_id = ioc->id;
8819
8820 if (max_sectors != 0xFFFF) {
8821 if (max_sectors < 64) {
8822 shost->max_sectors = 64;
8823 pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
8824 "for max_sectors, range is 64 to 32767. Assigning "
8825 "value of 64.\n", ioc->name, max_sectors);
8826 } else if (max_sectors > 32767) {
8827 shost->max_sectors = 32767;
8828 pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
8829 "for max_sectors, range is 64 to 32767. Assigning "
8830 "default value of 32767.\n", ioc->name,
8831 max_sectors);
8832 } else {
8833 shost->max_sectors = max_sectors & 0xFFFE;
8834 pr_info(MPT3SAS_FMT
8835 "The max_sectors value is set to %d\n",
8836 ioc->name, shost->max_sectors);
8837 }
8838 }
8839
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308840 /* register EEDP capabilities with SCSI layer */
8841 if (prot_mask > 0)
8842 scsi_host_set_prot(shost, prot_mask);
8843 else
8844 scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
8845 | SHOST_DIF_TYPE2_PROTECTION
8846 | SHOST_DIF_TYPE3_PROTECTION);
8847
8848 scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
8849
8850 /* event thread */
8851 snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308852 "fw_event_%s%d", ioc->driver_name, ioc->id);
Sreekanth Reddybdff7852015-06-30 12:25:03 +05308853 ioc->firmware_event_thread = alloc_ordered_workqueue(
8854 ioc->firmware_event_name, WQ_MEM_RECLAIM);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308855 if (!ioc->firmware_event_thread) {
8856 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8857 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308858 rv = -ENODEV;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308859 goto out_thread_fail;
8860 }
8861
8862 ioc->is_driver_loading = 1;
8863 if ((mpt3sas_base_attach(ioc))) {
8864 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8865 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308866 rv = -ENODEV;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308867 goto out_attach_fail;
8868 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308869
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308870 if (ioc->is_warpdrive) {
8871 if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
8872 ioc->hide_drives = 0;
8873 else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS)
8874 ioc->hide_drives = 1;
8875 else {
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05308876 if (mpt3sas_get_num_volumes(ioc))
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308877 ioc->hide_drives = 1;
8878 else
8879 ioc->hide_drives = 0;
8880 }
8881 } else
8882 ioc->hide_drives = 0;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308883
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308884 rv = scsi_add_host(shost, &pdev->dev);
8885 if (rv) {
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308886 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8887 ioc->name, __FILE__, __LINE__, __func__);
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308888 goto out_add_shost_fail;
8889 }
8890
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308891 scsi_scan_host(shost);
8892 return 0;
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308893out_add_shost_fail:
8894 mpt3sas_base_detach(ioc);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308895 out_attach_fail:
8896 destroy_workqueue(ioc->firmware_event_thread);
8897 out_thread_fail:
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308898 spin_lock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308899 list_del(&ioc->list);
Sreekanth Reddy08c4d552015-11-11 17:30:33 +05308900 spin_unlock(&gioc_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308901 scsi_host_put(shost);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308902 return rv;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308903}
8904
8905#ifdef CONFIG_PM
8906/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308907 * scsih_suspend - power management suspend main entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308908 * @pdev: PCI device struct
8909 * @state: PM state change to (usually PCI_D3)
8910 *
8911 * Returns 0 success, anything else error.
8912 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008913static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308914scsih_suspend(struct pci_dev *pdev, pm_message_t state)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308915{
8916 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8917 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8918 pci_power_t device_state;
8919
8920 mpt3sas_base_stop_watchdog(ioc);
8921 flush_scheduled_work();
8922 scsi_block_requests(shost);
8923 device_state = pci_choose_state(pdev, state);
8924 pr_info(MPT3SAS_FMT
8925 "pdev=0x%p, slot=%s, entering operating state [D%d]\n",
8926 ioc->name, pdev, pci_name(pdev), device_state);
8927
8928 pci_save_state(pdev);
8929 mpt3sas_base_free_resources(ioc);
8930 pci_set_power_state(pdev, device_state);
8931 return 0;
8932}
8933
8934/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308935 * scsih_resume - power management resume main entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308936 * @pdev: PCI device struct
8937 *
8938 * Returns 0 success, anything else error.
8939 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008940static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308941scsih_resume(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308942{
8943 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8944 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8945 pci_power_t device_state = pdev->current_state;
8946 int r;
8947
8948 pr_info(MPT3SAS_FMT
8949 "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
8950 ioc->name, pdev, pci_name(pdev), device_state);
8951
8952 pci_set_power_state(pdev, PCI_D0);
8953 pci_enable_wake(pdev, PCI_D0, 0);
8954 pci_restore_state(pdev);
8955 ioc->pdev = pdev;
8956 r = mpt3sas_base_map_resources(ioc);
8957 if (r)
8958 return r;
8959
Calvin Owens98c56ad2016-07-28 21:38:21 -07008960 mpt3sas_base_hard_reset_handler(ioc, SOFT_RESET);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308961 scsi_unblock_requests(shost);
8962 mpt3sas_base_start_watchdog(ioc);
8963 return 0;
8964}
8965#endif /* CONFIG_PM */
8966
8967/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308968 * scsih_pci_error_detected - Called when a PCI error is detected.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308969 * @pdev: PCI device struct
8970 * @state: PCI channel state
8971 *
8972 * Description: Called when a PCI error is detected.
8973 *
8974 * Return value:
8975 * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
8976 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07008977static pci_ers_result_t
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308978scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308979{
8980 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8981 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8982
8983 pr_info(MPT3SAS_FMT "PCI error: detected callback, state(%d)!!\n",
8984 ioc->name, state);
8985
8986 switch (state) {
8987 case pci_channel_io_normal:
8988 return PCI_ERS_RESULT_CAN_RECOVER;
8989 case pci_channel_io_frozen:
8990 /* Fatal error, prepare for slot reset */
8991 ioc->pci_error_recovery = 1;
8992 scsi_block_requests(ioc->shost);
8993 mpt3sas_base_stop_watchdog(ioc);
8994 mpt3sas_base_free_resources(ioc);
8995 return PCI_ERS_RESULT_NEED_RESET;
8996 case pci_channel_io_perm_failure:
8997 /* Permanent error, prepare for device removal */
8998 ioc->pci_error_recovery = 1;
8999 mpt3sas_base_stop_watchdog(ioc);
9000 _scsih_flush_running_cmds(ioc);
9001 return PCI_ERS_RESULT_DISCONNECT;
9002 }
9003 return PCI_ERS_RESULT_NEED_RESET;
9004}
9005
9006/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309007 * scsih_pci_slot_reset - Called when PCI slot has been reset.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309008 * @pdev: PCI device struct
9009 *
9010 * Description: This routine is called by the pci error recovery
9011 * code after the PCI slot has been reset, just before we
9012 * should resume normal operations.
9013 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009014static pci_ers_result_t
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309015scsih_pci_slot_reset(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309016{
9017 struct Scsi_Host *shost = pci_get_drvdata(pdev);
9018 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
9019 int rc;
9020
9021 pr_info(MPT3SAS_FMT "PCI error: slot reset callback!!\n",
9022 ioc->name);
9023
9024 ioc->pci_error_recovery = 0;
9025 ioc->pdev = pdev;
9026 pci_restore_state(pdev);
9027 rc = mpt3sas_base_map_resources(ioc);
9028 if (rc)
9029 return PCI_ERS_RESULT_DISCONNECT;
9030
Calvin Owens98c56ad2016-07-28 21:38:21 -07009031 rc = mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309032
9033 pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name,
9034 (rc == 0) ? "success" : "failed");
9035
9036 if (!rc)
9037 return PCI_ERS_RESULT_RECOVERED;
9038 else
9039 return PCI_ERS_RESULT_DISCONNECT;
9040}
9041
9042/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309043 * scsih_pci_resume() - resume normal ops after PCI reset
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309044 * @pdev: pointer to PCI device
9045 *
9046 * Called when the error recovery driver tells us that its
9047 * OK to resume normal operation. Use completion to allow
9048 * halted scsi ops to resume.
9049 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009050static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309051scsih_pci_resume(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
9056 pr_info(MPT3SAS_FMT "PCI error: resume callback!!\n", ioc->name);
9057
9058 pci_cleanup_aer_uncorrect_error_status(pdev);
9059 mpt3sas_base_start_watchdog(ioc);
9060 scsi_unblock_requests(ioc->shost);
9061}
9062
9063/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309064 * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309065 * @pdev: pointer to PCI device
9066 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009067static pci_ers_result_t
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309068scsih_pci_mmio_enabled(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309069{
9070 struct Scsi_Host *shost = pci_get_drvdata(pdev);
9071 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
9072
9073 pr_info(MPT3SAS_FMT "PCI error: mmio enabled callback!!\n",
9074 ioc->name);
9075
9076 /* TODO - dump whatever for debugging purposes */
9077
Kefeng Wang83c3d342016-07-12 17:43:25 +08009078 /* This called only if scsih_pci_error_detected returns
9079 * PCI_ERS_RESULT_CAN_RECOVER. Read/write to the device still
9080 * works, no need to reset slot.
9081 */
9082 return PCI_ERS_RESULT_RECOVERED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309083}
9084
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05309085/*
9086 * The pci device ids are defined in mpi/mpi2_cnfg.h.
9087 */
9088static const struct pci_device_id mpt3sas_pci_table[] = {
9089 /* Spitfire ~ 2004 */
9090 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
9091 PCI_ANY_ID, PCI_ANY_ID },
9092 /* Falcon ~ 2008 */
9093 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
9094 PCI_ANY_ID, PCI_ANY_ID },
9095 /* Liberator ~ 2108 */
9096 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
9097 PCI_ANY_ID, PCI_ANY_ID },
9098 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
9099 PCI_ANY_ID, PCI_ANY_ID },
9100 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
9101 PCI_ANY_ID, PCI_ANY_ID },
9102 /* Meteor ~ 2116 */
9103 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
9104 PCI_ANY_ID, PCI_ANY_ID },
9105 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
9106 PCI_ANY_ID, PCI_ANY_ID },
9107 /* Thunderbolt ~ 2208 */
9108 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1,
9109 PCI_ANY_ID, PCI_ANY_ID },
9110 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2,
9111 PCI_ANY_ID, PCI_ANY_ID },
9112 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3,
9113 PCI_ANY_ID, PCI_ANY_ID },
9114 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4,
9115 PCI_ANY_ID, PCI_ANY_ID },
9116 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5,
9117 PCI_ANY_ID, PCI_ANY_ID },
9118 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6,
9119 PCI_ANY_ID, PCI_ANY_ID },
9120 /* Mustang ~ 2308 */
9121 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1,
9122 PCI_ANY_ID, PCI_ANY_ID },
9123 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2,
9124 PCI_ANY_ID, PCI_ANY_ID },
9125 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
9126 PCI_ANY_ID, PCI_ANY_ID },
9127 /* SSS6200 */
9128 { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
9129 PCI_ANY_ID, PCI_ANY_ID },
9130 /* Fury ~ 3004 and 3008 */
9131 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004,
9132 PCI_ANY_ID, PCI_ANY_ID },
9133 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008,
9134 PCI_ANY_ID, PCI_ANY_ID },
9135 /* Invader ~ 3108 */
9136 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1,
9137 PCI_ANY_ID, PCI_ANY_ID },
9138 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2,
9139 PCI_ANY_ID, PCI_ANY_ID },
9140 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5,
9141 PCI_ANY_ID, PCI_ANY_ID },
9142 { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6,
9143 PCI_ANY_ID, PCI_ANY_ID },
Suganath prabu Subramanib130b0d2016-01-28 12:06:58 +05309144 /* Cutlass ~ 3216 and 3224 */
9145 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3216,
9146 PCI_ANY_ID, PCI_ANY_ID },
9147 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3224,
9148 PCI_ANY_ID, PCI_ANY_ID },
9149 /* Intruder ~ 3316 and 3324 */
9150 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_1,
9151 PCI_ANY_ID, PCI_ANY_ID },
9152 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_2,
9153 PCI_ANY_ID, PCI_ANY_ID },
9154 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_3,
9155 PCI_ANY_ID, PCI_ANY_ID },
9156 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3316_4,
9157 PCI_ANY_ID, PCI_ANY_ID },
9158 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_1,
9159 PCI_ANY_ID, PCI_ANY_ID },
9160 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_2,
9161 PCI_ANY_ID, PCI_ANY_ID },
9162 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_3,
9163 PCI_ANY_ID, PCI_ANY_ID },
9164 { MPI2_MFGPAGE_VENDORID_LSI, MPI26_MFGPAGE_DEVID_SAS3324_4,
9165 PCI_ANY_ID, PCI_ANY_ID },
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05309166 {0} /* Terminating entry */
9167};
9168MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table);
9169
9170static struct pci_error_handlers _mpt3sas_err_handler = {
9171 .error_detected = scsih_pci_error_detected,
9172 .mmio_enabled = scsih_pci_mmio_enabled,
9173 .slot_reset = scsih_pci_slot_reset,
9174 .resume = scsih_pci_resume,
9175};
9176
9177static struct pci_driver mpt3sas_driver = {
9178 .name = MPT3SAS_DRIVER_NAME,
9179 .id_table = mpt3sas_pci_table,
9180 .probe = _scsih_probe,
9181 .remove = scsih_remove,
9182 .shutdown = scsih_shutdown,
9183 .err_handler = &_mpt3sas_err_handler,
9184#ifdef CONFIG_PM
9185 .suspend = scsih_suspend,
9186 .resume = scsih_resume,
9187#endif
9188};
9189
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309190/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309191 * scsih_init - main entry point for this driver.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309192 *
9193 * Returns 0 success, anything else error.
9194 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009195static int
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309196scsih_init(void)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309197{
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05309198 mpt2_ids = 0;
9199 mpt3_ids = 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309200
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309201 mpt3sas_base_initialize_callback_handler();
9202
9203 /* queuecommand callback hander */
9204 scsi_io_cb_idx = mpt3sas_base_register_callback_handler(_scsih_io_done);
9205
9206 /* task managment callback handler */
9207 tm_cb_idx = mpt3sas_base_register_callback_handler(_scsih_tm_done);
9208
9209 /* base internal commands callback handler */
9210 base_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_base_done);
9211 port_enable_cb_idx = mpt3sas_base_register_callback_handler(
9212 mpt3sas_port_enable_done);
9213
9214 /* transport internal commands callback handler */
9215 transport_cb_idx = mpt3sas_base_register_callback_handler(
9216 mpt3sas_transport_done);
9217
9218 /* scsih internal commands callback handler */
9219 scsih_cb_idx = mpt3sas_base_register_callback_handler(_scsih_done);
9220
9221 /* configuration page API internal commands callback handler */
9222 config_cb_idx = mpt3sas_base_register_callback_handler(
9223 mpt3sas_config_done);
9224
9225 /* ctl module callback handler */
9226 ctl_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_ctl_done);
9227
9228 tm_tr_cb_idx = mpt3sas_base_register_callback_handler(
9229 _scsih_tm_tr_complete);
9230
9231 tm_tr_volume_cb_idx = mpt3sas_base_register_callback_handler(
9232 _scsih_tm_volume_tr_complete);
9233
9234 tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
9235 _scsih_sas_control_complete);
9236
Sreekanth Reddy7497392a2015-11-11 17:30:19 +05309237 return 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309238}
9239
9240/**
Sreekanth Reddy7497392a2015-11-11 17:30:19 +05309241 * scsih_exit - exit point for this driver (when it is a module).
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309242 *
9243 * Returns 0 success, anything else error.
9244 */
Calvin Owens8bbb1cf2016-07-28 21:38:22 -07009245static void
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05309246scsih_exit(void)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309247{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309248
9249 mpt3sas_base_release_callback_handler(scsi_io_cb_idx);
9250 mpt3sas_base_release_callback_handler(tm_cb_idx);
9251 mpt3sas_base_release_callback_handler(base_cb_idx);
9252 mpt3sas_base_release_callback_handler(port_enable_cb_idx);
9253 mpt3sas_base_release_callback_handler(transport_cb_idx);
9254 mpt3sas_base_release_callback_handler(scsih_cb_idx);
9255 mpt3sas_base_release_callback_handler(config_cb_idx);
9256 mpt3sas_base_release_callback_handler(ctl_cb_idx);
9257
9258 mpt3sas_base_release_callback_handler(tm_tr_cb_idx);
9259 mpt3sas_base_release_callback_handler(tm_tr_volume_cb_idx);
9260 mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx);
9261
9262/* raid transport support */
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05309263 if (hbas_to_enumerate != 1)
9264 raid_class_release(mpt3sas_raid_template);
9265 if (hbas_to_enumerate != 2)
9266 raid_class_release(mpt2sas_raid_template);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05309267 sas_release_transport(mpt3sas_transport_template);
9268}
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05309269
Sreekanth Reddyc84b06a2015-11-11 17:30:35 +05309270/**
9271 * _mpt3sas_init - main entry point for this driver.
9272 *
9273 * Returns 0 success, anything else error.
9274 */
9275static int __init
9276_mpt3sas_init(void)
9277{
9278 int error;
9279
9280 pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME,
9281 MPT3SAS_DRIVER_VERSION);
9282
9283 mpt3sas_transport_template =
9284 sas_attach_transport(&mpt3sas_transport_functions);
9285 if (!mpt3sas_transport_template)
9286 return -ENODEV;
9287
9288 /* No need attach mpt3sas raid functions template
9289 * if hbas_to_enumarate value is one.
9290 */
9291 if (hbas_to_enumerate != 1) {
9292 mpt3sas_raid_template =
9293 raid_class_attach(&mpt3sas_raid_functions);
9294 if (!mpt3sas_raid_template) {
9295 sas_release_transport(mpt3sas_transport_template);
9296 return -ENODEV;
9297 }
9298 }
9299
9300 /* No need to attach mpt2sas raid functions template
9301 * if hbas_to_enumarate value is two
9302 */
9303 if (hbas_to_enumerate != 2) {
9304 mpt2sas_raid_template =
9305 raid_class_attach(&mpt2sas_raid_functions);
9306 if (!mpt2sas_raid_template) {
9307 sas_release_transport(mpt3sas_transport_template);
9308 return -ENODEV;
9309 }
9310 }
9311
9312 error = scsih_init();
9313 if (error) {
9314 scsih_exit();
9315 return error;
9316 }
9317
9318 mpt3sas_ctl_init(hbas_to_enumerate);
9319
9320 error = pci_register_driver(&mpt3sas_driver);
9321 if (error)
9322 scsih_exit();
9323
9324 return error;
9325}
9326
9327/**
9328 * _mpt3sas_exit - exit point for this driver (when it is a module).
9329 *
9330 */
9331static void __exit
9332_mpt3sas_exit(void)
9333{
9334 pr_info("mpt3sas version %s unloading\n",
9335 MPT3SAS_DRIVER_VERSION);
9336
9337 pci_unregister_driver(&mpt3sas_driver);
9338
9339 mpt3sas_ctl_exit(hbas_to_enumerate);
9340
9341 scsih_exit();
9342}
9343
9344module_init(_mpt3sas_init);
9345module_exit(_mpt3sas_exit);