blob: 436e65e513ae79f396a5997b6f87af868374c43c [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>
54#include <linux/interrupt.h>
55#include <linux/aer.h>
56#include <linux/raid_class.h>
Sreekanth Reddy7786ab62015-11-11 17:30:28 +053057#include <asm/unaligned.h>
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053058
59#include "mpt3sas_base.h"
60
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053061#define RAID_CHANNEL 1
62/* forward proto's */
63static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
64 struct _sas_node *sas_expander);
65static void _firmware_event_work(struct work_struct *work);
66
67static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
68 struct _sas_device *sas_device);
69static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
70 u8 retry_count, u8 is_pd);
71
72static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
73
Sreekanth Reddy7786ab62015-11-11 17:30:28 +053074#ifdef SCSI_MPT2SAS
75static void _scsih_disable_ddio(struct MPT3SAS_ADAPTER *ioc);
76static u8 _scsih_get_num_volumes(struct MPT3SAS_ADAPTER *ioc);
77static void
78_scsih_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc,
79 struct _raid_device *raid_device);
80static inline u8
81_scsih_scsi_direct_io_get(struct MPT3SAS_ADAPTER *ioc, u16 smid);
82static inline void
83_scsih_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io);
84static void
85_scsih_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
86 struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request,
87 u16 smid);
88#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053089
90/* global parameters */
91LIST_HEAD(mpt3sas_ioc_list);
Sreekanth Reddyd357e842015-11-11 17:30:22 +053092char driver_name[MPT_NAME_LENGTH];
Sreekanth Reddyf92363d2012-11-30 07:44:21 +053093
94/* local parameters */
95static u8 scsi_io_cb_idx = -1;
96static u8 tm_cb_idx = -1;
97static u8 ctl_cb_idx = -1;
98static u8 base_cb_idx = -1;
99static u8 port_enable_cb_idx = -1;
100static u8 transport_cb_idx = -1;
101static u8 scsih_cb_idx = -1;
102static u8 config_cb_idx = -1;
103static int mpt_ids;
104
105static u8 tm_tr_cb_idx = -1 ;
106static u8 tm_tr_volume_cb_idx = -1 ;
107static u8 tm_sas_control_cb_idx = -1;
108
109/* command line options */
110static u32 logging_level;
111MODULE_PARM_DESC(logging_level,
112 " bits for enabling additional logging info (default=0)");
113
114
115static ushort max_sectors = 0xFFFF;
116module_param(max_sectors, ushort, 0);
117MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767");
118
119
120static int missing_delay[2] = {-1, -1};
121module_param_array(missing_delay, int, NULL, 0);
122MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
123
124/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
125#define MPT3SAS_MAX_LUN (16895)
Hannes Reinecke1abf6352014-06-25 15:27:38 +0200126static u64 max_lun = MPT3SAS_MAX_LUN;
127module_param(max_lun, ullong, 0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530128MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
129
130
131
132
133/* diag_buffer_enable is bitwise
134 * bit 0 set = TRACE
135 * bit 1 set = SNAPSHOT
136 * bit 2 set = EXTENDED
137 *
138 * Either bit can be set, or both
139 */
140static int diag_buffer_enable = -1;
141module_param(diag_buffer_enable, int, 0);
142MODULE_PARM_DESC(diag_buffer_enable,
143 " post diag buffers (TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)");
144static int disable_discovery = -1;
145module_param(disable_discovery, int, 0);
146MODULE_PARM_DESC(disable_discovery, " disable discovery ");
147
148
149/* permit overriding the host protection capabilities mask (EEDP/T10 PI) */
150static int prot_mask = -1;
151module_param(prot_mask, int, 0);
152MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
153
154
155/* raid transport support */
Sreekanth Reddy7497392a2015-11-11 17:30:19 +0530156struct raid_template *mpt3sas_raid_template;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530157
158
159/**
160 * struct sense_info - common structure for obtaining sense keys
161 * @skey: sense key
162 * @asc: additional sense code
163 * @ascq: additional sense code qualifier
164 */
165struct sense_info {
166 u8 skey;
167 u8 asc;
168 u8 ascq;
169};
170
171#define MPT3SAS_PROCESS_TRIGGER_DIAG (0xFFFB)
Sreekanth Reddy0f624c32014-09-12 15:35:26 +0530172#define MPT3SAS_TURN_ON_PFA_LED (0xFFFC)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530173#define MPT3SAS_PORT_ENABLE_COMPLETE (0xFFFD)
174#define MPT3SAS_ABRT_TASK_SET (0xFFFE)
175#define MPT3SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF)
176/**
177 * struct fw_event_work - firmware event struct
178 * @list: link list framework
179 * @work: work object (ioc->fault_reset_work_q)
180 * @cancel_pending_work: flag set during reset handling
181 * @ioc: per adapter object
182 * @device_handle: device handle
183 * @VF_ID: virtual function id
184 * @VP_ID: virtual port id
185 * @ignore: flag meaning this event has been marked to ignore
186 * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h
187 * @event_data: reply event data payload follows
188 *
189 * This object stored on ioc->fw_event_list.
190 */
191struct fw_event_work {
192 struct list_head list;
193 struct work_struct work;
194 u8 cancel_pending_work;
195 struct delayed_work delayed_work;
196
197 struct MPT3SAS_ADAPTER *ioc;
198 u16 device_handle;
199 u8 VF_ID;
200 u8 VP_ID;
201 u8 ignore;
202 u16 event;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +0530203 struct kref refcount;
Joe Lawrence35b62362014-06-25 17:05:34 -0400204 char event_data[0] __aligned(4);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530205};
206
Sreekanth Reddy146b16c2015-11-11 17:30:31 +0530207static void fw_event_work_free(struct kref *r)
208{
209 kfree(container_of(r, struct fw_event_work, refcount));
210}
211
212static void fw_event_work_get(struct fw_event_work *fw_work)
213{
214 kref_get(&fw_work->refcount);
215}
216
217static void fw_event_work_put(struct fw_event_work *fw_work)
218{
219 kref_put(&fw_work->refcount, fw_event_work_free);
220}
221
222static struct fw_event_work *alloc_fw_event_work(int len)
223{
224 struct fw_event_work *fw_event;
225
226 fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC);
227 if (!fw_event)
228 return NULL;
229
230 kref_init(&fw_event->refcount);
231 return fw_event;
232}
233
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530234/**
235 * struct _scsi_io_transfer - scsi io transfer
236 * @handle: sas device handle (assigned by firmware)
237 * @is_raid: flag set for hidden raid components
238 * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE,
239 * @data_length: data transfer length
240 * @data_dma: dma pointer to data
241 * @sense: sense data
242 * @lun: lun number
243 * @cdb_length: cdb length
244 * @cdb: cdb contents
245 * @timeout: timeout for this command
246 * @VF_ID: virtual function id
247 * @VP_ID: virtual port id
248 * @valid_reply: flag set for reply message
249 * @sense_length: sense length
250 * @ioc_status: ioc status
251 * @scsi_state: scsi state
252 * @scsi_status: scsi staus
253 * @log_info: log information
254 * @transfer_length: data length transfer when there is a reply message
255 *
256 * Used for sending internal scsi commands to devices within this module.
257 * Refer to _scsi_send_scsi_io().
258 */
259struct _scsi_io_transfer {
260 u16 handle;
261 u8 is_raid;
262 enum dma_data_direction dir;
263 u32 data_length;
264 dma_addr_t data_dma;
265 u8 sense[SCSI_SENSE_BUFFERSIZE];
266 u32 lun;
267 u8 cdb_length;
268 u8 cdb[32];
269 u8 timeout;
270 u8 VF_ID;
271 u8 VP_ID;
272 u8 valid_reply;
273 /* the following bits are only valid when 'valid_reply = 1' */
274 u32 sense_length;
275 u16 ioc_status;
276 u8 scsi_state;
277 u8 scsi_status;
278 u32 log_info;
279 u32 transfer_length;
280};
281
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530282/**
283 * _scsih_set_debug_level - global setting of ioc->logging_level.
284 *
285 * Note: The logging levels are defined in mpt3sas_debug.h.
286 */
287static int
288_scsih_set_debug_level(const char *val, struct kernel_param *kp)
289{
290 int ret = param_set_int(val, kp);
291 struct MPT3SAS_ADAPTER *ioc;
292
293 if (ret)
294 return ret;
295
296 pr_info("setting logging_level(0x%08x)\n", logging_level);
297 list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
298 ioc->logging_level = logging_level;
299 return 0;
300}
301module_param_call(logging_level, _scsih_set_debug_level, param_get_int,
302 &logging_level, 0644);
303
304/**
305 * _scsih_srch_boot_sas_address - search based on sas_address
306 * @sas_address: sas address
307 * @boot_device: boot device object from bios page 2
308 *
309 * Returns 1 when there's a match, 0 means no match.
310 */
311static inline int
312_scsih_srch_boot_sas_address(u64 sas_address,
313 Mpi2BootDeviceSasWwid_t *boot_device)
314{
315 return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0;
316}
317
318/**
319 * _scsih_srch_boot_device_name - search based on device name
320 * @device_name: device name specified in INDENTIFY fram
321 * @boot_device: boot device object from bios page 2
322 *
323 * Returns 1 when there's a match, 0 means no match.
324 */
325static inline int
326_scsih_srch_boot_device_name(u64 device_name,
327 Mpi2BootDeviceDeviceName_t *boot_device)
328{
329 return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0;
330}
331
332/**
333 * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot
334 * @enclosure_logical_id: enclosure logical id
335 * @slot_number: slot number
336 * @boot_device: boot device object from bios page 2
337 *
338 * Returns 1 when there's a match, 0 means no match.
339 */
340static inline int
341_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
342 Mpi2BootDeviceEnclosureSlot_t *boot_device)
343{
344 return (enclosure_logical_id == le64_to_cpu(boot_device->
345 EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device->
346 SlotNumber)) ? 1 : 0;
347}
348
349/**
350 * _scsih_is_boot_device - search for matching boot device.
351 * @sas_address: sas address
352 * @device_name: device name specified in INDENTIFY fram
353 * @enclosure_logical_id: enclosure logical id
354 * @slot_number: slot number
355 * @form: specifies boot device form
356 * @boot_device: boot device object from bios page 2
357 *
358 * Returns 1 when there's a match, 0 means no match.
359 */
360static int
361_scsih_is_boot_device(u64 sas_address, u64 device_name,
362 u64 enclosure_logical_id, u16 slot, u8 form,
363 Mpi2BiosPage2BootDevice_t *boot_device)
364{
365 int rc = 0;
366
367 switch (form) {
368 case MPI2_BIOSPAGE2_FORM_SAS_WWID:
369 if (!sas_address)
370 break;
371 rc = _scsih_srch_boot_sas_address(
372 sas_address, &boot_device->SasWwid);
373 break;
374 case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT:
375 if (!enclosure_logical_id)
376 break;
377 rc = _scsih_srch_boot_encl_slot(
378 enclosure_logical_id,
379 slot, &boot_device->EnclosureSlot);
380 break;
381 case MPI2_BIOSPAGE2_FORM_DEVICE_NAME:
382 if (!device_name)
383 break;
384 rc = _scsih_srch_boot_device_name(
385 device_name, &boot_device->DeviceName);
386 break;
387 case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED:
388 break;
389 }
390
391 return rc;
392}
393
394/**
395 * _scsih_get_sas_address - set the sas_address for given device handle
396 * @handle: device handle
397 * @sas_address: sas address
398 *
399 * Returns 0 success, non-zero when failure
400 */
401static int
402_scsih_get_sas_address(struct MPT3SAS_ADAPTER *ioc, u16 handle,
403 u64 *sas_address)
404{
405 Mpi2SasDevicePage0_t sas_device_pg0;
406 Mpi2ConfigReply_t mpi_reply;
407 u32 ioc_status;
408
409 *sas_address = 0;
410
411 if (handle <= ioc->sas_hba.num_phys) {
412 *sas_address = ioc->sas_hba.sas_address;
413 return 0;
414 }
415
416 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
417 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
418 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
419 __FILE__, __LINE__, __func__);
420 return -ENXIO;
421 }
422
423 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
424 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
425 *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
426 return 0;
427 }
428
429 /* we hit this becuase the given parent handle doesn't exist */
430 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
431 return -ENXIO;
432
433 /* else error case */
434 pr_err(MPT3SAS_FMT
435 "handle(0x%04x), ioc_status(0x%04x), failure at %s:%d/%s()!\n",
436 ioc->name, handle, ioc_status,
437 __FILE__, __LINE__, __func__);
438 return -EIO;
439}
440
441/**
442 * _scsih_determine_boot_device - determine boot device.
443 * @ioc: per adapter object
444 * @device: either sas_device or raid_device object
445 * @is_raid: [flag] 1 = raid object, 0 = sas object
446 *
447 * Determines whether this device should be first reported device to
448 * to scsi-ml or sas transport, this purpose is for persistent boot device.
449 * There are primary, alternate, and current entries in bios page 2. The order
450 * priority is primary, alternate, then current. This routine saves
451 * the corresponding device object and is_raid flag in the ioc object.
452 * The saved data to be used later in _scsih_probe_boot_devices().
453 */
454static void
455_scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc,
456 void *device, u8 is_raid)
457{
458 struct _sas_device *sas_device;
459 struct _raid_device *raid_device;
460 u64 sas_address;
461 u64 device_name;
462 u64 enclosure_logical_id;
463 u16 slot;
464
465 /* only process this function when driver loads */
466 if (!ioc->is_driver_loading)
467 return;
468
469 /* no Bios, return immediately */
470 if (!ioc->bios_pg3.BiosVersion)
471 return;
472
473 if (!is_raid) {
474 sas_device = device;
475 sas_address = sas_device->sas_address;
476 device_name = sas_device->device_name;
477 enclosure_logical_id = sas_device->enclosure_logical_id;
478 slot = sas_device->slot;
479 } else {
480 raid_device = device;
481 sas_address = raid_device->wwid;
482 device_name = 0;
483 enclosure_logical_id = 0;
484 slot = 0;
485 }
486
487 if (!ioc->req_boot_device.device) {
488 if (_scsih_is_boot_device(sas_address, device_name,
489 enclosure_logical_id, slot,
490 (ioc->bios_pg2.ReqBootDeviceForm &
491 MPI2_BIOSPAGE2_FORM_MASK),
492 &ioc->bios_pg2.RequestedBootDevice)) {
493 dinitprintk(ioc, pr_info(MPT3SAS_FMT
494 "%s: req_boot_device(0x%016llx)\n",
495 ioc->name, __func__,
496 (unsigned long long)sas_address));
497 ioc->req_boot_device.device = device;
498 ioc->req_boot_device.is_raid = is_raid;
499 }
500 }
501
502 if (!ioc->req_alt_boot_device.device) {
503 if (_scsih_is_boot_device(sas_address, device_name,
504 enclosure_logical_id, slot,
505 (ioc->bios_pg2.ReqAltBootDeviceForm &
506 MPI2_BIOSPAGE2_FORM_MASK),
507 &ioc->bios_pg2.RequestedAltBootDevice)) {
508 dinitprintk(ioc, pr_info(MPT3SAS_FMT
509 "%s: req_alt_boot_device(0x%016llx)\n",
510 ioc->name, __func__,
511 (unsigned long long)sas_address));
512 ioc->req_alt_boot_device.device = device;
513 ioc->req_alt_boot_device.is_raid = is_raid;
514 }
515 }
516
517 if (!ioc->current_boot_device.device) {
518 if (_scsih_is_boot_device(sas_address, device_name,
519 enclosure_logical_id, slot,
520 (ioc->bios_pg2.CurrentBootDeviceForm &
521 MPI2_BIOSPAGE2_FORM_MASK),
522 &ioc->bios_pg2.CurrentBootDevice)) {
523 dinitprintk(ioc, pr_info(MPT3SAS_FMT
524 "%s: current_boot_device(0x%016llx)\n",
525 ioc->name, __func__,
526 (unsigned long long)sas_address));
527 ioc->current_boot_device.device = device;
528 ioc->current_boot_device.is_raid = is_raid;
529 }
530 }
531}
532
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530533static struct _sas_device *
534__mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc,
535 struct MPT3SAS_TARGET *tgt_priv)
536{
537 struct _sas_device *ret;
538
539 assert_spin_locked(&ioc->sas_device_lock);
540
541 ret = tgt_priv->sdev;
542 if (ret)
543 sas_device_get(ret);
544
545 return ret;
546}
547
548static struct _sas_device *
549mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc,
550 struct MPT3SAS_TARGET *tgt_priv)
551{
552 struct _sas_device *ret;
553 unsigned long flags;
554
555 spin_lock_irqsave(&ioc->sas_device_lock, flags);
556 ret = __mpt3sas_get_sdev_from_target(ioc, tgt_priv);
557 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
558
559 return ret;
560}
561
562
563struct _sas_device *
564__mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
565 u64 sas_address)
566{
567 struct _sas_device *sas_device;
568
569 assert_spin_locked(&ioc->sas_device_lock);
570
571 list_for_each_entry(sas_device, &ioc->sas_device_list, list)
572 if (sas_device->sas_address == sas_address)
573 goto found_device;
574
575 list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
576 if (sas_device->sas_address == sas_address)
577 goto found_device;
578
579 return NULL;
580
581found_device:
582 sas_device_get(sas_device);
583 return sas_device;
584}
585
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530586/**
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530587 * mpt3sas_get_sdev_by_addr - sas device search
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530588 * @ioc: per adapter object
589 * @sas_address: sas address
590 * Context: Calling function should acquire ioc->sas_device_lock
591 *
592 * This searches for sas_device based on sas_address, then return sas_device
593 * object.
594 */
595struct _sas_device *
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530596mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530597 u64 sas_address)
598{
599 struct _sas_device *sas_device;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530600 unsigned long flags;
601
602 spin_lock_irqsave(&ioc->sas_device_lock, flags);
603 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
604 sas_address);
605 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
606
607 return sas_device;
608}
609
610static struct _sas_device *
611__mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
612{
613 struct _sas_device *sas_device;
614
615 assert_spin_locked(&ioc->sas_device_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530616
617 list_for_each_entry(sas_device, &ioc->sas_device_list, list)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530618 if (sas_device->handle == handle)
619 goto found_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530620
621 list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530622 if (sas_device->handle == handle)
623 goto found_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530624
625 return NULL;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530626
627found_device:
628 sas_device_get(sas_device);
629 return sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530630}
631
632/**
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530633 * mpt3sas_get_sdev_by_handle - sas device search
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530634 * @ioc: per adapter object
635 * @handle: sas device handle (assigned by firmware)
636 * Context: Calling function should acquire ioc->sas_device_lock
637 *
638 * This searches for sas_device based on sas_address, then return sas_device
639 * object.
640 */
641static struct _sas_device *
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530642mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530643{
644 struct _sas_device *sas_device;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530645 unsigned long flags;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530646
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530647 spin_lock_irqsave(&ioc->sas_device_lock, flags);
648 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
649 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530650
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530651 return sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530652}
653
654/**
655 * _scsih_sas_device_remove - remove sas_device from list.
656 * @ioc: per adapter object
657 * @sas_device: the sas_device object
658 * Context: This function will acquire ioc->sas_device_lock.
659 *
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530660 * If sas_device is on the list, remove it and decrement its reference count.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530661 */
662static void
663_scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
664 struct _sas_device *sas_device)
665{
666 unsigned long flags;
667
668 if (!sas_device)
669 return;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +0530670 pr_info(MPT3SAS_FMT
671 "removing handle(0x%04x), sas_addr(0x%016llx)\n",
672 ioc->name, sas_device->handle,
673 (unsigned long long) sas_device->sas_address);
674
675 if (sas_device->enclosure_handle != 0)
676 pr_info(MPT3SAS_FMT
677 "removing enclosure logical id(0x%016llx), slot(%d)\n",
678 ioc->name, (unsigned long long)
679 sas_device->enclosure_logical_id, sas_device->slot);
680
681 if (sas_device->connector_name[0] != '\0')
682 pr_info(MPT3SAS_FMT
683 "removing enclosure level(0x%04x), connector name( %s)\n",
684 ioc->name, sas_device->enclosure_level,
685 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530686
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530687 /*
688 * The lock serializes access to the list, but we still need to verify
689 * that nobody removed the entry while we were waiting on the lock.
690 */
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530691 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530692 if (!list_empty(&sas_device->list)) {
693 list_del_init(&sas_device->list);
694 sas_device_put(sas_device);
695 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530696 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
697}
698
699/**
700 * _scsih_device_remove_by_handle - removing device object by handle
701 * @ioc: per adapter object
702 * @handle: device handle
703 *
704 * Return nothing.
705 */
706static void
707_scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
708{
709 struct _sas_device *sas_device;
710 unsigned long flags;
711
712 if (ioc->shost_recovery)
713 return;
714
715 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530716 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
717 if (sas_device) {
718 list_del_init(&sas_device->list);
719 sas_device_put(sas_device);
720 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530721 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530722 if (sas_device) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530723 _scsih_remove_device(ioc, sas_device);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530724 sas_device_put(sas_device);
725 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530726}
727
728/**
729 * mpt3sas_device_remove_by_sas_address - removing device object by sas address
730 * @ioc: per adapter object
731 * @sas_address: device sas_address
732 *
733 * Return nothing.
734 */
735void
736mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
737 u64 sas_address)
738{
739 struct _sas_device *sas_device;
740 unsigned long flags;
741
742 if (ioc->shost_recovery)
743 return;
744
745 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530746 sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address);
747 if (sas_device) {
748 list_del_init(&sas_device->list);
749 sas_device_put(sas_device);
750 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530751 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530752 if (sas_device) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530753 _scsih_remove_device(ioc, sas_device);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530754 sas_device_put(sas_device);
755 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530756}
757
758/**
759 * _scsih_sas_device_add - insert sas_device to the list.
760 * @ioc: per adapter object
761 * @sas_device: the sas_device object
762 * Context: This function will acquire ioc->sas_device_lock.
763 *
764 * Adding new object to the ioc->sas_device_list.
765 */
766static void
767_scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
768 struct _sas_device *sas_device)
769{
770 unsigned long flags;
771
772 dewtprintk(ioc, pr_info(MPT3SAS_FMT
773 "%s: handle(0x%04x), sas_addr(0x%016llx)\n",
774 ioc->name, __func__, sas_device->handle,
775 (unsigned long long)sas_device->sas_address));
776
Sreekanth Reddye6d45e32015-06-30 12:24:52 +0530777 if (sas_device->enclosure_handle != 0)
778 dewtprintk(ioc, pr_info(MPT3SAS_FMT
779 "%s: enclosure logical id(0x%016llx), slot( %d)\n",
780 ioc->name, __func__, (unsigned long long)
781 sas_device->enclosure_logical_id, sas_device->slot));
782
783 if (sas_device->connector_name[0] != '\0')
784 dewtprintk(ioc, pr_info(MPT3SAS_FMT
785 "%s: enclosure level(0x%04x), connector name( %s)\n",
786 ioc->name, __func__,
787 sas_device->enclosure_level, sas_device->connector_name));
788
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530789 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530790 sas_device_get(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530791 list_add_tail(&sas_device->list, &ioc->sas_device_list);
792 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
793
794 if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
795 sas_device->sas_address_parent)) {
796 _scsih_sas_device_remove(ioc, sas_device);
797 } else if (!sas_device->starget) {
798 /*
799 * When asyn scanning is enabled, its not possible to remove
800 * devices while scanning is turned on due to an oops in
801 * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start()
802 */
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +0530803 if (!ioc->is_driver_loading) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530804 mpt3sas_transport_port_remove(ioc,
805 sas_device->sas_address,
806 sas_device->sas_address_parent);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +0530807 _scsih_sas_device_remove(ioc, sas_device);
808 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530809 }
810}
811
812/**
813 * _scsih_sas_device_init_add - insert sas_device to the list.
814 * @ioc: per adapter object
815 * @sas_device: the sas_device object
816 * Context: This function will acquire ioc->sas_device_lock.
817 *
818 * Adding new object at driver load time to the ioc->sas_device_init_list.
819 */
820static void
821_scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc,
822 struct _sas_device *sas_device)
823{
824 unsigned long flags;
825
826 dewtprintk(ioc, pr_info(MPT3SAS_FMT
827 "%s: handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
828 __func__, sas_device->handle,
829 (unsigned long long)sas_device->sas_address));
830
Sreekanth Reddye6d45e32015-06-30 12:24:52 +0530831 if (sas_device->enclosure_handle != 0)
832 dewtprintk(ioc, pr_info(MPT3SAS_FMT
833 "%s: enclosure logical id(0x%016llx), slot( %d)\n",
834 ioc->name, __func__, (unsigned long long)
835 sas_device->enclosure_logical_id, sas_device->slot));
836
837 if (sas_device->connector_name[0] != '\0')
838 dewtprintk(ioc, pr_info(MPT3SAS_FMT
839 "%s: enclosure level(0x%04x), connector name( %s)\n",
840 ioc->name, __func__, sas_device->enclosure_level,
841 sas_device->connector_name));
842
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530843 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530844 sas_device_get(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530845 list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
846 _scsih_determine_boot_device(ioc, sas_device, 0);
847 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
848}
849
850/**
851 * _scsih_raid_device_find_by_id - raid device search
852 * @ioc: per adapter object
853 * @id: sas device target id
854 * @channel: sas device channel
855 * Context: Calling function should acquire ioc->raid_device_lock
856 *
857 * This searches for raid_device based on target id, then return raid_device
858 * object.
859 */
860static struct _raid_device *
861_scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel)
862{
863 struct _raid_device *raid_device, *r;
864
865 r = NULL;
866 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
867 if (raid_device->id == id && raid_device->channel == channel) {
868 r = raid_device;
869 goto out;
870 }
871 }
872
873 out:
874 return r;
875}
876
877/**
878 * _scsih_raid_device_find_by_handle - raid device search
879 * @ioc: per adapter object
880 * @handle: sas device handle (assigned by firmware)
881 * Context: Calling function should acquire ioc->raid_device_lock
882 *
883 * This searches for raid_device based on handle, then return raid_device
884 * object.
885 */
886static struct _raid_device *
887_scsih_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
888{
889 struct _raid_device *raid_device, *r;
890
891 r = NULL;
892 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
893 if (raid_device->handle != handle)
894 continue;
895 r = raid_device;
896 goto out;
897 }
898
899 out:
900 return r;
901}
902
903/**
904 * _scsih_raid_device_find_by_wwid - raid device search
905 * @ioc: per adapter object
906 * @handle: sas device handle (assigned by firmware)
907 * Context: Calling function should acquire ioc->raid_device_lock
908 *
909 * This searches for raid_device based on wwid, then return raid_device
910 * object.
911 */
912static struct _raid_device *
913_scsih_raid_device_find_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid)
914{
915 struct _raid_device *raid_device, *r;
916
917 r = NULL;
918 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
919 if (raid_device->wwid != wwid)
920 continue;
921 r = raid_device;
922 goto out;
923 }
924
925 out:
926 return r;
927}
928
929/**
930 * _scsih_raid_device_add - add raid_device object
931 * @ioc: per adapter object
932 * @raid_device: raid_device object
933 *
934 * This is added to the raid_device_list link list.
935 */
936static void
937_scsih_raid_device_add(struct MPT3SAS_ADAPTER *ioc,
938 struct _raid_device *raid_device)
939{
940 unsigned long flags;
941
942 dewtprintk(ioc, pr_info(MPT3SAS_FMT
943 "%s: handle(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
944 raid_device->handle, (unsigned long long)raid_device->wwid));
945
946 spin_lock_irqsave(&ioc->raid_device_lock, flags);
947 list_add_tail(&raid_device->list, &ioc->raid_device_list);
948 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
949}
950
951/**
952 * _scsih_raid_device_remove - delete raid_device object
953 * @ioc: per adapter object
954 * @raid_device: raid_device object
955 *
956 */
957static void
958_scsih_raid_device_remove(struct MPT3SAS_ADAPTER *ioc,
959 struct _raid_device *raid_device)
960{
961 unsigned long flags;
962
963 spin_lock_irqsave(&ioc->raid_device_lock, flags);
964 list_del(&raid_device->list);
965 kfree(raid_device);
966 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
967}
968
969/**
970 * mpt3sas_scsih_expander_find_by_handle - expander device search
971 * @ioc: per adapter object
972 * @handle: expander handle (assigned by firmware)
973 * Context: Calling function should acquire ioc->sas_device_lock
974 *
975 * This searches for expander device based on handle, then returns the
976 * sas_node object.
977 */
978struct _sas_node *
979mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
980{
981 struct _sas_node *sas_expander, *r;
982
983 r = NULL;
984 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
985 if (sas_expander->handle != handle)
986 continue;
987 r = sas_expander;
988 goto out;
989 }
990 out:
991 return r;
992}
993
994/**
995 * mpt3sas_scsih_expander_find_by_sas_address - expander device search
996 * @ioc: per adapter object
997 * @sas_address: sas address
998 * Context: Calling function should acquire ioc->sas_node_lock.
999 *
1000 * This searches for expander device based on sas_address, then returns the
1001 * sas_node object.
1002 */
1003struct _sas_node *
1004mpt3sas_scsih_expander_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
1005 u64 sas_address)
1006{
1007 struct _sas_node *sas_expander, *r;
1008
1009 r = NULL;
1010 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
1011 if (sas_expander->sas_address != sas_address)
1012 continue;
1013 r = sas_expander;
1014 goto out;
1015 }
1016 out:
1017 return r;
1018}
1019
1020/**
1021 * _scsih_expander_node_add - insert expander device to the list.
1022 * @ioc: per adapter object
1023 * @sas_expander: the sas_device object
1024 * Context: This function will acquire ioc->sas_node_lock.
1025 *
1026 * Adding new object to the ioc->sas_expander_list.
1027 *
1028 * Return nothing.
1029 */
1030static void
1031_scsih_expander_node_add(struct MPT3SAS_ADAPTER *ioc,
1032 struct _sas_node *sas_expander)
1033{
1034 unsigned long flags;
1035
1036 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1037 list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
1038 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1039}
1040
1041/**
1042 * _scsih_is_end_device - determines if device is an end device
1043 * @device_info: bitfield providing information about the device.
1044 * Context: none
1045 *
1046 * Returns 1 if end device.
1047 */
1048static int
1049_scsih_is_end_device(u32 device_info)
1050{
1051 if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
1052 ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
1053 (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
1054 (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
1055 return 1;
1056 else
1057 return 0;
1058}
1059
1060/**
1061 * _scsih_scsi_lookup_get - returns scmd entry
1062 * @ioc: per adapter object
1063 * @smid: system request message index
1064 *
1065 * Returns the smid stored scmd pointer.
1066 */
1067static struct scsi_cmnd *
1068_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
1069{
1070 return ioc->scsi_lookup[smid - 1].scmd;
1071}
1072
1073/**
1074 * _scsih_scsi_lookup_get_clear - returns scmd entry
1075 * @ioc: per adapter object
1076 * @smid: system request message index
1077 *
1078 * Returns the smid stored scmd pointer.
1079 * Then will derefrence the stored scmd pointer.
1080 */
1081static inline struct scsi_cmnd *
1082_scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, u16 smid)
1083{
1084 unsigned long flags;
1085 struct scsi_cmnd *scmd;
1086
1087 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1088 scmd = ioc->scsi_lookup[smid - 1].scmd;
1089 ioc->scsi_lookup[smid - 1].scmd = NULL;
1090 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1091
1092 return scmd;
1093}
1094
1095/**
1096 * _scsih_scsi_lookup_find_by_scmd - scmd lookup
1097 * @ioc: per adapter object
1098 * @smid: system request message index
1099 * @scmd: pointer to scsi command object
1100 * Context: This function will acquire ioc->scsi_lookup_lock.
1101 *
1102 * This will search for a scmd pointer in the scsi_lookup array,
1103 * returning the revelent smid. A returned value of zero means invalid.
1104 */
1105static u16
1106_scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd
1107 *scmd)
1108{
1109 u16 smid;
1110 unsigned long flags;
1111 int i;
1112
1113 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1114 smid = 0;
1115 for (i = 0; i < ioc->scsiio_depth; i++) {
1116 if (ioc->scsi_lookup[i].scmd == scmd) {
1117 smid = ioc->scsi_lookup[i].smid;
1118 goto out;
1119 }
1120 }
1121 out:
1122 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1123 return smid;
1124}
1125
1126/**
1127 * _scsih_scsi_lookup_find_by_target - search for matching channel:id
1128 * @ioc: per adapter object
1129 * @id: target id
1130 * @channel: channel
1131 * Context: This function will acquire ioc->scsi_lookup_lock.
1132 *
1133 * This will search for a matching channel:id in the scsi_lookup array,
1134 * returning 1 if found.
1135 */
1136static u8
1137_scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id,
1138 int channel)
1139{
1140 u8 found;
1141 unsigned long flags;
1142 int i;
1143
1144 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1145 found = 0;
1146 for (i = 0 ; i < ioc->scsiio_depth; i++) {
1147 if (ioc->scsi_lookup[i].scmd &&
1148 (ioc->scsi_lookup[i].scmd->device->id == id &&
1149 ioc->scsi_lookup[i].scmd->device->channel == channel)) {
1150 found = 1;
1151 goto out;
1152 }
1153 }
1154 out:
1155 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1156 return found;
1157}
1158
1159/**
1160 * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
1161 * @ioc: per adapter object
1162 * @id: target id
1163 * @lun: lun number
1164 * @channel: channel
1165 * Context: This function will acquire ioc->scsi_lookup_lock.
1166 *
1167 * This will search for a matching channel:id:lun in the scsi_lookup array,
1168 * returning 1 if found.
1169 */
1170static u8
1171_scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
1172 unsigned int lun, int channel)
1173{
1174 u8 found;
1175 unsigned long flags;
1176 int i;
1177
1178 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1179 found = 0;
1180 for (i = 0 ; i < ioc->scsiio_depth; i++) {
1181 if (ioc->scsi_lookup[i].scmd &&
1182 (ioc->scsi_lookup[i].scmd->device->id == id &&
1183 ioc->scsi_lookup[i].scmd->device->channel == channel &&
1184 ioc->scsi_lookup[i].scmd->device->lun == lun)) {
1185 found = 1;
1186 goto out;
1187 }
1188 }
1189 out:
1190 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1191 return found;
1192}
1193
Christoph Hellwigcf75d5d2014-11-13 15:13:20 +01001194/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301195 * scsih_change_queue_depth - setting device queue depth
Christoph Hellwigcf75d5d2014-11-13 15:13:20 +01001196 * @sdev: scsi device struct
1197 * @qdepth: requested queue depth
1198 *
1199 * Returns queue depth.
1200 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301201int
1202scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301203{
1204 struct Scsi_Host *shost = sdev->host;
1205 int max_depth;
1206 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1207 struct MPT3SAS_DEVICE *sas_device_priv_data;
1208 struct MPT3SAS_TARGET *sas_target_priv_data;
1209 struct _sas_device *sas_device;
1210 unsigned long flags;
1211
1212 max_depth = shost->can_queue;
1213
1214 /* limit max device queue for SATA to 32 */
1215 sas_device_priv_data = sdev->hostdata;
1216 if (!sas_device_priv_data)
1217 goto not_sata;
1218 sas_target_priv_data = sas_device_priv_data->sas_target;
1219 if (!sas_target_priv_data)
1220 goto not_sata;
1221 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))
1222 goto not_sata;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301223
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301224 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301225 sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
1226 if (sas_device) {
1227 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1228 max_depth = MPT3SAS_SATA_QUEUE_DEPTH;
1229
1230 sas_device_put(sas_device);
1231 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301232 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1233
1234 not_sata:
1235
1236 if (!sdev->tagged_supported)
1237 max_depth = 1;
1238 if (qdepth > max_depth)
1239 qdepth = max_depth;
Christoph Hellwigcf75d5d2014-11-13 15:13:20 +01001240 return scsi_change_queue_depth(sdev, qdepth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301241}
1242
1243/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301244 * scsih_target_alloc - target add routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301245 * @starget: scsi target struct
1246 *
1247 * Returns 0 if ok. Any other return is assumed to be an error and
1248 * the device is ignored.
1249 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301250int
1251scsih_target_alloc(struct scsi_target *starget)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301252{
1253 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1254 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1255 struct MPT3SAS_TARGET *sas_target_priv_data;
1256 struct _sas_device *sas_device;
1257 struct _raid_device *raid_device;
1258 unsigned long flags;
1259 struct sas_rphy *rphy;
1260
Joe Lawrence62c4da42014-06-25 17:04:22 -04001261 sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data),
1262 GFP_KERNEL);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301263 if (!sas_target_priv_data)
1264 return -ENOMEM;
1265
1266 starget->hostdata = sas_target_priv_data;
1267 sas_target_priv_data->starget = starget;
1268 sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
1269
1270 /* RAID volumes */
1271 if (starget->channel == RAID_CHANNEL) {
1272 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1273 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1274 starget->channel);
1275 if (raid_device) {
1276 sas_target_priv_data->handle = raid_device->handle;
1277 sas_target_priv_data->sas_address = raid_device->wwid;
1278 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301279 sas_target_priv_data->raid_device = raid_device;
1280 if (ioc->is_warpdrive)
1281 raid_device->starget = starget;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301282 }
1283 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1284 return 0;
1285 }
1286
1287 /* sas/sata devices */
1288 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1289 rphy = dev_to_rphy(starget->dev.parent);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301290 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301291 rphy->identify.sas_address);
1292
1293 if (sas_device) {
1294 sas_target_priv_data->handle = sas_device->handle;
1295 sas_target_priv_data->sas_address = sas_device->sas_address;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301296 sas_target_priv_data->sdev = sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301297 sas_device->starget = starget;
1298 sas_device->id = starget->id;
1299 sas_device->channel = starget->channel;
1300 if (test_bit(sas_device->handle, ioc->pd_handles))
1301 sas_target_priv_data->flags |=
1302 MPT_TARGET_FLAGS_RAID_COMPONENT;
Sreekanth Reddy45506042015-11-11 17:30:25 +05301303#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301304 if (sas_device->fast_path)
1305 sas_target_priv_data->flags |= MPT_TARGET_FASTPATH_IO;
Sreekanth Reddy45506042015-11-11 17:30:25 +05301306#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301307 }
1308 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1309
1310 return 0;
1311}
1312
1313/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301314 * scsih_target_destroy - target destroy routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301315 * @starget: scsi target struct
1316 *
1317 * Returns nothing.
1318 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301319void
1320scsih_target_destroy(struct scsi_target *starget)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301321{
1322 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1323 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1324 struct MPT3SAS_TARGET *sas_target_priv_data;
1325 struct _sas_device *sas_device;
1326 struct _raid_device *raid_device;
1327 unsigned long flags;
1328 struct sas_rphy *rphy;
1329
1330 sas_target_priv_data = starget->hostdata;
1331 if (!sas_target_priv_data)
1332 return;
1333
1334 if (starget->channel == RAID_CHANNEL) {
1335 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1336 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1337 starget->channel);
1338 if (raid_device) {
1339 raid_device->starget = NULL;
1340 raid_device->sdev = NULL;
1341 }
1342 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1343 goto out;
1344 }
1345
1346 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1347 rphy = dev_to_rphy(starget->dev.parent);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301348 sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301349 if (sas_device && (sas_device->starget == starget) &&
1350 (sas_device->id == starget->id) &&
1351 (sas_device->channel == starget->channel))
1352 sas_device->starget = NULL;
1353
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301354 if (sas_device) {
1355 /*
1356 * Corresponding get() is in _scsih_target_alloc()
1357 */
1358 sas_target_priv_data->sdev = NULL;
1359 sas_device_put(sas_device);
1360
1361 sas_device_put(sas_device);
1362 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301363 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1364
1365 out:
1366 kfree(sas_target_priv_data);
1367 starget->hostdata = NULL;
1368}
1369
1370/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301371 * scsih_slave_alloc - device add routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301372 * @sdev: scsi device struct
1373 *
1374 * Returns 0 if ok. Any other return is assumed to be an error and
1375 * the device is ignored.
1376 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301377int
1378scsih_slave_alloc(struct scsi_device *sdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301379{
1380 struct Scsi_Host *shost;
1381 struct MPT3SAS_ADAPTER *ioc;
1382 struct MPT3SAS_TARGET *sas_target_priv_data;
1383 struct MPT3SAS_DEVICE *sas_device_priv_data;
1384 struct scsi_target *starget;
1385 struct _raid_device *raid_device;
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301386 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301387 unsigned long flags;
1388
Joe Lawrence62c4da42014-06-25 17:04:22 -04001389 sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data),
1390 GFP_KERNEL);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301391 if (!sas_device_priv_data)
1392 return -ENOMEM;
1393
1394 sas_device_priv_data->lun = sdev->lun;
1395 sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
1396
1397 starget = scsi_target(sdev);
1398 sas_target_priv_data = starget->hostdata;
1399 sas_target_priv_data->num_luns++;
1400 sas_device_priv_data->sas_target = sas_target_priv_data;
1401 sdev->hostdata = sas_device_priv_data;
1402 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
1403 sdev->no_uld_attach = 1;
1404
1405 shost = dev_to_shost(&starget->dev);
1406 ioc = shost_priv(shost);
1407 if (starget->channel == RAID_CHANNEL) {
1408 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1409 raid_device = _scsih_raid_device_find_by_id(ioc,
1410 starget->id, starget->channel);
1411 if (raid_device)
1412 raid_device->sdev = sdev; /* raid is single lun */
1413 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1414 }
1415
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301416 if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
1417 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301418 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301419 sas_target_priv_data->sas_address);
1420 if (sas_device && (sas_device->starget == NULL)) {
1421 sdev_printk(KERN_INFO, sdev,
1422 "%s : sas_device->starget set to starget @ %d\n",
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301423 __func__, __LINE__);
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301424 sas_device->starget = starget;
1425 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301426
1427 if (sas_device)
1428 sas_device_put(sas_device);
1429
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301430 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1431 }
1432
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301433 return 0;
1434}
1435
1436/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301437 * scsih_slave_destroy - device destroy routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301438 * @sdev: scsi device struct
1439 *
1440 * Returns nothing.
1441 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301442void
1443scsih_slave_destroy(struct scsi_device *sdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301444{
1445 struct MPT3SAS_TARGET *sas_target_priv_data;
1446 struct scsi_target *starget;
1447 struct Scsi_Host *shost;
1448 struct MPT3SAS_ADAPTER *ioc;
1449 struct _sas_device *sas_device;
1450 unsigned long flags;
1451
1452 if (!sdev->hostdata)
1453 return;
1454
1455 starget = scsi_target(sdev);
1456 sas_target_priv_data = starget->hostdata;
1457 sas_target_priv_data->num_luns--;
1458
1459 shost = dev_to_shost(&starget->dev);
1460 ioc = shost_priv(shost);
1461
1462 if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
1463 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301464 sas_device = __mpt3sas_get_sdev_from_target(ioc,
1465 sas_target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301466 if (sas_device && !sas_target_priv_data->num_luns)
1467 sas_device->starget = NULL;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301468
1469 if (sas_device)
1470 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301471 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1472 }
1473
1474 kfree(sdev->hostdata);
1475 sdev->hostdata = NULL;
1476}
1477
1478/**
1479 * _scsih_display_sata_capabilities - sata capabilities
1480 * @ioc: per adapter object
1481 * @handle: device handle
1482 * @sdev: scsi device struct
1483 */
1484static void
1485_scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc,
1486 u16 handle, struct scsi_device *sdev)
1487{
1488 Mpi2ConfigReply_t mpi_reply;
1489 Mpi2SasDevicePage0_t sas_device_pg0;
1490 u32 ioc_status;
1491 u16 flags;
1492 u32 device_info;
1493
1494 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
1495 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
1496 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1497 ioc->name, __FILE__, __LINE__, __func__);
1498 return;
1499 }
1500
1501 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1502 MPI2_IOCSTATUS_MASK;
1503 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1504 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1505 ioc->name, __FILE__, __LINE__, __func__);
1506 return;
1507 }
1508
1509 flags = le16_to_cpu(sas_device_pg0.Flags);
1510 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
1511
1512 sdev_printk(KERN_INFO, sdev,
1513 "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
1514 "sw_preserve(%s)\n",
1515 (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
1516 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
1517 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
1518 "n",
1519 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
1520 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
1521 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
1522}
1523
1524/*
1525 * raid transport support -
1526 * Enabled for SLES11 and newer, in older kernels the driver will panic when
1527 * unloading the driver followed by a load - I beleive that the subroutine
1528 * raid_class_release() is not cleaning up properly.
1529 */
1530
1531/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301532 * scsih_is_raid - return boolean indicating device is raid volume
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301533 * @dev the device struct object
1534 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301535int
1536scsih_is_raid(struct device *dev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301537{
1538 struct scsi_device *sdev = to_scsi_device(dev);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301539 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301540
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301541 if (ioc->is_warpdrive)
1542 return 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301543 return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
1544}
1545
1546/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301547 * scsih_get_resync - get raid volume resync percent complete
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301548 * @dev the device struct object
1549 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301550void
1551scsih_get_resync(struct device *dev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301552{
1553 struct scsi_device *sdev = to_scsi_device(dev);
1554 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
1555 static struct _raid_device *raid_device;
1556 unsigned long flags;
1557 Mpi2RaidVolPage0_t vol_pg0;
1558 Mpi2ConfigReply_t mpi_reply;
1559 u32 volume_status_flags;
1560 u8 percent_complete;
1561 u16 handle;
1562
1563 percent_complete = 0;
1564 handle = 0;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301565 if (ioc->is_warpdrive)
1566 goto out;
1567
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301568 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1569 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1570 sdev->channel);
1571 if (raid_device) {
1572 handle = raid_device->handle;
1573 percent_complete = raid_device->percent_complete;
1574 }
1575 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1576
1577 if (!handle)
1578 goto out;
1579
1580 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
1581 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
1582 sizeof(Mpi2RaidVolPage0_t))) {
1583 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1584 ioc->name, __FILE__, __LINE__, __func__);
1585 percent_complete = 0;
1586 goto out;
1587 }
1588
1589 volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1590 if (!(volume_status_flags &
1591 MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS))
1592 percent_complete = 0;
1593
1594 out:
1595 raid_set_resync(mpt3sas_raid_template, dev, percent_complete);
1596}
1597
1598/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301599 * scsih_get_state - get raid volume level
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301600 * @dev the device struct object
1601 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301602void
1603scsih_get_state(struct device *dev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301604{
1605 struct scsi_device *sdev = to_scsi_device(dev);
1606 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
1607 static struct _raid_device *raid_device;
1608 unsigned long flags;
1609 Mpi2RaidVolPage0_t vol_pg0;
1610 Mpi2ConfigReply_t mpi_reply;
1611 u32 volstate;
1612 enum raid_state state = RAID_STATE_UNKNOWN;
1613 u16 handle = 0;
1614
1615 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1616 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1617 sdev->channel);
1618 if (raid_device)
1619 handle = raid_device->handle;
1620 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1621
1622 if (!raid_device)
1623 goto out;
1624
1625 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
1626 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
1627 sizeof(Mpi2RaidVolPage0_t))) {
1628 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1629 ioc->name, __FILE__, __LINE__, __func__);
1630 goto out;
1631 }
1632
1633 volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1634 if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
1635 state = RAID_STATE_RESYNCING;
1636 goto out;
1637 }
1638
1639 switch (vol_pg0.VolumeState) {
1640 case MPI2_RAID_VOL_STATE_OPTIMAL:
1641 case MPI2_RAID_VOL_STATE_ONLINE:
1642 state = RAID_STATE_ACTIVE;
1643 break;
1644 case MPI2_RAID_VOL_STATE_DEGRADED:
1645 state = RAID_STATE_DEGRADED;
1646 break;
1647 case MPI2_RAID_VOL_STATE_FAILED:
1648 case MPI2_RAID_VOL_STATE_MISSING:
1649 state = RAID_STATE_OFFLINE;
1650 break;
1651 }
1652 out:
1653 raid_set_state(mpt3sas_raid_template, dev, state);
1654}
1655
1656/**
1657 * _scsih_set_level - set raid level
1658 * @sdev: scsi device struct
1659 * @volume_type: volume type
1660 */
1661static void
1662_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
1663{
1664 enum raid_level level = RAID_LEVEL_UNKNOWN;
1665
1666 switch (volume_type) {
1667 case MPI2_RAID_VOL_TYPE_RAID0:
1668 level = RAID_LEVEL_0;
1669 break;
1670 case MPI2_RAID_VOL_TYPE_RAID10:
1671 level = RAID_LEVEL_10;
1672 break;
1673 case MPI2_RAID_VOL_TYPE_RAID1E:
1674 level = RAID_LEVEL_1E;
1675 break;
1676 case MPI2_RAID_VOL_TYPE_RAID1:
1677 level = RAID_LEVEL_1;
1678 break;
1679 }
1680
1681 raid_set_level(mpt3sas_raid_template, &sdev->sdev_gendev, level);
1682}
1683
1684
1685/**
1686 * _scsih_get_volume_capabilities - volume capabilities
1687 * @ioc: per adapter object
1688 * @sas_device: the raid_device object
1689 *
1690 * Returns 0 for success, else 1
1691 */
1692static int
1693_scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc,
1694 struct _raid_device *raid_device)
1695{
1696 Mpi2RaidVolPage0_t *vol_pg0;
1697 Mpi2RaidPhysDiskPage0_t pd_pg0;
1698 Mpi2SasDevicePage0_t sas_device_pg0;
1699 Mpi2ConfigReply_t mpi_reply;
1700 u16 sz;
1701 u8 num_pds;
1702
1703 if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle,
1704 &num_pds)) || !num_pds) {
1705 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1706 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1707 __func__));
1708 return 1;
1709 }
1710
1711 raid_device->num_pds = num_pds;
1712 sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
1713 sizeof(Mpi2RaidVol0PhysDisk_t));
1714 vol_pg0 = kzalloc(sz, GFP_KERNEL);
1715 if (!vol_pg0) {
1716 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1717 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1718 __func__));
1719 return 1;
1720 }
1721
1722 if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
1723 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
1724 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1725 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1726 __func__));
1727 kfree(vol_pg0);
1728 return 1;
1729 }
1730
1731 raid_device->volume_type = vol_pg0->VolumeType;
1732
1733 /* figure out what the underlying devices are by
1734 * obtaining the device_info bits for the 1st device
1735 */
1736 if (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
1737 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
1738 vol_pg0->PhysDisk[0].PhysDiskNum))) {
1739 if (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
1740 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
1741 le16_to_cpu(pd_pg0.DevHandle)))) {
1742 raid_device->device_info =
1743 le32_to_cpu(sas_device_pg0.DeviceInfo);
1744 }
1745 }
1746
1747 kfree(vol_pg0);
1748 return 0;
1749}
1750
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301751/**
1752 * _scsih_enable_tlr - setting TLR flags
1753 * @ioc: per adapter object
1754 * @sdev: scsi device struct
1755 *
1756 * Enabling Transaction Layer Retries for tape devices when
1757 * vpd page 0x90 is present
1758 *
1759 */
1760static void
1761_scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev)
1762{
1763
1764 /* only for TAPE */
1765 if (sdev->type != TYPE_TAPE)
1766 return;
1767
1768 if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR))
1769 return;
1770
1771 sas_enable_tlr(sdev);
1772 sdev_printk(KERN_INFO, sdev, "TLR %s\n",
1773 sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled");
1774 return;
1775
1776}
1777
1778/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301779 * scsih_slave_configure - device configure routine.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301780 * @sdev: scsi device struct
1781 *
1782 * Returns 0 if ok. Any other return is assumed to be an error and
1783 * the device is ignored.
1784 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301785int
1786scsih_slave_configure(struct scsi_device *sdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301787{
1788 struct Scsi_Host *shost = sdev->host;
1789 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1790 struct MPT3SAS_DEVICE *sas_device_priv_data;
1791 struct MPT3SAS_TARGET *sas_target_priv_data;
1792 struct _sas_device *sas_device;
1793 struct _raid_device *raid_device;
1794 unsigned long flags;
1795 int qdepth;
1796 u8 ssp_target = 0;
1797 char *ds = "";
1798 char *r_level = "";
1799 u16 handle, volume_handle = 0;
1800 u64 volume_wwid = 0;
1801
1802 qdepth = 1;
1803 sas_device_priv_data = sdev->hostdata;
1804 sas_device_priv_data->configured_lun = 1;
1805 sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
1806 sas_target_priv_data = sas_device_priv_data->sas_target;
1807 handle = sas_target_priv_data->handle;
1808
1809 /* raid volume handling */
1810 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
1811
1812 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1813 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
1814 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1815 if (!raid_device) {
1816 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1817 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
1818 __LINE__, __func__));
1819 return 1;
1820 }
1821
1822 if (_scsih_get_volume_capabilities(ioc, raid_device)) {
1823 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1824 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
1825 __LINE__, __func__));
1826 return 1;
1827 }
1828
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301829#ifdef SCSI_MPT2SAS
1830 /*
1831 * WARPDRIVE: Initialize the required data for Direct IO
1832 */
1833 _scsih_init_warpdrive_properties(ioc, raid_device);
1834#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301835
1836 /* RAID Queue Depth Support
1837 * IS volume = underlying qdepth of drive type, either
1838 * MPT3SAS_SAS_QUEUE_DEPTH or MPT3SAS_SATA_QUEUE_DEPTH
1839 * IM/IME/R10 = 128 (MPT3SAS_RAID_QUEUE_DEPTH)
1840 */
1841 if (raid_device->device_info &
1842 MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1843 qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
1844 ds = "SSP";
1845 } else {
1846 qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
1847 if (raid_device->device_info &
1848 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1849 ds = "SATA";
1850 else
1851 ds = "STP";
1852 }
1853
1854 switch (raid_device->volume_type) {
1855 case MPI2_RAID_VOL_TYPE_RAID0:
1856 r_level = "RAID0";
1857 break;
1858 case MPI2_RAID_VOL_TYPE_RAID1E:
1859 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1860 if (ioc->manu_pg10.OEMIdentifier &&
1861 (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
1862 MFG10_GF0_R10_DISPLAY) &&
1863 !(raid_device->num_pds % 2))
1864 r_level = "RAID10";
1865 else
1866 r_level = "RAID1E";
1867 break;
1868 case MPI2_RAID_VOL_TYPE_RAID1:
1869 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1870 r_level = "RAID1";
1871 break;
1872 case MPI2_RAID_VOL_TYPE_RAID10:
1873 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1874 r_level = "RAID10";
1875 break;
1876 case MPI2_RAID_VOL_TYPE_UNKNOWN:
1877 default:
1878 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1879 r_level = "RAIDX";
1880 break;
1881 }
1882
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301883 if (!ioc->hide_ir_msg)
1884 sdev_printk(KERN_INFO, sdev,
1885 "%s: handle(0x%04x), wwid(0x%016llx),"
1886 " pd_count(%d), type(%s)\n",
1887 r_level, raid_device->handle,
1888 (unsigned long long)raid_device->wwid,
1889 raid_device->num_pds, ds);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301890
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301891 scsih_change_queue_depth(sdev, qdepth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301892
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301893 /* raid transport support */
1894 if (!ioc->is_warpdrive)
1895 _scsih_set_level(sdev, raid_device->volume_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301896 return 0;
1897 }
1898
1899 /* non-raid handling */
1900 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1901 if (mpt3sas_config_get_volume_handle(ioc, handle,
1902 &volume_handle)) {
1903 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1904 "failure at %s:%d/%s()!\n", ioc->name,
1905 __FILE__, __LINE__, __func__));
1906 return 1;
1907 }
1908 if (volume_handle && mpt3sas_config_get_volume_wwid(ioc,
1909 volume_handle, &volume_wwid)) {
1910 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1911 "failure at %s:%d/%s()!\n", ioc->name,
1912 __FILE__, __LINE__, __func__));
1913 return 1;
1914 }
1915 }
1916
1917 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301918 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301919 sas_device_priv_data->sas_target->sas_address);
1920 if (!sas_device) {
1921 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1922 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1923 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1924 __func__));
1925 return 1;
1926 }
1927
1928 sas_device->volume_handle = volume_handle;
1929 sas_device->volume_wwid = volume_wwid;
1930 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1931 qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
1932 ssp_target = 1;
1933 ds = "SSP";
1934 } else {
1935 qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
1936 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
1937 ds = "STP";
1938 else if (sas_device->device_info &
1939 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1940 ds = "SATA";
1941 }
1942
1943 sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " \
1944 "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
1945 ds, handle, (unsigned long long)sas_device->sas_address,
1946 sas_device->phy, (unsigned long long)sas_device->device_name);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05301947 if (sas_device->enclosure_handle != 0)
1948 sdev_printk(KERN_INFO, sdev,
1949 "%s: enclosure_logical_id(0x%016llx), slot(%d)\n",
1950 ds, (unsigned long long)
1951 sas_device->enclosure_logical_id, sas_device->slot);
1952 if (sas_device->connector_name[0] != '\0')
1953 sdev_printk(KERN_INFO, sdev,
1954 "%s: enclosure level(0x%04x), connector name( %s)\n",
1955 ds, sas_device->enclosure_level,
1956 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301957
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301958 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301959 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1960
1961 if (!ssp_target)
1962 _scsih_display_sata_capabilities(ioc, handle, sdev);
1963
1964
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301965 scsih_change_queue_depth(sdev, qdepth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301966
1967 if (ssp_target) {
1968 sas_read_port_mode_page(sdev);
1969 _scsih_enable_tlr(ioc, sdev);
1970 }
1971
1972 return 0;
1973}
1974
1975/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301976 * scsih_bios_param - fetch head, sector, cylinder info for a disk
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301977 * @sdev: scsi device struct
1978 * @bdev: pointer to block device context
1979 * @capacity: device size (in 512 byte sectors)
1980 * @params: three element array to place output:
1981 * params[0] number of heads (max 255)
1982 * params[1] number of sectors (max 63)
1983 * params[2] number of cylinders
1984 *
1985 * Return nothing.
1986 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301987int
1988scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301989 sector_t capacity, int params[])
1990{
1991 int heads;
1992 int sectors;
1993 sector_t cylinders;
1994 ulong dummy;
1995
1996 heads = 64;
1997 sectors = 32;
1998
1999 dummy = heads * sectors;
2000 cylinders = capacity;
2001 sector_div(cylinders, dummy);
2002
2003 /*
2004 * Handle extended translation size for logical drives
2005 * > 1Gb
2006 */
2007 if ((ulong)capacity >= 0x200000) {
2008 heads = 255;
2009 sectors = 63;
2010 dummy = heads * sectors;
2011 cylinders = capacity;
2012 sector_div(cylinders, dummy);
2013 }
2014
2015 /* return result */
2016 params[0] = heads;
2017 params[1] = sectors;
2018 params[2] = cylinders;
2019
2020 return 0;
2021}
2022
2023/**
2024 * _scsih_response_code - translation of device response code
2025 * @ioc: per adapter object
2026 * @response_code: response code returned by the device
2027 *
2028 * Return nothing.
2029 */
2030static void
2031_scsih_response_code(struct MPT3SAS_ADAPTER *ioc, u8 response_code)
2032{
2033 char *desc;
2034
2035 switch (response_code) {
2036 case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
2037 desc = "task management request completed";
2038 break;
2039 case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
2040 desc = "invalid frame";
2041 break;
2042 case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2043 desc = "task management request not supported";
2044 break;
2045 case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
2046 desc = "task management request failed";
2047 break;
2048 case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2049 desc = "task management request succeeded";
2050 break;
2051 case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2052 desc = "invalid lun";
2053 break;
2054 case 0xA:
2055 desc = "overlapped tag attempted";
2056 break;
2057 case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2058 desc = "task queued, however not sent to target";
2059 break;
2060 default:
2061 desc = "unknown";
2062 break;
2063 }
2064 pr_warn(MPT3SAS_FMT "response_code(0x%01x): %s\n",
2065 ioc->name, response_code, desc);
2066}
2067
2068/**
2069 * _scsih_tm_done - tm completion routine
2070 * @ioc: per adapter object
2071 * @smid: system request message index
2072 * @msix_index: MSIX table index supplied by the OS
2073 * @reply: reply message frame(lower 32bit addr)
2074 * Context: none.
2075 *
2076 * The callback handler when using scsih_issue_tm.
2077 *
2078 * Return 1 meaning mf should be freed from _base_interrupt
2079 * 0 means the mf is freed from this function.
2080 */
2081static u8
2082_scsih_tm_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
2083{
2084 MPI2DefaultReply_t *mpi_reply;
2085
2086 if (ioc->tm_cmds.status == MPT3_CMD_NOT_USED)
2087 return 1;
2088 if (ioc->tm_cmds.smid != smid)
2089 return 1;
2090 mpt3sas_base_flush_reply_queues(ioc);
2091 ioc->tm_cmds.status |= MPT3_CMD_COMPLETE;
2092 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
2093 if (mpi_reply) {
2094 memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
2095 ioc->tm_cmds.status |= MPT3_CMD_REPLY_VALID;
2096 }
2097 ioc->tm_cmds.status &= ~MPT3_CMD_PENDING;
2098 complete(&ioc->tm_cmds.done);
2099 return 1;
2100}
2101
2102/**
2103 * mpt3sas_scsih_set_tm_flag - set per target tm_busy
2104 * @ioc: per adapter object
2105 * @handle: device handle
2106 *
2107 * During taskmangement request, we need to freeze the device queue.
2108 */
2109void
2110mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2111{
2112 struct MPT3SAS_DEVICE *sas_device_priv_data;
2113 struct scsi_device *sdev;
2114 u8 skip = 0;
2115
2116 shost_for_each_device(sdev, ioc->shost) {
2117 if (skip)
2118 continue;
2119 sas_device_priv_data = sdev->hostdata;
2120 if (!sas_device_priv_data)
2121 continue;
2122 if (sas_device_priv_data->sas_target->handle == handle) {
2123 sas_device_priv_data->sas_target->tm_busy = 1;
2124 skip = 1;
2125 ioc->ignore_loginfos = 1;
2126 }
2127 }
2128}
2129
2130/**
2131 * mpt3sas_scsih_clear_tm_flag - clear per target tm_busy
2132 * @ioc: per adapter object
2133 * @handle: device handle
2134 *
2135 * During taskmangement request, we need to freeze the device queue.
2136 */
2137void
2138mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2139{
2140 struct MPT3SAS_DEVICE *sas_device_priv_data;
2141 struct scsi_device *sdev;
2142 u8 skip = 0;
2143
2144 shost_for_each_device(sdev, ioc->shost) {
2145 if (skip)
2146 continue;
2147 sas_device_priv_data = sdev->hostdata;
2148 if (!sas_device_priv_data)
2149 continue;
2150 if (sas_device_priv_data->sas_target->handle == handle) {
2151 sas_device_priv_data->sas_target->tm_busy = 0;
2152 skip = 1;
2153 ioc->ignore_loginfos = 0;
2154 }
2155 }
2156}
2157
2158/**
2159 * mpt3sas_scsih_issue_tm - main routine for sending tm requests
2160 * @ioc: per adapter struct
2161 * @device_handle: device handle
2162 * @channel: the channel assigned by the OS
2163 * @id: the id assigned by the OS
2164 * @lun: lun number
2165 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
2166 * @smid_task: smid assigned to the task
2167 * @timeout: timeout in seconds
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302168 * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
2169 * Context: user
2170 *
2171 * A generic API for sending task management requests to firmware.
2172 *
2173 * The callback index is set inside `ioc->tm_cb_idx`.
2174 *
2175 * Return SUCCESS or FAILED.
2176 */
2177int
2178mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
2179 uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04002180 enum mutex_type m_type)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302181{
2182 Mpi2SCSITaskManagementRequest_t *mpi_request;
2183 Mpi2SCSITaskManagementReply_t *mpi_reply;
2184 u16 smid = 0;
2185 u32 ioc_state;
2186 unsigned long timeleft;
2187 struct scsiio_tracker *scsi_lookup = NULL;
2188 int rc;
2189
2190 if (m_type == TM_MUTEX_ON)
2191 mutex_lock(&ioc->tm_cmds.mutex);
2192 if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) {
2193 pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n",
2194 __func__, ioc->name);
2195 rc = FAILED;
2196 goto err_out;
2197 }
2198
2199 if (ioc->shost_recovery || ioc->remove_host ||
2200 ioc->pci_error_recovery) {
2201 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
2202 __func__, ioc->name);
2203 rc = FAILED;
2204 goto err_out;
2205 }
2206
2207 ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
2208 if (ioc_state & MPI2_DOORBELL_USED) {
2209 dhsprintk(ioc, pr_info(MPT3SAS_FMT
2210 "unexpected doorbell active!\n", ioc->name));
2211 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2212 FORCE_BIG_HAMMER);
2213 rc = (!rc) ? SUCCESS : FAILED;
2214 goto err_out;
2215 }
2216
2217 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
2218 mpt3sas_base_fault_info(ioc, ioc_state &
2219 MPI2_DOORBELL_DATA_MASK);
2220 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2221 FORCE_BIG_HAMMER);
2222 rc = (!rc) ? SUCCESS : FAILED;
2223 goto err_out;
2224 }
2225
2226 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
2227 if (!smid) {
2228 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
2229 ioc->name, __func__);
2230 rc = FAILED;
2231 goto err_out;
2232 }
2233
2234 if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2235 scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
2236
2237 dtmprintk(ioc, pr_info(MPT3SAS_FMT
2238 "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n",
2239 ioc->name, handle, type, smid_task));
2240 ioc->tm_cmds.status = MPT3_CMD_PENDING;
2241 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2242 ioc->tm_cmds.smid = smid;
2243 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
2244 memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
2245 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
2246 mpi_request->DevHandle = cpu_to_le16(handle);
2247 mpi_request->TaskType = type;
2248 mpi_request->TaskMID = cpu_to_le16(smid_task);
2249 int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
2250 mpt3sas_scsih_set_tm_flag(ioc, handle);
2251 init_completion(&ioc->tm_cmds.done);
2252 mpt3sas_base_put_smid_hi_priority(ioc, smid);
2253 timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
2254 if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) {
2255 pr_err(MPT3SAS_FMT "%s: timeout\n",
2256 ioc->name, __func__);
2257 _debug_dump_mf(mpi_request,
2258 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2259 if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) {
2260 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2261 FORCE_BIG_HAMMER);
2262 rc = (!rc) ? SUCCESS : FAILED;
2263 ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
2264 mpt3sas_scsih_clear_tm_flag(ioc, handle);
2265 goto err_out;
2266 }
2267 }
2268
2269 if (ioc->tm_cmds.status & MPT3_CMD_REPLY_VALID) {
2270 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
2271 mpi_reply = ioc->tm_cmds.reply;
2272 dtmprintk(ioc, pr_info(MPT3SAS_FMT "complete tm: " \
2273 "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
2274 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
2275 le32_to_cpu(mpi_reply->IOCLogInfo),
2276 le32_to_cpu(mpi_reply->TerminationCount)));
2277 if (ioc->logging_level & MPT_DEBUG_TM) {
2278 _scsih_response_code(ioc, mpi_reply->ResponseCode);
2279 if (mpi_reply->IOCStatus)
2280 _debug_dump_mf(mpi_request,
2281 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2282 }
2283 }
2284
2285 switch (type) {
2286 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2287 rc = SUCCESS;
2288 if (scsi_lookup->scmd == NULL)
2289 break;
2290 rc = FAILED;
2291 break;
2292
2293 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2294 if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
2295 rc = FAILED;
2296 else
2297 rc = SUCCESS;
2298 break;
2299 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
2300 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
2301 if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
2302 rc = FAILED;
2303 else
2304 rc = SUCCESS;
2305 break;
2306 case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
2307 rc = SUCCESS;
2308 break;
2309 default:
2310 rc = FAILED;
2311 break;
2312 }
2313
2314 mpt3sas_scsih_clear_tm_flag(ioc, handle);
2315 ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
2316 if (m_type == TM_MUTEX_ON)
2317 mutex_unlock(&ioc->tm_cmds.mutex);
2318
2319 return rc;
2320
2321 err_out:
2322 if (m_type == TM_MUTEX_ON)
2323 mutex_unlock(&ioc->tm_cmds.mutex);
2324 return rc;
2325}
2326
2327/**
2328 * _scsih_tm_display_info - displays info about the device
2329 * @ioc: per adapter struct
2330 * @scmd: pointer to scsi command object
2331 *
2332 * Called by task management callback handlers.
2333 */
2334static void
2335_scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
2336{
2337 struct scsi_target *starget = scmd->device->sdev_target;
2338 struct MPT3SAS_TARGET *priv_target = starget->hostdata;
2339 struct _sas_device *sas_device = NULL;
2340 unsigned long flags;
2341 char *device_str = NULL;
2342
2343 if (!priv_target)
2344 return;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05302345 if (ioc->hide_ir_msg)
2346 device_str = "WarpDrive";
2347 else
2348 device_str = "volume";
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302349
2350 scsi_print_command(scmd);
2351 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
2352 starget_printk(KERN_INFO, starget,
2353 "%s handle(0x%04x), %s wwid(0x%016llx)\n",
2354 device_str, priv_target->handle,
2355 device_str, (unsigned long long)priv_target->sas_address);
2356 } else {
2357 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302358 sas_device = __mpt3sas_get_sdev_from_target(ioc, priv_target);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302359 if (sas_device) {
2360 if (priv_target->flags &
2361 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2362 starget_printk(KERN_INFO, starget,
2363 "volume handle(0x%04x), "
2364 "volume wwid(0x%016llx)\n",
2365 sas_device->volume_handle,
2366 (unsigned long long)sas_device->volume_wwid);
2367 }
2368 starget_printk(KERN_INFO, starget,
2369 "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
2370 sas_device->handle,
2371 (unsigned long long)sas_device->sas_address,
2372 sas_device->phy);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05302373 if (sas_device->enclosure_handle != 0)
2374 starget_printk(KERN_INFO, starget,
2375 "enclosure_logical_id(0x%016llx), slot(%d)\n",
2376 (unsigned long long)
2377 sas_device->enclosure_logical_id,
2378 sas_device->slot);
2379 if (sas_device->connector_name)
2380 starget_printk(KERN_INFO, starget,
2381 "enclosure level(0x%04x),connector name(%s)\n",
2382 sas_device->enclosure_level,
2383 sas_device->connector_name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302384
2385 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302386 }
2387 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2388 }
2389}
2390
2391/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302392 * scsih_abort - eh threads main abort routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302393 * @scmd: pointer to scsi command object
2394 *
2395 * Returns SUCCESS if command aborted else FAILED
2396 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302397int
2398scsih_abort(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302399{
2400 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2401 struct MPT3SAS_DEVICE *sas_device_priv_data;
2402 u16 smid;
2403 u16 handle;
2404 int r;
2405
2406 sdev_printk(KERN_INFO, scmd->device,
2407 "attempting task abort! scmd(%p)\n", scmd);
2408 _scsih_tm_display_info(ioc, scmd);
2409
2410 sas_device_priv_data = scmd->device->hostdata;
2411 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2412 sdev_printk(KERN_INFO, scmd->device,
2413 "device been deleted! scmd(%p)\n", scmd);
2414 scmd->result = DID_NO_CONNECT << 16;
2415 scmd->scsi_done(scmd);
2416 r = SUCCESS;
2417 goto out;
2418 }
2419
2420 /* search for the command */
2421 smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
2422 if (!smid) {
2423 scmd->result = DID_RESET << 16;
2424 r = SUCCESS;
2425 goto out;
2426 }
2427
2428 /* for hidden raid components and volumes this is not supported */
2429 if (sas_device_priv_data->sas_target->flags &
2430 MPT_TARGET_FLAGS_RAID_COMPONENT ||
2431 sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
2432 scmd->result = DID_RESET << 16;
2433 r = FAILED;
2434 goto out;
2435 }
2436
2437 mpt3sas_halt_firmware(ioc);
2438
2439 handle = sas_device_priv_data->sas_target->handle;
2440 r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2441 scmd->device->id, scmd->device->lun,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04002442 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, TM_MUTEX_ON);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302443
2444 out:
2445 sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
2446 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2447 return r;
2448}
2449
2450/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302451 * scsih_dev_reset - eh threads main device reset routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302452 * @scmd: pointer to scsi command object
2453 *
2454 * Returns SUCCESS if command aborted else FAILED
2455 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302456int
2457scsih_dev_reset(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302458{
2459 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2460 struct MPT3SAS_DEVICE *sas_device_priv_data;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302461 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302462 u16 handle;
2463 int r;
2464
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302465 struct scsi_target *starget = scmd->device->sdev_target;
2466 struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
2467
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302468 sdev_printk(KERN_INFO, scmd->device,
2469 "attempting device reset! scmd(%p)\n", scmd);
2470 _scsih_tm_display_info(ioc, scmd);
2471
2472 sas_device_priv_data = scmd->device->hostdata;
2473 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2474 sdev_printk(KERN_INFO, scmd->device,
2475 "device been deleted! scmd(%p)\n", scmd);
2476 scmd->result = DID_NO_CONNECT << 16;
2477 scmd->scsi_done(scmd);
2478 r = SUCCESS;
2479 goto out;
2480 }
2481
2482 /* for hidden raid components obtain the volume_handle */
2483 handle = 0;
2484 if (sas_device_priv_data->sas_target->flags &
2485 MPT_TARGET_FLAGS_RAID_COMPONENT) {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302486 sas_device = mpt3sas_get_sdev_from_target(ioc,
2487 target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302488 if (sas_device)
2489 handle = sas_device->volume_handle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302490 } else
2491 handle = sas_device_priv_data->sas_target->handle;
2492
2493 if (!handle) {
2494 scmd->result = DID_RESET << 16;
2495 r = FAILED;
2496 goto out;
2497 }
2498
2499 r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2500 scmd->device->id, scmd->device->lun,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04002501 MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, TM_MUTEX_ON);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302502
2503 out:
2504 sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
2505 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302506
2507 if (sas_device)
2508 sas_device_put(sas_device);
2509
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302510 return r;
2511}
2512
2513/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302514 * scsih_target_reset - eh threads main target reset routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302515 * @scmd: pointer to scsi command object
2516 *
2517 * Returns SUCCESS if command aborted else FAILED
2518 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302519int
2520scsih_target_reset(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302521{
2522 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2523 struct MPT3SAS_DEVICE *sas_device_priv_data;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302524 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302525 u16 handle;
2526 int r;
2527 struct scsi_target *starget = scmd->device->sdev_target;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302528 struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302529
2530 starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n",
2531 scmd);
2532 _scsih_tm_display_info(ioc, scmd);
2533
2534 sas_device_priv_data = scmd->device->hostdata;
2535 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2536 starget_printk(KERN_INFO, starget, "target been deleted! scmd(%p)\n",
2537 scmd);
2538 scmd->result = DID_NO_CONNECT << 16;
2539 scmd->scsi_done(scmd);
2540 r = SUCCESS;
2541 goto out;
2542 }
2543
2544 /* for hidden raid components obtain the volume_handle */
2545 handle = 0;
2546 if (sas_device_priv_data->sas_target->flags &
2547 MPT_TARGET_FLAGS_RAID_COMPONENT) {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302548 sas_device = mpt3sas_get_sdev_from_target(ioc,
2549 target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302550 if (sas_device)
2551 handle = sas_device->volume_handle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302552 } else
2553 handle = sas_device_priv_data->sas_target->handle;
2554
2555 if (!handle) {
2556 scmd->result = DID_RESET << 16;
2557 r = FAILED;
2558 goto out;
2559 }
2560
2561 r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2562 scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04002563 30, TM_MUTEX_ON);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302564
2565 out:
2566 starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
2567 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302568
2569 if (sas_device)
2570 sas_device_put(sas_device);
2571
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302572 return r;
2573}
2574
2575
2576/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302577 * scsih_host_reset - eh threads main host reset routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302578 * @scmd: pointer to scsi command object
2579 *
2580 * Returns SUCCESS if command aborted else FAILED
2581 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302582int
2583scsih_host_reset(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302584{
2585 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2586 int r, retval;
2587
2588 pr_info(MPT3SAS_FMT "attempting host reset! scmd(%p)\n",
2589 ioc->name, scmd);
2590 scsi_print_command(scmd);
2591
Sreekanth Reddyddb588b2015-01-12 11:38:57 +05302592 if (ioc->is_driver_loading) {
2593 pr_info(MPT3SAS_FMT "Blocking the host reset\n",
2594 ioc->name);
2595 r = FAILED;
2596 goto out;
2597 }
2598
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302599 retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2600 FORCE_BIG_HAMMER);
2601 r = (retval < 0) ? FAILED : SUCCESS;
Sreekanth Reddyddb588b2015-01-12 11:38:57 +05302602out:
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302603 pr_info(MPT3SAS_FMT "host reset: %s scmd(%p)\n",
2604 ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2605
2606 return r;
2607}
2608
2609/**
2610 * _scsih_fw_event_add - insert and queue up fw_event
2611 * @ioc: per adapter object
2612 * @fw_event: object describing the event
2613 * Context: This function will acquire ioc->fw_event_lock.
2614 *
2615 * This adds the firmware event object into link list, then queues it up to
2616 * be processed from user context.
2617 *
2618 * Return nothing.
2619 */
2620static void
2621_scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
2622{
2623 unsigned long flags;
2624
2625 if (ioc->firmware_event_thread == NULL)
2626 return;
2627
2628 spin_lock_irqsave(&ioc->fw_event_lock, flags);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302629 fw_event_work_get(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302630 INIT_LIST_HEAD(&fw_event->list);
2631 list_add_tail(&fw_event->list, &ioc->fw_event_list);
2632 INIT_WORK(&fw_event->work, _firmware_event_work);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302633 fw_event_work_get(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302634 queue_work(ioc->firmware_event_thread, &fw_event->work);
2635 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2636}
2637
2638/**
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302639 * _scsih_fw_event_del_from_list - delete fw_event from the list
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302640 * @ioc: per adapter object
2641 * @fw_event: object describing the event
2642 * Context: This function will acquire ioc->fw_event_lock.
2643 *
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302644 * If the fw_event is on the fw_event_list, remove it and do a put.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302645 *
2646 * Return nothing.
2647 */
2648static void
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302649_scsih_fw_event_del_from_list(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302650 *fw_event)
2651{
2652 unsigned long flags;
2653
2654 spin_lock_irqsave(&ioc->fw_event_lock, flags);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302655 if (!list_empty(&fw_event->list)) {
2656 list_del_init(&fw_event->list);
2657 fw_event_work_put(fw_event);
2658 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302659 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2660}
2661
2662
2663 /**
2664 * mpt3sas_send_trigger_data_event - send event for processing trigger data
2665 * @ioc: per adapter object
2666 * @event_data: trigger event data
2667 *
2668 * Return nothing.
2669 */
2670void
2671mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
2672 struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
2673{
2674 struct fw_event_work *fw_event;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302675 u16 sz;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302676
2677 if (ioc->is_driver_loading)
2678 return;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302679 sz = sizeof(*event_data);
2680 fw_event = alloc_fw_event_work(sz);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302681 if (!fw_event)
2682 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302683 fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG;
2684 fw_event->ioc = ioc;
2685 memcpy(fw_event->event_data, event_data, sizeof(*event_data));
2686 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302687 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302688}
2689
2690/**
2691 * _scsih_error_recovery_delete_devices - remove devices not responding
2692 * @ioc: per adapter object
2693 *
2694 * Return nothing.
2695 */
2696static void
2697_scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc)
2698{
2699 struct fw_event_work *fw_event;
2700
2701 if (ioc->is_driver_loading)
2702 return;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302703 fw_event = alloc_fw_event_work(0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302704 if (!fw_event)
2705 return;
2706 fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES;
2707 fw_event->ioc = ioc;
2708 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302709 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302710}
2711
2712/**
2713 * mpt3sas_port_enable_complete - port enable completed (fake event)
2714 * @ioc: per adapter object
2715 *
2716 * Return nothing.
2717 */
2718void
2719mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc)
2720{
2721 struct fw_event_work *fw_event;
2722
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302723 fw_event = alloc_fw_event_work(0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302724 if (!fw_event)
2725 return;
2726 fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE;
2727 fw_event->ioc = ioc;
2728 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302729 fw_event_work_put(fw_event);
2730}
2731
2732static struct fw_event_work *dequeue_next_fw_event(struct MPT3SAS_ADAPTER *ioc)
2733{
2734 unsigned long flags;
2735 struct fw_event_work *fw_event = NULL;
2736
2737 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2738 if (!list_empty(&ioc->fw_event_list)) {
2739 fw_event = list_first_entry(&ioc->fw_event_list,
2740 struct fw_event_work, list);
2741 list_del_init(&fw_event->list);
2742 }
2743 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2744
2745 return fw_event;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302746}
2747
2748/**
2749 * _scsih_fw_event_cleanup_queue - cleanup event queue
2750 * @ioc: per adapter object
2751 *
2752 * Walk the firmware event queue, either killing timers, or waiting
2753 * for outstanding events to complete
2754 *
2755 * Return nothing.
2756 */
2757static void
2758_scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
2759{
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302760 struct fw_event_work *fw_event;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302761
2762 if (list_empty(&ioc->fw_event_list) ||
2763 !ioc->firmware_event_thread || in_interrupt())
2764 return;
2765
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05302766 while ((fw_event = dequeue_next_fw_event(ioc))) {
2767 /*
2768 * Wait on the fw_event to complete. If this returns 1, then
2769 * the event was never executed, and we need a put for the
2770 * reference the delayed_work had on the fw_event.
2771 *
2772 * If it did execute, we wait for it to finish, and the put will
2773 * happen from _firmware_event_work()
2774 */
2775 if (cancel_delayed_work_sync(&fw_event->delayed_work))
2776 fw_event_work_put(fw_event);
2777
2778 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302779 }
2780}
2781
2782/**
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302783 * _scsih_internal_device_block - block the sdev device
2784 * @sdev: per device object
2785 * @sas_device_priv_data : per device driver private data
2786 *
2787 * make sure device is blocked without error, if not
2788 * print an error
2789 */
2790static void
2791_scsih_internal_device_block(struct scsi_device *sdev,
2792 struct MPT3SAS_DEVICE *sas_device_priv_data)
2793{
2794 int r = 0;
2795
2796 sdev_printk(KERN_INFO, sdev, "device_block, handle(0x%04x)\n",
2797 sas_device_priv_data->sas_target->handle);
2798 sas_device_priv_data->block = 1;
2799
2800 r = scsi_internal_device_block(sdev);
2801 if (r == -EINVAL)
2802 sdev_printk(KERN_WARNING, sdev,
2803 "device_block failed with return(%d) for handle(0x%04x)\n",
2804 sas_device_priv_data->sas_target->handle, r);
2805}
2806
2807/**
2808 * _scsih_internal_device_unblock - unblock the sdev device
2809 * @sdev: per device object
2810 * @sas_device_priv_data : per device driver private data
2811 * make sure device is unblocked without error, if not retry
2812 * by blocking and then unblocking
2813 */
2814
2815static void
2816_scsih_internal_device_unblock(struct scsi_device *sdev,
2817 struct MPT3SAS_DEVICE *sas_device_priv_data)
2818{
2819 int r = 0;
2820
2821 sdev_printk(KERN_WARNING, sdev, "device_unblock and setting to running, "
2822 "handle(0x%04x)\n", sas_device_priv_data->sas_target->handle);
2823 sas_device_priv_data->block = 0;
2824 r = scsi_internal_device_unblock(sdev, SDEV_RUNNING);
2825 if (r == -EINVAL) {
2826 /* The device has been set to SDEV_RUNNING by SD layer during
2827 * device addition but the request queue is still stopped by
2828 * our earlier block call. We need to perform a block again
2829 * to get the device to SDEV_BLOCK and then to SDEV_RUNNING */
2830
2831 sdev_printk(KERN_WARNING, sdev,
2832 "device_unblock failed with return(%d) for handle(0x%04x) "
2833 "performing a block followed by an unblock\n",
2834 sas_device_priv_data->sas_target->handle, r);
2835 sas_device_priv_data->block = 1;
2836 r = scsi_internal_device_block(sdev);
2837 if (r)
2838 sdev_printk(KERN_WARNING, sdev, "retried device_block "
2839 "failed with return(%d) for handle(0x%04x)\n",
2840 sas_device_priv_data->sas_target->handle, r);
2841
2842 sas_device_priv_data->block = 0;
2843 r = scsi_internal_device_unblock(sdev, SDEV_RUNNING);
2844 if (r)
2845 sdev_printk(KERN_WARNING, sdev, "retried device_unblock"
2846 " failed with return(%d) for handle(0x%04x)\n",
2847 sas_device_priv_data->sas_target->handle, r);
2848 }
2849}
2850
2851/**
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302852 * _scsih_ublock_io_all_device - unblock every device
2853 * @ioc: per adapter object
2854 *
2855 * change the device state from block to running
2856 */
2857static void
2858_scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
2859{
2860 struct MPT3SAS_DEVICE *sas_device_priv_data;
2861 struct scsi_device *sdev;
2862
2863 shost_for_each_device(sdev, ioc->shost) {
2864 sas_device_priv_data = sdev->hostdata;
2865 if (!sas_device_priv_data)
2866 continue;
2867 if (!sas_device_priv_data->block)
2868 continue;
2869
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302870 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2871 "device_running, handle(0x%04x)\n",
2872 sas_device_priv_data->sas_target->handle));
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302873 _scsih_internal_device_unblock(sdev, sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302874 }
2875}
2876
2877
2878/**
2879 * _scsih_ublock_io_device - prepare device to be deleted
2880 * @ioc: per adapter object
2881 * @sas_addr: sas address
2882 *
2883 * unblock then put device in offline state
2884 */
2885static void
2886_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
2887{
2888 struct MPT3SAS_DEVICE *sas_device_priv_data;
2889 struct scsi_device *sdev;
2890
2891 shost_for_each_device(sdev, ioc->shost) {
2892 sas_device_priv_data = sdev->hostdata;
2893 if (!sas_device_priv_data)
2894 continue;
2895 if (sas_device_priv_data->sas_target->sas_address
2896 != sas_address)
2897 continue;
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302898 if (sas_device_priv_data->block)
2899 _scsih_internal_device_unblock(sdev,
2900 sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302901 }
2902}
2903
2904/**
2905 * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
2906 * @ioc: per adapter object
2907 * @handle: device handle
2908 *
2909 * During device pull we need to appropiately set the sdev state.
2910 */
2911static void
2912_scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc)
2913{
2914 struct MPT3SAS_DEVICE *sas_device_priv_data;
2915 struct scsi_device *sdev;
2916
2917 shost_for_each_device(sdev, ioc->shost) {
2918 sas_device_priv_data = sdev->hostdata;
2919 if (!sas_device_priv_data)
2920 continue;
2921 if (sas_device_priv_data->block)
2922 continue;
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302923 _scsih_internal_device_block(sdev, sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302924 }
2925}
2926
2927/**
2928 * _scsih_block_io_device - set the device state to SDEV_BLOCK
2929 * @ioc: per adapter object
2930 * @handle: device handle
2931 *
2932 * During device pull we need to appropiately set the sdev state.
2933 */
2934static void
2935_scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2936{
2937 struct MPT3SAS_DEVICE *sas_device_priv_data;
2938 struct scsi_device *sdev;
Sreekanth Reddye4bc7f52015-06-30 12:24:49 +05302939 struct _sas_device *sas_device;
2940
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302941 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddye4bc7f52015-06-30 12:24:49 +05302942 if (!sas_device)
2943 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302944
2945 shost_for_each_device(sdev, ioc->shost) {
2946 sas_device_priv_data = sdev->hostdata;
2947 if (!sas_device_priv_data)
2948 continue;
2949 if (sas_device_priv_data->sas_target->handle != handle)
2950 continue;
2951 if (sas_device_priv_data->block)
2952 continue;
Sreekanth Reddye4bc7f52015-06-30 12:24:49 +05302953 if (sas_device->pend_sas_rphy_add)
2954 continue;
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302955 _scsih_internal_device_block(sdev, sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302956 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302957
2958 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302959}
2960
2961/**
2962 * _scsih_block_io_to_children_attached_to_ex
2963 * @ioc: per adapter object
2964 * @sas_expander: the sas_device object
2965 *
2966 * This routine set sdev state to SDEV_BLOCK for all devices
2967 * attached to this expander. This function called when expander is
2968 * pulled.
2969 */
2970static void
2971_scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc,
2972 struct _sas_node *sas_expander)
2973{
2974 struct _sas_port *mpt3sas_port;
2975 struct _sas_device *sas_device;
2976 struct _sas_node *expander_sibling;
2977 unsigned long flags;
2978
2979 if (!sas_expander)
2980 return;
2981
2982 list_for_each_entry(mpt3sas_port,
2983 &sas_expander->sas_port_list, port_list) {
2984 if (mpt3sas_port->remote_identify.device_type ==
2985 SAS_END_DEVICE) {
2986 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302987 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
2988 mpt3sas_port->remote_identify.sas_address);
2989 if (sas_device) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302990 set_bit(sas_device->handle,
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302991 ioc->blocking_handles);
2992 sas_device_put(sas_device);
2993 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302994 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2995 }
2996 }
2997
2998 list_for_each_entry(mpt3sas_port,
2999 &sas_expander->sas_port_list, port_list) {
3000
3001 if (mpt3sas_port->remote_identify.device_type ==
3002 SAS_EDGE_EXPANDER_DEVICE ||
3003 mpt3sas_port->remote_identify.device_type ==
3004 SAS_FANOUT_EXPANDER_DEVICE) {
3005 expander_sibling =
3006 mpt3sas_scsih_expander_find_by_sas_address(
3007 ioc, mpt3sas_port->remote_identify.sas_address);
3008 _scsih_block_io_to_children_attached_to_ex(ioc,
3009 expander_sibling);
3010 }
3011 }
3012}
3013
3014/**
3015 * _scsih_block_io_to_children_attached_directly
3016 * @ioc: per adapter object
3017 * @event_data: topology change event data
3018 *
3019 * This routine set sdev state to SDEV_BLOCK for all devices
3020 * direct attached during device pull.
3021 */
3022static void
3023_scsih_block_io_to_children_attached_directly(struct MPT3SAS_ADAPTER *ioc,
3024 Mpi2EventDataSasTopologyChangeList_t *event_data)
3025{
3026 int i;
3027 u16 handle;
3028 u16 reason_code;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303029
3030 for (i = 0; i < event_data->NumEntries; i++) {
3031 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3032 if (!handle)
3033 continue;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303034 reason_code = event_data->PHY[i].PhyStatus &
3035 MPI2_EVENT_SAS_TOPO_RC_MASK;
3036 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
3037 _scsih_block_io_device(ioc, handle);
3038 }
3039}
3040
3041/**
3042 * _scsih_tm_tr_send - send task management request
3043 * @ioc: per adapter object
3044 * @handle: device handle
3045 * Context: interrupt time.
3046 *
3047 * This code is to initiate the device removal handshake protocol
3048 * with controller firmware. This function will issue target reset
3049 * using high priority request queue. It will send a sas iounit
3050 * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
3051 *
3052 * This is designed to send muliple task management request at the same
3053 * time to the fifo. If the fifo is full, we will append the request,
3054 * and process it in a future completion.
3055 */
3056static void
3057_scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3058{
3059 Mpi2SCSITaskManagementRequest_t *mpi_request;
3060 u16 smid;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303061 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303062 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
3063 u64 sas_address = 0;
3064 unsigned long flags;
3065 struct _tr_list *delayed_tr;
3066 u32 ioc_state;
3067
3068 if (ioc->remove_host) {
3069 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3070 "%s: host has been removed: handle(0x%04x)\n",
3071 __func__, ioc->name, handle));
3072 return;
3073 } else if (ioc->pci_error_recovery) {
3074 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3075 "%s: host in pci error recovery: handle(0x%04x)\n",
3076 __func__, ioc->name,
3077 handle));
3078 return;
3079 }
3080 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3081 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3082 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3083 "%s: host is not operational: handle(0x%04x)\n",
3084 __func__, ioc->name,
3085 handle));
3086 return;
3087 }
3088
3089 /* if PD, then return */
3090 if (test_bit(handle, ioc->pd_handles))
3091 return;
3092
3093 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303094 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303095 if (sas_device && sas_device->starget &&
3096 sas_device->starget->hostdata) {
3097 sas_target_priv_data = sas_device->starget->hostdata;
3098 sas_target_priv_data->deleted = 1;
3099 sas_address = sas_device->sas_address;
3100 }
3101 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3102
3103 if (sas_target_priv_data) {
3104 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3105 "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n",
3106 ioc->name, handle,
3107 (unsigned long long)sas_address));
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05303108 if (sas_device->enclosure_handle != 0)
3109 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3110 "setting delete flag:enclosure logical id(0x%016llx),"
3111 " slot(%d)\n", ioc->name, (unsigned long long)
3112 sas_device->enclosure_logical_id,
3113 sas_device->slot));
3114 if (sas_device->connector_name)
3115 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3116 "setting delete flag: enclosure level(0x%04x),"
3117 " connector name( %s)\n", ioc->name,
3118 sas_device->enclosure_level,
3119 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303120 _scsih_ublock_io_device(ioc, sas_address);
3121 sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
3122 }
3123
3124 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
3125 if (!smid) {
3126 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3127 if (!delayed_tr)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303128 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303129 INIT_LIST_HEAD(&delayed_tr->list);
3130 delayed_tr->handle = handle;
3131 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3132 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3133 "DELAYED:tr:handle(0x%04x), (open)\n",
3134 ioc->name, handle));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303135 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303136 }
3137
3138 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3139 "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3140 ioc->name, handle, smid,
3141 ioc->tm_tr_cb_idx));
3142 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3143 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3144 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3145 mpi_request->DevHandle = cpu_to_le16(handle);
3146 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
3147 mpt3sas_base_put_smid_hi_priority(ioc, smid);
3148 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303149
3150out:
3151 if (sas_device)
3152 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303153}
3154
3155/**
3156 * _scsih_tm_tr_complete -
3157 * @ioc: per adapter object
3158 * @smid: system request message index
3159 * @msix_index: MSIX table index supplied by the OS
3160 * @reply: reply message frame(lower 32bit addr)
3161 * Context: interrupt time.
3162 *
3163 * This is the target reset completion routine.
3164 * This code is part of the code to initiate the device removal
3165 * handshake protocol with controller firmware.
3166 * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE)
3167 *
3168 * Return 1 meaning mf should be freed from _base_interrupt
3169 * 0 means the mf is freed from this function.
3170 */
3171static u8
3172_scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
3173 u32 reply)
3174{
3175 u16 handle;
3176 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
3177 Mpi2SCSITaskManagementReply_t *mpi_reply =
3178 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3179 Mpi2SasIoUnitControlRequest_t *mpi_request;
3180 u16 smid_sas_ctrl;
3181 u32 ioc_state;
3182
3183 if (ioc->remove_host) {
3184 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3185 "%s: host has been removed\n", __func__, ioc->name));
3186 return 1;
3187 } else if (ioc->pci_error_recovery) {
3188 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3189 "%s: host in pci error recovery\n", __func__,
3190 ioc->name));
3191 return 1;
3192 }
3193 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3194 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3195 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3196 "%s: host is not operational\n", __func__, ioc->name));
3197 return 1;
3198 }
3199 if (unlikely(!mpi_reply)) {
3200 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3201 ioc->name, __FILE__, __LINE__, __func__);
3202 return 1;
3203 }
3204 mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
3205 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3206 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3207 dewtprintk(ioc, pr_err(MPT3SAS_FMT
3208 "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
3209 ioc->name, handle,
3210 le16_to_cpu(mpi_reply->DevHandle), smid));
3211 return 0;
3212 }
3213
3214 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
3215 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3216 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3217 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3218 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3219 le32_to_cpu(mpi_reply->IOCLogInfo),
3220 le32_to_cpu(mpi_reply->TerminationCount)));
3221
3222 smid_sas_ctrl = mpt3sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx);
3223 if (!smid_sas_ctrl) {
3224 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
3225 ioc->name, __func__);
3226 return 1;
3227 }
3228
3229 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3230 "sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3231 ioc->name, handle, smid_sas_ctrl,
3232 ioc->tm_sas_control_cb_idx));
3233 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid_sas_ctrl);
3234 memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
3235 mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
3236 mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
3237 mpi_request->DevHandle = mpi_request_tm->DevHandle;
3238 mpt3sas_base_put_smid_default(ioc, smid_sas_ctrl);
3239
3240 return _scsih_check_for_pending_tm(ioc, smid);
3241}
3242
3243
3244/**
3245 * _scsih_sas_control_complete - completion routine
3246 * @ioc: per adapter object
3247 * @smid: system request message index
3248 * @msix_index: MSIX table index supplied by the OS
3249 * @reply: reply message frame(lower 32bit addr)
3250 * Context: interrupt time.
3251 *
3252 * This is the sas iounit control completion routine.
3253 * This code is part of the code to initiate the device removal
3254 * handshake protocol with controller firmware.
3255 *
3256 * Return 1 meaning mf should be freed from _base_interrupt
3257 * 0 means the mf is freed from this function.
3258 */
3259static u8
3260_scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
3261 u8 msix_index, u32 reply)
3262{
3263 Mpi2SasIoUnitControlReply_t *mpi_reply =
3264 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3265
3266 if (likely(mpi_reply)) {
3267 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3268 "sc_complete:handle(0x%04x), (open) "
3269 "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
3270 ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
3271 le16_to_cpu(mpi_reply->IOCStatus),
3272 le32_to_cpu(mpi_reply->IOCLogInfo)));
3273 } else {
3274 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3275 ioc->name, __FILE__, __LINE__, __func__);
3276 }
3277 return 1;
3278}
3279
3280/**
3281 * _scsih_tm_tr_volume_send - send target reset request for volumes
3282 * @ioc: per adapter object
3283 * @handle: device handle
3284 * Context: interrupt time.
3285 *
3286 * This is designed to send muliple task management request at the same
3287 * time to the fifo. If the fifo is full, we will append the request,
3288 * and process it in a future completion.
3289 */
3290static void
3291_scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3292{
3293 Mpi2SCSITaskManagementRequest_t *mpi_request;
3294 u16 smid;
3295 struct _tr_list *delayed_tr;
3296
3297 if (ioc->shost_recovery || ioc->remove_host ||
3298 ioc->pci_error_recovery) {
3299 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3300 "%s: host reset in progress!\n",
3301 __func__, ioc->name));
3302 return;
3303 }
3304
3305 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx);
3306 if (!smid) {
3307 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3308 if (!delayed_tr)
3309 return;
3310 INIT_LIST_HEAD(&delayed_tr->list);
3311 delayed_tr->handle = handle;
3312 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list);
3313 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3314 "DELAYED:tr:handle(0x%04x), (open)\n",
3315 ioc->name, handle));
3316 return;
3317 }
3318
3319 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3320 "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3321 ioc->name, handle, smid,
3322 ioc->tm_tr_volume_cb_idx));
3323 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3324 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3325 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3326 mpi_request->DevHandle = cpu_to_le16(handle);
3327 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
3328 mpt3sas_base_put_smid_hi_priority(ioc, smid);
3329}
3330
3331/**
3332 * _scsih_tm_volume_tr_complete - target reset completion
3333 * @ioc: per adapter object
3334 * @smid: system request message index
3335 * @msix_index: MSIX table index supplied by the OS
3336 * @reply: reply message frame(lower 32bit addr)
3337 * Context: interrupt time.
3338 *
3339 * Return 1 meaning mf should be freed from _base_interrupt
3340 * 0 means the mf is freed from this function.
3341 */
3342static u8
3343_scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
3344 u8 msix_index, u32 reply)
3345{
3346 u16 handle;
3347 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
3348 Mpi2SCSITaskManagementReply_t *mpi_reply =
3349 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3350
3351 if (ioc->shost_recovery || ioc->remove_host ||
3352 ioc->pci_error_recovery) {
3353 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3354 "%s: host reset in progress!\n",
3355 __func__, ioc->name));
3356 return 1;
3357 }
3358 if (unlikely(!mpi_reply)) {
3359 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3360 ioc->name, __FILE__, __LINE__, __func__);
3361 return 1;
3362 }
3363
3364 mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
3365 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3366 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3367 dewtprintk(ioc, pr_err(MPT3SAS_FMT
3368 "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
3369 ioc->name, handle,
3370 le16_to_cpu(mpi_reply->DevHandle), smid));
3371 return 0;
3372 }
3373
3374 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3375 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3376 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3377 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3378 le32_to_cpu(mpi_reply->IOCLogInfo),
3379 le32_to_cpu(mpi_reply->TerminationCount)));
3380
3381 return _scsih_check_for_pending_tm(ioc, smid);
3382}
3383
3384
3385/**
3386 * _scsih_check_for_pending_tm - check for pending task management
3387 * @ioc: per adapter object
3388 * @smid: system request message index
3389 *
3390 * This will check delayed target reset list, and feed the
3391 * next reqeust.
3392 *
3393 * Return 1 meaning mf should be freed from _base_interrupt
3394 * 0 means the mf is freed from this function.
3395 */
3396static u8
3397_scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid)
3398{
3399 struct _tr_list *delayed_tr;
3400
3401 if (!list_empty(&ioc->delayed_tr_volume_list)) {
3402 delayed_tr = list_entry(ioc->delayed_tr_volume_list.next,
3403 struct _tr_list, list);
3404 mpt3sas_base_free_smid(ioc, smid);
3405 _scsih_tm_tr_volume_send(ioc, delayed_tr->handle);
3406 list_del(&delayed_tr->list);
3407 kfree(delayed_tr);
3408 return 0;
3409 }
3410
3411 if (!list_empty(&ioc->delayed_tr_list)) {
3412 delayed_tr = list_entry(ioc->delayed_tr_list.next,
3413 struct _tr_list, list);
3414 mpt3sas_base_free_smid(ioc, smid);
3415 _scsih_tm_tr_send(ioc, delayed_tr->handle);
3416 list_del(&delayed_tr->list);
3417 kfree(delayed_tr);
3418 return 0;
3419 }
3420
3421 return 1;
3422}
3423
3424/**
3425 * _scsih_check_topo_delete_events - sanity check on topo events
3426 * @ioc: per adapter object
3427 * @event_data: the event data payload
3428 *
3429 * This routine added to better handle cable breaker.
3430 *
3431 * This handles the case where driver receives multiple expander
3432 * add and delete events in a single shot. When there is a delete event
3433 * the routine will void any pending add events waiting in the event queue.
3434 *
3435 * Return nothing.
3436 */
3437static void
3438_scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc,
3439 Mpi2EventDataSasTopologyChangeList_t *event_data)
3440{
3441 struct fw_event_work *fw_event;
3442 Mpi2EventDataSasTopologyChangeList_t *local_event_data;
3443 u16 expander_handle;
3444 struct _sas_node *sas_expander;
3445 unsigned long flags;
3446 int i, reason_code;
3447 u16 handle;
3448
3449 for (i = 0 ; i < event_data->NumEntries; i++) {
3450 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3451 if (!handle)
3452 continue;
3453 reason_code = event_data->PHY[i].PhyStatus &
3454 MPI2_EVENT_SAS_TOPO_RC_MASK;
3455 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)
3456 _scsih_tm_tr_send(ioc, handle);
3457 }
3458
3459 expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
3460 if (expander_handle < ioc->sas_hba.num_phys) {
3461 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3462 return;
3463 }
3464 if (event_data->ExpStatus ==
3465 MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
3466 /* put expander attached devices into blocking state */
3467 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3468 sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
3469 expander_handle);
3470 _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
3471 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3472 do {
3473 handle = find_first_bit(ioc->blocking_handles,
3474 ioc->facts.MaxDevHandle);
3475 if (handle < ioc->facts.MaxDevHandle)
3476 _scsih_block_io_device(ioc, handle);
3477 } while (test_and_clear_bit(handle, ioc->blocking_handles));
3478 } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
3479 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3480
3481 if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
3482 return;
3483
3484 /* mark ignore flag for pending events */
3485 spin_lock_irqsave(&ioc->fw_event_lock, flags);
3486 list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
3487 if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
3488 fw_event->ignore)
3489 continue;
Joe Lawrence35b62362014-06-25 17:05:34 -04003490 local_event_data = (Mpi2EventDataSasTopologyChangeList_t *)
3491 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303492 if (local_event_data->ExpStatus ==
3493 MPI2_EVENT_SAS_TOPO_ES_ADDED ||
3494 local_event_data->ExpStatus ==
3495 MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
3496 if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
3497 expander_handle) {
3498 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3499 "setting ignoring flag\n", ioc->name));
3500 fw_event->ignore = 1;
3501 }
3502 }
3503 }
3504 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
3505}
3506
3507/**
3508 * _scsih_set_volume_delete_flag - setting volume delete flag
3509 * @ioc: per adapter object
3510 * @handle: device handle
3511 *
3512 * This returns nothing.
3513 */
3514static void
3515_scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3516{
3517 struct _raid_device *raid_device;
3518 struct MPT3SAS_TARGET *sas_target_priv_data;
3519 unsigned long flags;
3520
3521 spin_lock_irqsave(&ioc->raid_device_lock, flags);
3522 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
3523 if (raid_device && raid_device->starget &&
3524 raid_device->starget->hostdata) {
3525 sas_target_priv_data =
3526 raid_device->starget->hostdata;
3527 sas_target_priv_data->deleted = 1;
3528 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3529 "setting delete flag: handle(0x%04x), "
3530 "wwid(0x%016llx)\n", ioc->name, handle,
3531 (unsigned long long) raid_device->wwid));
3532 }
3533 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
3534}
3535
3536/**
3537 * _scsih_set_volume_handle_for_tr - set handle for target reset to volume
3538 * @handle: input handle
3539 * @a: handle for volume a
3540 * @b: handle for volume b
3541 *
3542 * IR firmware only supports two raid volumes. The purpose of this
3543 * routine is to set the volume handle in either a or b. When the given
3544 * input handle is non-zero, or when a and b have not been set before.
3545 */
3546static void
3547_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b)
3548{
3549 if (!handle || handle == *a || handle == *b)
3550 return;
3551 if (!*a)
3552 *a = handle;
3553 else if (!*b)
3554 *b = handle;
3555}
3556
3557/**
3558 * _scsih_check_ir_config_unhide_events - check for UNHIDE events
3559 * @ioc: per adapter object
3560 * @event_data: the event data payload
3561 * Context: interrupt time.
3562 *
3563 * This routine will send target reset to volume, followed by target
3564 * resets to the PDs. This is called when a PD has been removed, or
3565 * volume has been deleted or removed. When the target reset is sent
3566 * to volume, the PD target resets need to be queued to start upon
3567 * completion of the volume target reset.
3568 *
3569 * Return nothing.
3570 */
3571static void
3572_scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc,
3573 Mpi2EventDataIrConfigChangeList_t *event_data)
3574{
3575 Mpi2EventIrConfigElement_t *element;
3576 int i;
3577 u16 handle, volume_handle, a, b;
3578 struct _tr_list *delayed_tr;
3579
3580 a = 0;
3581 b = 0;
3582
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303583 if (ioc->is_warpdrive)
3584 return;
3585
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303586 /* Volume Resets for Deleted or Removed */
3587 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3588 for (i = 0; i < event_data->NumElements; i++, element++) {
3589 if (le32_to_cpu(event_data->Flags) &
3590 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3591 continue;
3592 if (element->ReasonCode ==
3593 MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED ||
3594 element->ReasonCode ==
3595 MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
3596 volume_handle = le16_to_cpu(element->VolDevHandle);
3597 _scsih_set_volume_delete_flag(ioc, volume_handle);
3598 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3599 }
3600 }
3601
3602 /* Volume Resets for UNHIDE events */
3603 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3604 for (i = 0; i < event_data->NumElements; i++, element++) {
3605 if (le32_to_cpu(event_data->Flags) &
3606 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3607 continue;
3608 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) {
3609 volume_handle = le16_to_cpu(element->VolDevHandle);
3610 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3611 }
3612 }
3613
3614 if (a)
3615 _scsih_tm_tr_volume_send(ioc, a);
3616 if (b)
3617 _scsih_tm_tr_volume_send(ioc, b);
3618
3619 /* PD target resets */
3620 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3621 for (i = 0; i < event_data->NumElements; i++, element++) {
3622 if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE)
3623 continue;
3624 handle = le16_to_cpu(element->PhysDiskDevHandle);
3625 volume_handle = le16_to_cpu(element->VolDevHandle);
3626 clear_bit(handle, ioc->pd_handles);
3627 if (!volume_handle)
3628 _scsih_tm_tr_send(ioc, handle);
3629 else if (volume_handle == a || volume_handle == b) {
3630 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3631 BUG_ON(!delayed_tr);
3632 INIT_LIST_HEAD(&delayed_tr->list);
3633 delayed_tr->handle = handle;
3634 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3635 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3636 "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name,
3637 handle));
3638 } else
3639 _scsih_tm_tr_send(ioc, handle);
3640 }
3641}
3642
3643
3644/**
3645 * _scsih_check_volume_delete_events - set delete flag for volumes
3646 * @ioc: per adapter object
3647 * @event_data: the event data payload
3648 * Context: interrupt time.
3649 *
3650 * This will handle the case when the cable connected to entire volume is
3651 * pulled. We will take care of setting the deleted flag so normal IO will
3652 * not be sent.
3653 *
3654 * Return nothing.
3655 */
3656static void
3657_scsih_check_volume_delete_events(struct MPT3SAS_ADAPTER *ioc,
3658 Mpi2EventDataIrVolume_t *event_data)
3659{
3660 u32 state;
3661
3662 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
3663 return;
3664 state = le32_to_cpu(event_data->NewValue);
3665 if (state == MPI2_RAID_VOL_STATE_MISSING || state ==
3666 MPI2_RAID_VOL_STATE_FAILED)
3667 _scsih_set_volume_delete_flag(ioc,
3668 le16_to_cpu(event_data->VolDevHandle));
3669}
3670
3671/**
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05303672 * _scsih_temp_threshold_events - display temperature threshold exceeded events
3673 * @ioc: per adapter object
3674 * @event_data: the temp threshold event data
3675 * Context: interrupt time.
3676 *
3677 * Return nothing.
3678 */
3679static void
3680_scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc,
3681 Mpi2EventDataTemperature_t *event_data)
3682{
3683 if (ioc->temp_sensors_count >= event_data->SensorNum) {
3684 pr_err(MPT3SAS_FMT "Temperature Threshold flags %s%s%s%s"
3685 " exceeded for Sensor: %d !!!\n", ioc->name,
3686 ((le16_to_cpu(event_data->Status) & 0x1) == 1) ? "0 " : " ",
3687 ((le16_to_cpu(event_data->Status) & 0x2) == 2) ? "1 " : " ",
3688 ((le16_to_cpu(event_data->Status) & 0x4) == 4) ? "2 " : " ",
3689 ((le16_to_cpu(event_data->Status) & 0x8) == 8) ? "3 " : " ",
3690 event_data->SensorNum);
3691 pr_err(MPT3SAS_FMT "Current Temp In Celsius: %d\n",
3692 ioc->name, event_data->CurrentTemperature);
3693 }
3694}
3695
3696/**
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303697 * _scsih_flush_running_cmds - completing outstanding commands.
3698 * @ioc: per adapter object
3699 *
3700 * The flushing out of all pending scmd commands following host reset,
3701 * where all IO is dropped to the floor.
3702 *
3703 * Return nothing.
3704 */
3705static void
3706_scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
3707{
3708 struct scsi_cmnd *scmd;
3709 u16 smid;
3710 u16 count = 0;
3711
3712 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
3713 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
3714 if (!scmd)
3715 continue;
3716 count++;
3717 mpt3sas_base_free_smid(ioc, smid);
3718 scsi_dma_unmap(scmd);
3719 if (ioc->pci_error_recovery)
3720 scmd->result = DID_NO_CONNECT << 16;
3721 else
3722 scmd->result = DID_RESET << 16;
3723 scmd->scsi_done(scmd);
3724 }
3725 dtmprintk(ioc, pr_info(MPT3SAS_FMT "completing %d cmds\n",
3726 ioc->name, count));
3727}
3728
3729/**
3730 * _scsih_setup_eedp - setup MPI request for EEDP transfer
3731 * @ioc: per adapter object
3732 * @scmd: pointer to scsi command object
3733 * @mpi_request: pointer to the SCSI_IO reqest message frame
3734 *
3735 * Supporting protection 1 and 3.
3736 *
3737 * Returns nothing
3738 */
3739static void
3740_scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
3741 Mpi2SCSIIORequest_t *mpi_request)
3742{
3743 u16 eedp_flags;
3744 unsigned char prot_op = scsi_get_prot_op(scmd);
3745 unsigned char prot_type = scsi_get_prot_type(scmd);
3746 Mpi25SCSIIORequest_t *mpi_request_3v =
3747 (Mpi25SCSIIORequest_t *)mpi_request;
3748
3749 if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
3750 return;
3751
3752 if (prot_op == SCSI_PROT_READ_STRIP)
3753 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
3754 else if (prot_op == SCSI_PROT_WRITE_INSERT)
3755 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
3756 else
3757 return;
3758
3759 switch (prot_type) {
3760 case SCSI_PROT_DIF_TYPE1:
3761 case SCSI_PROT_DIF_TYPE2:
3762
3763 /*
3764 * enable ref/guard checking
3765 * auto increment ref tag
3766 */
3767 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
3768 MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
3769 MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
3770 mpi_request->CDB.EEDP32.PrimaryReferenceTag =
3771 cpu_to_be32(scsi_get_lba(scmd));
3772 break;
3773
3774 case SCSI_PROT_DIF_TYPE3:
3775
3776 /*
3777 * enable guard checking
3778 */
3779 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
3780
3781 break;
3782 }
3783
3784 mpi_request_3v->EEDPBlockSize =
3785 cpu_to_le16(scmd->device->sector_size);
3786 mpi_request->EEDPFlags = cpu_to_le16(eedp_flags);
3787}
3788
3789/**
3790 * _scsih_eedp_error_handling - return sense code for EEDP errors
3791 * @scmd: pointer to scsi command object
3792 * @ioc_status: ioc status
3793 *
3794 * Returns nothing
3795 */
3796static void
3797_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
3798{
3799 u8 ascq;
3800
3801 switch (ioc_status) {
3802 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
3803 ascq = 0x01;
3804 break;
3805 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
3806 ascq = 0x02;
3807 break;
3808 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
3809 ascq = 0x03;
3810 break;
3811 default:
3812 ascq = 0x00;
3813 break;
3814 }
3815 scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10,
3816 ascq);
3817 scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) |
3818 SAM_STAT_CHECK_CONDITION;
3819}
3820
3821
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303822
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303823/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05303824 * scsih_qcmd - main scsi request entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303825 * @scmd: pointer to scsi command object
3826 * @done: function pointer to be invoked on completion
3827 *
3828 * The callback index is set inside `ioc->scsi_io_cb_idx`.
3829 *
3830 * Returns 0 on success. If there's a failure, return either:
3831 * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
3832 * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
3833 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05303834int
3835scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303836{
Matthew Wilcoxd8bfbd82014-03-27 16:40:31 -04003837 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303838 struct MPT3SAS_DEVICE *sas_device_priv_data;
3839 struct MPT3SAS_TARGET *sas_target_priv_data;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303840#ifdef SCSI_MPT2SAS
3841 struct _raid_device *raid_device;
3842#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303843 Mpi2SCSIIORequest_t *mpi_request;
3844 u32 mpi_control;
3845 u16 smid;
3846 u16 handle;
3847
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303848 if (ioc->logging_level & MPT_DEBUG_SCSI)
3849 scsi_print_command(scmd);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303850
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303851 sas_device_priv_data = scmd->device->hostdata;
3852 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
3853 scmd->result = DID_NO_CONNECT << 16;
3854 scmd->scsi_done(scmd);
3855 return 0;
3856 }
3857
3858 if (ioc->pci_error_recovery || ioc->remove_host) {
3859 scmd->result = DID_NO_CONNECT << 16;
3860 scmd->scsi_done(scmd);
3861 return 0;
3862 }
3863
3864 sas_target_priv_data = sas_device_priv_data->sas_target;
3865
3866 /* invalid device handle */
3867 handle = sas_target_priv_data->handle;
3868 if (handle == MPT3SAS_INVALID_DEVICE_HANDLE) {
3869 scmd->result = DID_NO_CONNECT << 16;
3870 scmd->scsi_done(scmd);
3871 return 0;
3872 }
3873
3874
3875 /* host recovery or link resets sent via IOCTLs */
3876 if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
3877 return SCSI_MLQUEUE_HOST_BUSY;
3878
3879 /* device has been deleted */
3880 else if (sas_target_priv_data->deleted) {
3881 scmd->result = DID_NO_CONNECT << 16;
3882 scmd->scsi_done(scmd);
3883 return 0;
3884 /* device busy with task managment */
3885 } else if (sas_target_priv_data->tm_busy ||
3886 sas_device_priv_data->block)
3887 return SCSI_MLQUEUE_DEVICE_BUSY;
3888
3889 if (scmd->sc_data_direction == DMA_FROM_DEVICE)
3890 mpi_control = MPI2_SCSIIO_CONTROL_READ;
3891 else if (scmd->sc_data_direction == DMA_TO_DEVICE)
3892 mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
3893 else
3894 mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
3895
3896 /* set tags */
Christoph Hellwig609aa222014-10-30 11:54:58 +01003897 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303898
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303899 /* Make sure Device is not raid volume.
3900 * We do not expose raid functionality to upper layer for warpdrive.
3901 */
3902 if (!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev)
3903 && (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303904 scmd->cmd_len != 32)
3905 mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
3906
3907 smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
3908 if (!smid) {
3909 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
3910 ioc->name, __func__);
3911 goto out;
3912 }
3913 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3914 memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
3915 _scsih_setup_eedp(ioc, scmd, mpi_request);
3916
3917 if (scmd->cmd_len == 32)
3918 mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
3919 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
3920 if (sas_device_priv_data->sas_target->flags &
3921 MPT_TARGET_FLAGS_RAID_COMPONENT)
3922 mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3923 else
3924 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
3925 mpi_request->DevHandle = cpu_to_le16(handle);
3926 mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
3927 mpi_request->Control = cpu_to_le32(mpi_control);
3928 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
3929 mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
3930 mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
3931 mpi_request->SenseBufferLowAddress =
3932 mpt3sas_base_get_sense_buffer_dma(ioc, smid);
3933 mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
3934 int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
3935 mpi_request->LUN);
3936 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
3937
3938 if (mpi_request->DataLength) {
3939 if (ioc->build_sg_scmd(ioc, scmd, smid)) {
3940 mpt3sas_base_free_smid(ioc, smid);
3941 goto out;
3942 }
3943 } else
3944 ioc->build_zero_len_sge(ioc, &mpi_request->SGL);
3945
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303946#ifdef SCSI_MPT2SAS
3947 raid_device = sas_target_priv_data->raid_device;
3948 if (raid_device && raid_device->direct_io_enabled)
3949 _scsih_setup_direct_io(ioc, scmd, raid_device, mpi_request,
3950 smid);
3951#endif
3952
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303953 if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) {
Sreekanth Reddy45506042015-11-11 17:30:25 +05303954#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303955 if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
3956 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len |
3957 MPI25_SCSIIO_IOFLAGS_FAST_PATH);
3958 mpt3sas_base_put_smid_fast_path(ioc, smid, handle);
3959 } else
Sreekanth Reddy45506042015-11-11 17:30:25 +05303960#endif
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303961 mpt3sas_base_put_smid_scsi_io(ioc, smid,
3962 le16_to_cpu(mpi_request->DevHandle));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303963 } else
3964 mpt3sas_base_put_smid_default(ioc, smid);
3965 return 0;
3966
3967 out:
3968 return SCSI_MLQUEUE_HOST_BUSY;
3969}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303970
3971/**
3972 * _scsih_normalize_sense - normalize descriptor and fixed format sense data
3973 * @sense_buffer: sense data returned by target
3974 * @data: normalized skey/asc/ascq
3975 *
3976 * Return nothing.
3977 */
3978static void
3979_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
3980{
3981 if ((sense_buffer[0] & 0x7F) >= 0x72) {
3982 /* descriptor format */
3983 data->skey = sense_buffer[1] & 0x0F;
3984 data->asc = sense_buffer[2];
3985 data->ascq = sense_buffer[3];
3986 } else {
3987 /* fixed format */
3988 data->skey = sense_buffer[2] & 0x0F;
3989 data->asc = sense_buffer[12];
3990 data->ascq = sense_buffer[13];
3991 }
3992}
3993
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303994/**
3995 * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
3996 * @ioc: per adapter object
3997 * @scmd: pointer to scsi command object
3998 * @mpi_reply: reply mf payload returned from firmware
3999 *
4000 * scsi_status - SCSI Status code returned from target device
4001 * scsi_state - state info associated with SCSI_IO determined by ioc
4002 * ioc_status - ioc supplied status info
4003 *
4004 * Return nothing.
4005 */
4006static void
4007_scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
4008 Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
4009{
4010 u32 response_info;
4011 u8 *response_bytes;
4012 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
4013 MPI2_IOCSTATUS_MASK;
4014 u8 scsi_state = mpi_reply->SCSIState;
4015 u8 scsi_status = mpi_reply->SCSIStatus;
4016 char *desc_ioc_state = NULL;
4017 char *desc_scsi_status = NULL;
4018 char *desc_scsi_state = ioc->tmp_string;
4019 u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
4020 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304021 struct scsi_target *starget = scmd->device->sdev_target;
4022 struct MPT3SAS_TARGET *priv_target = starget->hostdata;
4023 char *device_str = NULL;
4024
4025 if (!priv_target)
4026 return;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304027 if (ioc->hide_ir_msg)
4028 device_str = "WarpDrive";
4029 else
4030 device_str = "volume";
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304031
4032 if (log_info == 0x31170000)
4033 return;
4034
4035 switch (ioc_status) {
4036 case MPI2_IOCSTATUS_SUCCESS:
4037 desc_ioc_state = "success";
4038 break;
4039 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4040 desc_ioc_state = "invalid function";
4041 break;
4042 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4043 desc_ioc_state = "scsi recovered error";
4044 break;
4045 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
4046 desc_ioc_state = "scsi invalid dev handle";
4047 break;
4048 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4049 desc_ioc_state = "scsi device not there";
4050 break;
4051 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4052 desc_ioc_state = "scsi data overrun";
4053 break;
4054 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4055 desc_ioc_state = "scsi data underrun";
4056 break;
4057 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4058 desc_ioc_state = "scsi io data error";
4059 break;
4060 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4061 desc_ioc_state = "scsi protocol error";
4062 break;
4063 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4064 desc_ioc_state = "scsi task terminated";
4065 break;
4066 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4067 desc_ioc_state = "scsi residual mismatch";
4068 break;
4069 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4070 desc_ioc_state = "scsi task mgmt failed";
4071 break;
4072 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4073 desc_ioc_state = "scsi ioc terminated";
4074 break;
4075 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4076 desc_ioc_state = "scsi ext terminated";
4077 break;
4078 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4079 desc_ioc_state = "eedp guard error";
4080 break;
4081 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4082 desc_ioc_state = "eedp ref tag error";
4083 break;
4084 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4085 desc_ioc_state = "eedp app tag error";
4086 break;
4087 default:
4088 desc_ioc_state = "unknown";
4089 break;
4090 }
4091
4092 switch (scsi_status) {
4093 case MPI2_SCSI_STATUS_GOOD:
4094 desc_scsi_status = "good";
4095 break;
4096 case MPI2_SCSI_STATUS_CHECK_CONDITION:
4097 desc_scsi_status = "check condition";
4098 break;
4099 case MPI2_SCSI_STATUS_CONDITION_MET:
4100 desc_scsi_status = "condition met";
4101 break;
4102 case MPI2_SCSI_STATUS_BUSY:
4103 desc_scsi_status = "busy";
4104 break;
4105 case MPI2_SCSI_STATUS_INTERMEDIATE:
4106 desc_scsi_status = "intermediate";
4107 break;
4108 case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
4109 desc_scsi_status = "intermediate condmet";
4110 break;
4111 case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
4112 desc_scsi_status = "reservation conflict";
4113 break;
4114 case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
4115 desc_scsi_status = "command terminated";
4116 break;
4117 case MPI2_SCSI_STATUS_TASK_SET_FULL:
4118 desc_scsi_status = "task set full";
4119 break;
4120 case MPI2_SCSI_STATUS_ACA_ACTIVE:
4121 desc_scsi_status = "aca active";
4122 break;
4123 case MPI2_SCSI_STATUS_TASK_ABORTED:
4124 desc_scsi_status = "task aborted";
4125 break;
4126 default:
4127 desc_scsi_status = "unknown";
4128 break;
4129 }
4130
4131 desc_scsi_state[0] = '\0';
4132 if (!scsi_state)
4133 desc_scsi_state = " ";
4134 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4135 strcat(desc_scsi_state, "response info ");
4136 if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4137 strcat(desc_scsi_state, "state terminated ");
4138 if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
4139 strcat(desc_scsi_state, "no status ");
4140 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
4141 strcat(desc_scsi_state, "autosense failed ");
4142 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
4143 strcat(desc_scsi_state, "autosense valid ");
4144
4145 scsi_print_command(scmd);
4146
4147 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
4148 pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
4149 device_str, (unsigned long long)priv_target->sas_address);
4150 } else {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304151 sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304152 if (sas_device) {
4153 pr_warn(MPT3SAS_FMT
4154 "\tsas_address(0x%016llx), phy(%d)\n",
4155 ioc->name, (unsigned long long)
4156 sas_device->sas_address, sas_device->phy);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304157 if (sas_device->enclosure_handle != 0)
4158 pr_warn(MPT3SAS_FMT
4159 "\tenclosure_logical_id(0x%016llx),"
4160 "slot(%d)\n", ioc->name,
4161 (unsigned long long)
4162 sas_device->enclosure_logical_id,
4163 sas_device->slot);
4164 if (sas_device->connector_name[0])
4165 pr_warn(MPT3SAS_FMT
4166 "\tenclosure level(0x%04x),"
4167 " connector name( %s)\n", ioc->name,
4168 sas_device->enclosure_level,
4169 sas_device->connector_name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304170
4171 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304172 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304173 }
4174
4175 pr_warn(MPT3SAS_FMT
4176 "\thandle(0x%04x), ioc_status(%s)(0x%04x), smid(%d)\n",
4177 ioc->name, le16_to_cpu(mpi_reply->DevHandle),
4178 desc_ioc_state, ioc_status, smid);
4179 pr_warn(MPT3SAS_FMT
4180 "\trequest_len(%d), underflow(%d), resid(%d)\n",
4181 ioc->name, scsi_bufflen(scmd), scmd->underflow,
4182 scsi_get_resid(scmd));
4183 pr_warn(MPT3SAS_FMT
4184 "\ttag(%d), transfer_count(%d), sc->result(0x%08x)\n",
4185 ioc->name, le16_to_cpu(mpi_reply->TaskTag),
4186 le32_to_cpu(mpi_reply->TransferCount), scmd->result);
4187 pr_warn(MPT3SAS_FMT
4188 "\tscsi_status(%s)(0x%02x), scsi_state(%s)(0x%02x)\n",
4189 ioc->name, desc_scsi_status,
4190 scsi_status, desc_scsi_state, scsi_state);
4191
4192 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4193 struct sense_info data;
4194 _scsih_normalize_sense(scmd->sense_buffer, &data);
4195 pr_warn(MPT3SAS_FMT
4196 "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n",
4197 ioc->name, data.skey,
4198 data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
4199 }
4200
4201 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
4202 response_info = le32_to_cpu(mpi_reply->ResponseInfo);
4203 response_bytes = (u8 *)&response_info;
4204 _scsih_response_code(ioc, response_bytes[0]);
4205 }
4206}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304207
4208/**
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304209 * _scsih_turn_on_pfa_led - illuminate PFA LED
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304210 * @ioc: per adapter object
4211 * @handle: device handle
4212 * Context: process
4213 *
4214 * Return nothing.
4215 */
4216static void
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304217_scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304218{
4219 Mpi2SepReply_t mpi_reply;
4220 Mpi2SepRequest_t mpi_request;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304221 struct _sas_device *sas_device;
4222
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304223 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304224 if (!sas_device)
4225 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304226
4227 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
4228 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
4229 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
4230 mpi_request.SlotStatus =
4231 cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
4232 mpi_request.DevHandle = cpu_to_le16(handle);
4233 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
4234 if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
4235 &mpi_request)) != 0) {
4236 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
4237 __FILE__, __LINE__, __func__);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304238 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304239 }
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304240 sas_device->pfa_led_on = 1;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304241
4242 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
4243 dewtprintk(ioc, pr_info(MPT3SAS_FMT
4244 "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
4245 ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
4246 le32_to_cpu(mpi_reply.IOCLogInfo)));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304247 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304248 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304249out:
4250 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304251}
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304252
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304253/**
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304254 * _scsih_turn_off_pfa_led - turn off Fault LED
4255 * @ioc: per adapter object
4256 * @sas_device: sas device whose PFA LED has to turned off
4257 * Context: process
4258 *
4259 * Return nothing.
4260 */
4261static void
4262_scsih_turn_off_pfa_led(struct MPT3SAS_ADAPTER *ioc,
4263 struct _sas_device *sas_device)
4264{
4265 Mpi2SepReply_t mpi_reply;
4266 Mpi2SepRequest_t mpi_request;
4267
4268 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
4269 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
4270 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
4271 mpi_request.SlotStatus = 0;
4272 mpi_request.Slot = cpu_to_le16(sas_device->slot);
4273 mpi_request.DevHandle = 0;
4274 mpi_request.EnclosureHandle = cpu_to_le16(sas_device->enclosure_handle);
4275 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
4276 if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
4277 &mpi_request)) != 0) {
4278 printk(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
4279 __FILE__, __LINE__, __func__);
4280 return;
4281 }
4282
4283 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
4284 dewtprintk(ioc, printk(MPT3SAS_FMT
4285 "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
4286 ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
4287 le32_to_cpu(mpi_reply.IOCLogInfo)));
4288 return;
4289 }
4290}
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304291
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304292/**
4293 * _scsih_send_event_to_turn_on_pfa_led - fire delayed event
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304294 * @ioc: per adapter object
4295 * @handle: device handle
4296 * Context: interrupt.
4297 *
4298 * Return nothing.
4299 */
4300static void
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304301_scsih_send_event_to_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304302{
4303 struct fw_event_work *fw_event;
4304
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05304305 fw_event = alloc_fw_event_work(0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304306 if (!fw_event)
4307 return;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304308 fw_event->event = MPT3SAS_TURN_ON_PFA_LED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304309 fw_event->device_handle = handle;
4310 fw_event->ioc = ioc;
4311 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05304312 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304313}
4314
4315/**
4316 * _scsih_smart_predicted_fault - process smart errors
4317 * @ioc: per adapter object
4318 * @handle: device handle
4319 * Context: interrupt.
4320 *
4321 * Return nothing.
4322 */
4323static void
4324_scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
4325{
4326 struct scsi_target *starget;
4327 struct MPT3SAS_TARGET *sas_target_priv_data;
4328 Mpi2EventNotificationReply_t *event_reply;
4329 Mpi2EventDataSasDeviceStatusChange_t *event_data;
4330 struct _sas_device *sas_device;
4331 ssize_t sz;
4332 unsigned long flags;
4333
4334 /* only handle non-raid devices */
4335 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304336 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
4337 if (!sas_device)
4338 goto out_unlock;
4339
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304340 starget = sas_device->starget;
4341 sas_target_priv_data = starget->hostdata;
4342
4343 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304344 ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)))
4345 goto out_unlock;
4346
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304347 if (sas_device->enclosure_handle != 0)
4348 starget_printk(KERN_INFO, starget, "predicted fault, "
4349 "enclosure logical id(0x%016llx), slot(%d)\n",
4350 (unsigned long long)sas_device->enclosure_logical_id,
4351 sas_device->slot);
4352 if (sas_device->connector_name[0] != '\0')
4353 starget_printk(KERN_WARNING, starget, "predicted fault, "
4354 "enclosure level(0x%04x), connector name( %s)\n",
4355 sas_device->enclosure_level,
4356 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304357 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4358
4359 if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304360 _scsih_send_event_to_turn_on_pfa_led(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304361
4362 /* insert into event log */
4363 sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
4364 sizeof(Mpi2EventDataSasDeviceStatusChange_t);
4365 event_reply = kzalloc(sz, GFP_KERNEL);
4366 if (!event_reply) {
4367 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4368 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304369 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304370 }
4371
4372 event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
4373 event_reply->Event =
4374 cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
4375 event_reply->MsgLength = sz/4;
4376 event_reply->EventDataLength =
4377 cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
4378 event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
4379 event_reply->EventData;
4380 event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
4381 event_data->ASC = 0x5D;
4382 event_data->DevHandle = cpu_to_le16(handle);
4383 event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
4384 mpt3sas_ctl_add_to_event_log(ioc, event_reply);
4385 kfree(event_reply);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304386out:
4387 if (sas_device)
4388 sas_device_put(sas_device);
4389 return;
4390
4391out_unlock:
4392 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4393 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304394}
4395
4396/**
4397 * _scsih_io_done - scsi request callback
4398 * @ioc: per adapter object
4399 * @smid: system request message index
4400 * @msix_index: MSIX table index supplied by the OS
4401 * @reply: reply message frame(lower 32bit addr)
4402 *
4403 * Callback handler when using _scsih_qcmd.
4404 *
4405 * Return 1 meaning mf should be freed from _base_interrupt
4406 * 0 means the mf is freed from this function.
4407 */
4408static u8
4409_scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4410{
4411 Mpi2SCSIIORequest_t *mpi_request;
4412 Mpi2SCSIIOReply_t *mpi_reply;
4413 struct scsi_cmnd *scmd;
4414 u16 ioc_status;
4415 u32 xfer_cnt;
4416 u8 scsi_state;
4417 u8 scsi_status;
4418 u32 log_info;
4419 struct MPT3SAS_DEVICE *sas_device_priv_data;
4420 u32 response_code = 0;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304421#ifdef SCSI_MPT2SAS
4422 unsigned long flags;
4423#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304424
4425 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
4426 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
4427 if (scmd == NULL)
4428 return 1;
4429
4430 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
4431
4432 if (mpi_reply == NULL) {
4433 scmd->result = DID_OK << 16;
4434 goto out;
4435 }
4436
4437 sas_device_priv_data = scmd->device->hostdata;
4438 if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
4439 sas_device_priv_data->sas_target->deleted) {
4440 scmd->result = DID_NO_CONNECT << 16;
4441 goto out;
4442 }
4443 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
4444
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304445#ifdef SCSI_MPT2SAS
4446 /*
4447 * WARPDRIVE: If direct_io is set then it is directIO,
4448 * the failed direct I/O should be redirected to volume
4449 */
4450 if (_scsih_scsi_direct_io_get(ioc, smid) &&
4451 ((ioc_status & MPI2_IOCSTATUS_MASK)
4452 != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
4453 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
4454 ioc->scsi_lookup[smid - 1].scmd = scmd;
4455 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
4456 _scsih_scsi_direct_io_set(ioc, smid, 0);
4457 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
4458 mpi_request->DevHandle =
4459 cpu_to_le16(sas_device_priv_data->sas_target->handle);
4460 mpt3sas_base_put_smid_scsi_io(ioc, smid,
4461 sas_device_priv_data->sas_target->handle);
4462 return 0;
4463 }
4464#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304465 /* turning off TLR */
4466 scsi_state = mpi_reply->SCSIState;
4467 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4468 response_code =
4469 le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
4470 if (!sas_device_priv_data->tlr_snoop_check) {
4471 sas_device_priv_data->tlr_snoop_check++;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304472 if (!ioc->is_warpdrive &&
4473 !scsih_is_raid(&scmd->device->sdev_gendev) &&
4474 (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304475 response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME)
4476 sas_device_priv_data->flags &=
4477 ~MPT_DEVICE_TLR_ON;
4478 }
4479
4480 xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
4481 scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
4482 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
4483 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
4484 else
4485 log_info = 0;
4486 ioc_status &= MPI2_IOCSTATUS_MASK;
4487 scsi_status = mpi_reply->SCSIStatus;
4488
4489 if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
4490 (scsi_status == MPI2_SCSI_STATUS_BUSY ||
4491 scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
4492 scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
4493 ioc_status = MPI2_IOCSTATUS_SUCCESS;
4494 }
4495
4496 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4497 struct sense_info data;
4498 const void *sense_data = mpt3sas_base_get_sense_buffer(ioc,
4499 smid);
4500 u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
4501 le32_to_cpu(mpi_reply->SenseCount));
4502 memcpy(scmd->sense_buffer, sense_data, sz);
4503 _scsih_normalize_sense(scmd->sense_buffer, &data);
4504 /* failure prediction threshold exceeded */
4505 if (data.asc == 0x5D)
4506 _scsih_smart_predicted_fault(ioc,
4507 le16_to_cpu(mpi_reply->DevHandle));
4508 mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304509
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304510 if (!(ioc->logging_level & MPT_DEBUG_REPLY) &&
4511 ((scmd->sense_buffer[2] == UNIT_ATTENTION) ||
4512 (scmd->sense_buffer[2] == MEDIUM_ERROR) ||
4513 (scmd->sense_buffer[2] == HARDWARE_ERROR)))
4514 _scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304515 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304516 switch (ioc_status) {
4517 case MPI2_IOCSTATUS_BUSY:
4518 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
4519 scmd->result = SAM_STAT_BUSY;
4520 break;
4521
4522 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4523 scmd->result = DID_NO_CONNECT << 16;
4524 break;
4525
4526 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4527 if (sas_device_priv_data->block) {
4528 scmd->result = DID_TRANSPORT_DISRUPTED << 16;
4529 goto out;
4530 }
4531 if (log_info == 0x31110630) {
4532 if (scmd->retries > 2) {
4533 scmd->result = DID_NO_CONNECT << 16;
4534 scsi_device_set_state(scmd->device,
4535 SDEV_OFFLINE);
4536 } else {
4537 scmd->result = DID_SOFT_ERROR << 16;
4538 scmd->device->expecting_cc_ua = 1;
4539 }
4540 break;
Sreekanth Reddy3898f082015-06-30 12:25:00 +05304541 } else if (log_info == VIRTUAL_IO_FAILED_RETRY) {
4542 scmd->result = DID_RESET << 16;
4543 break;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304544 }
4545 scmd->result = DID_SOFT_ERROR << 16;
4546 break;
4547 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4548 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4549 scmd->result = DID_RESET << 16;
4550 break;
4551
4552 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4553 if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
4554 scmd->result = DID_SOFT_ERROR << 16;
4555 else
4556 scmd->result = (DID_OK << 16) | scsi_status;
4557 break;
4558
4559 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4560 scmd->result = (DID_OK << 16) | scsi_status;
4561
4562 if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
4563 break;
4564
4565 if (xfer_cnt < scmd->underflow) {
4566 if (scsi_status == SAM_STAT_BUSY)
4567 scmd->result = SAM_STAT_BUSY;
4568 else
4569 scmd->result = DID_SOFT_ERROR << 16;
4570 } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4571 MPI2_SCSI_STATE_NO_SCSI_STATUS))
4572 scmd->result = DID_SOFT_ERROR << 16;
4573 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4574 scmd->result = DID_RESET << 16;
4575 else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
4576 mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
4577 mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
4578 scmd->result = (DRIVER_SENSE << 24) |
4579 SAM_STAT_CHECK_CONDITION;
4580 scmd->sense_buffer[0] = 0x70;
4581 scmd->sense_buffer[2] = ILLEGAL_REQUEST;
4582 scmd->sense_buffer[12] = 0x20;
4583 scmd->sense_buffer[13] = 0;
4584 }
4585 break;
4586
4587 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4588 scsi_set_resid(scmd, 0);
4589 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4590 case MPI2_IOCSTATUS_SUCCESS:
4591 scmd->result = (DID_OK << 16) | scsi_status;
4592 if (response_code ==
4593 MPI2_SCSITASKMGMT_RSP_INVALID_FRAME ||
4594 (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4595 MPI2_SCSI_STATE_NO_SCSI_STATUS)))
4596 scmd->result = DID_SOFT_ERROR << 16;
4597 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4598 scmd->result = DID_RESET << 16;
4599 break;
4600
4601 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4602 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4603 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4604 _scsih_eedp_error_handling(scmd, ioc_status);
4605 break;
4606
4607 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4608 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4609 case MPI2_IOCSTATUS_INVALID_SGL:
4610 case MPI2_IOCSTATUS_INTERNAL_ERROR:
4611 case MPI2_IOCSTATUS_INVALID_FIELD:
4612 case MPI2_IOCSTATUS_INVALID_STATE:
4613 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4614 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4615 default:
4616 scmd->result = DID_SOFT_ERROR << 16;
4617 break;
4618
4619 }
4620
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304621 if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
4622 _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304623
4624 out:
4625
4626 scsi_dma_unmap(scmd);
4627
4628 scmd->scsi_done(scmd);
4629 return 1;
4630}
4631
4632/**
4633 * _scsih_sas_host_refresh - refreshing sas host object contents
4634 * @ioc: per adapter object
4635 * Context: user
4636 *
4637 * During port enable, fw will send topology events for every device. Its
4638 * possible that the handles may change from the previous setting, so this
4639 * code keeping handles updating if changed.
4640 *
4641 * Return nothing.
4642 */
4643static void
4644_scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
4645{
4646 u16 sz;
4647 u16 ioc_status;
4648 int i;
4649 Mpi2ConfigReply_t mpi_reply;
4650 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4651 u16 attached_handle;
4652 u8 link_rate;
4653
4654 dtmprintk(ioc, pr_info(MPT3SAS_FMT
4655 "updating handles for sas_host(0x%016llx)\n",
4656 ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
4657
4658 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
4659 * sizeof(Mpi2SasIOUnit0PhyData_t));
4660 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4661 if (!sas_iounit_pg0) {
4662 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4663 ioc->name, __FILE__, __LINE__, __func__);
4664 return;
4665 }
4666
4667 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4668 sas_iounit_pg0, sz)) != 0)
4669 goto out;
4670 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
4671 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
4672 goto out;
4673 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
4674 link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
4675 if (i == 0)
4676 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4677 PhyData[0].ControllerDevHandle);
4678 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4679 attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
4680 AttachedDevHandle);
4681 if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
4682 link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
4683 mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
4684 attached_handle, i, link_rate);
4685 }
4686 out:
4687 kfree(sas_iounit_pg0);
4688}
4689
4690/**
4691 * _scsih_sas_host_add - create sas host object
4692 * @ioc: per adapter object
4693 *
4694 * Creating host side data object, stored in ioc->sas_hba
4695 *
4696 * Return nothing.
4697 */
4698static void
4699_scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
4700{
4701 int i;
4702 Mpi2ConfigReply_t mpi_reply;
4703 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4704 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
4705 Mpi2SasPhyPage0_t phy_pg0;
4706 Mpi2SasDevicePage0_t sas_device_pg0;
4707 Mpi2SasEnclosurePage0_t enclosure_pg0;
4708 u16 ioc_status;
4709 u16 sz;
4710 u8 device_missing_delay;
4711
4712 mpt3sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
4713 if (!ioc->sas_hba.num_phys) {
4714 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4715 ioc->name, __FILE__, __LINE__, __func__);
4716 return;
4717 }
4718
4719 /* sas_iounit page 0 */
4720 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
4721 sizeof(Mpi2SasIOUnit0PhyData_t));
4722 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4723 if (!sas_iounit_pg0) {
4724 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4725 ioc->name, __FILE__, __LINE__, __func__);
4726 return;
4727 }
4728 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4729 sas_iounit_pg0, sz))) {
4730 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4731 ioc->name, __FILE__, __LINE__, __func__);
4732 goto out;
4733 }
4734 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4735 MPI2_IOCSTATUS_MASK;
4736 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4737 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4738 ioc->name, __FILE__, __LINE__, __func__);
4739 goto out;
4740 }
4741
4742 /* sas_iounit page 1 */
4743 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
4744 sizeof(Mpi2SasIOUnit1PhyData_t));
4745 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
4746 if (!sas_iounit_pg1) {
4747 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4748 ioc->name, __FILE__, __LINE__, __func__);
4749 goto out;
4750 }
4751 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
4752 sas_iounit_pg1, sz))) {
4753 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4754 ioc->name, __FILE__, __LINE__, __func__);
4755 goto out;
4756 }
4757 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4758 MPI2_IOCSTATUS_MASK;
4759 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4760 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4761 ioc->name, __FILE__, __LINE__, __func__);
4762 goto out;
4763 }
4764
4765 ioc->io_missing_delay =
4766 sas_iounit_pg1->IODeviceMissingDelay;
4767 device_missing_delay =
4768 sas_iounit_pg1->ReportDeviceMissingDelay;
4769 if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
4770 ioc->device_missing_delay = (device_missing_delay &
4771 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
4772 else
4773 ioc->device_missing_delay = device_missing_delay &
4774 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
4775
4776 ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
4777 ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
4778 sizeof(struct _sas_phy), GFP_KERNEL);
4779 if (!ioc->sas_hba.phy) {
4780 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4781 ioc->name, __FILE__, __LINE__, __func__);
4782 goto out;
4783 }
4784 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
4785 if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
4786 i))) {
4787 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4788 ioc->name, __FILE__, __LINE__, __func__);
4789 goto out;
4790 }
4791 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4792 MPI2_IOCSTATUS_MASK;
4793 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4794 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4795 ioc->name, __FILE__, __LINE__, __func__);
4796 goto out;
4797 }
4798
4799 if (i == 0)
4800 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4801 PhyData[0].ControllerDevHandle);
4802 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4803 ioc->sas_hba.phy[i].phy_id = i;
4804 mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
4805 phy_pg0, ioc->sas_hba.parent_dev);
4806 }
4807 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
4808 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
4809 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4810 ioc->name, __FILE__, __LINE__, __func__);
4811 goto out;
4812 }
4813 ioc->sas_hba.enclosure_handle =
4814 le16_to_cpu(sas_device_pg0.EnclosureHandle);
4815 ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
4816 pr_info(MPT3SAS_FMT
4817 "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
4818 ioc->name, ioc->sas_hba.handle,
4819 (unsigned long long) ioc->sas_hba.sas_address,
4820 ioc->sas_hba.num_phys) ;
4821
4822 if (ioc->sas_hba.enclosure_handle) {
4823 if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
4824 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4825 ioc->sas_hba.enclosure_handle)))
4826 ioc->sas_hba.enclosure_logical_id =
4827 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4828 }
4829
4830 out:
4831 kfree(sas_iounit_pg1);
4832 kfree(sas_iounit_pg0);
4833}
4834
4835/**
4836 * _scsih_expander_add - creating expander object
4837 * @ioc: per adapter object
4838 * @handle: expander handle
4839 *
4840 * Creating expander object, stored in ioc->sas_expander_list.
4841 *
4842 * Return 0 for success, else error.
4843 */
4844static int
4845_scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
4846{
4847 struct _sas_node *sas_expander;
4848 Mpi2ConfigReply_t mpi_reply;
4849 Mpi2ExpanderPage0_t expander_pg0;
4850 Mpi2ExpanderPage1_t expander_pg1;
4851 Mpi2SasEnclosurePage0_t enclosure_pg0;
4852 u32 ioc_status;
4853 u16 parent_handle;
4854 u64 sas_address, sas_address_parent = 0;
4855 int i;
4856 unsigned long flags;
4857 struct _sas_port *mpt3sas_port = NULL;
4858
4859 int rc = 0;
4860
4861 if (!handle)
4862 return -1;
4863
4864 if (ioc->shost_recovery || ioc->pci_error_recovery)
4865 return -1;
4866
4867 if ((mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
4868 MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
4869 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4870 ioc->name, __FILE__, __LINE__, __func__);
4871 return -1;
4872 }
4873
4874 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4875 MPI2_IOCSTATUS_MASK;
4876 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4877 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4878 ioc->name, __FILE__, __LINE__, __func__);
4879 return -1;
4880 }
4881
4882 /* handle out of order topology events */
4883 parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
4884 if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
4885 != 0) {
4886 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4887 ioc->name, __FILE__, __LINE__, __func__);
4888 return -1;
4889 }
4890 if (sas_address_parent != ioc->sas_hba.sas_address) {
4891 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4892 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
4893 sas_address_parent);
4894 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4895 if (!sas_expander) {
4896 rc = _scsih_expander_add(ioc, parent_handle);
4897 if (rc != 0)
4898 return rc;
4899 }
4900 }
4901
4902 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4903 sas_address = le64_to_cpu(expander_pg0.SASAddress);
4904 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
4905 sas_address);
4906 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4907
4908 if (sas_expander)
4909 return 0;
4910
4911 sas_expander = kzalloc(sizeof(struct _sas_node),
4912 GFP_KERNEL);
4913 if (!sas_expander) {
4914 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4915 ioc->name, __FILE__, __LINE__, __func__);
4916 return -1;
4917 }
4918
4919 sas_expander->handle = handle;
4920 sas_expander->num_phys = expander_pg0.NumPhys;
4921 sas_expander->sas_address_parent = sas_address_parent;
4922 sas_expander->sas_address = sas_address;
4923
4924 pr_info(MPT3SAS_FMT "expander_add: handle(0x%04x)," \
4925 " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
4926 handle, parent_handle, (unsigned long long)
4927 sas_expander->sas_address, sas_expander->num_phys);
4928
4929 if (!sas_expander->num_phys)
4930 goto out_fail;
4931 sas_expander->phy = kcalloc(sas_expander->num_phys,
4932 sizeof(struct _sas_phy), GFP_KERNEL);
4933 if (!sas_expander->phy) {
4934 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4935 ioc->name, __FILE__, __LINE__, __func__);
4936 rc = -1;
4937 goto out_fail;
4938 }
4939
4940 INIT_LIST_HEAD(&sas_expander->sas_port_list);
4941 mpt3sas_port = mpt3sas_transport_port_add(ioc, handle,
4942 sas_address_parent);
4943 if (!mpt3sas_port) {
4944 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4945 ioc->name, __FILE__, __LINE__, __func__);
4946 rc = -1;
4947 goto out_fail;
4948 }
4949 sas_expander->parent_dev = &mpt3sas_port->rphy->dev;
4950
4951 for (i = 0 ; i < sas_expander->num_phys ; i++) {
4952 if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
4953 &expander_pg1, i, handle))) {
4954 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4955 ioc->name, __FILE__, __LINE__, __func__);
4956 rc = -1;
4957 goto out_fail;
4958 }
4959 sas_expander->phy[i].handle = handle;
4960 sas_expander->phy[i].phy_id = i;
4961
4962 if ((mpt3sas_transport_add_expander_phy(ioc,
4963 &sas_expander->phy[i], expander_pg1,
4964 sas_expander->parent_dev))) {
4965 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4966 ioc->name, __FILE__, __LINE__, __func__);
4967 rc = -1;
4968 goto out_fail;
4969 }
4970 }
4971
4972 if (sas_expander->enclosure_handle) {
4973 if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
4974 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4975 sas_expander->enclosure_handle)))
4976 sas_expander->enclosure_logical_id =
4977 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4978 }
4979
4980 _scsih_expander_node_add(ioc, sas_expander);
4981 return 0;
4982
4983 out_fail:
4984
4985 if (mpt3sas_port)
4986 mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
4987 sas_address_parent);
4988 kfree(sas_expander);
4989 return rc;
4990}
4991
4992/**
4993 * mpt3sas_expander_remove - removing expander object
4994 * @ioc: per adapter object
4995 * @sas_address: expander sas_address
4996 *
4997 * Return nothing.
4998 */
4999void
5000mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
5001{
5002 struct _sas_node *sas_expander;
5003 unsigned long flags;
5004
5005 if (ioc->shost_recovery)
5006 return;
5007
5008 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5009 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
5010 sas_address);
5011 if (sas_expander)
5012 list_del(&sas_expander->list);
5013 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5014 if (sas_expander)
5015 _scsih_expander_node_remove(ioc, sas_expander);
5016}
5017
5018/**
5019 * _scsih_done - internal SCSI_IO callback handler.
5020 * @ioc: per adapter object
5021 * @smid: system request message index
5022 * @msix_index: MSIX table index supplied by the OS
5023 * @reply: reply message frame(lower 32bit addr)
5024 *
5025 * Callback handler when sending internal generated SCSI_IO.
5026 * The callback index passed is `ioc->scsih_cb_idx`
5027 *
5028 * Return 1 meaning mf should be freed from _base_interrupt
5029 * 0 means the mf is freed from this function.
5030 */
5031static u8
5032_scsih_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
5033{
5034 MPI2DefaultReply_t *mpi_reply;
5035
5036 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
5037 if (ioc->scsih_cmds.status == MPT3_CMD_NOT_USED)
5038 return 1;
5039 if (ioc->scsih_cmds.smid != smid)
5040 return 1;
5041 ioc->scsih_cmds.status |= MPT3_CMD_COMPLETE;
5042 if (mpi_reply) {
5043 memcpy(ioc->scsih_cmds.reply, mpi_reply,
5044 mpi_reply->MsgLength*4);
5045 ioc->scsih_cmds.status |= MPT3_CMD_REPLY_VALID;
5046 }
5047 ioc->scsih_cmds.status &= ~MPT3_CMD_PENDING;
5048 complete(&ioc->scsih_cmds.done);
5049 return 1;
5050}
5051
5052
5053
5054
5055#define MPT3_MAX_LUNS (255)
5056
5057
5058/**
5059 * _scsih_check_access_status - check access flags
5060 * @ioc: per adapter object
5061 * @sas_address: sas address
5062 * @handle: sas device handle
5063 * @access_flags: errors returned during discovery of the device
5064 *
5065 * Return 0 for success, else failure
5066 */
5067static u8
5068_scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
5069 u16 handle, u8 access_status)
5070{
5071 u8 rc = 1;
5072 char *desc = NULL;
5073
5074 switch (access_status) {
5075 case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS:
5076 case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION:
5077 rc = 0;
5078 break;
5079 case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED:
5080 desc = "sata capability failed";
5081 break;
5082 case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT:
5083 desc = "sata affiliation conflict";
5084 break;
5085 case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE:
5086 desc = "route not addressable";
5087 break;
5088 case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE:
5089 desc = "smp error not addressable";
5090 break;
5091 case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED:
5092 desc = "device blocked";
5093 break;
5094 case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED:
5095 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN:
5096 case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT:
5097 case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG:
5098 case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION:
5099 case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER:
5100 case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN:
5101 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN:
5102 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN:
5103 case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION:
5104 case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE:
5105 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX:
5106 desc = "sata initialization failed";
5107 break;
5108 default:
5109 desc = "unknown";
5110 break;
5111 }
5112
5113 if (!rc)
5114 return 0;
5115
5116 pr_err(MPT3SAS_FMT
5117 "discovery errors(%s): sas_address(0x%016llx), handle(0x%04x)\n",
5118 ioc->name, desc, (unsigned long long)sas_address, handle);
5119 return rc;
5120}
5121
5122/**
5123 * _scsih_check_device - checking device responsiveness
5124 * @ioc: per adapter object
5125 * @parent_sas_address: sas address of parent expander or sas host
5126 * @handle: attached device handle
5127 * @phy_numberv: phy number
5128 * @link_rate: new link rate
5129 *
5130 * Returns nothing.
5131 */
5132static void
5133_scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
5134 u64 parent_sas_address, u16 handle, u8 phy_number, u8 link_rate)
5135{
5136 Mpi2ConfigReply_t mpi_reply;
5137 Mpi2SasDevicePage0_t sas_device_pg0;
5138 struct _sas_device *sas_device;
5139 u32 ioc_status;
5140 unsigned long flags;
5141 u64 sas_address;
5142 struct scsi_target *starget;
5143 struct MPT3SAS_TARGET *sas_target_priv_data;
5144 u32 device_info;
5145
5146
5147 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5148 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
5149 return;
5150
5151 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
5152 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
5153 return;
5154
5155 /* wide port handling ~ we need only handle device once for the phy that
5156 * is matched in sas device page zero
5157 */
5158 if (phy_number != sas_device_pg0.PhyNum)
5159 return;
5160
5161 /* check if this is end device */
5162 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5163 if (!(_scsih_is_end_device(device_info)))
5164 return;
5165
5166 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5167 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305168 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305169 sas_address);
5170
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305171 if (!sas_device)
5172 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305173
5174 if (unlikely(sas_device->handle != handle)) {
5175 starget = sas_device->starget;
5176 sas_target_priv_data = starget->hostdata;
5177 starget_printk(KERN_INFO, starget,
5178 "handle changed from(0x%04x) to (0x%04x)!!!\n",
5179 sas_device->handle, handle);
5180 sas_target_priv_data->handle = handle;
5181 sas_device->handle = handle;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305182 if (sas_device_pg0.Flags &
5183 MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
5184 sas_device->enclosure_level =
5185 le16_to_cpu(sas_device_pg0.EnclosureLevel);
5186 memcpy(&sas_device->connector_name[0],
5187 &sas_device_pg0.ConnectorName[0], 4);
5188 } else {
5189 sas_device->enclosure_level = 0;
5190 sas_device->connector_name[0] = '\0';
5191 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305192 }
5193
5194 /* check if device is present */
5195 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5196 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5197 pr_err(MPT3SAS_FMT
5198 "device is not present handle(0x%04x), flags!!!\n",
5199 ioc->name, handle);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305200 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305201 }
5202
5203 /* check if there were any issues with discovery */
5204 if (_scsih_check_access_status(ioc, sas_address, handle,
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305205 sas_device_pg0.AccessStatus))
5206 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305207
5208 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5209 _scsih_ublock_io_device(ioc, sas_address);
5210
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305211 if (sas_device)
5212 sas_device_put(sas_device);
5213 return;
5214
5215out_unlock:
5216 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5217 if (sas_device)
5218 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305219}
5220
5221/**
5222 * _scsih_add_device - creating sas device object
5223 * @ioc: per adapter object
5224 * @handle: sas device handle
5225 * @phy_num: phy number end device attached to
5226 * @is_pd: is this hidden raid component
5227 *
5228 * Creating end device object, stored in ioc->sas_device_list.
5229 *
5230 * Returns 0 for success, non-zero for failure.
5231 */
5232static int
5233_scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
5234 u8 is_pd)
5235{
5236 Mpi2ConfigReply_t mpi_reply;
5237 Mpi2SasDevicePage0_t sas_device_pg0;
5238 Mpi2SasEnclosurePage0_t enclosure_pg0;
5239 struct _sas_device *sas_device;
5240 u32 ioc_status;
5241 u64 sas_address;
5242 u32 device_info;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305243
5244 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5245 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
5246 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5247 ioc->name, __FILE__, __LINE__, __func__);
5248 return -1;
5249 }
5250
5251 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5252 MPI2_IOCSTATUS_MASK;
5253 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5254 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5255 ioc->name, __FILE__, __LINE__, __func__);
5256 return -1;
5257 }
5258
5259 /* check if this is end device */
5260 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5261 if (!(_scsih_is_end_device(device_info)))
5262 return -1;
5263 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
5264
5265 /* check if device is present */
5266 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5267 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5268 pr_err(MPT3SAS_FMT "device is not present handle(0x04%x)!!!\n",
5269 ioc->name, handle);
5270 return -1;
5271 }
5272
5273 /* check if there were any issues with discovery */
5274 if (_scsih_check_access_status(ioc, sas_address, handle,
5275 sas_device_pg0.AccessStatus))
5276 return -1;
5277
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305278 sas_device = mpt3sas_get_sdev_by_addr(ioc,
5279 sas_address);
5280 if (sas_device) {
5281 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305282 return -1;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305283 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305284
5285 sas_device = kzalloc(sizeof(struct _sas_device),
5286 GFP_KERNEL);
5287 if (!sas_device) {
5288 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5289 ioc->name, __FILE__, __LINE__, __func__);
5290 return 0;
5291 }
5292
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305293 kref_init(&sas_device->refcount);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305294 sas_device->handle = handle;
5295 if (_scsih_get_sas_address(ioc,
5296 le16_to_cpu(sas_device_pg0.ParentDevHandle),
5297 &sas_device->sas_address_parent) != 0)
5298 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5299 ioc->name, __FILE__, __LINE__, __func__);
5300 sas_device->enclosure_handle =
5301 le16_to_cpu(sas_device_pg0.EnclosureHandle);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305302 if (sas_device->enclosure_handle != 0)
5303 sas_device->slot =
5304 le16_to_cpu(sas_device_pg0.Slot);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305305 sas_device->device_info = device_info;
5306 sas_device->sas_address = sas_address;
5307 sas_device->phy = sas_device_pg0.PhyNum;
Sreekanth Reddy45506042015-11-11 17:30:25 +05305308#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305309 sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) &
5310 MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
Sreekanth Reddy45506042015-11-11 17:30:25 +05305311#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305312
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305313 if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
5314 sas_device->enclosure_level =
5315 le16_to_cpu(sas_device_pg0.EnclosureLevel);
5316 memcpy(&sas_device->connector_name[0],
5317 &sas_device_pg0.ConnectorName[0], 4);
5318 } else {
5319 sas_device->enclosure_level = 0;
5320 sas_device->connector_name[0] = '\0';
5321 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305322 /* get enclosure_logical_id */
5323 if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0(
5324 ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
5325 sas_device->enclosure_handle)))
5326 sas_device->enclosure_logical_id =
5327 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
5328
5329 /* get device name */
5330 sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
5331
5332 if (ioc->wait_for_discovery_to_complete)
5333 _scsih_sas_device_init_add(ioc, sas_device);
5334 else
5335 _scsih_sas_device_add(ioc, sas_device);
5336
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305337 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305338 return 0;
5339}
5340
5341/**
5342 * _scsih_remove_device - removing sas device object
5343 * @ioc: per adapter object
5344 * @sas_device_delete: the sas_device object
5345 *
5346 * Return nothing.
5347 */
5348static void
5349_scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
5350 struct _sas_device *sas_device)
5351{
5352 struct MPT3SAS_TARGET *sas_target_priv_data;
5353
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05305354 if ((ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) &&
5355 (sas_device->pfa_led_on)) {
5356 _scsih_turn_off_pfa_led(ioc, sas_device);
5357 sas_device->pfa_led_on = 0;
5358 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305359 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5360 "%s: enter: handle(0x%04x), sas_addr(0x%016llx)\n",
5361 ioc->name, __func__,
5362 sas_device->handle, (unsigned long long)
5363 sas_device->sas_address));
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305364 if (sas_device->enclosure_handle != 0)
5365 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5366 "%s: enter: enclosure logical id(0x%016llx), slot(%d)\n",
5367 ioc->name, __func__,
5368 (unsigned long long)sas_device->enclosure_logical_id,
5369 sas_device->slot));
5370 if (sas_device->connector_name[0] != '\0')
5371 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5372 "%s: enter: enclosure level(0x%04x), connector name( %s)\n",
5373 ioc->name, __func__,
5374 sas_device->enclosure_level,
5375 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305376
5377 if (sas_device->starget && sas_device->starget->hostdata) {
5378 sas_target_priv_data = sas_device->starget->hostdata;
5379 sas_target_priv_data->deleted = 1;
5380 _scsih_ublock_io_device(ioc, sas_device->sas_address);
5381 sas_target_priv_data->handle =
5382 MPT3SAS_INVALID_DEVICE_HANDLE;
5383 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05305384
5385 if (!ioc->hide_drives)
5386 mpt3sas_transport_port_remove(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305387 sas_device->sas_address,
5388 sas_device->sas_address_parent);
5389
5390 pr_info(MPT3SAS_FMT
5391 "removing handle(0x%04x), sas_addr(0x%016llx)\n",
5392 ioc->name, sas_device->handle,
5393 (unsigned long long) sas_device->sas_address);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305394 if (sas_device->enclosure_handle != 0)
5395 pr_info(MPT3SAS_FMT
5396 "removing : enclosure logical id(0x%016llx), slot(%d)\n",
5397 ioc->name,
5398 (unsigned long long)sas_device->enclosure_logical_id,
5399 sas_device->slot);
5400 if (sas_device->connector_name[0] != '\0')
5401 pr_info(MPT3SAS_FMT
5402 "removing enclosure level(0x%04x), connector name( %s)\n",
5403 ioc->name, sas_device->enclosure_level,
5404 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305405
5406 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5407 "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n",
5408 ioc->name, __func__,
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305409 sas_device->handle, (unsigned long long)
5410 sas_device->sas_address));
5411 if (sas_device->enclosure_handle != 0)
5412 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5413 "%s: exit: enclosure logical id(0x%016llx), slot(%d)\n",
5414 ioc->name, __func__,
5415 (unsigned long long)sas_device->enclosure_logical_id,
5416 sas_device->slot));
5417 if (sas_device->connector_name[0] != '\0')
5418 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5419 "%s: exit: enclosure level(0x%04x), connector name(%s)\n",
5420 ioc->name, __func__, sas_device->enclosure_level,
5421 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305422}
5423
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305424/**
5425 * _scsih_sas_topology_change_event_debug - debug for topology event
5426 * @ioc: per adapter object
5427 * @event_data: event data payload
5428 * Context: user.
5429 */
5430static void
5431_scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5432 Mpi2EventDataSasTopologyChangeList_t *event_data)
5433{
5434 int i;
5435 u16 handle;
5436 u16 reason_code;
5437 u8 phy_number;
5438 char *status_str = NULL;
5439 u8 link_rate, prev_link_rate;
5440
5441 switch (event_data->ExpStatus) {
5442 case MPI2_EVENT_SAS_TOPO_ES_ADDED:
5443 status_str = "add";
5444 break;
5445 case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
5446 status_str = "remove";
5447 break;
5448 case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
5449 case 0:
5450 status_str = "responding";
5451 break;
5452 case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
5453 status_str = "remove delay";
5454 break;
5455 default:
5456 status_str = "unknown status";
5457 break;
5458 }
5459 pr_info(MPT3SAS_FMT "sas topology change: (%s)\n",
5460 ioc->name, status_str);
5461 pr_info("\thandle(0x%04x), enclosure_handle(0x%04x) " \
5462 "start_phy(%02d), count(%d)\n",
5463 le16_to_cpu(event_data->ExpanderDevHandle),
5464 le16_to_cpu(event_data->EnclosureHandle),
5465 event_data->StartPhyNum, event_data->NumEntries);
5466 for (i = 0; i < event_data->NumEntries; i++) {
5467 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5468 if (!handle)
5469 continue;
5470 phy_number = event_data->StartPhyNum + i;
5471 reason_code = event_data->PHY[i].PhyStatus &
5472 MPI2_EVENT_SAS_TOPO_RC_MASK;
5473 switch (reason_code) {
5474 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
5475 status_str = "target add";
5476 break;
5477 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
5478 status_str = "target remove";
5479 break;
5480 case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
5481 status_str = "delay target remove";
5482 break;
5483 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
5484 status_str = "link rate change";
5485 break;
5486 case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
5487 status_str = "target responding";
5488 break;
5489 default:
5490 status_str = "unknown";
5491 break;
5492 }
5493 link_rate = event_data->PHY[i].LinkRate >> 4;
5494 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
5495 pr_info("\tphy(%02d), attached_handle(0x%04x): %s:" \
5496 " link rate: new(0x%02x), old(0x%02x)\n", phy_number,
5497 handle, status_str, link_rate, prev_link_rate);
5498
5499 }
5500}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305501
5502/**
5503 * _scsih_sas_topology_change_event - handle topology changes
5504 * @ioc: per adapter object
5505 * @fw_event: The fw_event_work object
5506 * Context: user.
5507 *
5508 */
5509static int
5510_scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
5511 struct fw_event_work *fw_event)
5512{
5513 int i;
5514 u16 parent_handle, handle;
5515 u16 reason_code;
5516 u8 phy_number, max_phys;
5517 struct _sas_node *sas_expander;
5518 u64 sas_address;
5519 unsigned long flags;
5520 u8 link_rate, prev_link_rate;
Joe Lawrence35b62362014-06-25 17:05:34 -04005521 Mpi2EventDataSasTopologyChangeList_t *event_data =
5522 (Mpi2EventDataSasTopologyChangeList_t *)
5523 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305524
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305525 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5526 _scsih_sas_topology_change_event_debug(ioc, event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305527
5528 if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
5529 return 0;
5530
5531 if (!ioc->sas_hba.num_phys)
5532 _scsih_sas_host_add(ioc);
5533 else
5534 _scsih_sas_host_refresh(ioc);
5535
5536 if (fw_event->ignore) {
5537 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5538 "ignoring expander event\n", ioc->name));
5539 return 0;
5540 }
5541
5542 parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
5543
5544 /* handle expander add */
5545 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
5546 if (_scsih_expander_add(ioc, parent_handle) != 0)
5547 return 0;
5548
5549 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5550 sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
5551 parent_handle);
5552 if (sas_expander) {
5553 sas_address = sas_expander->sas_address;
5554 max_phys = sas_expander->num_phys;
5555 } else if (parent_handle < ioc->sas_hba.num_phys) {
5556 sas_address = ioc->sas_hba.sas_address;
5557 max_phys = ioc->sas_hba.num_phys;
5558 } else {
5559 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5560 return 0;
5561 }
5562 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5563
5564 /* handle siblings events */
5565 for (i = 0; i < event_data->NumEntries; i++) {
5566 if (fw_event->ignore) {
5567 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5568 "ignoring expander event\n", ioc->name));
5569 return 0;
5570 }
5571 if (ioc->remove_host || ioc->pci_error_recovery)
5572 return 0;
5573 phy_number = event_data->StartPhyNum + i;
5574 if (phy_number >= max_phys)
5575 continue;
5576 reason_code = event_data->PHY[i].PhyStatus &
5577 MPI2_EVENT_SAS_TOPO_RC_MASK;
5578 if ((event_data->PHY[i].PhyStatus &
5579 MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
5580 MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
5581 continue;
5582 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5583 if (!handle)
5584 continue;
5585 link_rate = event_data->PHY[i].LinkRate >> 4;
5586 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
5587 switch (reason_code) {
5588 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
5589
5590 if (ioc->shost_recovery)
5591 break;
5592
5593 if (link_rate == prev_link_rate)
5594 break;
5595
5596 mpt3sas_transport_update_links(ioc, sas_address,
5597 handle, phy_number, link_rate);
5598
5599 if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
5600 break;
5601
5602 _scsih_check_device(ioc, sas_address, handle,
5603 phy_number, link_rate);
5604
5605
5606 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
5607
5608 if (ioc->shost_recovery)
5609 break;
5610
5611 mpt3sas_transport_update_links(ioc, sas_address,
5612 handle, phy_number, link_rate);
5613
5614 _scsih_add_device(ioc, handle, phy_number, 0);
5615
5616 break;
5617 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
5618
5619 _scsih_device_remove_by_handle(ioc, handle);
5620 break;
5621 }
5622 }
5623
5624 /* handle expander removal */
5625 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
5626 sas_expander)
5627 mpt3sas_expander_remove(ioc, sas_address);
5628
5629 return 0;
5630}
5631
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305632/**
5633 * _scsih_sas_device_status_change_event_debug - debug for device event
5634 * @event_data: event data payload
5635 * Context: user.
5636 *
5637 * Return nothing.
5638 */
5639static void
5640_scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5641 Mpi2EventDataSasDeviceStatusChange_t *event_data)
5642{
5643 char *reason_str = NULL;
5644
5645 switch (event_data->ReasonCode) {
5646 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5647 reason_str = "smart data";
5648 break;
5649 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
5650 reason_str = "unsupported device discovered";
5651 break;
5652 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
5653 reason_str = "internal device reset";
5654 break;
5655 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
5656 reason_str = "internal task abort";
5657 break;
5658 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
5659 reason_str = "internal task abort set";
5660 break;
5661 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
5662 reason_str = "internal clear task set";
5663 break;
5664 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
5665 reason_str = "internal query task";
5666 break;
5667 case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
5668 reason_str = "sata init failure";
5669 break;
5670 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
5671 reason_str = "internal device reset complete";
5672 break;
5673 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
5674 reason_str = "internal task abort complete";
5675 break;
5676 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
5677 reason_str = "internal async notification";
5678 break;
5679 case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY:
5680 reason_str = "expander reduced functionality";
5681 break;
5682 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY:
5683 reason_str = "expander reduced functionality complete";
5684 break;
5685 default:
5686 reason_str = "unknown reason";
5687 break;
5688 }
5689 pr_info(MPT3SAS_FMT "device status change: (%s)\n"
5690 "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
5691 ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
5692 (unsigned long long)le64_to_cpu(event_data->SASAddress),
5693 le16_to_cpu(event_data->TaskTag));
5694 if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
5695 pr_info(MPT3SAS_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
5696 event_data->ASC, event_data->ASCQ);
5697 pr_info("\n");
5698}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305699
5700/**
5701 * _scsih_sas_device_status_change_event - handle device status change
5702 * @ioc: per adapter object
5703 * @fw_event: The fw_event_work object
5704 * Context: user.
5705 *
5706 * Return nothing.
5707 */
5708static void
5709_scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
5710 struct fw_event_work *fw_event)
5711{
5712 struct MPT3SAS_TARGET *target_priv_data;
5713 struct _sas_device *sas_device;
5714 u64 sas_address;
5715 unsigned long flags;
5716 Mpi2EventDataSasDeviceStatusChange_t *event_data =
Joe Lawrence35b62362014-06-25 17:05:34 -04005717 (Mpi2EventDataSasDeviceStatusChange_t *)
5718 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305719
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305720 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5721 _scsih_sas_device_status_change_event_debug(ioc,
5722 event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305723
5724 /* In MPI Revision K (0xC), the internal device reset complete was
5725 * implemented, so avoid setting tm_busy flag for older firmware.
5726 */
5727 if ((ioc->facts.HeaderVersion >> 8) < 0xC)
5728 return;
5729
5730 if (event_data->ReasonCode !=
5731 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
5732 event_data->ReasonCode !=
5733 MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)
5734 return;
5735
5736 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5737 sas_address = le64_to_cpu(event_data->SASAddress);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305738 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305739 sas_address);
5740
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305741 if (!sas_device || !sas_device->starget)
5742 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305743
5744 target_priv_data = sas_device->starget->hostdata;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305745 if (!target_priv_data)
5746 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305747
5748 if (event_data->ReasonCode ==
5749 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
5750 target_priv_data->tm_busy = 1;
5751 else
5752 target_priv_data->tm_busy = 0;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305753
5754out:
5755 if (sas_device)
5756 sas_device_put(sas_device);
5757
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305758 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305759
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305760}
5761
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305762/**
5763 * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure
5764 * event
5765 * @ioc: per adapter object
5766 * @event_data: event data payload
5767 * Context: user.
5768 *
5769 * Return nothing.
5770 */
5771static void
5772_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5773 Mpi2EventDataSasEnclDevStatusChange_t *event_data)
5774{
5775 char *reason_str = NULL;
5776
5777 switch (event_data->ReasonCode) {
5778 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
5779 reason_str = "enclosure add";
5780 break;
5781 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
5782 reason_str = "enclosure remove";
5783 break;
5784 default:
5785 reason_str = "unknown reason";
5786 break;
5787 }
5788
5789 pr_info(MPT3SAS_FMT "enclosure status change: (%s)\n"
5790 "\thandle(0x%04x), enclosure logical id(0x%016llx)"
5791 " number slots(%d)\n", ioc->name, reason_str,
5792 le16_to_cpu(event_data->EnclosureHandle),
5793 (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
5794 le16_to_cpu(event_data->StartSlot));
5795}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305796
5797/**
5798 * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
5799 * @ioc: per adapter object
5800 * @fw_event: The fw_event_work object
5801 * Context: user.
5802 *
5803 * Return nothing.
5804 */
5805static void
5806_scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
5807 struct fw_event_work *fw_event)
5808{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305809 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5810 _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
Joe Lawrence35b62362014-06-25 17:05:34 -04005811 (Mpi2EventDataSasEnclDevStatusChange_t *)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305812 fw_event->event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305813}
5814
5815/**
5816 * _scsih_sas_broadcast_primitive_event - handle broadcast events
5817 * @ioc: per adapter object
5818 * @fw_event: The fw_event_work object
5819 * Context: user.
5820 *
5821 * Return nothing.
5822 */
5823static void
5824_scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
5825 struct fw_event_work *fw_event)
5826{
5827 struct scsi_cmnd *scmd;
5828 struct scsi_device *sdev;
5829 u16 smid, handle;
5830 u32 lun;
5831 struct MPT3SAS_DEVICE *sas_device_priv_data;
5832 u32 termination_count;
5833 u32 query_count;
5834 Mpi2SCSITaskManagementReply_t *mpi_reply;
Joe Lawrence35b62362014-06-25 17:05:34 -04005835 Mpi2EventDataSasBroadcastPrimitive_t *event_data =
5836 (Mpi2EventDataSasBroadcastPrimitive_t *)
5837 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305838 u16 ioc_status;
5839 unsigned long flags;
5840 int r;
5841 u8 max_retries = 0;
5842 u8 task_abort_retries;
5843
5844 mutex_lock(&ioc->tm_cmds.mutex);
5845 pr_info(MPT3SAS_FMT
5846 "%s: enter: phy number(%d), width(%d)\n",
5847 ioc->name, __func__, event_data->PhyNum,
5848 event_data->PortWidth);
5849
5850 _scsih_block_io_all_device(ioc);
5851
5852 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5853 mpi_reply = ioc->tm_cmds.reply;
5854 broadcast_aen_retry:
5855
5856 /* sanity checks for retrying this loop */
5857 if (max_retries++ == 5) {
5858 dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: giving up\n",
5859 ioc->name, __func__));
5860 goto out;
5861 } else if (max_retries > 1)
5862 dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: %d retry\n",
5863 ioc->name, __func__, max_retries - 1));
5864
5865 termination_count = 0;
5866 query_count = 0;
5867 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
5868 if (ioc->shost_recovery)
5869 goto out;
5870 scmd = _scsih_scsi_lookup_get(ioc, smid);
5871 if (!scmd)
5872 continue;
5873 sdev = scmd->device;
5874 sas_device_priv_data = sdev->hostdata;
5875 if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
5876 continue;
5877 /* skip hidden raid components */
5878 if (sas_device_priv_data->sas_target->flags &
5879 MPT_TARGET_FLAGS_RAID_COMPONENT)
5880 continue;
5881 /* skip volumes */
5882 if (sas_device_priv_data->sas_target->flags &
5883 MPT_TARGET_FLAGS_VOLUME)
5884 continue;
5885
5886 handle = sas_device_priv_data->sas_target->handle;
5887 lun = sas_device_priv_data->lun;
5888 query_count++;
5889
5890 if (ioc->shost_recovery)
5891 goto out;
5892
5893 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5894 r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04005895 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305896 TM_MUTEX_OFF);
5897 if (r == FAILED) {
5898 sdev_printk(KERN_WARNING, sdev,
5899 "mpt3sas_scsih_issue_tm: FAILED when sending "
5900 "QUERY_TASK: scmd(%p)\n", scmd);
5901 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5902 goto broadcast_aen_retry;
5903 }
5904 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
5905 & MPI2_IOCSTATUS_MASK;
5906 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5907 sdev_printk(KERN_WARNING, sdev,
5908 "query task: FAILED with IOCSTATUS(0x%04x), scmd(%p)\n",
5909 ioc_status, scmd);
5910 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5911 goto broadcast_aen_retry;
5912 }
5913
5914 /* see if IO is still owned by IOC and target */
5915 if (mpi_reply->ResponseCode ==
5916 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
5917 mpi_reply->ResponseCode ==
5918 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
5919 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5920 continue;
5921 }
5922 task_abort_retries = 0;
5923 tm_retry:
5924 if (task_abort_retries++ == 60) {
5925 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5926 "%s: ABORT_TASK: giving up\n", ioc->name,
5927 __func__));
5928 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5929 goto broadcast_aen_retry;
5930 }
5931
5932 if (ioc->shost_recovery)
5933 goto out_no_lock;
5934
5935 r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
5936 sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04005937 TM_MUTEX_OFF);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305938 if (r == FAILED) {
5939 sdev_printk(KERN_WARNING, sdev,
5940 "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : "
5941 "scmd(%p)\n", scmd);
5942 goto tm_retry;
5943 }
5944
5945 if (task_abort_retries > 1)
5946 sdev_printk(KERN_WARNING, sdev,
5947 "mpt3sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
5948 " scmd(%p)\n",
5949 task_abort_retries - 1, scmd);
5950
5951 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
5952 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5953 }
5954
5955 if (ioc->broadcast_aen_pending) {
5956 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5957 "%s: loop back due to pending AEN\n",
5958 ioc->name, __func__));
5959 ioc->broadcast_aen_pending = 0;
5960 goto broadcast_aen_retry;
5961 }
5962
5963 out:
5964 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5965 out_no_lock:
5966
5967 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5968 "%s - exit, query_count = %d termination_count = %d\n",
5969 ioc->name, __func__, query_count, termination_count));
5970
5971 ioc->broadcast_aen_busy = 0;
5972 if (!ioc->shost_recovery)
5973 _scsih_ublock_io_all_device(ioc);
5974 mutex_unlock(&ioc->tm_cmds.mutex);
5975}
5976
5977/**
5978 * _scsih_sas_discovery_event - handle discovery events
5979 * @ioc: per adapter object
5980 * @fw_event: The fw_event_work object
5981 * Context: user.
5982 *
5983 * Return nothing.
5984 */
5985static void
5986_scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
5987 struct fw_event_work *fw_event)
5988{
Joe Lawrence35b62362014-06-25 17:05:34 -04005989 Mpi2EventDataSasDiscovery_t *event_data =
5990 (Mpi2EventDataSasDiscovery_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305991
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305992 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
5993 pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name,
5994 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
5995 "start" : "stop");
Sreekanth Reddyaf009412015-11-11 17:30:23 +05305996 if (event_data->DiscoveryStatus)
5997 pr_info("discovery_status(0x%08x)",
5998 le32_to_cpu(event_data->DiscoveryStatus));
5999 pr_info("\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306000 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306001
6002 if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
6003 !ioc->sas_hba.num_phys) {
6004 if (disable_discovery > 0 && ioc->shost_recovery) {
6005 /* Wait for the reset to complete */
6006 while (ioc->shost_recovery)
6007 ssleep(1);
6008 }
6009 _scsih_sas_host_add(ioc);
6010 }
6011}
6012
Sreekanth Reddy45506042015-11-11 17:30:25 +05306013#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306014/**
6015 * _scsih_ir_fastpath - turn on fastpath for IR physdisk
6016 * @ioc: per adapter object
6017 * @handle: device handle for physical disk
6018 * @phys_disk_num: physical disk number
6019 *
6020 * Return 0 for success, else failure.
6021 */
6022static int
6023_scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
6024{
6025 Mpi2RaidActionRequest_t *mpi_request;
6026 Mpi2RaidActionReply_t *mpi_reply;
6027 u16 smid;
6028 u8 issue_reset = 0;
6029 int rc = 0;
6030 u16 ioc_status;
6031 u32 log_info;
6032
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306033 mutex_lock(&ioc->scsih_cmds.mutex);
6034
6035 if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
6036 pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
6037 ioc->name, __func__);
6038 rc = -EAGAIN;
6039 goto out;
6040 }
6041 ioc->scsih_cmds.status = MPT3_CMD_PENDING;
6042
6043 smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
6044 if (!smid) {
6045 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
6046 ioc->name, __func__);
6047 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
6048 rc = -EAGAIN;
6049 goto out;
6050 }
6051
6052 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
6053 ioc->scsih_cmds.smid = smid;
6054 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
6055
6056 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
6057 mpi_request->Action = MPI2_RAID_ACTION_PHYSDISK_HIDDEN;
6058 mpi_request->PhysDiskNum = phys_disk_num;
6059
6060 dewtprintk(ioc, pr_info(MPT3SAS_FMT "IR RAID_ACTION: turning fast "\
6061 "path on for handle(0x%04x), phys_disk_num (0x%02x)\n", ioc->name,
6062 handle, phys_disk_num));
6063
6064 init_completion(&ioc->scsih_cmds.done);
6065 mpt3sas_base_put_smid_default(ioc, smid);
6066 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
6067
6068 if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
6069 pr_err(MPT3SAS_FMT "%s: timeout\n",
6070 ioc->name, __func__);
6071 if (!(ioc->scsih_cmds.status & MPT3_CMD_RESET))
6072 issue_reset = 1;
6073 rc = -EFAULT;
6074 goto out;
6075 }
6076
6077 if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
6078
6079 mpi_reply = ioc->scsih_cmds.reply;
6080 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
6081 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
6082 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
6083 else
6084 log_info = 0;
6085 ioc_status &= MPI2_IOCSTATUS_MASK;
6086 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6087 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6088 "IR RAID_ACTION: failed: ioc_status(0x%04x), "
6089 "loginfo(0x%08x)!!!\n", ioc->name, ioc_status,
6090 log_info));
6091 rc = -EFAULT;
6092 } else
6093 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6094 "IR RAID_ACTION: completed successfully\n",
6095 ioc->name));
6096 }
6097
6098 out:
6099 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
6100 mutex_unlock(&ioc->scsih_cmds.mutex);
6101
6102 if (issue_reset)
6103 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
6104 FORCE_BIG_HAMMER);
6105 return rc;
6106}
Sreekanth Reddy45506042015-11-11 17:30:25 +05306107/* End of not defined SCSI_MPT2SAS */
6108#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306109
6110/**
6111 * _scsih_reprobe_lun - reprobing lun
6112 * @sdev: scsi device struct
6113 * @no_uld_attach: sdev->no_uld_attach flag setting
6114 *
6115 **/
6116static void
6117_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
6118{
6119 int rc;
6120 sdev->no_uld_attach = no_uld_attach ? 1 : 0;
6121 sdev_printk(KERN_INFO, sdev, "%s raid component\n",
6122 sdev->no_uld_attach ? "hidding" : "exposing");
6123 rc = scsi_device_reprobe(sdev);
6124}
6125
6126/**
6127 * _scsih_sas_volume_add - add new volume
6128 * @ioc: per adapter object
6129 * @element: IR config element data
6130 * Context: user.
6131 *
6132 * Return nothing.
6133 */
6134static void
6135_scsih_sas_volume_add(struct MPT3SAS_ADAPTER *ioc,
6136 Mpi2EventIrConfigElement_t *element)
6137{
6138 struct _raid_device *raid_device;
6139 unsigned long flags;
6140 u64 wwid;
6141 u16 handle = le16_to_cpu(element->VolDevHandle);
6142 int rc;
6143
6144 mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
6145 if (!wwid) {
6146 pr_err(MPT3SAS_FMT
6147 "failure at %s:%d/%s()!\n", ioc->name,
6148 __FILE__, __LINE__, __func__);
6149 return;
6150 }
6151
6152 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6153 raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
6154 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6155
6156 if (raid_device)
6157 return;
6158
6159 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6160 if (!raid_device) {
6161 pr_err(MPT3SAS_FMT
6162 "failure at %s:%d/%s()!\n", ioc->name,
6163 __FILE__, __LINE__, __func__);
6164 return;
6165 }
6166
6167 raid_device->id = ioc->sas_id++;
6168 raid_device->channel = RAID_CHANNEL;
6169 raid_device->handle = handle;
6170 raid_device->wwid = wwid;
6171 _scsih_raid_device_add(ioc, raid_device);
6172 if (!ioc->wait_for_discovery_to_complete) {
6173 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6174 raid_device->id, 0);
6175 if (rc)
6176 _scsih_raid_device_remove(ioc, raid_device);
6177 } else {
6178 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6179 _scsih_determine_boot_device(ioc, raid_device, 1);
6180 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6181 }
6182}
6183
6184/**
6185 * _scsih_sas_volume_delete - delete volume
6186 * @ioc: per adapter object
6187 * @handle: volume device handle
6188 * Context: user.
6189 *
6190 * Return nothing.
6191 */
6192static void
6193_scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle)
6194{
6195 struct _raid_device *raid_device;
6196 unsigned long flags;
6197 struct MPT3SAS_TARGET *sas_target_priv_data;
6198 struct scsi_target *starget = NULL;
6199
6200 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6201 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6202 if (raid_device) {
6203 if (raid_device->starget) {
6204 starget = raid_device->starget;
6205 sas_target_priv_data = starget->hostdata;
6206 sas_target_priv_data->deleted = 1;
6207 }
6208 pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
6209 ioc->name, raid_device->handle,
6210 (unsigned long long) raid_device->wwid);
6211 list_del(&raid_device->list);
6212 kfree(raid_device);
6213 }
6214 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6215 if (starget)
6216 scsi_remove_target(&starget->dev);
6217}
6218
6219/**
6220 * _scsih_sas_pd_expose - expose pd component to /dev/sdX
6221 * @ioc: per adapter object
6222 * @element: IR config element data
6223 * Context: user.
6224 *
6225 * Return nothing.
6226 */
6227static void
6228_scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc,
6229 Mpi2EventIrConfigElement_t *element)
6230{
6231 struct _sas_device *sas_device;
6232 struct scsi_target *starget = NULL;
6233 struct MPT3SAS_TARGET *sas_target_priv_data;
6234 unsigned long flags;
6235 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6236
6237 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306238 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306239 if (sas_device) {
6240 sas_device->volume_handle = 0;
6241 sas_device->volume_wwid = 0;
6242 clear_bit(handle, ioc->pd_handles);
6243 if (sas_device->starget && sas_device->starget->hostdata) {
6244 starget = sas_device->starget;
6245 sas_target_priv_data = starget->hostdata;
6246 sas_target_priv_data->flags &=
6247 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
6248 }
6249 }
6250 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6251 if (!sas_device)
6252 return;
6253
6254 /* exposing raid component */
6255 if (starget)
6256 starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306257
6258 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306259}
6260
6261/**
6262 * _scsih_sas_pd_hide - hide pd component from /dev/sdX
6263 * @ioc: per adapter object
6264 * @element: IR config element data
6265 * Context: user.
6266 *
6267 * Return nothing.
6268 */
6269static void
6270_scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc,
6271 Mpi2EventIrConfigElement_t *element)
6272{
6273 struct _sas_device *sas_device;
6274 struct scsi_target *starget = NULL;
6275 struct MPT3SAS_TARGET *sas_target_priv_data;
6276 unsigned long flags;
6277 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6278 u16 volume_handle = 0;
6279 u64 volume_wwid = 0;
6280
6281 mpt3sas_config_get_volume_handle(ioc, handle, &volume_handle);
6282 if (volume_handle)
6283 mpt3sas_config_get_volume_wwid(ioc, volume_handle,
6284 &volume_wwid);
6285
6286 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306287 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306288 if (sas_device) {
6289 set_bit(handle, ioc->pd_handles);
6290 if (sas_device->starget && sas_device->starget->hostdata) {
6291 starget = sas_device->starget;
6292 sas_target_priv_data = starget->hostdata;
6293 sas_target_priv_data->flags |=
6294 MPT_TARGET_FLAGS_RAID_COMPONENT;
6295 sas_device->volume_handle = volume_handle;
6296 sas_device->volume_wwid = volume_wwid;
6297 }
6298 }
6299 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6300 if (!sas_device)
6301 return;
6302
Sreekanth Reddy45506042015-11-11 17:30:25 +05306303#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306304 /* hiding raid component */
6305 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
Sreekanth Reddy45506042015-11-11 17:30:25 +05306306#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306307 if (starget)
6308 starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306309
6310 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306311}
6312
6313/**
6314 * _scsih_sas_pd_delete - delete pd component
6315 * @ioc: per adapter object
6316 * @element: IR config element data
6317 * Context: user.
6318 *
6319 * Return nothing.
6320 */
6321static void
6322_scsih_sas_pd_delete(struct MPT3SAS_ADAPTER *ioc,
6323 Mpi2EventIrConfigElement_t *element)
6324{
6325 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6326
6327 _scsih_device_remove_by_handle(ioc, handle);
6328}
6329
6330/**
6331 * _scsih_sas_pd_add - remove pd component
6332 * @ioc: per adapter object
6333 * @element: IR config element data
6334 * Context: user.
6335 *
6336 * Return nothing.
6337 */
6338static void
6339_scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
6340 Mpi2EventIrConfigElement_t *element)
6341{
6342 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306343 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6344 Mpi2ConfigReply_t mpi_reply;
6345 Mpi2SasDevicePage0_t sas_device_pg0;
6346 u32 ioc_status;
6347 u64 sas_address;
6348 u16 parent_handle;
6349
6350 set_bit(handle, ioc->pd_handles);
6351
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306352 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306353 if (sas_device) {
Sreekanth Reddy45506042015-11-11 17:30:25 +05306354#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306355 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
Sreekanth Reddy45506042015-11-11 17:30:25 +05306356#endif
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306357 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306358 return;
6359 }
6360
6361 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
6362 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
6363 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6364 ioc->name, __FILE__, __LINE__, __func__);
6365 return;
6366 }
6367
6368 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6369 MPI2_IOCSTATUS_MASK;
6370 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6371 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6372 ioc->name, __FILE__, __LINE__, __func__);
6373 return;
6374 }
6375
6376 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6377 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6378 mpt3sas_transport_update_links(ioc, sas_address, handle,
6379 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
6380
Sreekanth Reddy45506042015-11-11 17:30:25 +05306381#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306382 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
Sreekanth Reddy45506042015-11-11 17:30:25 +05306383#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306384 _scsih_add_device(ioc, handle, 0, 1);
6385}
6386
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306387/**
6388 * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
6389 * @ioc: per adapter object
6390 * @event_data: event data payload
6391 * Context: user.
6392 *
6393 * Return nothing.
6394 */
6395static void
6396_scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
6397 Mpi2EventDataIrConfigChangeList_t *event_data)
6398{
6399 Mpi2EventIrConfigElement_t *element;
6400 u8 element_type;
6401 int i;
6402 char *reason_str = NULL, *element_str = NULL;
6403
6404 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6405
6406 pr_info(MPT3SAS_FMT "raid config change: (%s), elements(%d)\n",
6407 ioc->name, (le32_to_cpu(event_data->Flags) &
6408 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
6409 "foreign" : "native", event_data->NumElements);
6410 for (i = 0; i < event_data->NumElements; i++, element++) {
6411 switch (element->ReasonCode) {
6412 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6413 reason_str = "add";
6414 break;
6415 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6416 reason_str = "remove";
6417 break;
6418 case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
6419 reason_str = "no change";
6420 break;
6421 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6422 reason_str = "hide";
6423 break;
6424 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
6425 reason_str = "unhide";
6426 break;
6427 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6428 reason_str = "volume_created";
6429 break;
6430 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6431 reason_str = "volume_deleted";
6432 break;
6433 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6434 reason_str = "pd_created";
6435 break;
6436 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
6437 reason_str = "pd_deleted";
6438 break;
6439 default:
6440 reason_str = "unknown reason";
6441 break;
6442 }
6443 element_type = le16_to_cpu(element->ElementFlags) &
6444 MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
6445 switch (element_type) {
6446 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
6447 element_str = "volume";
6448 break;
6449 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
6450 element_str = "phys disk";
6451 break;
6452 case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
6453 element_str = "hot spare";
6454 break;
6455 default:
6456 element_str = "unknown element";
6457 break;
6458 }
6459 pr_info("\t(%s:%s), vol handle(0x%04x), " \
6460 "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
6461 reason_str, le16_to_cpu(element->VolDevHandle),
6462 le16_to_cpu(element->PhysDiskDevHandle),
6463 element->PhysDiskNum);
6464 }
6465}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306466
6467/**
6468 * _scsih_sas_ir_config_change_event - handle ir configuration change events
6469 * @ioc: per adapter object
6470 * @fw_event: The fw_event_work object
6471 * Context: user.
6472 *
6473 * Return nothing.
6474 */
6475static void
6476_scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
6477 struct fw_event_work *fw_event)
6478{
6479 Mpi2EventIrConfigElement_t *element;
6480 int i;
6481 u8 foreign_config;
Joe Lawrence35b62362014-06-25 17:05:34 -04006482 Mpi2EventDataIrConfigChangeList_t *event_data =
6483 (Mpi2EventDataIrConfigChangeList_t *)
6484 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306485
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306486 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
6487 (!ioc->hide_ir_msg))
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306488 _scsih_sas_ir_config_change_event_debug(ioc, event_data);
6489
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306490 foreign_config = (le32_to_cpu(event_data->Flags) &
6491 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
6492
6493 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6494 if (ioc->shost_recovery) {
Sreekanth Reddy45506042015-11-11 17:30:25 +05306495#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306496 for (i = 0; i < event_data->NumElements; i++, element++) {
6497 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE)
6498 _scsih_ir_fastpath(ioc,
6499 le16_to_cpu(element->PhysDiskDevHandle),
6500 element->PhysDiskNum);
6501 }
Sreekanth Reddy45506042015-11-11 17:30:25 +05306502#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306503 return;
6504 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306505
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306506 for (i = 0; i < event_data->NumElements; i++, element++) {
6507
6508 switch (element->ReasonCode) {
6509 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6510 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6511 if (!foreign_config)
6512 _scsih_sas_volume_add(ioc, element);
6513 break;
6514 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6515 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6516 if (!foreign_config)
6517 _scsih_sas_volume_delete(ioc,
6518 le16_to_cpu(element->VolDevHandle));
6519 break;
6520 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306521 if (!ioc->is_warpdrive)
6522 _scsih_sas_pd_hide(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306523 break;
6524 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306525 if (!ioc->is_warpdrive)
6526 _scsih_sas_pd_expose(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306527 break;
6528 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306529 if (!ioc->is_warpdrive)
6530 _scsih_sas_pd_add(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306531 break;
6532 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306533 if (!ioc->is_warpdrive)
6534 _scsih_sas_pd_delete(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306535 break;
6536 }
6537 }
6538}
6539
6540/**
6541 * _scsih_sas_ir_volume_event - IR volume event
6542 * @ioc: per adapter object
6543 * @fw_event: The fw_event_work object
6544 * Context: user.
6545 *
6546 * Return nothing.
6547 */
6548static void
6549_scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
6550 struct fw_event_work *fw_event)
6551{
6552 u64 wwid;
6553 unsigned long flags;
6554 struct _raid_device *raid_device;
6555 u16 handle;
6556 u32 state;
6557 int rc;
Joe Lawrence35b62362014-06-25 17:05:34 -04006558 Mpi2EventDataIrVolume_t *event_data =
6559 (Mpi2EventDataIrVolume_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306560
6561 if (ioc->shost_recovery)
6562 return;
6563
6564 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
6565 return;
6566
6567 handle = le16_to_cpu(event_data->VolDevHandle);
6568 state = le32_to_cpu(event_data->NewValue);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306569 if (!ioc->hide_ir_msg)
6570 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6571 "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
6572 ioc->name, __func__, handle,
6573 le32_to_cpu(event_data->PreviousValue), state));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306574 switch (state) {
6575 case MPI2_RAID_VOL_STATE_MISSING:
6576 case MPI2_RAID_VOL_STATE_FAILED:
6577 _scsih_sas_volume_delete(ioc, handle);
6578 break;
6579
6580 case MPI2_RAID_VOL_STATE_ONLINE:
6581 case MPI2_RAID_VOL_STATE_DEGRADED:
6582 case MPI2_RAID_VOL_STATE_OPTIMAL:
6583
6584 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6585 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6586 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6587
6588 if (raid_device)
6589 break;
6590
6591 mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
6592 if (!wwid) {
6593 pr_err(MPT3SAS_FMT
6594 "failure at %s:%d/%s()!\n", ioc->name,
6595 __FILE__, __LINE__, __func__);
6596 break;
6597 }
6598
6599 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6600 if (!raid_device) {
6601 pr_err(MPT3SAS_FMT
6602 "failure at %s:%d/%s()!\n", ioc->name,
6603 __FILE__, __LINE__, __func__);
6604 break;
6605 }
6606
6607 raid_device->id = ioc->sas_id++;
6608 raid_device->channel = RAID_CHANNEL;
6609 raid_device->handle = handle;
6610 raid_device->wwid = wwid;
6611 _scsih_raid_device_add(ioc, raid_device);
6612 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6613 raid_device->id, 0);
6614 if (rc)
6615 _scsih_raid_device_remove(ioc, raid_device);
6616 break;
6617
6618 case MPI2_RAID_VOL_STATE_INITIALIZING:
6619 default:
6620 break;
6621 }
6622}
6623
6624/**
6625 * _scsih_sas_ir_physical_disk_event - PD event
6626 * @ioc: per adapter object
6627 * @fw_event: The fw_event_work object
6628 * Context: user.
6629 *
6630 * Return nothing.
6631 */
6632static void
6633_scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
6634 struct fw_event_work *fw_event)
6635{
6636 u16 handle, parent_handle;
6637 u32 state;
6638 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306639 Mpi2ConfigReply_t mpi_reply;
6640 Mpi2SasDevicePage0_t sas_device_pg0;
6641 u32 ioc_status;
Joe Lawrence35b62362014-06-25 17:05:34 -04006642 Mpi2EventDataIrPhysicalDisk_t *event_data =
6643 (Mpi2EventDataIrPhysicalDisk_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306644 u64 sas_address;
6645
6646 if (ioc->shost_recovery)
6647 return;
6648
6649 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
6650 return;
6651
6652 handle = le16_to_cpu(event_data->PhysDiskDevHandle);
6653 state = le32_to_cpu(event_data->NewValue);
6654
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306655 if (!ioc->hide_ir_msg)
6656 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6657 "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
6658 ioc->name, __func__, handle,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306659 le32_to_cpu(event_data->PreviousValue), state));
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306660
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306661 switch (state) {
6662 case MPI2_RAID_PD_STATE_ONLINE:
6663 case MPI2_RAID_PD_STATE_DEGRADED:
6664 case MPI2_RAID_PD_STATE_REBUILDING:
6665 case MPI2_RAID_PD_STATE_OPTIMAL:
6666 case MPI2_RAID_PD_STATE_HOT_SPARE:
6667
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306668 if (!ioc->is_warpdrive)
6669 set_bit(handle, ioc->pd_handles);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306670
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306671 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
6672 if (sas_device) {
6673 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306674 return;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306675 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306676
6677 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6678 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
6679 handle))) {
6680 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6681 ioc->name, __FILE__, __LINE__, __func__);
6682 return;
6683 }
6684
6685 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6686 MPI2_IOCSTATUS_MASK;
6687 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6688 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6689 ioc->name, __FILE__, __LINE__, __func__);
6690 return;
6691 }
6692
6693 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6694 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6695 mpt3sas_transport_update_links(ioc, sas_address, handle,
6696 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
6697
6698 _scsih_add_device(ioc, handle, 0, 1);
6699
6700 break;
6701
6702 case MPI2_RAID_PD_STATE_OFFLINE:
6703 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
6704 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
6705 default:
6706 break;
6707 }
6708}
6709
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306710/**
6711 * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
6712 * @ioc: per adapter object
6713 * @event_data: event data payload
6714 * Context: user.
6715 *
6716 * Return nothing.
6717 */
6718static void
6719_scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc,
6720 Mpi2EventDataIrOperationStatus_t *event_data)
6721{
6722 char *reason_str = NULL;
6723
6724 switch (event_data->RAIDOperation) {
6725 case MPI2_EVENT_IR_RAIDOP_RESYNC:
6726 reason_str = "resync";
6727 break;
6728 case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
6729 reason_str = "online capacity expansion";
6730 break;
6731 case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
6732 reason_str = "consistency check";
6733 break;
6734 case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT:
6735 reason_str = "background init";
6736 break;
6737 case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT:
6738 reason_str = "make data consistent";
6739 break;
6740 }
6741
6742 if (!reason_str)
6743 return;
6744
6745 pr_info(MPT3SAS_FMT "raid operational status: (%s)" \
6746 "\thandle(0x%04x), percent complete(%d)\n",
6747 ioc->name, reason_str,
6748 le16_to_cpu(event_data->VolDevHandle),
6749 event_data->PercentComplete);
6750}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306751
6752/**
6753 * _scsih_sas_ir_operation_status_event - handle RAID operation events
6754 * @ioc: per adapter object
6755 * @fw_event: The fw_event_work object
6756 * Context: user.
6757 *
6758 * Return nothing.
6759 */
6760static void
6761_scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
6762 struct fw_event_work *fw_event)
6763{
Joe Lawrence35b62362014-06-25 17:05:34 -04006764 Mpi2EventDataIrOperationStatus_t *event_data =
6765 (Mpi2EventDataIrOperationStatus_t *)
6766 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306767 static struct _raid_device *raid_device;
6768 unsigned long flags;
6769 u16 handle;
6770
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306771 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
6772 (!ioc->hide_ir_msg))
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306773 _scsih_sas_ir_operation_status_event_debug(ioc,
6774 event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306775
6776 /* code added for raid transport support */
6777 if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
6778
6779 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6780 handle = le16_to_cpu(event_data->VolDevHandle);
6781 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6782 if (raid_device)
6783 raid_device->percent_complete =
6784 event_data->PercentComplete;
6785 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6786 }
6787}
6788
6789/**
6790 * _scsih_prep_device_scan - initialize parameters prior to device scan
6791 * @ioc: per adapter object
6792 *
6793 * Set the deleted flag prior to device scan. If the device is found during
6794 * the scan, then we clear the deleted flag.
6795 */
6796static void
6797_scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc)
6798{
6799 struct MPT3SAS_DEVICE *sas_device_priv_data;
6800 struct scsi_device *sdev;
6801
6802 shost_for_each_device(sdev, ioc->shost) {
6803 sas_device_priv_data = sdev->hostdata;
6804 if (sas_device_priv_data && sas_device_priv_data->sas_target)
6805 sas_device_priv_data->sas_target->deleted = 1;
6806 }
6807}
6808
6809/**
6810 * _scsih_mark_responding_sas_device - mark a sas_devices as responding
6811 * @ioc: per adapter object
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306812 * @sas_device_pg0: SAS Device page 0
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306813 *
6814 * After host reset, find out whether devices are still responding.
6815 * Used in _scsih_remove_unresponsive_sas_devices.
6816 *
6817 * Return nothing.
6818 */
6819static void
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306820_scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc,
6821Mpi2SasDevicePage0_t *sas_device_pg0)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306822{
6823 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
6824 struct scsi_target *starget;
6825 struct _sas_device *sas_device;
6826 unsigned long flags;
6827
6828 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6829 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306830 if ((sas_device->sas_address == sas_device_pg0->SASAddress) &&
6831 (sas_device->slot == sas_device_pg0->Slot)) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306832 sas_device->responding = 1;
6833 starget = sas_device->starget;
6834 if (starget && starget->hostdata) {
6835 sas_target_priv_data = starget->hostdata;
6836 sas_target_priv_data->tm_busy = 0;
6837 sas_target_priv_data->deleted = 0;
6838 } else
6839 sas_target_priv_data = NULL;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306840 if (starget) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306841 starget_printk(KERN_INFO, starget,
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306842 "handle(0x%04x), sas_addr(0x%016llx)\n",
6843 sas_device_pg0->DevHandle,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306844 (unsigned long long)
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306845 sas_device->sas_address);
6846
6847 if (sas_device->enclosure_handle != 0)
6848 starget_printk(KERN_INFO, starget,
6849 "enclosure logical id(0x%016llx),"
6850 " slot(%d)\n",
6851 (unsigned long long)
6852 sas_device->enclosure_logical_id,
6853 sas_device->slot);
6854 }
6855 if (sas_device_pg0->Flags &
6856 MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
6857 sas_device->enclosure_level =
6858 le16_to_cpu(sas_device_pg0->EnclosureLevel);
6859 memcpy(&sas_device->connector_name[0],
6860 &sas_device_pg0->ConnectorName[0], 4);
6861 } else {
6862 sas_device->enclosure_level = 0;
6863 sas_device->connector_name[0] = '\0';
6864 }
6865
6866 if (sas_device->handle == sas_device_pg0->DevHandle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306867 goto out;
6868 pr_info("\thandle changed from(0x%04x)!!!\n",
6869 sas_device->handle);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306870 sas_device->handle = sas_device_pg0->DevHandle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306871 if (sas_target_priv_data)
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306872 sas_target_priv_data->handle =
6873 sas_device_pg0->DevHandle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306874 goto out;
6875 }
6876 }
6877 out:
6878 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6879}
6880
6881/**
6882 * _scsih_search_responding_sas_devices -
6883 * @ioc: per adapter object
6884 *
6885 * After host reset, find out whether devices are still responding.
6886 * If not remove.
6887 *
6888 * Return nothing.
6889 */
6890static void
6891_scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
6892{
6893 Mpi2SasDevicePage0_t sas_device_pg0;
6894 Mpi2ConfigReply_t mpi_reply;
6895 u16 ioc_status;
6896 u16 handle;
6897 u32 device_info;
6898
6899 pr_info(MPT3SAS_FMT "search for end-devices: start\n", ioc->name);
6900
6901 if (list_empty(&ioc->sas_device_list))
6902 goto out;
6903
6904 handle = 0xFFFF;
6905 while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6906 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
6907 handle))) {
6908 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6909 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05306910 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306911 break;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306912 handle = sas_device_pg0.DevHandle =
6913 le16_to_cpu(sas_device_pg0.DevHandle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306914 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
6915 if (!(_scsih_is_end_device(device_info)))
6916 continue;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306917 sas_device_pg0.SASAddress =
6918 le64_to_cpu(sas_device_pg0.SASAddress);
6919 sas_device_pg0.Slot = le16_to_cpu(sas_device_pg0.Slot);
6920 _scsih_mark_responding_sas_device(ioc, &sas_device_pg0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306921 }
6922
6923 out:
6924 pr_info(MPT3SAS_FMT "search for end-devices: complete\n",
6925 ioc->name);
6926}
6927
6928/**
6929 * _scsih_mark_responding_raid_device - mark a raid_device as responding
6930 * @ioc: per adapter object
6931 * @wwid: world wide identifier for raid volume
6932 * @handle: device handle
6933 *
6934 * After host reset, find out whether devices are still responding.
6935 * Used in _scsih_remove_unresponsive_raid_devices.
6936 *
6937 * Return nothing.
6938 */
6939static void
6940_scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
6941 u16 handle)
6942{
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306943 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306944 struct scsi_target *starget;
6945 struct _raid_device *raid_device;
6946 unsigned long flags;
6947
6948 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6949 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
6950 if (raid_device->wwid == wwid && raid_device->starget) {
6951 starget = raid_device->starget;
6952 if (starget && starget->hostdata) {
6953 sas_target_priv_data = starget->hostdata;
6954 sas_target_priv_data->deleted = 0;
6955 } else
6956 sas_target_priv_data = NULL;
6957 raid_device->responding = 1;
6958 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6959 starget_printk(KERN_INFO, raid_device->starget,
6960 "handle(0x%04x), wwid(0x%016llx)\n", handle,
6961 (unsigned long long)raid_device->wwid);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306962
6963#ifdef SCSI_MPT2SAS
6964 /*
6965 * WARPDRIVE: The handles of the PDs might have changed
6966 * across the host reset so re-initialize the
6967 * required data for Direct IO
6968 */
6969 _scsih_init_warpdrive_properties(ioc, raid_device);
6970#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306971 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6972 if (raid_device->handle == handle) {
6973 spin_unlock_irqrestore(&ioc->raid_device_lock,
6974 flags);
6975 return;
6976 }
6977 pr_info("\thandle changed from(0x%04x)!!!\n",
6978 raid_device->handle);
6979 raid_device->handle = handle;
6980 if (sas_target_priv_data)
6981 sas_target_priv_data->handle = handle;
6982 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6983 return;
6984 }
6985 }
6986 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6987}
6988
6989/**
6990 * _scsih_search_responding_raid_devices -
6991 * @ioc: per adapter object
6992 *
6993 * After host reset, find out whether devices are still responding.
6994 * If not remove.
6995 *
6996 * Return nothing.
6997 */
6998static void
6999_scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
7000{
7001 Mpi2RaidVolPage1_t volume_pg1;
7002 Mpi2RaidVolPage0_t volume_pg0;
7003 Mpi2RaidPhysDiskPage0_t pd_pg0;
7004 Mpi2ConfigReply_t mpi_reply;
7005 u16 ioc_status;
7006 u16 handle;
7007 u8 phys_disk_num;
7008
7009 if (!ioc->ir_firmware)
7010 return;
7011
7012 pr_info(MPT3SAS_FMT "search for raid volumes: start\n",
7013 ioc->name);
7014
7015 if (list_empty(&ioc->raid_device_list))
7016 goto out;
7017
7018 handle = 0xFFFF;
7019 while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
7020 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
7021 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7022 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307023 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307024 break;
7025 handle = le16_to_cpu(volume_pg1.DevHandle);
7026
7027 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
7028 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
7029 sizeof(Mpi2RaidVolPage0_t)))
7030 continue;
7031
7032 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
7033 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
7034 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED)
7035 _scsih_mark_responding_raid_device(ioc,
7036 le64_to_cpu(volume_pg1.WWID), handle);
7037 }
7038
7039 /* refresh the pd_handles */
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307040 if (!ioc->is_warpdrive) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307041 phys_disk_num = 0xFF;
7042 memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
7043 while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
7044 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
7045 phys_disk_num))) {
7046 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7047 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307048 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307049 break;
7050 phys_disk_num = pd_pg0.PhysDiskNum;
7051 handle = le16_to_cpu(pd_pg0.DevHandle);
7052 set_bit(handle, ioc->pd_handles);
7053 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307054 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307055 out:
7056 pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n",
7057 ioc->name);
7058}
7059
7060/**
7061 * _scsih_mark_responding_expander - mark a expander as responding
7062 * @ioc: per adapter object
7063 * @sas_address: sas address
7064 * @handle:
7065 *
7066 * After host reset, find out whether devices are still responding.
7067 * Used in _scsih_remove_unresponsive_expanders.
7068 *
7069 * Return nothing.
7070 */
7071static void
7072_scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
7073 u16 handle)
7074{
7075 struct _sas_node *sas_expander;
7076 unsigned long flags;
7077 int i;
7078
7079 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7080 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
7081 if (sas_expander->sas_address != sas_address)
7082 continue;
7083 sas_expander->responding = 1;
7084 if (sas_expander->handle == handle)
7085 goto out;
7086 pr_info("\texpander(0x%016llx): handle changed" \
7087 " from(0x%04x) to (0x%04x)!!!\n",
7088 (unsigned long long)sas_expander->sas_address,
7089 sas_expander->handle, handle);
7090 sas_expander->handle = handle;
7091 for (i = 0 ; i < sas_expander->num_phys ; i++)
7092 sas_expander->phy[i].handle = handle;
7093 goto out;
7094 }
7095 out:
7096 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7097}
7098
7099/**
7100 * _scsih_search_responding_expanders -
7101 * @ioc: per adapter object
7102 *
7103 * After host reset, find out whether devices are still responding.
7104 * If not remove.
7105 *
7106 * Return nothing.
7107 */
7108static void
7109_scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
7110{
7111 Mpi2ExpanderPage0_t expander_pg0;
7112 Mpi2ConfigReply_t mpi_reply;
7113 u16 ioc_status;
7114 u64 sas_address;
7115 u16 handle;
7116
7117 pr_info(MPT3SAS_FMT "search for expanders: start\n", ioc->name);
7118
7119 if (list_empty(&ioc->sas_expander_list))
7120 goto out;
7121
7122 handle = 0xFFFF;
7123 while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
7124 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
7125
7126 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7127 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307128 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307129 break;
7130
7131 handle = le16_to_cpu(expander_pg0.DevHandle);
7132 sas_address = le64_to_cpu(expander_pg0.SASAddress);
7133 pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n",
7134 handle,
7135 (unsigned long long)sas_address);
7136 _scsih_mark_responding_expander(ioc, sas_address, handle);
7137 }
7138
7139 out:
7140 pr_info(MPT3SAS_FMT "search for expanders: complete\n", ioc->name);
7141}
7142
7143/**
7144 * _scsih_remove_unresponding_sas_devices - removing unresponding devices
7145 * @ioc: per adapter object
7146 *
7147 * Return nothing.
7148 */
7149static void
7150_scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
7151{
7152 struct _sas_device *sas_device, *sas_device_next;
7153 struct _sas_node *sas_expander, *sas_expander_next;
7154 struct _raid_device *raid_device, *raid_device_next;
7155 struct list_head tmp_list;
7156 unsigned long flags;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307157 LIST_HEAD(head);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307158
7159 pr_info(MPT3SAS_FMT "removing unresponding devices: start\n",
7160 ioc->name);
7161
7162 /* removing unresponding end devices */
7163 pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n",
7164 ioc->name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307165 /*
7166 * Iterate, pulling off devices marked as non-responding. We become the
7167 * owner for the reference the list had on any object we prune.
7168 */
7169 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307170 list_for_each_entry_safe(sas_device, sas_device_next,
7171 &ioc->sas_device_list, list) {
7172 if (!sas_device->responding)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307173 list_move_tail(&sas_device->list, &head);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307174 else
7175 sas_device->responding = 0;
7176 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307177 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
7178
7179 /*
7180 * Now, uninitialize and remove the unresponding devices we pruned.
7181 */
7182 list_for_each_entry_safe(sas_device, sas_device_next, &head, list) {
7183 _scsih_remove_device(ioc, sas_device);
7184 list_del_init(&sas_device->list);
7185 sas_device_put(sas_device);
7186 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307187
7188 /* removing unresponding volumes */
7189 if (ioc->ir_firmware) {
7190 pr_info(MPT3SAS_FMT "removing unresponding devices: volumes\n",
7191 ioc->name);
7192 list_for_each_entry_safe(raid_device, raid_device_next,
7193 &ioc->raid_device_list, list) {
7194 if (!raid_device->responding)
7195 _scsih_sas_volume_delete(ioc,
7196 raid_device->handle);
7197 else
7198 raid_device->responding = 0;
7199 }
7200 }
7201
7202 /* removing unresponding expanders */
7203 pr_info(MPT3SAS_FMT "removing unresponding devices: expanders\n",
7204 ioc->name);
7205 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7206 INIT_LIST_HEAD(&tmp_list);
7207 list_for_each_entry_safe(sas_expander, sas_expander_next,
7208 &ioc->sas_expander_list, list) {
7209 if (!sas_expander->responding)
7210 list_move_tail(&sas_expander->list, &tmp_list);
7211 else
7212 sas_expander->responding = 0;
7213 }
7214 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7215 list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
7216 list) {
7217 list_del(&sas_expander->list);
7218 _scsih_expander_node_remove(ioc, sas_expander);
7219 }
7220
7221 pr_info(MPT3SAS_FMT "removing unresponding devices: complete\n",
7222 ioc->name);
7223
7224 /* unblock devices */
7225 _scsih_ublock_io_all_device(ioc);
7226}
7227
7228static void
7229_scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc,
7230 struct _sas_node *sas_expander, u16 handle)
7231{
7232 Mpi2ExpanderPage1_t expander_pg1;
7233 Mpi2ConfigReply_t mpi_reply;
7234 int i;
7235
7236 for (i = 0 ; i < sas_expander->num_phys ; i++) {
7237 if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
7238 &expander_pg1, i, handle))) {
7239 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7240 ioc->name, __FILE__, __LINE__, __func__);
7241 return;
7242 }
7243
7244 mpt3sas_transport_update_links(ioc, sas_expander->sas_address,
7245 le16_to_cpu(expander_pg1.AttachedDevHandle), i,
7246 expander_pg1.NegotiatedLinkRate >> 4);
7247 }
7248}
7249
7250/**
7251 * _scsih_scan_for_devices_after_reset - scan for devices after host reset
7252 * @ioc: per adapter object
7253 *
7254 * Return nothing.
7255 */
7256static void
7257_scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
7258{
7259 Mpi2ExpanderPage0_t expander_pg0;
7260 Mpi2SasDevicePage0_t sas_device_pg0;
7261 Mpi2RaidVolPage1_t volume_pg1;
7262 Mpi2RaidVolPage0_t volume_pg0;
7263 Mpi2RaidPhysDiskPage0_t pd_pg0;
7264 Mpi2EventIrConfigElement_t element;
7265 Mpi2ConfigReply_t mpi_reply;
7266 u8 phys_disk_num;
7267 u16 ioc_status;
7268 u16 handle, parent_handle;
7269 u64 sas_address;
7270 struct _sas_device *sas_device;
7271 struct _sas_node *expander_device;
7272 static struct _raid_device *raid_device;
7273 u8 retry_count;
7274 unsigned long flags;
7275
7276 pr_info(MPT3SAS_FMT "scan devices: start\n", ioc->name);
7277
7278 _scsih_sas_host_refresh(ioc);
7279
7280 pr_info(MPT3SAS_FMT "\tscan devices: expanders start\n", ioc->name);
7281
7282 /* expanders */
7283 handle = 0xFFFF;
7284 while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
7285 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
7286 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7287 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307288 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7289 pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \
7290 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7291 ioc->name, ioc_status,
7292 le32_to_cpu(mpi_reply.IOCLogInfo));
7293 break;
7294 }
7295 handle = le16_to_cpu(expander_pg0.DevHandle);
7296 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7297 expander_device = mpt3sas_scsih_expander_find_by_sas_address(
7298 ioc, le64_to_cpu(expander_pg0.SASAddress));
7299 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7300 if (expander_device)
7301 _scsih_refresh_expander_links(ioc, expander_device,
7302 handle);
7303 else {
7304 pr_info(MPT3SAS_FMT "\tBEFORE adding expander: " \
7305 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7306 handle, (unsigned long long)
7307 le64_to_cpu(expander_pg0.SASAddress));
7308 _scsih_expander_add(ioc, handle);
7309 pr_info(MPT3SAS_FMT "\tAFTER adding expander: " \
7310 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7311 handle, (unsigned long long)
7312 le64_to_cpu(expander_pg0.SASAddress));
7313 }
7314 }
7315
7316 pr_info(MPT3SAS_FMT "\tscan devices: expanders complete\n",
7317 ioc->name);
7318
7319 if (!ioc->ir_firmware)
7320 goto skip_to_sas;
7321
7322 pr_info(MPT3SAS_FMT "\tscan devices: phys disk start\n", ioc->name);
7323
7324 /* phys disk */
7325 phys_disk_num = 0xFF;
7326 while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
7327 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
7328 phys_disk_num))) {
7329 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7330 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307331 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7332 pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\
7333 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7334 ioc->name, ioc_status,
7335 le32_to_cpu(mpi_reply.IOCLogInfo));
7336 break;
7337 }
7338 phys_disk_num = pd_pg0.PhysDiskNum;
7339 handle = le16_to_cpu(pd_pg0.DevHandle);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307340 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
7341 if (sas_device) {
7342 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307343 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307344 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307345 if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7346 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
7347 handle) != 0)
7348 continue;
7349 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7350 MPI2_IOCSTATUS_MASK;
7351 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7352 pr_info(MPT3SAS_FMT "\tbreak from phys disk scan " \
7353 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7354 ioc->name, ioc_status,
7355 le32_to_cpu(mpi_reply.IOCLogInfo));
7356 break;
7357 }
7358 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7359 if (!_scsih_get_sas_address(ioc, parent_handle,
7360 &sas_address)) {
7361 pr_info(MPT3SAS_FMT "\tBEFORE adding phys disk: " \
7362 " handle (0x%04x), sas_addr(0x%016llx)\n",
7363 ioc->name, handle, (unsigned long long)
7364 le64_to_cpu(sas_device_pg0.SASAddress));
7365 mpt3sas_transport_update_links(ioc, sas_address,
7366 handle, sas_device_pg0.PhyNum,
7367 MPI2_SAS_NEG_LINK_RATE_1_5);
7368 set_bit(handle, ioc->pd_handles);
7369 retry_count = 0;
7370 /* This will retry adding the end device.
7371 * _scsih_add_device() will decide on retries and
7372 * return "1" when it should be retried
7373 */
7374 while (_scsih_add_device(ioc, handle, retry_count++,
7375 1)) {
7376 ssleep(1);
7377 }
7378 pr_info(MPT3SAS_FMT "\tAFTER adding phys disk: " \
7379 " handle (0x%04x), sas_addr(0x%016llx)\n",
7380 ioc->name, handle, (unsigned long long)
7381 le64_to_cpu(sas_device_pg0.SASAddress));
7382 }
7383 }
7384
7385 pr_info(MPT3SAS_FMT "\tscan devices: phys disk complete\n",
7386 ioc->name);
7387
7388 pr_info(MPT3SAS_FMT "\tscan devices: volumes start\n", ioc->name);
7389
7390 /* volumes */
7391 handle = 0xFFFF;
7392 while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
7393 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
7394 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7395 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307396 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7397 pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
7398 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7399 ioc->name, ioc_status,
7400 le32_to_cpu(mpi_reply.IOCLogInfo));
7401 break;
7402 }
7403 handle = le16_to_cpu(volume_pg1.DevHandle);
7404 spin_lock_irqsave(&ioc->raid_device_lock, flags);
7405 raid_device = _scsih_raid_device_find_by_wwid(ioc,
7406 le64_to_cpu(volume_pg1.WWID));
7407 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7408 if (raid_device)
7409 continue;
7410 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
7411 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
7412 sizeof(Mpi2RaidVolPage0_t)))
7413 continue;
7414 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7415 MPI2_IOCSTATUS_MASK;
7416 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7417 pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
7418 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7419 ioc->name, ioc_status,
7420 le32_to_cpu(mpi_reply.IOCLogInfo));
7421 break;
7422 }
7423 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
7424 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
7425 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
7426 memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
7427 element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
7428 element.VolDevHandle = volume_pg1.DevHandle;
7429 pr_info(MPT3SAS_FMT
7430 "\tBEFORE adding volume: handle (0x%04x)\n",
7431 ioc->name, volume_pg1.DevHandle);
7432 _scsih_sas_volume_add(ioc, &element);
7433 pr_info(MPT3SAS_FMT
7434 "\tAFTER adding volume: handle (0x%04x)\n",
7435 ioc->name, volume_pg1.DevHandle);
7436 }
7437 }
7438
7439 pr_info(MPT3SAS_FMT "\tscan devices: volumes complete\n",
7440 ioc->name);
7441
7442 skip_to_sas:
7443
7444 pr_info(MPT3SAS_FMT "\tscan devices: end devices start\n",
7445 ioc->name);
7446
7447 /* sas devices */
7448 handle = 0xFFFF;
7449 while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7450 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
7451 handle))) {
7452 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7453 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307454 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7455 pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\
7456 " ioc_status(0x%04x), loginfo(0x%08x)\n",
7457 ioc->name, ioc_status,
7458 le32_to_cpu(mpi_reply.IOCLogInfo));
7459 break;
7460 }
7461 handle = le16_to_cpu(sas_device_pg0.DevHandle);
7462 if (!(_scsih_is_end_device(
7463 le32_to_cpu(sas_device_pg0.DeviceInfo))))
7464 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307465 sas_device = mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307466 le64_to_cpu(sas_device_pg0.SASAddress));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307467 if (sas_device) {
7468 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307469 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307470 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307471 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7472 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
7473 pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \
7474 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7475 handle, (unsigned long long)
7476 le64_to_cpu(sas_device_pg0.SASAddress));
7477 mpt3sas_transport_update_links(ioc, sas_address, handle,
7478 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
7479 retry_count = 0;
7480 /* This will retry adding the end device.
7481 * _scsih_add_device() will decide on retries and
7482 * return "1" when it should be retried
7483 */
7484 while (_scsih_add_device(ioc, handle, retry_count++,
7485 0)) {
7486 ssleep(1);
7487 }
7488 pr_info(MPT3SAS_FMT "\tAFTER adding end device: " \
7489 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7490 handle, (unsigned long long)
7491 le64_to_cpu(sas_device_pg0.SASAddress));
7492 }
7493 }
7494 pr_info(MPT3SAS_FMT "\tscan devices: end devices complete\n",
7495 ioc->name);
7496
7497 pr_info(MPT3SAS_FMT "scan devices: complete\n", ioc->name);
7498}
7499/**
7500 * mpt3sas_scsih_reset_handler - reset callback handler (for scsih)
7501 * @ioc: per adapter object
7502 * @reset_phase: phase
7503 *
7504 * The handler for doing any required cleanup or initialization.
7505 *
7506 * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET,
7507 * MPT3_IOC_DONE_RESET
7508 *
7509 * Return nothing.
7510 */
7511void
7512mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
7513{
7514 switch (reset_phase) {
7515 case MPT3_IOC_PRE_RESET:
7516 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7517 "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__));
7518 break;
7519 case MPT3_IOC_AFTER_RESET:
7520 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7521 "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__));
7522 if (ioc->scsih_cmds.status & MPT3_CMD_PENDING) {
7523 ioc->scsih_cmds.status |= MPT3_CMD_RESET;
7524 mpt3sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
7525 complete(&ioc->scsih_cmds.done);
7526 }
7527 if (ioc->tm_cmds.status & MPT3_CMD_PENDING) {
7528 ioc->tm_cmds.status |= MPT3_CMD_RESET;
7529 mpt3sas_base_free_smid(ioc, ioc->tm_cmds.smid);
7530 complete(&ioc->tm_cmds.done);
7531 }
7532
7533 _scsih_fw_event_cleanup_queue(ioc);
7534 _scsih_flush_running_cmds(ioc);
7535 break;
7536 case MPT3_IOC_DONE_RESET:
7537 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7538 "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__));
7539 if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
7540 !ioc->sas_hba.num_phys)) {
7541 _scsih_prep_device_scan(ioc);
7542 _scsih_search_responding_sas_devices(ioc);
7543 _scsih_search_responding_raid_devices(ioc);
7544 _scsih_search_responding_expanders(ioc);
7545 _scsih_error_recovery_delete_devices(ioc);
7546 }
7547 break;
7548 }
7549}
7550
7551/**
7552 * _mpt3sas_fw_work - delayed task for processing firmware events
7553 * @ioc: per adapter object
7554 * @fw_event: The fw_event_work object
7555 * Context: user.
7556 *
7557 * Return nothing.
7558 */
7559static void
7560_mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
7561{
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307562 _scsih_fw_event_del_from_list(ioc, fw_event);
7563
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307564 /* the queue is being flushed so ignore this event */
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307565 if (ioc->remove_host || ioc->pci_error_recovery) {
7566 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307567 return;
7568 }
7569
7570 switch (fw_event->event) {
7571 case MPT3SAS_PROCESS_TRIGGER_DIAG:
Joe Lawrence35b62362014-06-25 17:05:34 -04007572 mpt3sas_process_trigger_data(ioc,
7573 (struct SL_WH_TRIGGERS_EVENT_DATA_T *)
7574 fw_event->event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307575 break;
7576 case MPT3SAS_REMOVE_UNRESPONDING_DEVICES:
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307577 while (scsi_host_in_recovery(ioc->shost) ||
7578 ioc->shost_recovery) {
7579 /*
7580 * If we're unloading, bail. Otherwise, this can become
7581 * an infinite loop.
7582 */
7583 if (ioc->remove_host)
7584 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307585 ssleep(1);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307586 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307587 _scsih_remove_unresponding_sas_devices(ioc);
7588 _scsih_scan_for_devices_after_reset(ioc);
7589 break;
7590 case MPT3SAS_PORT_ENABLE_COMPLETE:
7591 ioc->start_scan = 0;
7592 if (missing_delay[0] != -1 && missing_delay[1] != -1)
7593 mpt3sas_base_update_missing_delay(ioc, missing_delay[0],
7594 missing_delay[1]);
7595 dewtprintk(ioc, pr_info(MPT3SAS_FMT
7596 "port enable: complete from worker thread\n",
7597 ioc->name));
7598 break;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05307599 case MPT3SAS_TURN_ON_PFA_LED:
7600 _scsih_turn_on_pfa_led(ioc, fw_event->device_handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307601 break;
7602 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7603 _scsih_sas_topology_change_event(ioc, fw_event);
7604 break;
7605 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7606 _scsih_sas_device_status_change_event(ioc, fw_event);
7607 break;
7608 case MPI2_EVENT_SAS_DISCOVERY:
7609 _scsih_sas_discovery_event(ioc, fw_event);
7610 break;
7611 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7612 _scsih_sas_broadcast_primitive_event(ioc, fw_event);
7613 break;
7614 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7615 _scsih_sas_enclosure_dev_status_change_event(ioc,
7616 fw_event);
7617 break;
7618 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7619 _scsih_sas_ir_config_change_event(ioc, fw_event);
7620 break;
7621 case MPI2_EVENT_IR_VOLUME:
7622 _scsih_sas_ir_volume_event(ioc, fw_event);
7623 break;
7624 case MPI2_EVENT_IR_PHYSICAL_DISK:
7625 _scsih_sas_ir_physical_disk_event(ioc, fw_event);
7626 break;
7627 case MPI2_EVENT_IR_OPERATION_STATUS:
7628 _scsih_sas_ir_operation_status_event(ioc, fw_event);
7629 break;
7630 }
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307631out:
7632 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307633}
7634
7635/**
7636 * _firmware_event_work
7637 * @ioc: per adapter object
7638 * @work: The fw_event_work object
7639 * Context: user.
7640 *
7641 * wrappers for the work thread handling firmware events
7642 *
7643 * Return nothing.
7644 */
7645
7646static void
7647_firmware_event_work(struct work_struct *work)
7648{
7649 struct fw_event_work *fw_event = container_of(work,
7650 struct fw_event_work, work);
7651
7652 _mpt3sas_fw_work(fw_event->ioc, fw_event);
7653}
7654
7655/**
7656 * mpt3sas_scsih_event_callback - firmware event handler (called at ISR time)
7657 * @ioc: per adapter object
7658 * @msix_index: MSIX table index supplied by the OS
7659 * @reply: reply message frame(lower 32bit addr)
7660 * Context: interrupt.
7661 *
7662 * This function merely adds a new work task into ioc->firmware_event_thread.
7663 * The tasks are worked from _firmware_event_work in user context.
7664 *
7665 * Return 1 meaning mf should be freed from _base_interrupt
7666 * 0 means the mf is freed from this function.
7667 */
7668u8
7669mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
7670 u32 reply)
7671{
7672 struct fw_event_work *fw_event;
7673 Mpi2EventNotificationReply_t *mpi_reply;
7674 u16 event;
7675 u16 sz;
7676
7677 /* events turned off due to host reset or driver unloading */
7678 if (ioc->remove_host || ioc->pci_error_recovery)
7679 return 1;
7680
7681 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
7682
7683 if (unlikely(!mpi_reply)) {
7684 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
7685 ioc->name, __FILE__, __LINE__, __func__);
7686 return 1;
7687 }
7688
7689 event = le16_to_cpu(mpi_reply->Event);
7690
7691 if (event != MPI2_EVENT_LOG_ENTRY_ADDED)
7692 mpt3sas_trigger_event(ioc, event, 0);
7693
7694 switch (event) {
7695 /* handle these */
7696 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7697 {
7698 Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
7699 (Mpi2EventDataSasBroadcastPrimitive_t *)
7700 mpi_reply->EventData;
7701
7702 if (baen_data->Primitive !=
7703 MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
7704 return 1;
7705
7706 if (ioc->broadcast_aen_busy) {
7707 ioc->broadcast_aen_pending++;
7708 return 1;
7709 } else
7710 ioc->broadcast_aen_busy = 1;
7711 break;
7712 }
7713
7714 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7715 _scsih_check_topo_delete_events(ioc,
7716 (Mpi2EventDataSasTopologyChangeList_t *)
7717 mpi_reply->EventData);
7718 break;
7719 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7720 _scsih_check_ir_config_unhide_events(ioc,
7721 (Mpi2EventDataIrConfigChangeList_t *)
7722 mpi_reply->EventData);
7723 break;
7724 case MPI2_EVENT_IR_VOLUME:
7725 _scsih_check_volume_delete_events(ioc,
7726 (Mpi2EventDataIrVolume_t *)
7727 mpi_reply->EventData);
7728 break;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307729 case MPI2_EVENT_LOG_ENTRY_ADDED:
7730 {
7731 Mpi2EventDataLogEntryAdded_t *log_entry;
7732 u32 *log_code;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307733
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307734 if (!ioc->is_warpdrive)
7735 break;
7736
7737 log_entry = (Mpi2EventDataLogEntryAdded_t *)
7738 mpi_reply->EventData;
7739 log_code = (u32 *)log_entry->LogData;
7740
7741 if (le16_to_cpu(log_entry->LogEntryQualifier)
7742 != MPT2_WARPDRIVE_LOGENTRY)
7743 break;
7744
7745 switch (le32_to_cpu(*log_code)) {
7746 case MPT2_WARPDRIVE_LC_SSDT:
7747 pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
7748 "IO Throttling has occurred in the WarpDrive "
7749 "subsystem. Check WarpDrive documentation for "
7750 "additional details.\n", ioc->name);
7751 break;
7752 case MPT2_WARPDRIVE_LC_SSDLW:
7753 pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
7754 "Program/Erase Cycles for the WarpDrive subsystem "
7755 "in degraded range. Check WarpDrive documentation "
7756 "for additional details.\n", ioc->name);
7757 break;
7758 case MPT2_WARPDRIVE_LC_SSDLF:
7759 pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
7760 "There are no Program/Erase Cycles for the "
7761 "WarpDrive subsystem. The storage device will be "
7762 "in read-only mode. Check WarpDrive documentation "
7763 "for additional details.\n", ioc->name);
7764 break;
7765 case MPT2_WARPDRIVE_LC_BRMF:
7766 pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
7767 "The Backup Rail Monitor has failed on the "
7768 "WarpDrive subsystem. Check WarpDrive "
7769 "documentation for additional details.\n",
7770 ioc->name);
7771 break;
7772 }
7773
7774 break;
7775 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307776 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7777 case MPI2_EVENT_IR_OPERATION_STATUS:
7778 case MPI2_EVENT_SAS_DISCOVERY:
7779 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7780 case MPI2_EVENT_IR_PHYSICAL_DISK:
7781 break;
7782
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05307783 case MPI2_EVENT_TEMP_THRESHOLD:
7784 _scsih_temp_threshold_events(ioc,
7785 (Mpi2EventDataTemperature_t *)
7786 mpi_reply->EventData);
7787 break;
7788
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307789 default: /* ignore the rest */
7790 return 1;
7791 }
7792
Joe Lawrence35b62362014-06-25 17:05:34 -04007793 sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307794 fw_event = alloc_fw_event_work(sz);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307795 if (!fw_event) {
7796 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7797 ioc->name, __FILE__, __LINE__, __func__);
7798 return 1;
7799 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307800
7801 memcpy(fw_event->event_data, mpi_reply->EventData, sz);
7802 fw_event->ioc = ioc;
7803 fw_event->VF_ID = mpi_reply->VF_ID;
7804 fw_event->VP_ID = mpi_reply->VP_ID;
7805 fw_event->event = event;
7806 _scsih_fw_event_add(ioc, fw_event);
Sreekanth Reddy146b16c2015-11-11 17:30:31 +05307807 fw_event_work_put(fw_event);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307808 return 1;
7809}
7810
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307811/**
7812 * _scsih_expander_node_remove - removing expander device from list.
7813 * @ioc: per adapter object
7814 * @sas_expander: the sas_device object
7815 * Context: Calling function should acquire ioc->sas_node_lock.
7816 *
7817 * Removing object and freeing associated memory from the
7818 * ioc->sas_expander_list.
7819 *
7820 * Return nothing.
7821 */
7822static void
7823_scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
7824 struct _sas_node *sas_expander)
7825{
7826 struct _sas_port *mpt3sas_port, *next;
7827
7828 /* remove sibling ports attached to this expander */
7829 list_for_each_entry_safe(mpt3sas_port, next,
7830 &sas_expander->sas_port_list, port_list) {
7831 if (ioc->shost_recovery)
7832 return;
7833 if (mpt3sas_port->remote_identify.device_type ==
7834 SAS_END_DEVICE)
7835 mpt3sas_device_remove_by_sas_address(ioc,
7836 mpt3sas_port->remote_identify.sas_address);
7837 else if (mpt3sas_port->remote_identify.device_type ==
7838 SAS_EDGE_EXPANDER_DEVICE ||
7839 mpt3sas_port->remote_identify.device_type ==
7840 SAS_FANOUT_EXPANDER_DEVICE)
7841 mpt3sas_expander_remove(ioc,
7842 mpt3sas_port->remote_identify.sas_address);
7843 }
7844
7845 mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
7846 sas_expander->sas_address_parent);
7847
7848 pr_info(MPT3SAS_FMT
7849 "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n",
7850 ioc->name,
7851 sas_expander->handle, (unsigned long long)
7852 sas_expander->sas_address);
7853
7854 kfree(sas_expander->phy);
7855 kfree(sas_expander);
7856}
7857
7858/**
7859 * _scsih_ir_shutdown - IR shutdown notification
7860 * @ioc: per adapter object
7861 *
7862 * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
7863 * the host system is shutting down.
7864 *
7865 * Return nothing.
7866 */
7867static void
7868_scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
7869{
7870 Mpi2RaidActionRequest_t *mpi_request;
7871 Mpi2RaidActionReply_t *mpi_reply;
7872 u16 smid;
7873
7874 /* is IR firmware build loaded ? */
7875 if (!ioc->ir_firmware)
7876 return;
7877
7878 /* are there any volumes ? */
7879 if (list_empty(&ioc->raid_device_list))
7880 return;
7881
7882 mutex_lock(&ioc->scsih_cmds.mutex);
7883
7884 if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
7885 pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
7886 ioc->name, __func__);
7887 goto out;
7888 }
7889 ioc->scsih_cmds.status = MPT3_CMD_PENDING;
7890
7891 smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
7892 if (!smid) {
7893 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
7894 ioc->name, __func__);
7895 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
7896 goto out;
7897 }
7898
7899 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
7900 ioc->scsih_cmds.smid = smid;
7901 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
7902
7903 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
7904 mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
7905
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307906 if (!ioc->hide_ir_msg)
7907 pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307908 init_completion(&ioc->scsih_cmds.done);
7909 mpt3sas_base_put_smid_default(ioc, smid);
7910 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
7911
7912 if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
7913 pr_err(MPT3SAS_FMT "%s: timeout\n",
7914 ioc->name, __func__);
7915 goto out;
7916 }
7917
7918 if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
7919 mpi_reply = ioc->scsih_cmds.reply;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307920 if (!ioc->hide_ir_msg)
7921 pr_info(MPT3SAS_FMT "IR shutdown "
7922 "(complete): ioc_status(0x%04x), loginfo(0x%08x)\n",
7923 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
7924 le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307925 }
7926
7927 out:
7928 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
7929 mutex_unlock(&ioc->scsih_cmds.mutex);
7930}
7931
7932/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05307933 * scsih_remove - detach and remove add host
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307934 * @pdev: PCI device struct
7935 *
7936 * Routine called when unloading the driver.
7937 * Return nothing.
7938 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05307939void scsih_remove(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307940{
7941 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7942 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
7943 struct _sas_port *mpt3sas_port, *next_port;
7944 struct _raid_device *raid_device, *next;
7945 struct MPT3SAS_TARGET *sas_target_priv_data;
7946 struct workqueue_struct *wq;
7947 unsigned long flags;
7948
7949 ioc->remove_host = 1;
7950 _scsih_fw_event_cleanup_queue(ioc);
7951
7952 spin_lock_irqsave(&ioc->fw_event_lock, flags);
7953 wq = ioc->firmware_event_thread;
7954 ioc->firmware_event_thread = NULL;
7955 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
7956 if (wq)
7957 destroy_workqueue(wq);
7958
7959 /* release all the volumes */
7960 _scsih_ir_shutdown(ioc);
7961 list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
7962 list) {
7963 if (raid_device->starget) {
7964 sas_target_priv_data =
7965 raid_device->starget->hostdata;
7966 sas_target_priv_data->deleted = 1;
7967 scsi_remove_target(&raid_device->starget->dev);
7968 }
7969 pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
7970 ioc->name, raid_device->handle,
7971 (unsigned long long) raid_device->wwid);
7972 _scsih_raid_device_remove(ioc, raid_device);
7973 }
7974
7975 /* free ports attached to the sas_host */
7976 list_for_each_entry_safe(mpt3sas_port, next_port,
7977 &ioc->sas_hba.sas_port_list, port_list) {
7978 if (mpt3sas_port->remote_identify.device_type ==
7979 SAS_END_DEVICE)
7980 mpt3sas_device_remove_by_sas_address(ioc,
7981 mpt3sas_port->remote_identify.sas_address);
7982 else if (mpt3sas_port->remote_identify.device_type ==
7983 SAS_EDGE_EXPANDER_DEVICE ||
7984 mpt3sas_port->remote_identify.device_type ==
7985 SAS_FANOUT_EXPANDER_DEVICE)
7986 mpt3sas_expander_remove(ioc,
7987 mpt3sas_port->remote_identify.sas_address);
7988 }
7989
7990 /* free phys attached to the sas_host */
7991 if (ioc->sas_hba.num_phys) {
7992 kfree(ioc->sas_hba.phy);
7993 ioc->sas_hba.phy = NULL;
7994 ioc->sas_hba.num_phys = 0;
7995 }
7996
7997 sas_remove_host(shost);
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05307998 scsi_remove_host(shost);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307999 mpt3sas_base_detach(ioc);
8000 list_del(&ioc->list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308001 scsi_host_put(shost);
8002}
8003
8004/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308005 * scsih_shutdown - routine call during system shutdown
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308006 * @pdev: PCI device struct
8007 *
8008 * Return nothing.
8009 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308010void
8011scsih_shutdown(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308012{
8013 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8014 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8015 struct workqueue_struct *wq;
8016 unsigned long flags;
8017
8018 ioc->remove_host = 1;
8019 _scsih_fw_event_cleanup_queue(ioc);
8020
8021 spin_lock_irqsave(&ioc->fw_event_lock, flags);
8022 wq = ioc->firmware_event_thread;
8023 ioc->firmware_event_thread = NULL;
8024 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
8025 if (wq)
8026 destroy_workqueue(wq);
8027
8028 _scsih_ir_shutdown(ioc);
8029 mpt3sas_base_detach(ioc);
8030}
8031
8032
8033/**
8034 * _scsih_probe_boot_devices - reports 1st device
8035 * @ioc: per adapter object
8036 *
8037 * If specified in bios page 2, this routine reports the 1st
8038 * device scsi-ml or sas transport for persistent boot device
8039 * purposes. Please refer to function _scsih_determine_boot_device()
8040 */
8041static void
8042_scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
8043{
8044 u8 is_raid;
8045 void *device;
8046 struct _sas_device *sas_device;
8047 struct _raid_device *raid_device;
8048 u16 handle;
8049 u64 sas_address_parent;
8050 u64 sas_address;
8051 unsigned long flags;
8052 int rc;
8053
8054 /* no Bios, return immediately */
8055 if (!ioc->bios_pg3.BiosVersion)
8056 return;
8057
8058 device = NULL;
8059 is_raid = 0;
8060 if (ioc->req_boot_device.device) {
8061 device = ioc->req_boot_device.device;
8062 is_raid = ioc->req_boot_device.is_raid;
8063 } else if (ioc->req_alt_boot_device.device) {
8064 device = ioc->req_alt_boot_device.device;
8065 is_raid = ioc->req_alt_boot_device.is_raid;
8066 } else if (ioc->current_boot_device.device) {
8067 device = ioc->current_boot_device.device;
8068 is_raid = ioc->current_boot_device.is_raid;
8069 }
8070
8071 if (!device)
8072 return;
8073
8074 if (is_raid) {
8075 raid_device = device;
8076 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
8077 raid_device->id, 0);
8078 if (rc)
8079 _scsih_raid_device_remove(ioc, raid_device);
8080 } else {
8081 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8082 sas_device = device;
8083 handle = sas_device->handle;
8084 sas_address_parent = sas_device->sas_address_parent;
8085 sas_address = sas_device->sas_address;
8086 list_move_tail(&sas_device->list, &ioc->sas_device_list);
8087 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8088
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308089 if (ioc->hide_drives)
8090 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308091 if (!mpt3sas_transport_port_add(ioc, handle,
8092 sas_address_parent)) {
8093 _scsih_sas_device_remove(ioc, sas_device);
8094 } else if (!sas_device->starget) {
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308095 if (!ioc->is_driver_loading) {
8096 mpt3sas_transport_port_remove(ioc,
8097 sas_address,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308098 sas_address_parent);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308099 _scsih_sas_device_remove(ioc, sas_device);
8100 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308101 }
8102 }
8103}
8104
8105/**
8106 * _scsih_probe_raid - reporting raid volumes to scsi-ml
8107 * @ioc: per adapter object
8108 *
8109 * Called during initial loading of the driver.
8110 */
8111static void
8112_scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc)
8113{
8114 struct _raid_device *raid_device, *raid_next;
8115 int rc;
8116
8117 list_for_each_entry_safe(raid_device, raid_next,
8118 &ioc->raid_device_list, list) {
8119 if (raid_device->starget)
8120 continue;
8121 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
8122 raid_device->id, 0);
8123 if (rc)
8124 _scsih_raid_device_remove(ioc, raid_device);
8125 }
8126}
8127
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308128static struct _sas_device *get_next_sas_device(struct MPT3SAS_ADAPTER *ioc)
8129{
8130 struct _sas_device *sas_device = NULL;
8131 unsigned long flags;
8132
8133 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8134 if (!list_empty(&ioc->sas_device_init_list)) {
8135 sas_device = list_first_entry(&ioc->sas_device_init_list,
8136 struct _sas_device, list);
8137 sas_device_get(sas_device);
8138 }
8139 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8140
8141 return sas_device;
8142}
8143
8144static void sas_device_make_active(struct MPT3SAS_ADAPTER *ioc,
8145 struct _sas_device *sas_device)
8146{
8147 unsigned long flags;
8148
8149 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8150
8151 /*
8152 * Since we dropped the lock during the call to port_add(), we need to
8153 * be careful here that somebody else didn't move or delete this item
8154 * while we were busy with other things.
8155 *
8156 * If it was on the list, we need a put() for the reference the list
8157 * had. Either way, we need a get() for the destination list.
8158 */
8159 if (!list_empty(&sas_device->list)) {
8160 list_del_init(&sas_device->list);
8161 sas_device_put(sas_device);
8162 }
8163
8164 sas_device_get(sas_device);
8165 list_add_tail(&sas_device->list, &ioc->sas_device_list);
8166
8167 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8168}
8169
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308170/**
8171 * _scsih_probe_sas - reporting sas devices to sas transport
8172 * @ioc: per adapter object
8173 *
8174 * Called during initial loading of the driver.
8175 */
8176static void
8177_scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
8178{
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308179 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308180
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308181 if (ioc->hide_drives)
8182 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308183
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308184 while ((sas_device = get_next_sas_device(ioc))) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308185 if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
8186 sas_device->sas_address_parent)) {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308187 _scsih_sas_device_remove(ioc, sas_device);
8188 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308189 continue;
8190 } else if (!sas_device->starget) {
8191 /*
8192 * When asyn scanning is enabled, its not possible to
8193 * remove devices while scanning is turned on due to an
8194 * oops in scsi_sysfs_add_sdev()->add_device()->
8195 * sysfs_addrm_start()
8196 */
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308197 if (!ioc->is_driver_loading) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308198 mpt3sas_transport_port_remove(ioc,
8199 sas_device->sas_address,
8200 sas_device->sas_address_parent);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308201 _scsih_sas_device_remove(ioc, sas_device);
8202 sas_device_put(sas_device);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308203 continue;
8204 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308205 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308206 sas_device_make_active(ioc, sas_device);
8207 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308208 }
8209}
8210
8211/**
8212 * _scsih_probe_devices - probing for devices
8213 * @ioc: per adapter object
8214 *
8215 * Called during initial loading of the driver.
8216 */
8217static void
8218_scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc)
8219{
8220 u16 volume_mapping_flags;
8221
8222 if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
8223 return; /* return when IOC doesn't support initiator mode */
8224
8225 _scsih_probe_boot_devices(ioc);
8226
8227 if (ioc->ir_firmware) {
8228 volume_mapping_flags =
8229 le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
8230 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
8231 if (volume_mapping_flags ==
8232 MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
8233 _scsih_probe_raid(ioc);
8234 _scsih_probe_sas(ioc);
8235 } else {
8236 _scsih_probe_sas(ioc);
8237 _scsih_probe_raid(ioc);
8238 }
8239 } else
8240 _scsih_probe_sas(ioc);
8241}
8242
8243/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308244 * scsih_scan_start - scsi lld callback for .scan_start
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308245 * @shost: SCSI host pointer
8246 *
8247 * The shost has the ability to discover targets on its own instead
8248 * of scanning the entire bus. In our implemention, we will kick off
8249 * firmware discovery.
8250 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308251void
8252scsih_scan_start(struct Scsi_Host *shost)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308253{
8254 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8255 int rc;
8256 if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
8257 mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable);
8258
8259 if (disable_discovery > 0)
8260 return;
8261
8262 ioc->start_scan = 1;
8263 rc = mpt3sas_port_enable(ioc);
8264
8265 if (rc != 0)
8266 pr_info(MPT3SAS_FMT "port enable: FAILED\n", ioc->name);
8267}
8268
8269/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308270 * scsih_scan_finished - scsi lld callback for .scan_finished
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308271 * @shost: SCSI host pointer
8272 * @time: elapsed time of the scan in jiffies
8273 *
8274 * This function will be called periodicallyn until it returns 1 with the
8275 * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
8276 * we wait for firmware discovery to complete, then return 1.
8277 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308278int
8279scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308280{
8281 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8282
8283 if (disable_discovery > 0) {
8284 ioc->is_driver_loading = 0;
8285 ioc->wait_for_discovery_to_complete = 0;
8286 return 1;
8287 }
8288
8289 if (time >= (300 * HZ)) {
8290 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
8291 pr_info(MPT3SAS_FMT
8292 "port enable: FAILED with timeout (timeout=300s)\n",
8293 ioc->name);
8294 ioc->is_driver_loading = 0;
8295 return 1;
8296 }
8297
8298 if (ioc->start_scan)
8299 return 0;
8300
8301 if (ioc->start_scan_failed) {
8302 pr_info(MPT3SAS_FMT
8303 "port enable: FAILED with (ioc_status=0x%08x)\n",
8304 ioc->name, ioc->start_scan_failed);
8305 ioc->is_driver_loading = 0;
8306 ioc->wait_for_discovery_to_complete = 0;
8307 ioc->remove_host = 1;
8308 return 1;
8309 }
8310
8311 pr_info(MPT3SAS_FMT "port enable: SUCCESS\n", ioc->name);
8312 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
8313
8314 if (ioc->wait_for_discovery_to_complete) {
8315 ioc->wait_for_discovery_to_complete = 0;
8316 _scsih_probe_devices(ioc);
8317 }
8318 mpt3sas_base_start_watchdog(ioc);
8319 ioc->is_driver_loading = 0;
8320 return 1;
8321}
8322
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308323void
8324_scsih_determine_hba_mpi_version(struct MPT3SAS_ADAPTER *ioc) {
8325
8326 switch (ioc->pdev->device) {
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308327 case MPI2_MFGPAGE_DEVID_SSS6200:
8328 ioc->is_warpdrive = 1;
8329 ioc->hide_ir_msg = 1;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308330 case MPI2_MFGPAGE_DEVID_SAS2004:
8331 case MPI2_MFGPAGE_DEVID_SAS2008:
8332 case MPI2_MFGPAGE_DEVID_SAS2108_1:
8333 case MPI2_MFGPAGE_DEVID_SAS2108_2:
8334 case MPI2_MFGPAGE_DEVID_SAS2108_3:
8335 case MPI2_MFGPAGE_DEVID_SAS2116_1:
8336 case MPI2_MFGPAGE_DEVID_SAS2116_2:
8337 case MPI2_MFGPAGE_DEVID_SAS2208_1:
8338 case MPI2_MFGPAGE_DEVID_SAS2208_2:
8339 case MPI2_MFGPAGE_DEVID_SAS2208_3:
8340 case MPI2_MFGPAGE_DEVID_SAS2208_4:
8341 case MPI2_MFGPAGE_DEVID_SAS2208_5:
8342 case MPI2_MFGPAGE_DEVID_SAS2208_6:
8343 case MPI2_MFGPAGE_DEVID_SAS2308_1:
8344 case MPI2_MFGPAGE_DEVID_SAS2308_2:
8345 case MPI2_MFGPAGE_DEVID_SAS2308_3:
8346 ioc->hba_mpi_version_belonged = MPI2_VERSION;
8347 break;
8348 case MPI25_MFGPAGE_DEVID_SAS3004:
8349 case MPI25_MFGPAGE_DEVID_SAS3008:
8350 case MPI25_MFGPAGE_DEVID_SAS3108_1:
8351 case MPI25_MFGPAGE_DEVID_SAS3108_2:
8352 case MPI25_MFGPAGE_DEVID_SAS3108_5:
8353 case MPI25_MFGPAGE_DEVID_SAS3108_6:
8354 ioc->hba_mpi_version_belonged = MPI25_VERSION;
Sreekanth Reddy42081172015-11-11 17:30:26 +05308355
8356 /* Check whether the controller revision is C0 or above.
8357 * only C0 and above revision controllers support 96 MSI-X
8358 * vectors.
8359 */
8360 if (ioc->pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION)
8361 ioc->msix96_vector = 1;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308362 break;
8363 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308364
8365 if ((ioc->pdev->device != MPI2_MFGPAGE_DEVID_SSS6200) &&
8366 (ioc->hba_mpi_version_belonged == MPI2_VERSION))
8367 ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308368}
8369
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308370/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308371 * scsih_probe - attach and add scsi host
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308372 * @pdev: PCI device struct
8373 * @id: pci device id
8374 *
8375 * Returns 0 success, anything else error.
8376 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308377int
Sreekanth Reddy7497392a2015-11-11 17:30:19 +05308378scsih_probe(struct pci_dev *pdev, struct Scsi_Host *shost)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308379{
8380 struct MPT3SAS_ADAPTER *ioc;
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308381 int rv;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308382
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308383 /* init local params */
8384 ioc = shost_priv(shost);
8385 memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
8386 INIT_LIST_HEAD(&ioc->list);
8387 list_add_tail(&ioc->list, &mpt3sas_ioc_list);
8388 ioc->shost = shost;
8389 ioc->id = mpt_ids++;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308390 ioc->pdev = pdev;
8391 ioc->scsi_io_cb_idx = scsi_io_cb_idx;
8392 ioc->tm_cb_idx = tm_cb_idx;
8393 ioc->ctl_cb_idx = ctl_cb_idx;
8394 ioc->base_cb_idx = base_cb_idx;
8395 ioc->port_enable_cb_idx = port_enable_cb_idx;
8396 ioc->transport_cb_idx = transport_cb_idx;
8397 ioc->scsih_cb_idx = scsih_cb_idx;
8398 ioc->config_cb_idx = config_cb_idx;
8399 ioc->tm_tr_cb_idx = tm_tr_cb_idx;
8400 ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx;
8401 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
8402 ioc->logging_level = logging_level;
8403 ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
8404 /* misc semaphores and spin locks */
8405 mutex_init(&ioc->reset_in_progress_mutex);
8406 spin_lock_init(&ioc->ioc_reset_in_progress_lock);
8407 spin_lock_init(&ioc->scsi_lookup_lock);
8408 spin_lock_init(&ioc->sas_device_lock);
8409 spin_lock_init(&ioc->sas_node_lock);
8410 spin_lock_init(&ioc->fw_event_lock);
8411 spin_lock_init(&ioc->raid_device_lock);
8412 spin_lock_init(&ioc->diag_trigger_lock);
8413
8414 INIT_LIST_HEAD(&ioc->sas_device_list);
8415 INIT_LIST_HEAD(&ioc->sas_device_init_list);
8416 INIT_LIST_HEAD(&ioc->sas_expander_list);
8417 INIT_LIST_HEAD(&ioc->fw_event_list);
8418 INIT_LIST_HEAD(&ioc->raid_device_list);
8419 INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
8420 INIT_LIST_HEAD(&ioc->delayed_tr_list);
8421 INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
Joe Lawrencecf9bd21a2013-08-08 16:45:39 -04008422 INIT_LIST_HEAD(&ioc->reply_queue_list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308423
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308424 _scsih_determine_hba_mpi_version(ioc);
8425 sprintf(ioc->name, "%s_cm%d", driver_name, ioc->id);
8426
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308427 /* init shost parameters */
8428 shost->max_cmd_len = 32;
8429 shost->max_lun = max_lun;
8430 shost->transportt = mpt3sas_transport_template;
8431 shost->unique_id = ioc->id;
8432
8433 if (max_sectors != 0xFFFF) {
8434 if (max_sectors < 64) {
8435 shost->max_sectors = 64;
8436 pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
8437 "for max_sectors, range is 64 to 32767. Assigning "
8438 "value of 64.\n", ioc->name, max_sectors);
8439 } else if (max_sectors > 32767) {
8440 shost->max_sectors = 32767;
8441 pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
8442 "for max_sectors, range is 64 to 32767. Assigning "
8443 "default value of 32767.\n", ioc->name,
8444 max_sectors);
8445 } else {
8446 shost->max_sectors = max_sectors & 0xFFFE;
8447 pr_info(MPT3SAS_FMT
8448 "The max_sectors value is set to %d\n",
8449 ioc->name, shost->max_sectors);
8450 }
8451 }
8452
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308453 /* register EEDP capabilities with SCSI layer */
8454 if (prot_mask > 0)
8455 scsi_host_set_prot(shost, prot_mask);
8456 else
8457 scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
8458 | SHOST_DIF_TYPE2_PROTECTION
8459 | SHOST_DIF_TYPE3_PROTECTION);
8460
8461 scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
8462
8463 /* event thread */
8464 snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
8465 "fw_event%d", ioc->id);
Sreekanth Reddybdff7852015-06-30 12:25:03 +05308466 ioc->firmware_event_thread = alloc_ordered_workqueue(
8467 ioc->firmware_event_name, WQ_MEM_RECLAIM);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308468 if (!ioc->firmware_event_thread) {
8469 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8470 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308471 rv = -ENODEV;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308472 goto out_thread_fail;
8473 }
8474
8475 ioc->is_driver_loading = 1;
8476 if ((mpt3sas_base_attach(ioc))) {
8477 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8478 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308479 rv = -ENODEV;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308480 goto out_attach_fail;
8481 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308482
8483#ifdef SCSI_MPT2SAS
8484 if (ioc->is_warpdrive) {
8485 if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
8486 ioc->hide_drives = 0;
8487 else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS)
8488 ioc->hide_drives = 1;
8489 else {
8490 if (_scsih_get_num_volumes(ioc))
8491 ioc->hide_drives = 1;
8492 else
8493 ioc->hide_drives = 0;
8494 }
8495 } else
8496 ioc->hide_drives = 0;
8497#endif
8498
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308499 rv = scsi_add_host(shost, &pdev->dev);
8500 if (rv) {
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308501 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8502 ioc->name, __FILE__, __LINE__, __func__);
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308503 goto out_add_shost_fail;
8504 }
8505
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308506 scsi_scan_host(shost);
8507 return 0;
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308508out_add_shost_fail:
8509 mpt3sas_base_detach(ioc);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308510 out_attach_fail:
8511 destroy_workqueue(ioc->firmware_event_thread);
8512 out_thread_fail:
8513 list_del(&ioc->list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308514 scsi_host_put(shost);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308515 return rv;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308516}
8517
8518#ifdef CONFIG_PM
8519/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308520 * scsih_suspend - power management suspend main entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308521 * @pdev: PCI device struct
8522 * @state: PM state change to (usually PCI_D3)
8523 *
8524 * Returns 0 success, anything else error.
8525 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308526int
8527scsih_suspend(struct pci_dev *pdev, pm_message_t state)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308528{
8529 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8530 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8531 pci_power_t device_state;
8532
8533 mpt3sas_base_stop_watchdog(ioc);
8534 flush_scheduled_work();
8535 scsi_block_requests(shost);
8536 device_state = pci_choose_state(pdev, state);
8537 pr_info(MPT3SAS_FMT
8538 "pdev=0x%p, slot=%s, entering operating state [D%d]\n",
8539 ioc->name, pdev, pci_name(pdev), device_state);
8540
8541 pci_save_state(pdev);
8542 mpt3sas_base_free_resources(ioc);
8543 pci_set_power_state(pdev, device_state);
8544 return 0;
8545}
8546
8547/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308548 * scsih_resume - power management resume main entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308549 * @pdev: PCI device struct
8550 *
8551 * Returns 0 success, anything else error.
8552 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308553int
8554scsih_resume(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308555{
8556 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8557 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8558 pci_power_t device_state = pdev->current_state;
8559 int r;
8560
8561 pr_info(MPT3SAS_FMT
8562 "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
8563 ioc->name, pdev, pci_name(pdev), device_state);
8564
8565 pci_set_power_state(pdev, PCI_D0);
8566 pci_enable_wake(pdev, PCI_D0, 0);
8567 pci_restore_state(pdev);
8568 ioc->pdev = pdev;
8569 r = mpt3sas_base_map_resources(ioc);
8570 if (r)
8571 return r;
8572
8573 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
8574 scsi_unblock_requests(shost);
8575 mpt3sas_base_start_watchdog(ioc);
8576 return 0;
8577}
8578#endif /* CONFIG_PM */
8579
8580/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308581 * scsih_pci_error_detected - Called when a PCI error is detected.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308582 * @pdev: PCI device struct
8583 * @state: PCI channel state
8584 *
8585 * Description: Called when a PCI error is detected.
8586 *
8587 * Return value:
8588 * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
8589 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308590pci_ers_result_t
8591scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308592{
8593 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8594 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8595
8596 pr_info(MPT3SAS_FMT "PCI error: detected callback, state(%d)!!\n",
8597 ioc->name, state);
8598
8599 switch (state) {
8600 case pci_channel_io_normal:
8601 return PCI_ERS_RESULT_CAN_RECOVER;
8602 case pci_channel_io_frozen:
8603 /* Fatal error, prepare for slot reset */
8604 ioc->pci_error_recovery = 1;
8605 scsi_block_requests(ioc->shost);
8606 mpt3sas_base_stop_watchdog(ioc);
8607 mpt3sas_base_free_resources(ioc);
8608 return PCI_ERS_RESULT_NEED_RESET;
8609 case pci_channel_io_perm_failure:
8610 /* Permanent error, prepare for device removal */
8611 ioc->pci_error_recovery = 1;
8612 mpt3sas_base_stop_watchdog(ioc);
8613 _scsih_flush_running_cmds(ioc);
8614 return PCI_ERS_RESULT_DISCONNECT;
8615 }
8616 return PCI_ERS_RESULT_NEED_RESET;
8617}
8618
8619/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308620 * scsih_pci_slot_reset - Called when PCI slot has been reset.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308621 * @pdev: PCI device struct
8622 *
8623 * Description: This routine is called by the pci error recovery
8624 * code after the PCI slot has been reset, just before we
8625 * should resume normal operations.
8626 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308627pci_ers_result_t
8628scsih_pci_slot_reset(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308629{
8630 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8631 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8632 int rc;
8633
8634 pr_info(MPT3SAS_FMT "PCI error: slot reset callback!!\n",
8635 ioc->name);
8636
8637 ioc->pci_error_recovery = 0;
8638 ioc->pdev = pdev;
8639 pci_restore_state(pdev);
8640 rc = mpt3sas_base_map_resources(ioc);
8641 if (rc)
8642 return PCI_ERS_RESULT_DISCONNECT;
8643
8644 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
8645 FORCE_BIG_HAMMER);
8646
8647 pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name,
8648 (rc == 0) ? "success" : "failed");
8649
8650 if (!rc)
8651 return PCI_ERS_RESULT_RECOVERED;
8652 else
8653 return PCI_ERS_RESULT_DISCONNECT;
8654}
8655
8656/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308657 * scsih_pci_resume() - resume normal ops after PCI reset
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308658 * @pdev: pointer to PCI device
8659 *
8660 * Called when the error recovery driver tells us that its
8661 * OK to resume normal operation. Use completion to allow
8662 * halted scsi ops to resume.
8663 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308664void
8665scsih_pci_resume(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308666{
8667 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8668 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8669
8670 pr_info(MPT3SAS_FMT "PCI error: resume callback!!\n", ioc->name);
8671
8672 pci_cleanup_aer_uncorrect_error_status(pdev);
8673 mpt3sas_base_start_watchdog(ioc);
8674 scsi_unblock_requests(ioc->shost);
8675}
8676
8677/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308678 * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308679 * @pdev: pointer to PCI device
8680 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308681pci_ers_result_t
8682scsih_pci_mmio_enabled(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308683{
8684 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8685 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8686
8687 pr_info(MPT3SAS_FMT "PCI error: mmio enabled callback!!\n",
8688 ioc->name);
8689
8690 /* TODO - dump whatever for debugging purposes */
8691
8692 /* Request a slot reset. */
8693 return PCI_ERS_RESULT_NEED_RESET;
8694}
8695
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308696/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308697 * scsih_init - main entry point for this driver.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308698 *
8699 * Returns 0 success, anything else error.
8700 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308701int
8702scsih_init(void)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308703{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308704 mpt_ids = 0;
8705
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308706 mpt3sas_base_initialize_callback_handler();
8707
8708 /* queuecommand callback hander */
8709 scsi_io_cb_idx = mpt3sas_base_register_callback_handler(_scsih_io_done);
8710
8711 /* task managment callback handler */
8712 tm_cb_idx = mpt3sas_base_register_callback_handler(_scsih_tm_done);
8713
8714 /* base internal commands callback handler */
8715 base_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_base_done);
8716 port_enable_cb_idx = mpt3sas_base_register_callback_handler(
8717 mpt3sas_port_enable_done);
8718
8719 /* transport internal commands callback handler */
8720 transport_cb_idx = mpt3sas_base_register_callback_handler(
8721 mpt3sas_transport_done);
8722
8723 /* scsih internal commands callback handler */
8724 scsih_cb_idx = mpt3sas_base_register_callback_handler(_scsih_done);
8725
8726 /* configuration page API internal commands callback handler */
8727 config_cb_idx = mpt3sas_base_register_callback_handler(
8728 mpt3sas_config_done);
8729
8730 /* ctl module callback handler */
8731 ctl_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_ctl_done);
8732
8733 tm_tr_cb_idx = mpt3sas_base_register_callback_handler(
8734 _scsih_tm_tr_complete);
8735
8736 tm_tr_volume_cb_idx = mpt3sas_base_register_callback_handler(
8737 _scsih_tm_volume_tr_complete);
8738
8739 tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
8740 _scsih_sas_control_complete);
8741
Sreekanth Reddy7497392a2015-11-11 17:30:19 +05308742 return 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308743}
8744
8745/**
Sreekanth Reddy7497392a2015-11-11 17:30:19 +05308746 * scsih_exit - exit point for this driver (when it is a module).
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308747 *
8748 * Returns 0 success, anything else error.
8749 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308750void
8751scsih_exit(void)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308752{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308753
8754 mpt3sas_base_release_callback_handler(scsi_io_cb_idx);
8755 mpt3sas_base_release_callback_handler(tm_cb_idx);
8756 mpt3sas_base_release_callback_handler(base_cb_idx);
8757 mpt3sas_base_release_callback_handler(port_enable_cb_idx);
8758 mpt3sas_base_release_callback_handler(transport_cb_idx);
8759 mpt3sas_base_release_callback_handler(scsih_cb_idx);
8760 mpt3sas_base_release_callback_handler(config_cb_idx);
8761 mpt3sas_base_release_callback_handler(ctl_cb_idx);
8762
8763 mpt3sas_base_release_callback_handler(tm_tr_cb_idx);
8764 mpt3sas_base_release_callback_handler(tm_tr_volume_cb_idx);
8765 mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx);
8766
8767/* raid transport support */
8768 raid_class_release(mpt3sas_raid_template);
8769 sas_release_transport(mpt3sas_transport_template);
8770}
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308771
8772#ifdef SCSI_MPT2SAS
8773#include "../mpt2sas/mpt2sas_warpdrive.c"
8774#endif