blob: 5dbf214ecf6d9d016ce7a598da8a13c7d1d093c9 [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;
Joe Lawrence35b62362014-06-25 17:05:34 -0400203 char event_data[0] __aligned(4);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530204};
205
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530206/**
207 * struct _scsi_io_transfer - scsi io transfer
208 * @handle: sas device handle (assigned by firmware)
209 * @is_raid: flag set for hidden raid components
210 * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE,
211 * @data_length: data transfer length
212 * @data_dma: dma pointer to data
213 * @sense: sense data
214 * @lun: lun number
215 * @cdb_length: cdb length
216 * @cdb: cdb contents
217 * @timeout: timeout for this command
218 * @VF_ID: virtual function id
219 * @VP_ID: virtual port id
220 * @valid_reply: flag set for reply message
221 * @sense_length: sense length
222 * @ioc_status: ioc status
223 * @scsi_state: scsi state
224 * @scsi_status: scsi staus
225 * @log_info: log information
226 * @transfer_length: data length transfer when there is a reply message
227 *
228 * Used for sending internal scsi commands to devices within this module.
229 * Refer to _scsi_send_scsi_io().
230 */
231struct _scsi_io_transfer {
232 u16 handle;
233 u8 is_raid;
234 enum dma_data_direction dir;
235 u32 data_length;
236 dma_addr_t data_dma;
237 u8 sense[SCSI_SENSE_BUFFERSIZE];
238 u32 lun;
239 u8 cdb_length;
240 u8 cdb[32];
241 u8 timeout;
242 u8 VF_ID;
243 u8 VP_ID;
244 u8 valid_reply;
245 /* the following bits are only valid when 'valid_reply = 1' */
246 u32 sense_length;
247 u16 ioc_status;
248 u8 scsi_state;
249 u8 scsi_status;
250 u32 log_info;
251 u32 transfer_length;
252};
253
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530254/**
255 * _scsih_set_debug_level - global setting of ioc->logging_level.
256 *
257 * Note: The logging levels are defined in mpt3sas_debug.h.
258 */
259static int
260_scsih_set_debug_level(const char *val, struct kernel_param *kp)
261{
262 int ret = param_set_int(val, kp);
263 struct MPT3SAS_ADAPTER *ioc;
264
265 if (ret)
266 return ret;
267
268 pr_info("setting logging_level(0x%08x)\n", logging_level);
269 list_for_each_entry(ioc, &mpt3sas_ioc_list, list)
270 ioc->logging_level = logging_level;
271 return 0;
272}
273module_param_call(logging_level, _scsih_set_debug_level, param_get_int,
274 &logging_level, 0644);
275
276/**
277 * _scsih_srch_boot_sas_address - search based on sas_address
278 * @sas_address: sas address
279 * @boot_device: boot device object from bios page 2
280 *
281 * Returns 1 when there's a match, 0 means no match.
282 */
283static inline int
284_scsih_srch_boot_sas_address(u64 sas_address,
285 Mpi2BootDeviceSasWwid_t *boot_device)
286{
287 return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0;
288}
289
290/**
291 * _scsih_srch_boot_device_name - search based on device name
292 * @device_name: device name specified in INDENTIFY fram
293 * @boot_device: boot device object from bios page 2
294 *
295 * Returns 1 when there's a match, 0 means no match.
296 */
297static inline int
298_scsih_srch_boot_device_name(u64 device_name,
299 Mpi2BootDeviceDeviceName_t *boot_device)
300{
301 return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0;
302}
303
304/**
305 * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot
306 * @enclosure_logical_id: enclosure logical id
307 * @slot_number: slot number
308 * @boot_device: boot device object from bios page 2
309 *
310 * Returns 1 when there's a match, 0 means no match.
311 */
312static inline int
313_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
314 Mpi2BootDeviceEnclosureSlot_t *boot_device)
315{
316 return (enclosure_logical_id == le64_to_cpu(boot_device->
317 EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device->
318 SlotNumber)) ? 1 : 0;
319}
320
321/**
322 * _scsih_is_boot_device - search for matching boot device.
323 * @sas_address: sas address
324 * @device_name: device name specified in INDENTIFY fram
325 * @enclosure_logical_id: enclosure logical id
326 * @slot_number: slot number
327 * @form: specifies boot device form
328 * @boot_device: boot device object from bios page 2
329 *
330 * Returns 1 when there's a match, 0 means no match.
331 */
332static int
333_scsih_is_boot_device(u64 sas_address, u64 device_name,
334 u64 enclosure_logical_id, u16 slot, u8 form,
335 Mpi2BiosPage2BootDevice_t *boot_device)
336{
337 int rc = 0;
338
339 switch (form) {
340 case MPI2_BIOSPAGE2_FORM_SAS_WWID:
341 if (!sas_address)
342 break;
343 rc = _scsih_srch_boot_sas_address(
344 sas_address, &boot_device->SasWwid);
345 break;
346 case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT:
347 if (!enclosure_logical_id)
348 break;
349 rc = _scsih_srch_boot_encl_slot(
350 enclosure_logical_id,
351 slot, &boot_device->EnclosureSlot);
352 break;
353 case MPI2_BIOSPAGE2_FORM_DEVICE_NAME:
354 if (!device_name)
355 break;
356 rc = _scsih_srch_boot_device_name(
357 device_name, &boot_device->DeviceName);
358 break;
359 case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED:
360 break;
361 }
362
363 return rc;
364}
365
366/**
367 * _scsih_get_sas_address - set the sas_address for given device handle
368 * @handle: device handle
369 * @sas_address: sas address
370 *
371 * Returns 0 success, non-zero when failure
372 */
373static int
374_scsih_get_sas_address(struct MPT3SAS_ADAPTER *ioc, u16 handle,
375 u64 *sas_address)
376{
377 Mpi2SasDevicePage0_t sas_device_pg0;
378 Mpi2ConfigReply_t mpi_reply;
379 u32 ioc_status;
380
381 *sas_address = 0;
382
383 if (handle <= ioc->sas_hba.num_phys) {
384 *sas_address = ioc->sas_hba.sas_address;
385 return 0;
386 }
387
388 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
389 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
390 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
391 __FILE__, __LINE__, __func__);
392 return -ENXIO;
393 }
394
395 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
396 if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
397 *sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
398 return 0;
399 }
400
401 /* we hit this becuase the given parent handle doesn't exist */
402 if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
403 return -ENXIO;
404
405 /* else error case */
406 pr_err(MPT3SAS_FMT
407 "handle(0x%04x), ioc_status(0x%04x), failure at %s:%d/%s()!\n",
408 ioc->name, handle, ioc_status,
409 __FILE__, __LINE__, __func__);
410 return -EIO;
411}
412
413/**
414 * _scsih_determine_boot_device - determine boot device.
415 * @ioc: per adapter object
416 * @device: either sas_device or raid_device object
417 * @is_raid: [flag] 1 = raid object, 0 = sas object
418 *
419 * Determines whether this device should be first reported device to
420 * to scsi-ml or sas transport, this purpose is for persistent boot device.
421 * There are primary, alternate, and current entries in bios page 2. The order
422 * priority is primary, alternate, then current. This routine saves
423 * the corresponding device object and is_raid flag in the ioc object.
424 * The saved data to be used later in _scsih_probe_boot_devices().
425 */
426static void
427_scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc,
428 void *device, u8 is_raid)
429{
430 struct _sas_device *sas_device;
431 struct _raid_device *raid_device;
432 u64 sas_address;
433 u64 device_name;
434 u64 enclosure_logical_id;
435 u16 slot;
436
437 /* only process this function when driver loads */
438 if (!ioc->is_driver_loading)
439 return;
440
441 /* no Bios, return immediately */
442 if (!ioc->bios_pg3.BiosVersion)
443 return;
444
445 if (!is_raid) {
446 sas_device = device;
447 sas_address = sas_device->sas_address;
448 device_name = sas_device->device_name;
449 enclosure_logical_id = sas_device->enclosure_logical_id;
450 slot = sas_device->slot;
451 } else {
452 raid_device = device;
453 sas_address = raid_device->wwid;
454 device_name = 0;
455 enclosure_logical_id = 0;
456 slot = 0;
457 }
458
459 if (!ioc->req_boot_device.device) {
460 if (_scsih_is_boot_device(sas_address, device_name,
461 enclosure_logical_id, slot,
462 (ioc->bios_pg2.ReqBootDeviceForm &
463 MPI2_BIOSPAGE2_FORM_MASK),
464 &ioc->bios_pg2.RequestedBootDevice)) {
465 dinitprintk(ioc, pr_info(MPT3SAS_FMT
466 "%s: req_boot_device(0x%016llx)\n",
467 ioc->name, __func__,
468 (unsigned long long)sas_address));
469 ioc->req_boot_device.device = device;
470 ioc->req_boot_device.is_raid = is_raid;
471 }
472 }
473
474 if (!ioc->req_alt_boot_device.device) {
475 if (_scsih_is_boot_device(sas_address, device_name,
476 enclosure_logical_id, slot,
477 (ioc->bios_pg2.ReqAltBootDeviceForm &
478 MPI2_BIOSPAGE2_FORM_MASK),
479 &ioc->bios_pg2.RequestedAltBootDevice)) {
480 dinitprintk(ioc, pr_info(MPT3SAS_FMT
481 "%s: req_alt_boot_device(0x%016llx)\n",
482 ioc->name, __func__,
483 (unsigned long long)sas_address));
484 ioc->req_alt_boot_device.device = device;
485 ioc->req_alt_boot_device.is_raid = is_raid;
486 }
487 }
488
489 if (!ioc->current_boot_device.device) {
490 if (_scsih_is_boot_device(sas_address, device_name,
491 enclosure_logical_id, slot,
492 (ioc->bios_pg2.CurrentBootDeviceForm &
493 MPI2_BIOSPAGE2_FORM_MASK),
494 &ioc->bios_pg2.CurrentBootDevice)) {
495 dinitprintk(ioc, pr_info(MPT3SAS_FMT
496 "%s: current_boot_device(0x%016llx)\n",
497 ioc->name, __func__,
498 (unsigned long long)sas_address));
499 ioc->current_boot_device.device = device;
500 ioc->current_boot_device.is_raid = is_raid;
501 }
502 }
503}
504
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530505static struct _sas_device *
506__mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc,
507 struct MPT3SAS_TARGET *tgt_priv)
508{
509 struct _sas_device *ret;
510
511 assert_spin_locked(&ioc->sas_device_lock);
512
513 ret = tgt_priv->sdev;
514 if (ret)
515 sas_device_get(ret);
516
517 return ret;
518}
519
520static struct _sas_device *
521mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc,
522 struct MPT3SAS_TARGET *tgt_priv)
523{
524 struct _sas_device *ret;
525 unsigned long flags;
526
527 spin_lock_irqsave(&ioc->sas_device_lock, flags);
528 ret = __mpt3sas_get_sdev_from_target(ioc, tgt_priv);
529 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
530
531 return ret;
532}
533
534
535struct _sas_device *
536__mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
537 u64 sas_address)
538{
539 struct _sas_device *sas_device;
540
541 assert_spin_locked(&ioc->sas_device_lock);
542
543 list_for_each_entry(sas_device, &ioc->sas_device_list, list)
544 if (sas_device->sas_address == sas_address)
545 goto found_device;
546
547 list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
548 if (sas_device->sas_address == sas_address)
549 goto found_device;
550
551 return NULL;
552
553found_device:
554 sas_device_get(sas_device);
555 return sas_device;
556}
557
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530558/**
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530559 * mpt3sas_get_sdev_by_addr - sas device search
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530560 * @ioc: per adapter object
561 * @sas_address: sas address
562 * Context: Calling function should acquire ioc->sas_device_lock
563 *
564 * This searches for sas_device based on sas_address, then return sas_device
565 * object.
566 */
567struct _sas_device *
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530568mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530569 u64 sas_address)
570{
571 struct _sas_device *sas_device;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530572 unsigned long flags;
573
574 spin_lock_irqsave(&ioc->sas_device_lock, flags);
575 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
576 sas_address);
577 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
578
579 return sas_device;
580}
581
582static struct _sas_device *
583__mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
584{
585 struct _sas_device *sas_device;
586
587 assert_spin_locked(&ioc->sas_device_lock);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530588
589 list_for_each_entry(sas_device, &ioc->sas_device_list, list)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530590 if (sas_device->handle == handle)
591 goto found_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530592
593 list_for_each_entry(sas_device, &ioc->sas_device_init_list, list)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530594 if (sas_device->handle == handle)
595 goto found_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530596
597 return NULL;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530598
599found_device:
600 sas_device_get(sas_device);
601 return sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530602}
603
604/**
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530605 * mpt3sas_get_sdev_by_handle - sas device search
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530606 * @ioc: per adapter object
607 * @handle: sas device handle (assigned by firmware)
608 * Context: Calling function should acquire ioc->sas_device_lock
609 *
610 * This searches for sas_device based on sas_address, then return sas_device
611 * object.
612 */
613static struct _sas_device *
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530614mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530615{
616 struct _sas_device *sas_device;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530617 unsigned long flags;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530618
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530619 spin_lock_irqsave(&ioc->sas_device_lock, flags);
620 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
621 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530622
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530623 return sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530624}
625
626/**
627 * _scsih_sas_device_remove - remove sas_device from list.
628 * @ioc: per adapter object
629 * @sas_device: the sas_device object
630 * Context: This function will acquire ioc->sas_device_lock.
631 *
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530632 * If sas_device is on the list, remove it and decrement its reference count.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530633 */
634static void
635_scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc,
636 struct _sas_device *sas_device)
637{
638 unsigned long flags;
639
640 if (!sas_device)
641 return;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +0530642 pr_info(MPT3SAS_FMT
643 "removing handle(0x%04x), sas_addr(0x%016llx)\n",
644 ioc->name, sas_device->handle,
645 (unsigned long long) sas_device->sas_address);
646
647 if (sas_device->enclosure_handle != 0)
648 pr_info(MPT3SAS_FMT
649 "removing enclosure logical id(0x%016llx), slot(%d)\n",
650 ioc->name, (unsigned long long)
651 sas_device->enclosure_logical_id, sas_device->slot);
652
653 if (sas_device->connector_name[0] != '\0')
654 pr_info(MPT3SAS_FMT
655 "removing enclosure level(0x%04x), connector name( %s)\n",
656 ioc->name, sas_device->enclosure_level,
657 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530658
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530659 /*
660 * The lock serializes access to the list, but we still need to verify
661 * that nobody removed the entry while we were waiting on the lock.
662 */
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530663 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530664 if (!list_empty(&sas_device->list)) {
665 list_del_init(&sas_device->list);
666 sas_device_put(sas_device);
667 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530668 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
669}
670
671/**
672 * _scsih_device_remove_by_handle - removing device object by handle
673 * @ioc: per adapter object
674 * @handle: device handle
675 *
676 * Return nothing.
677 */
678static void
679_scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
680{
681 struct _sas_device *sas_device;
682 unsigned long flags;
683
684 if (ioc->shost_recovery)
685 return;
686
687 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530688 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
689 if (sas_device) {
690 list_del_init(&sas_device->list);
691 sas_device_put(sas_device);
692 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530693 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530694 if (sas_device) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530695 _scsih_remove_device(ioc, sas_device);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530696 sas_device_put(sas_device);
697 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530698}
699
700/**
701 * mpt3sas_device_remove_by_sas_address - removing device object by sas address
702 * @ioc: per adapter object
703 * @sas_address: device sas_address
704 *
705 * Return nothing.
706 */
707void
708mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
709 u64 sas_address)
710{
711 struct _sas_device *sas_device;
712 unsigned long flags;
713
714 if (ioc->shost_recovery)
715 return;
716
717 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530718 sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address);
719 if (sas_device) {
720 list_del_init(&sas_device->list);
721 sas_device_put(sas_device);
722 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530723 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530724 if (sas_device) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530725 _scsih_remove_device(ioc, sas_device);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530726 sas_device_put(sas_device);
727 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530728}
729
730/**
731 * _scsih_sas_device_add - insert sas_device to the list.
732 * @ioc: per adapter object
733 * @sas_device: the sas_device object
734 * Context: This function will acquire ioc->sas_device_lock.
735 *
736 * Adding new object to the ioc->sas_device_list.
737 */
738static void
739_scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc,
740 struct _sas_device *sas_device)
741{
742 unsigned long flags;
743
744 dewtprintk(ioc, pr_info(MPT3SAS_FMT
745 "%s: handle(0x%04x), sas_addr(0x%016llx)\n",
746 ioc->name, __func__, sas_device->handle,
747 (unsigned long long)sas_device->sas_address));
748
Sreekanth Reddye6d45e32015-06-30 12:24:52 +0530749 if (sas_device->enclosure_handle != 0)
750 dewtprintk(ioc, pr_info(MPT3SAS_FMT
751 "%s: enclosure logical id(0x%016llx), slot( %d)\n",
752 ioc->name, __func__, (unsigned long long)
753 sas_device->enclosure_logical_id, sas_device->slot));
754
755 if (sas_device->connector_name[0] != '\0')
756 dewtprintk(ioc, pr_info(MPT3SAS_FMT
757 "%s: enclosure level(0x%04x), connector name( %s)\n",
758 ioc->name, __func__,
759 sas_device->enclosure_level, sas_device->connector_name));
760
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530761 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530762 sas_device_get(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530763 list_add_tail(&sas_device->list, &ioc->sas_device_list);
764 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
765
766 if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
767 sas_device->sas_address_parent)) {
768 _scsih_sas_device_remove(ioc, sas_device);
769 } else if (!sas_device->starget) {
770 /*
771 * When asyn scanning is enabled, its not possible to remove
772 * devices while scanning is turned on due to an oops in
773 * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start()
774 */
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +0530775 if (!ioc->is_driver_loading) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530776 mpt3sas_transport_port_remove(ioc,
777 sas_device->sas_address,
778 sas_device->sas_address_parent);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +0530779 _scsih_sas_device_remove(ioc, sas_device);
780 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530781 }
782}
783
784/**
785 * _scsih_sas_device_init_add - insert sas_device to the list.
786 * @ioc: per adapter object
787 * @sas_device: the sas_device object
788 * Context: This function will acquire ioc->sas_device_lock.
789 *
790 * Adding new object at driver load time to the ioc->sas_device_init_list.
791 */
792static void
793_scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc,
794 struct _sas_device *sas_device)
795{
796 unsigned long flags;
797
798 dewtprintk(ioc, pr_info(MPT3SAS_FMT
799 "%s: handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
800 __func__, sas_device->handle,
801 (unsigned long long)sas_device->sas_address));
802
Sreekanth Reddye6d45e32015-06-30 12:24:52 +0530803 if (sas_device->enclosure_handle != 0)
804 dewtprintk(ioc, pr_info(MPT3SAS_FMT
805 "%s: enclosure logical id(0x%016llx), slot( %d)\n",
806 ioc->name, __func__, (unsigned long long)
807 sas_device->enclosure_logical_id, sas_device->slot));
808
809 if (sas_device->connector_name[0] != '\0')
810 dewtprintk(ioc, pr_info(MPT3SAS_FMT
811 "%s: enclosure level(0x%04x), connector name( %s)\n",
812 ioc->name, __func__, sas_device->enclosure_level,
813 sas_device->connector_name));
814
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530815 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +0530816 sas_device_get(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +0530817 list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
818 _scsih_determine_boot_device(ioc, sas_device, 0);
819 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
820}
821
822/**
823 * _scsih_raid_device_find_by_id - raid device search
824 * @ioc: per adapter object
825 * @id: sas device target id
826 * @channel: sas device channel
827 * Context: Calling function should acquire ioc->raid_device_lock
828 *
829 * This searches for raid_device based on target id, then return raid_device
830 * object.
831 */
832static struct _raid_device *
833_scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel)
834{
835 struct _raid_device *raid_device, *r;
836
837 r = NULL;
838 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
839 if (raid_device->id == id && raid_device->channel == channel) {
840 r = raid_device;
841 goto out;
842 }
843 }
844
845 out:
846 return r;
847}
848
849/**
850 * _scsih_raid_device_find_by_handle - raid device search
851 * @ioc: per adapter object
852 * @handle: sas device handle (assigned by firmware)
853 * Context: Calling function should acquire ioc->raid_device_lock
854 *
855 * This searches for raid_device based on handle, then return raid_device
856 * object.
857 */
858static struct _raid_device *
859_scsih_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
860{
861 struct _raid_device *raid_device, *r;
862
863 r = NULL;
864 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
865 if (raid_device->handle != handle)
866 continue;
867 r = raid_device;
868 goto out;
869 }
870
871 out:
872 return r;
873}
874
875/**
876 * _scsih_raid_device_find_by_wwid - raid device search
877 * @ioc: per adapter object
878 * @handle: sas device handle (assigned by firmware)
879 * Context: Calling function should acquire ioc->raid_device_lock
880 *
881 * This searches for raid_device based on wwid, then return raid_device
882 * object.
883 */
884static struct _raid_device *
885_scsih_raid_device_find_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid)
886{
887 struct _raid_device *raid_device, *r;
888
889 r = NULL;
890 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
891 if (raid_device->wwid != wwid)
892 continue;
893 r = raid_device;
894 goto out;
895 }
896
897 out:
898 return r;
899}
900
901/**
902 * _scsih_raid_device_add - add raid_device object
903 * @ioc: per adapter object
904 * @raid_device: raid_device object
905 *
906 * This is added to the raid_device_list link list.
907 */
908static void
909_scsih_raid_device_add(struct MPT3SAS_ADAPTER *ioc,
910 struct _raid_device *raid_device)
911{
912 unsigned long flags;
913
914 dewtprintk(ioc, pr_info(MPT3SAS_FMT
915 "%s: handle(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
916 raid_device->handle, (unsigned long long)raid_device->wwid));
917
918 spin_lock_irqsave(&ioc->raid_device_lock, flags);
919 list_add_tail(&raid_device->list, &ioc->raid_device_list);
920 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
921}
922
923/**
924 * _scsih_raid_device_remove - delete raid_device object
925 * @ioc: per adapter object
926 * @raid_device: raid_device object
927 *
928 */
929static void
930_scsih_raid_device_remove(struct MPT3SAS_ADAPTER *ioc,
931 struct _raid_device *raid_device)
932{
933 unsigned long flags;
934
935 spin_lock_irqsave(&ioc->raid_device_lock, flags);
936 list_del(&raid_device->list);
937 kfree(raid_device);
938 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
939}
940
941/**
942 * mpt3sas_scsih_expander_find_by_handle - expander device search
943 * @ioc: per adapter object
944 * @handle: expander handle (assigned by firmware)
945 * Context: Calling function should acquire ioc->sas_device_lock
946 *
947 * This searches for expander device based on handle, then returns the
948 * sas_node object.
949 */
950struct _sas_node *
951mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
952{
953 struct _sas_node *sas_expander, *r;
954
955 r = NULL;
956 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
957 if (sas_expander->handle != handle)
958 continue;
959 r = sas_expander;
960 goto out;
961 }
962 out:
963 return r;
964}
965
966/**
967 * mpt3sas_scsih_expander_find_by_sas_address - expander device search
968 * @ioc: per adapter object
969 * @sas_address: sas address
970 * Context: Calling function should acquire ioc->sas_node_lock.
971 *
972 * This searches for expander device based on sas_address, then returns the
973 * sas_node object.
974 */
975struct _sas_node *
976mpt3sas_scsih_expander_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
977 u64 sas_address)
978{
979 struct _sas_node *sas_expander, *r;
980
981 r = NULL;
982 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
983 if (sas_expander->sas_address != sas_address)
984 continue;
985 r = sas_expander;
986 goto out;
987 }
988 out:
989 return r;
990}
991
992/**
993 * _scsih_expander_node_add - insert expander device to the list.
994 * @ioc: per adapter object
995 * @sas_expander: the sas_device object
996 * Context: This function will acquire ioc->sas_node_lock.
997 *
998 * Adding new object to the ioc->sas_expander_list.
999 *
1000 * Return nothing.
1001 */
1002static void
1003_scsih_expander_node_add(struct MPT3SAS_ADAPTER *ioc,
1004 struct _sas_node *sas_expander)
1005{
1006 unsigned long flags;
1007
1008 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1009 list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
1010 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1011}
1012
1013/**
1014 * _scsih_is_end_device - determines if device is an end device
1015 * @device_info: bitfield providing information about the device.
1016 * Context: none
1017 *
1018 * Returns 1 if end device.
1019 */
1020static int
1021_scsih_is_end_device(u32 device_info)
1022{
1023 if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
1024 ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
1025 (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
1026 (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
1027 return 1;
1028 else
1029 return 0;
1030}
1031
1032/**
1033 * _scsih_scsi_lookup_get - returns scmd entry
1034 * @ioc: per adapter object
1035 * @smid: system request message index
1036 *
1037 * Returns the smid stored scmd pointer.
1038 */
1039static struct scsi_cmnd *
1040_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
1041{
1042 return ioc->scsi_lookup[smid - 1].scmd;
1043}
1044
1045/**
1046 * _scsih_scsi_lookup_get_clear - returns scmd entry
1047 * @ioc: per adapter object
1048 * @smid: system request message index
1049 *
1050 * Returns the smid stored scmd pointer.
1051 * Then will derefrence the stored scmd pointer.
1052 */
1053static inline struct scsi_cmnd *
1054_scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, u16 smid)
1055{
1056 unsigned long flags;
1057 struct scsi_cmnd *scmd;
1058
1059 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1060 scmd = ioc->scsi_lookup[smid - 1].scmd;
1061 ioc->scsi_lookup[smid - 1].scmd = NULL;
1062 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1063
1064 return scmd;
1065}
1066
1067/**
1068 * _scsih_scsi_lookup_find_by_scmd - scmd lookup
1069 * @ioc: per adapter object
1070 * @smid: system request message index
1071 * @scmd: pointer to scsi command object
1072 * Context: This function will acquire ioc->scsi_lookup_lock.
1073 *
1074 * This will search for a scmd pointer in the scsi_lookup array,
1075 * returning the revelent smid. A returned value of zero means invalid.
1076 */
1077static u16
1078_scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd
1079 *scmd)
1080{
1081 u16 smid;
1082 unsigned long flags;
1083 int i;
1084
1085 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1086 smid = 0;
1087 for (i = 0; i < ioc->scsiio_depth; i++) {
1088 if (ioc->scsi_lookup[i].scmd == scmd) {
1089 smid = ioc->scsi_lookup[i].smid;
1090 goto out;
1091 }
1092 }
1093 out:
1094 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1095 return smid;
1096}
1097
1098/**
1099 * _scsih_scsi_lookup_find_by_target - search for matching channel:id
1100 * @ioc: per adapter object
1101 * @id: target id
1102 * @channel: channel
1103 * Context: This function will acquire ioc->scsi_lookup_lock.
1104 *
1105 * This will search for a matching channel:id in the scsi_lookup array,
1106 * returning 1 if found.
1107 */
1108static u8
1109_scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id,
1110 int channel)
1111{
1112 u8 found;
1113 unsigned long flags;
1114 int i;
1115
1116 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1117 found = 0;
1118 for (i = 0 ; i < ioc->scsiio_depth; i++) {
1119 if (ioc->scsi_lookup[i].scmd &&
1120 (ioc->scsi_lookup[i].scmd->device->id == id &&
1121 ioc->scsi_lookup[i].scmd->device->channel == channel)) {
1122 found = 1;
1123 goto out;
1124 }
1125 }
1126 out:
1127 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1128 return found;
1129}
1130
1131/**
1132 * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
1133 * @ioc: per adapter object
1134 * @id: target id
1135 * @lun: lun number
1136 * @channel: channel
1137 * Context: This function will acquire ioc->scsi_lookup_lock.
1138 *
1139 * This will search for a matching channel:id:lun in the scsi_lookup array,
1140 * returning 1 if found.
1141 */
1142static u8
1143_scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
1144 unsigned int lun, int channel)
1145{
1146 u8 found;
1147 unsigned long flags;
1148 int i;
1149
1150 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
1151 found = 0;
1152 for (i = 0 ; i < ioc->scsiio_depth; i++) {
1153 if (ioc->scsi_lookup[i].scmd &&
1154 (ioc->scsi_lookup[i].scmd->device->id == id &&
1155 ioc->scsi_lookup[i].scmd->device->channel == channel &&
1156 ioc->scsi_lookup[i].scmd->device->lun == lun)) {
1157 found = 1;
1158 goto out;
1159 }
1160 }
1161 out:
1162 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
1163 return found;
1164}
1165
Christoph Hellwigcf75d5d2014-11-13 15:13:20 +01001166/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301167 * scsih_change_queue_depth - setting device queue depth
Christoph Hellwigcf75d5d2014-11-13 15:13:20 +01001168 * @sdev: scsi device struct
1169 * @qdepth: requested queue depth
1170 *
1171 * Returns queue depth.
1172 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301173int
1174scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301175{
1176 struct Scsi_Host *shost = sdev->host;
1177 int max_depth;
1178 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1179 struct MPT3SAS_DEVICE *sas_device_priv_data;
1180 struct MPT3SAS_TARGET *sas_target_priv_data;
1181 struct _sas_device *sas_device;
1182 unsigned long flags;
1183
1184 max_depth = shost->can_queue;
1185
1186 /* limit max device queue for SATA to 32 */
1187 sas_device_priv_data = sdev->hostdata;
1188 if (!sas_device_priv_data)
1189 goto not_sata;
1190 sas_target_priv_data = sas_device_priv_data->sas_target;
1191 if (!sas_target_priv_data)
1192 goto not_sata;
1193 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))
1194 goto not_sata;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301195
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301196 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301197 sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
1198 if (sas_device) {
1199 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1200 max_depth = MPT3SAS_SATA_QUEUE_DEPTH;
1201
1202 sas_device_put(sas_device);
1203 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301204 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1205
1206 not_sata:
1207
1208 if (!sdev->tagged_supported)
1209 max_depth = 1;
1210 if (qdepth > max_depth)
1211 qdepth = max_depth;
Christoph Hellwigcf75d5d2014-11-13 15:13:20 +01001212 return scsi_change_queue_depth(sdev, qdepth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301213}
1214
1215/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301216 * scsih_target_alloc - target add routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301217 * @starget: scsi target struct
1218 *
1219 * Returns 0 if ok. Any other return is assumed to be an error and
1220 * the device is ignored.
1221 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301222int
1223scsih_target_alloc(struct scsi_target *starget)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301224{
1225 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1226 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1227 struct MPT3SAS_TARGET *sas_target_priv_data;
1228 struct _sas_device *sas_device;
1229 struct _raid_device *raid_device;
1230 unsigned long flags;
1231 struct sas_rphy *rphy;
1232
Joe Lawrence62c4da42014-06-25 17:04:22 -04001233 sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data),
1234 GFP_KERNEL);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301235 if (!sas_target_priv_data)
1236 return -ENOMEM;
1237
1238 starget->hostdata = sas_target_priv_data;
1239 sas_target_priv_data->starget = starget;
1240 sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
1241
1242 /* RAID volumes */
1243 if (starget->channel == RAID_CHANNEL) {
1244 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1245 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1246 starget->channel);
1247 if (raid_device) {
1248 sas_target_priv_data->handle = raid_device->handle;
1249 sas_target_priv_data->sas_address = raid_device->wwid;
1250 sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301251 sas_target_priv_data->raid_device = raid_device;
1252 if (ioc->is_warpdrive)
1253 raid_device->starget = starget;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301254 }
1255 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1256 return 0;
1257 }
1258
1259 /* sas/sata devices */
1260 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1261 rphy = dev_to_rphy(starget->dev.parent);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301262 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301263 rphy->identify.sas_address);
1264
1265 if (sas_device) {
1266 sas_target_priv_data->handle = sas_device->handle;
1267 sas_target_priv_data->sas_address = sas_device->sas_address;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301268 sas_target_priv_data->sdev = sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301269 sas_device->starget = starget;
1270 sas_device->id = starget->id;
1271 sas_device->channel = starget->channel;
1272 if (test_bit(sas_device->handle, ioc->pd_handles))
1273 sas_target_priv_data->flags |=
1274 MPT_TARGET_FLAGS_RAID_COMPONENT;
Sreekanth Reddy45506042015-11-11 17:30:25 +05301275#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301276 if (sas_device->fast_path)
1277 sas_target_priv_data->flags |= MPT_TARGET_FASTPATH_IO;
Sreekanth Reddy45506042015-11-11 17:30:25 +05301278#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301279 }
1280 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1281
1282 return 0;
1283}
1284
1285/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301286 * scsih_target_destroy - target destroy routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301287 * @starget: scsi target struct
1288 *
1289 * Returns nothing.
1290 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301291void
1292scsih_target_destroy(struct scsi_target *starget)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301293{
1294 struct Scsi_Host *shost = dev_to_shost(&starget->dev);
1295 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1296 struct MPT3SAS_TARGET *sas_target_priv_data;
1297 struct _sas_device *sas_device;
1298 struct _raid_device *raid_device;
1299 unsigned long flags;
1300 struct sas_rphy *rphy;
1301
1302 sas_target_priv_data = starget->hostdata;
1303 if (!sas_target_priv_data)
1304 return;
1305
1306 if (starget->channel == RAID_CHANNEL) {
1307 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1308 raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
1309 starget->channel);
1310 if (raid_device) {
1311 raid_device->starget = NULL;
1312 raid_device->sdev = NULL;
1313 }
1314 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1315 goto out;
1316 }
1317
1318 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1319 rphy = dev_to_rphy(starget->dev.parent);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301320 sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301321 if (sas_device && (sas_device->starget == starget) &&
1322 (sas_device->id == starget->id) &&
1323 (sas_device->channel == starget->channel))
1324 sas_device->starget = NULL;
1325
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301326 if (sas_device) {
1327 /*
1328 * Corresponding get() is in _scsih_target_alloc()
1329 */
1330 sas_target_priv_data->sdev = NULL;
1331 sas_device_put(sas_device);
1332
1333 sas_device_put(sas_device);
1334 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301335 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1336
1337 out:
1338 kfree(sas_target_priv_data);
1339 starget->hostdata = NULL;
1340}
1341
1342/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301343 * scsih_slave_alloc - device add routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301344 * @sdev: scsi device struct
1345 *
1346 * Returns 0 if ok. Any other return is assumed to be an error and
1347 * the device is ignored.
1348 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301349int
1350scsih_slave_alloc(struct scsi_device *sdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301351{
1352 struct Scsi_Host *shost;
1353 struct MPT3SAS_ADAPTER *ioc;
1354 struct MPT3SAS_TARGET *sas_target_priv_data;
1355 struct MPT3SAS_DEVICE *sas_device_priv_data;
1356 struct scsi_target *starget;
1357 struct _raid_device *raid_device;
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301358 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301359 unsigned long flags;
1360
Joe Lawrence62c4da42014-06-25 17:04:22 -04001361 sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data),
1362 GFP_KERNEL);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301363 if (!sas_device_priv_data)
1364 return -ENOMEM;
1365
1366 sas_device_priv_data->lun = sdev->lun;
1367 sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
1368
1369 starget = scsi_target(sdev);
1370 sas_target_priv_data = starget->hostdata;
1371 sas_target_priv_data->num_luns++;
1372 sas_device_priv_data->sas_target = sas_target_priv_data;
1373 sdev->hostdata = sas_device_priv_data;
1374 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
1375 sdev->no_uld_attach = 1;
1376
1377 shost = dev_to_shost(&starget->dev);
1378 ioc = shost_priv(shost);
1379 if (starget->channel == RAID_CHANNEL) {
1380 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1381 raid_device = _scsih_raid_device_find_by_id(ioc,
1382 starget->id, starget->channel);
1383 if (raid_device)
1384 raid_device->sdev = sdev; /* raid is single lun */
1385 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1386 }
1387
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301388 if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
1389 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301390 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301391 sas_target_priv_data->sas_address);
1392 if (sas_device && (sas_device->starget == NULL)) {
1393 sdev_printk(KERN_INFO, sdev,
1394 "%s : sas_device->starget set to starget @ %d\n",
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301395 __func__, __LINE__);
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301396 sas_device->starget = starget;
1397 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301398
1399 if (sas_device)
1400 sas_device_put(sas_device);
1401
Sreekanth Reddyb65cfed2013-06-29 03:52:03 +05301402 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1403 }
1404
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301405 return 0;
1406}
1407
1408/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301409 * scsih_slave_destroy - device destroy routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301410 * @sdev: scsi device struct
1411 *
1412 * Returns nothing.
1413 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301414void
1415scsih_slave_destroy(struct scsi_device *sdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301416{
1417 struct MPT3SAS_TARGET *sas_target_priv_data;
1418 struct scsi_target *starget;
1419 struct Scsi_Host *shost;
1420 struct MPT3SAS_ADAPTER *ioc;
1421 struct _sas_device *sas_device;
1422 unsigned long flags;
1423
1424 if (!sdev->hostdata)
1425 return;
1426
1427 starget = scsi_target(sdev);
1428 sas_target_priv_data = starget->hostdata;
1429 sas_target_priv_data->num_luns--;
1430
1431 shost = dev_to_shost(&starget->dev);
1432 ioc = shost_priv(shost);
1433
1434 if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) {
1435 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301436 sas_device = __mpt3sas_get_sdev_from_target(ioc,
1437 sas_target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301438 if (sas_device && !sas_target_priv_data->num_luns)
1439 sas_device->starget = NULL;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301440
1441 if (sas_device)
1442 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301443 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1444 }
1445
1446 kfree(sdev->hostdata);
1447 sdev->hostdata = NULL;
1448}
1449
1450/**
1451 * _scsih_display_sata_capabilities - sata capabilities
1452 * @ioc: per adapter object
1453 * @handle: device handle
1454 * @sdev: scsi device struct
1455 */
1456static void
1457_scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc,
1458 u16 handle, struct scsi_device *sdev)
1459{
1460 Mpi2ConfigReply_t mpi_reply;
1461 Mpi2SasDevicePage0_t sas_device_pg0;
1462 u32 ioc_status;
1463 u16 flags;
1464 u32 device_info;
1465
1466 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
1467 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
1468 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1469 ioc->name, __FILE__, __LINE__, __func__);
1470 return;
1471 }
1472
1473 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1474 MPI2_IOCSTATUS_MASK;
1475 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1476 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1477 ioc->name, __FILE__, __LINE__, __func__);
1478 return;
1479 }
1480
1481 flags = le16_to_cpu(sas_device_pg0.Flags);
1482 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
1483
1484 sdev_printk(KERN_INFO, sdev,
1485 "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
1486 "sw_preserve(%s)\n",
1487 (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
1488 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
1489 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
1490 "n",
1491 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
1492 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
1493 (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
1494}
1495
1496/*
1497 * raid transport support -
1498 * Enabled for SLES11 and newer, in older kernels the driver will panic when
1499 * unloading the driver followed by a load - I beleive that the subroutine
1500 * raid_class_release() is not cleaning up properly.
1501 */
1502
1503/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301504 * scsih_is_raid - return boolean indicating device is raid volume
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301505 * @dev the device struct object
1506 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301507int
1508scsih_is_raid(struct device *dev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301509{
1510 struct scsi_device *sdev = to_scsi_device(dev);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301511 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301512
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301513 if (ioc->is_warpdrive)
1514 return 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301515 return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
1516}
1517
1518/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301519 * scsih_get_resync - get raid volume resync percent complete
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301520 * @dev the device struct object
1521 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301522void
1523scsih_get_resync(struct device *dev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301524{
1525 struct scsi_device *sdev = to_scsi_device(dev);
1526 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
1527 static struct _raid_device *raid_device;
1528 unsigned long flags;
1529 Mpi2RaidVolPage0_t vol_pg0;
1530 Mpi2ConfigReply_t mpi_reply;
1531 u32 volume_status_flags;
1532 u8 percent_complete;
1533 u16 handle;
1534
1535 percent_complete = 0;
1536 handle = 0;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301537 if (ioc->is_warpdrive)
1538 goto out;
1539
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301540 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1541 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1542 sdev->channel);
1543 if (raid_device) {
1544 handle = raid_device->handle;
1545 percent_complete = raid_device->percent_complete;
1546 }
1547 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1548
1549 if (!handle)
1550 goto out;
1551
1552 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
1553 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
1554 sizeof(Mpi2RaidVolPage0_t))) {
1555 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1556 ioc->name, __FILE__, __LINE__, __func__);
1557 percent_complete = 0;
1558 goto out;
1559 }
1560
1561 volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1562 if (!(volume_status_flags &
1563 MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS))
1564 percent_complete = 0;
1565
1566 out:
1567 raid_set_resync(mpt3sas_raid_template, dev, percent_complete);
1568}
1569
1570/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301571 * scsih_get_state - get raid volume level
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301572 * @dev the device struct object
1573 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301574void
1575scsih_get_state(struct device *dev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301576{
1577 struct scsi_device *sdev = to_scsi_device(dev);
1578 struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host);
1579 static struct _raid_device *raid_device;
1580 unsigned long flags;
1581 Mpi2RaidVolPage0_t vol_pg0;
1582 Mpi2ConfigReply_t mpi_reply;
1583 u32 volstate;
1584 enum raid_state state = RAID_STATE_UNKNOWN;
1585 u16 handle = 0;
1586
1587 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1588 raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id,
1589 sdev->channel);
1590 if (raid_device)
1591 handle = raid_device->handle;
1592 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1593
1594 if (!raid_device)
1595 goto out;
1596
1597 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0,
1598 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
1599 sizeof(Mpi2RaidVolPage0_t))) {
1600 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
1601 ioc->name, __FILE__, __LINE__, __func__);
1602 goto out;
1603 }
1604
1605 volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags);
1606 if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) {
1607 state = RAID_STATE_RESYNCING;
1608 goto out;
1609 }
1610
1611 switch (vol_pg0.VolumeState) {
1612 case MPI2_RAID_VOL_STATE_OPTIMAL:
1613 case MPI2_RAID_VOL_STATE_ONLINE:
1614 state = RAID_STATE_ACTIVE;
1615 break;
1616 case MPI2_RAID_VOL_STATE_DEGRADED:
1617 state = RAID_STATE_DEGRADED;
1618 break;
1619 case MPI2_RAID_VOL_STATE_FAILED:
1620 case MPI2_RAID_VOL_STATE_MISSING:
1621 state = RAID_STATE_OFFLINE;
1622 break;
1623 }
1624 out:
1625 raid_set_state(mpt3sas_raid_template, dev, state);
1626}
1627
1628/**
1629 * _scsih_set_level - set raid level
1630 * @sdev: scsi device struct
1631 * @volume_type: volume type
1632 */
1633static void
1634_scsih_set_level(struct scsi_device *sdev, u8 volume_type)
1635{
1636 enum raid_level level = RAID_LEVEL_UNKNOWN;
1637
1638 switch (volume_type) {
1639 case MPI2_RAID_VOL_TYPE_RAID0:
1640 level = RAID_LEVEL_0;
1641 break;
1642 case MPI2_RAID_VOL_TYPE_RAID10:
1643 level = RAID_LEVEL_10;
1644 break;
1645 case MPI2_RAID_VOL_TYPE_RAID1E:
1646 level = RAID_LEVEL_1E;
1647 break;
1648 case MPI2_RAID_VOL_TYPE_RAID1:
1649 level = RAID_LEVEL_1;
1650 break;
1651 }
1652
1653 raid_set_level(mpt3sas_raid_template, &sdev->sdev_gendev, level);
1654}
1655
1656
1657/**
1658 * _scsih_get_volume_capabilities - volume capabilities
1659 * @ioc: per adapter object
1660 * @sas_device: the raid_device object
1661 *
1662 * Returns 0 for success, else 1
1663 */
1664static int
1665_scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc,
1666 struct _raid_device *raid_device)
1667{
1668 Mpi2RaidVolPage0_t *vol_pg0;
1669 Mpi2RaidPhysDiskPage0_t pd_pg0;
1670 Mpi2SasDevicePage0_t sas_device_pg0;
1671 Mpi2ConfigReply_t mpi_reply;
1672 u16 sz;
1673 u8 num_pds;
1674
1675 if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle,
1676 &num_pds)) || !num_pds) {
1677 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1678 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1679 __func__));
1680 return 1;
1681 }
1682
1683 raid_device->num_pds = num_pds;
1684 sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
1685 sizeof(Mpi2RaidVol0PhysDisk_t));
1686 vol_pg0 = kzalloc(sz, GFP_KERNEL);
1687 if (!vol_pg0) {
1688 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1689 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1690 __func__));
1691 return 1;
1692 }
1693
1694 if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
1695 MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
1696 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1697 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1698 __func__));
1699 kfree(vol_pg0);
1700 return 1;
1701 }
1702
1703 raid_device->volume_type = vol_pg0->VolumeType;
1704
1705 /* figure out what the underlying devices are by
1706 * obtaining the device_info bits for the 1st device
1707 */
1708 if (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
1709 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
1710 vol_pg0->PhysDisk[0].PhysDiskNum))) {
1711 if (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
1712 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
1713 le16_to_cpu(pd_pg0.DevHandle)))) {
1714 raid_device->device_info =
1715 le32_to_cpu(sas_device_pg0.DeviceInfo);
1716 }
1717 }
1718
1719 kfree(vol_pg0);
1720 return 0;
1721}
1722
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301723/**
1724 * _scsih_enable_tlr - setting TLR flags
1725 * @ioc: per adapter object
1726 * @sdev: scsi device struct
1727 *
1728 * Enabling Transaction Layer Retries for tape devices when
1729 * vpd page 0x90 is present
1730 *
1731 */
1732static void
1733_scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev)
1734{
1735
1736 /* only for TAPE */
1737 if (sdev->type != TYPE_TAPE)
1738 return;
1739
1740 if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR))
1741 return;
1742
1743 sas_enable_tlr(sdev);
1744 sdev_printk(KERN_INFO, sdev, "TLR %s\n",
1745 sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled");
1746 return;
1747
1748}
1749
1750/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301751 * scsih_slave_configure - device configure routine.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301752 * @sdev: scsi device struct
1753 *
1754 * Returns 0 if ok. Any other return is assumed to be an error and
1755 * the device is ignored.
1756 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301757int
1758scsih_slave_configure(struct scsi_device *sdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301759{
1760 struct Scsi_Host *shost = sdev->host;
1761 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
1762 struct MPT3SAS_DEVICE *sas_device_priv_data;
1763 struct MPT3SAS_TARGET *sas_target_priv_data;
1764 struct _sas_device *sas_device;
1765 struct _raid_device *raid_device;
1766 unsigned long flags;
1767 int qdepth;
1768 u8 ssp_target = 0;
1769 char *ds = "";
1770 char *r_level = "";
1771 u16 handle, volume_handle = 0;
1772 u64 volume_wwid = 0;
1773
1774 qdepth = 1;
1775 sas_device_priv_data = sdev->hostdata;
1776 sas_device_priv_data->configured_lun = 1;
1777 sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
1778 sas_target_priv_data = sas_device_priv_data->sas_target;
1779 handle = sas_target_priv_data->handle;
1780
1781 /* raid volume handling */
1782 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
1783
1784 spin_lock_irqsave(&ioc->raid_device_lock, flags);
1785 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
1786 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
1787 if (!raid_device) {
1788 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1789 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
1790 __LINE__, __func__));
1791 return 1;
1792 }
1793
1794 if (_scsih_get_volume_capabilities(ioc, raid_device)) {
1795 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1796 "failure at %s:%d/%s()!\n", ioc->name, __FILE__,
1797 __LINE__, __func__));
1798 return 1;
1799 }
1800
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301801#ifdef SCSI_MPT2SAS
1802 /*
1803 * WARPDRIVE: Initialize the required data for Direct IO
1804 */
1805 _scsih_init_warpdrive_properties(ioc, raid_device);
1806#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301807
1808 /* RAID Queue Depth Support
1809 * IS volume = underlying qdepth of drive type, either
1810 * MPT3SAS_SAS_QUEUE_DEPTH or MPT3SAS_SATA_QUEUE_DEPTH
1811 * IM/IME/R10 = 128 (MPT3SAS_RAID_QUEUE_DEPTH)
1812 */
1813 if (raid_device->device_info &
1814 MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1815 qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
1816 ds = "SSP";
1817 } else {
1818 qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
1819 if (raid_device->device_info &
1820 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1821 ds = "SATA";
1822 else
1823 ds = "STP";
1824 }
1825
1826 switch (raid_device->volume_type) {
1827 case MPI2_RAID_VOL_TYPE_RAID0:
1828 r_level = "RAID0";
1829 break;
1830 case MPI2_RAID_VOL_TYPE_RAID1E:
1831 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1832 if (ioc->manu_pg10.OEMIdentifier &&
1833 (le32_to_cpu(ioc->manu_pg10.GenericFlags0) &
1834 MFG10_GF0_R10_DISPLAY) &&
1835 !(raid_device->num_pds % 2))
1836 r_level = "RAID10";
1837 else
1838 r_level = "RAID1E";
1839 break;
1840 case MPI2_RAID_VOL_TYPE_RAID1:
1841 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1842 r_level = "RAID1";
1843 break;
1844 case MPI2_RAID_VOL_TYPE_RAID10:
1845 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1846 r_level = "RAID10";
1847 break;
1848 case MPI2_RAID_VOL_TYPE_UNKNOWN:
1849 default:
1850 qdepth = MPT3SAS_RAID_QUEUE_DEPTH;
1851 r_level = "RAIDX";
1852 break;
1853 }
1854
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301855 if (!ioc->hide_ir_msg)
1856 sdev_printk(KERN_INFO, sdev,
1857 "%s: handle(0x%04x), wwid(0x%016llx),"
1858 " pd_count(%d), type(%s)\n",
1859 r_level, raid_device->handle,
1860 (unsigned long long)raid_device->wwid,
1861 raid_device->num_pds, ds);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301862
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301863 scsih_change_queue_depth(sdev, qdepth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301864
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05301865 /* raid transport support */
1866 if (!ioc->is_warpdrive)
1867 _scsih_set_level(sdev, raid_device->volume_type);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301868 return 0;
1869 }
1870
1871 /* non-raid handling */
1872 if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1873 if (mpt3sas_config_get_volume_handle(ioc, handle,
1874 &volume_handle)) {
1875 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1876 "failure at %s:%d/%s()!\n", ioc->name,
1877 __FILE__, __LINE__, __func__));
1878 return 1;
1879 }
1880 if (volume_handle && mpt3sas_config_get_volume_wwid(ioc,
1881 volume_handle, &volume_wwid)) {
1882 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1883 "failure at %s:%d/%s()!\n", ioc->name,
1884 __FILE__, __LINE__, __func__));
1885 return 1;
1886 }
1887 }
1888
1889 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301890 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301891 sas_device_priv_data->sas_target->sas_address);
1892 if (!sas_device) {
1893 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1894 dfailprintk(ioc, pr_warn(MPT3SAS_FMT
1895 "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__,
1896 __func__));
1897 return 1;
1898 }
1899
1900 sas_device->volume_handle = volume_handle;
1901 sas_device->volume_wwid = volume_wwid;
1902 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
1903 qdepth = MPT3SAS_SAS_QUEUE_DEPTH;
1904 ssp_target = 1;
1905 ds = "SSP";
1906 } else {
1907 qdepth = MPT3SAS_SATA_QUEUE_DEPTH;
1908 if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
1909 ds = "STP";
1910 else if (sas_device->device_info &
1911 MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
1912 ds = "SATA";
1913 }
1914
1915 sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " \
1916 "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n",
1917 ds, handle, (unsigned long long)sas_device->sas_address,
1918 sas_device->phy, (unsigned long long)sas_device->device_name);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05301919 if (sas_device->enclosure_handle != 0)
1920 sdev_printk(KERN_INFO, sdev,
1921 "%s: enclosure_logical_id(0x%016llx), slot(%d)\n",
1922 ds, (unsigned long long)
1923 sas_device->enclosure_logical_id, sas_device->slot);
1924 if (sas_device->connector_name[0] != '\0')
1925 sdev_printk(KERN_INFO, sdev,
1926 "%s: enclosure level(0x%04x), connector name( %s)\n",
1927 ds, sas_device->enclosure_level,
1928 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301929
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05301930 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301931 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1932
1933 if (!ssp_target)
1934 _scsih_display_sata_capabilities(ioc, handle, sdev);
1935
1936
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301937 scsih_change_queue_depth(sdev, qdepth);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301938
1939 if (ssp_target) {
1940 sas_read_port_mode_page(sdev);
1941 _scsih_enable_tlr(ioc, sdev);
1942 }
1943
1944 return 0;
1945}
1946
1947/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301948 * scsih_bios_param - fetch head, sector, cylinder info for a disk
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301949 * @sdev: scsi device struct
1950 * @bdev: pointer to block device context
1951 * @capacity: device size (in 512 byte sectors)
1952 * @params: three element array to place output:
1953 * params[0] number of heads (max 255)
1954 * params[1] number of sectors (max 63)
1955 * params[2] number of cylinders
1956 *
1957 * Return nothing.
1958 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05301959int
1960scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05301961 sector_t capacity, int params[])
1962{
1963 int heads;
1964 int sectors;
1965 sector_t cylinders;
1966 ulong dummy;
1967
1968 heads = 64;
1969 sectors = 32;
1970
1971 dummy = heads * sectors;
1972 cylinders = capacity;
1973 sector_div(cylinders, dummy);
1974
1975 /*
1976 * Handle extended translation size for logical drives
1977 * > 1Gb
1978 */
1979 if ((ulong)capacity >= 0x200000) {
1980 heads = 255;
1981 sectors = 63;
1982 dummy = heads * sectors;
1983 cylinders = capacity;
1984 sector_div(cylinders, dummy);
1985 }
1986
1987 /* return result */
1988 params[0] = heads;
1989 params[1] = sectors;
1990 params[2] = cylinders;
1991
1992 return 0;
1993}
1994
1995/**
1996 * _scsih_response_code - translation of device response code
1997 * @ioc: per adapter object
1998 * @response_code: response code returned by the device
1999 *
2000 * Return nothing.
2001 */
2002static void
2003_scsih_response_code(struct MPT3SAS_ADAPTER *ioc, u8 response_code)
2004{
2005 char *desc;
2006
2007 switch (response_code) {
2008 case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
2009 desc = "task management request completed";
2010 break;
2011 case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
2012 desc = "invalid frame";
2013 break;
2014 case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
2015 desc = "task management request not supported";
2016 break;
2017 case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
2018 desc = "task management request failed";
2019 break;
2020 case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
2021 desc = "task management request succeeded";
2022 break;
2023 case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
2024 desc = "invalid lun";
2025 break;
2026 case 0xA:
2027 desc = "overlapped tag attempted";
2028 break;
2029 case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
2030 desc = "task queued, however not sent to target";
2031 break;
2032 default:
2033 desc = "unknown";
2034 break;
2035 }
2036 pr_warn(MPT3SAS_FMT "response_code(0x%01x): %s\n",
2037 ioc->name, response_code, desc);
2038}
2039
2040/**
2041 * _scsih_tm_done - tm completion routine
2042 * @ioc: per adapter object
2043 * @smid: system request message index
2044 * @msix_index: MSIX table index supplied by the OS
2045 * @reply: reply message frame(lower 32bit addr)
2046 * Context: none.
2047 *
2048 * The callback handler when using scsih_issue_tm.
2049 *
2050 * Return 1 meaning mf should be freed from _base_interrupt
2051 * 0 means the mf is freed from this function.
2052 */
2053static u8
2054_scsih_tm_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
2055{
2056 MPI2DefaultReply_t *mpi_reply;
2057
2058 if (ioc->tm_cmds.status == MPT3_CMD_NOT_USED)
2059 return 1;
2060 if (ioc->tm_cmds.smid != smid)
2061 return 1;
2062 mpt3sas_base_flush_reply_queues(ioc);
2063 ioc->tm_cmds.status |= MPT3_CMD_COMPLETE;
2064 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
2065 if (mpi_reply) {
2066 memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
2067 ioc->tm_cmds.status |= MPT3_CMD_REPLY_VALID;
2068 }
2069 ioc->tm_cmds.status &= ~MPT3_CMD_PENDING;
2070 complete(&ioc->tm_cmds.done);
2071 return 1;
2072}
2073
2074/**
2075 * mpt3sas_scsih_set_tm_flag - set per target tm_busy
2076 * @ioc: per adapter object
2077 * @handle: device handle
2078 *
2079 * During taskmangement request, we need to freeze the device queue.
2080 */
2081void
2082mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2083{
2084 struct MPT3SAS_DEVICE *sas_device_priv_data;
2085 struct scsi_device *sdev;
2086 u8 skip = 0;
2087
2088 shost_for_each_device(sdev, ioc->shost) {
2089 if (skip)
2090 continue;
2091 sas_device_priv_data = sdev->hostdata;
2092 if (!sas_device_priv_data)
2093 continue;
2094 if (sas_device_priv_data->sas_target->handle == handle) {
2095 sas_device_priv_data->sas_target->tm_busy = 1;
2096 skip = 1;
2097 ioc->ignore_loginfos = 1;
2098 }
2099 }
2100}
2101
2102/**
2103 * mpt3sas_scsih_clear_tm_flag - clear 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_clear_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 = 0;
2124 skip = 1;
2125 ioc->ignore_loginfos = 0;
2126 }
2127 }
2128}
2129
2130/**
2131 * mpt3sas_scsih_issue_tm - main routine for sending tm requests
2132 * @ioc: per adapter struct
2133 * @device_handle: device handle
2134 * @channel: the channel assigned by the OS
2135 * @id: the id assigned by the OS
2136 * @lun: lun number
2137 * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
2138 * @smid_task: smid assigned to the task
2139 * @timeout: timeout in seconds
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302140 * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF
2141 * Context: user
2142 *
2143 * A generic API for sending task management requests to firmware.
2144 *
2145 * The callback index is set inside `ioc->tm_cb_idx`.
2146 *
2147 * Return SUCCESS or FAILED.
2148 */
2149int
2150mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
2151 uint id, uint lun, u8 type, u16 smid_task, ulong timeout,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04002152 enum mutex_type m_type)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302153{
2154 Mpi2SCSITaskManagementRequest_t *mpi_request;
2155 Mpi2SCSITaskManagementReply_t *mpi_reply;
2156 u16 smid = 0;
2157 u32 ioc_state;
2158 unsigned long timeleft;
2159 struct scsiio_tracker *scsi_lookup = NULL;
2160 int rc;
2161
2162 if (m_type == TM_MUTEX_ON)
2163 mutex_lock(&ioc->tm_cmds.mutex);
2164 if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) {
2165 pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n",
2166 __func__, ioc->name);
2167 rc = FAILED;
2168 goto err_out;
2169 }
2170
2171 if (ioc->shost_recovery || ioc->remove_host ||
2172 ioc->pci_error_recovery) {
2173 pr_info(MPT3SAS_FMT "%s: host reset in progress!\n",
2174 __func__, ioc->name);
2175 rc = FAILED;
2176 goto err_out;
2177 }
2178
2179 ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
2180 if (ioc_state & MPI2_DOORBELL_USED) {
2181 dhsprintk(ioc, pr_info(MPT3SAS_FMT
2182 "unexpected doorbell active!\n", ioc->name));
2183 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2184 FORCE_BIG_HAMMER);
2185 rc = (!rc) ? SUCCESS : FAILED;
2186 goto err_out;
2187 }
2188
2189 if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
2190 mpt3sas_base_fault_info(ioc, ioc_state &
2191 MPI2_DOORBELL_DATA_MASK);
2192 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2193 FORCE_BIG_HAMMER);
2194 rc = (!rc) ? SUCCESS : FAILED;
2195 goto err_out;
2196 }
2197
2198 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
2199 if (!smid) {
2200 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
2201 ioc->name, __func__);
2202 rc = FAILED;
2203 goto err_out;
2204 }
2205
2206 if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
2207 scsi_lookup = &ioc->scsi_lookup[smid_task - 1];
2208
2209 dtmprintk(ioc, pr_info(MPT3SAS_FMT
2210 "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n",
2211 ioc->name, handle, type, smid_task));
2212 ioc->tm_cmds.status = MPT3_CMD_PENDING;
2213 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2214 ioc->tm_cmds.smid = smid;
2215 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
2216 memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t));
2217 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
2218 mpi_request->DevHandle = cpu_to_le16(handle);
2219 mpi_request->TaskType = type;
2220 mpi_request->TaskMID = cpu_to_le16(smid_task);
2221 int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
2222 mpt3sas_scsih_set_tm_flag(ioc, handle);
2223 init_completion(&ioc->tm_cmds.done);
2224 mpt3sas_base_put_smid_hi_priority(ioc, smid);
2225 timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
2226 if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) {
2227 pr_err(MPT3SAS_FMT "%s: timeout\n",
2228 ioc->name, __func__);
2229 _debug_dump_mf(mpi_request,
2230 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2231 if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) {
2232 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2233 FORCE_BIG_HAMMER);
2234 rc = (!rc) ? SUCCESS : FAILED;
2235 ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
2236 mpt3sas_scsih_clear_tm_flag(ioc, handle);
2237 goto err_out;
2238 }
2239 }
2240
2241 if (ioc->tm_cmds.status & MPT3_CMD_REPLY_VALID) {
2242 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
2243 mpi_reply = ioc->tm_cmds.reply;
2244 dtmprintk(ioc, pr_info(MPT3SAS_FMT "complete tm: " \
2245 "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
2246 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
2247 le32_to_cpu(mpi_reply->IOCLogInfo),
2248 le32_to_cpu(mpi_reply->TerminationCount)));
2249 if (ioc->logging_level & MPT_DEBUG_TM) {
2250 _scsih_response_code(ioc, mpi_reply->ResponseCode);
2251 if (mpi_reply->IOCStatus)
2252 _debug_dump_mf(mpi_request,
2253 sizeof(Mpi2SCSITaskManagementRequest_t)/4);
2254 }
2255 }
2256
2257 switch (type) {
2258 case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
2259 rc = SUCCESS;
2260 if (scsi_lookup->scmd == NULL)
2261 break;
2262 rc = FAILED;
2263 break;
2264
2265 case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
2266 if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
2267 rc = FAILED;
2268 else
2269 rc = SUCCESS;
2270 break;
2271 case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
2272 case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
2273 if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
2274 rc = FAILED;
2275 else
2276 rc = SUCCESS;
2277 break;
2278 case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
2279 rc = SUCCESS;
2280 break;
2281 default:
2282 rc = FAILED;
2283 break;
2284 }
2285
2286 mpt3sas_scsih_clear_tm_flag(ioc, handle);
2287 ioc->tm_cmds.status = MPT3_CMD_NOT_USED;
2288 if (m_type == TM_MUTEX_ON)
2289 mutex_unlock(&ioc->tm_cmds.mutex);
2290
2291 return rc;
2292
2293 err_out:
2294 if (m_type == TM_MUTEX_ON)
2295 mutex_unlock(&ioc->tm_cmds.mutex);
2296 return rc;
2297}
2298
2299/**
2300 * _scsih_tm_display_info - displays info about the device
2301 * @ioc: per adapter struct
2302 * @scmd: pointer to scsi command object
2303 *
2304 * Called by task management callback handlers.
2305 */
2306static void
2307_scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd)
2308{
2309 struct scsi_target *starget = scmd->device->sdev_target;
2310 struct MPT3SAS_TARGET *priv_target = starget->hostdata;
2311 struct _sas_device *sas_device = NULL;
2312 unsigned long flags;
2313 char *device_str = NULL;
2314
2315 if (!priv_target)
2316 return;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05302317 if (ioc->hide_ir_msg)
2318 device_str = "WarpDrive";
2319 else
2320 device_str = "volume";
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302321
2322 scsi_print_command(scmd);
2323 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
2324 starget_printk(KERN_INFO, starget,
2325 "%s handle(0x%04x), %s wwid(0x%016llx)\n",
2326 device_str, priv_target->handle,
2327 device_str, (unsigned long long)priv_target->sas_address);
2328 } else {
2329 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302330 sas_device = __mpt3sas_get_sdev_from_target(ioc, priv_target);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302331 if (sas_device) {
2332 if (priv_target->flags &
2333 MPT_TARGET_FLAGS_RAID_COMPONENT) {
2334 starget_printk(KERN_INFO, starget,
2335 "volume handle(0x%04x), "
2336 "volume wwid(0x%016llx)\n",
2337 sas_device->volume_handle,
2338 (unsigned long long)sas_device->volume_wwid);
2339 }
2340 starget_printk(KERN_INFO, starget,
2341 "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n",
2342 sas_device->handle,
2343 (unsigned long long)sas_device->sas_address,
2344 sas_device->phy);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05302345 if (sas_device->enclosure_handle != 0)
2346 starget_printk(KERN_INFO, starget,
2347 "enclosure_logical_id(0x%016llx), slot(%d)\n",
2348 (unsigned long long)
2349 sas_device->enclosure_logical_id,
2350 sas_device->slot);
2351 if (sas_device->connector_name)
2352 starget_printk(KERN_INFO, starget,
2353 "enclosure level(0x%04x),connector name(%s)\n",
2354 sas_device->enclosure_level,
2355 sas_device->connector_name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302356
2357 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302358 }
2359 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2360 }
2361}
2362
2363/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302364 * scsih_abort - eh threads main abort routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302365 * @scmd: pointer to scsi command object
2366 *
2367 * Returns SUCCESS if command aborted else FAILED
2368 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302369int
2370scsih_abort(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302371{
2372 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2373 struct MPT3SAS_DEVICE *sas_device_priv_data;
2374 u16 smid;
2375 u16 handle;
2376 int r;
2377
2378 sdev_printk(KERN_INFO, scmd->device,
2379 "attempting task abort! scmd(%p)\n", scmd);
2380 _scsih_tm_display_info(ioc, scmd);
2381
2382 sas_device_priv_data = scmd->device->hostdata;
2383 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2384 sdev_printk(KERN_INFO, scmd->device,
2385 "device been deleted! scmd(%p)\n", scmd);
2386 scmd->result = DID_NO_CONNECT << 16;
2387 scmd->scsi_done(scmd);
2388 r = SUCCESS;
2389 goto out;
2390 }
2391
2392 /* search for the command */
2393 smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
2394 if (!smid) {
2395 scmd->result = DID_RESET << 16;
2396 r = SUCCESS;
2397 goto out;
2398 }
2399
2400 /* for hidden raid components and volumes this is not supported */
2401 if (sas_device_priv_data->sas_target->flags &
2402 MPT_TARGET_FLAGS_RAID_COMPONENT ||
2403 sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
2404 scmd->result = DID_RESET << 16;
2405 r = FAILED;
2406 goto out;
2407 }
2408
2409 mpt3sas_halt_firmware(ioc);
2410
2411 handle = sas_device_priv_data->sas_target->handle;
2412 r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2413 scmd->device->id, scmd->device->lun,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04002414 MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, TM_MUTEX_ON);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302415
2416 out:
2417 sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
2418 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2419 return r;
2420}
2421
2422/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302423 * scsih_dev_reset - eh threads main device reset routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302424 * @scmd: pointer to scsi command object
2425 *
2426 * Returns SUCCESS if command aborted else FAILED
2427 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302428int
2429scsih_dev_reset(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302430{
2431 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2432 struct MPT3SAS_DEVICE *sas_device_priv_data;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302433 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302434 u16 handle;
2435 int r;
2436
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302437 struct scsi_target *starget = scmd->device->sdev_target;
2438 struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
2439
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302440 sdev_printk(KERN_INFO, scmd->device,
2441 "attempting device reset! scmd(%p)\n", scmd);
2442 _scsih_tm_display_info(ioc, scmd);
2443
2444 sas_device_priv_data = scmd->device->hostdata;
2445 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2446 sdev_printk(KERN_INFO, scmd->device,
2447 "device been deleted! scmd(%p)\n", scmd);
2448 scmd->result = DID_NO_CONNECT << 16;
2449 scmd->scsi_done(scmd);
2450 r = SUCCESS;
2451 goto out;
2452 }
2453
2454 /* for hidden raid components obtain the volume_handle */
2455 handle = 0;
2456 if (sas_device_priv_data->sas_target->flags &
2457 MPT_TARGET_FLAGS_RAID_COMPONENT) {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302458 sas_device = mpt3sas_get_sdev_from_target(ioc,
2459 target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302460 if (sas_device)
2461 handle = sas_device->volume_handle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302462 } else
2463 handle = sas_device_priv_data->sas_target->handle;
2464
2465 if (!handle) {
2466 scmd->result = DID_RESET << 16;
2467 r = FAILED;
2468 goto out;
2469 }
2470
2471 r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2472 scmd->device->id, scmd->device->lun,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04002473 MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, TM_MUTEX_ON);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302474
2475 out:
2476 sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
2477 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302478
2479 if (sas_device)
2480 sas_device_put(sas_device);
2481
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302482 return r;
2483}
2484
2485/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302486 * scsih_target_reset - eh threads main target reset routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302487 * @scmd: pointer to scsi command object
2488 *
2489 * Returns SUCCESS if command aborted else FAILED
2490 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302491int
2492scsih_target_reset(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302493{
2494 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2495 struct MPT3SAS_DEVICE *sas_device_priv_data;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302496 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302497 u16 handle;
2498 int r;
2499 struct scsi_target *starget = scmd->device->sdev_target;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302500 struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302501
2502 starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n",
2503 scmd);
2504 _scsih_tm_display_info(ioc, scmd);
2505
2506 sas_device_priv_data = scmd->device->hostdata;
2507 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
2508 starget_printk(KERN_INFO, starget, "target been deleted! scmd(%p)\n",
2509 scmd);
2510 scmd->result = DID_NO_CONNECT << 16;
2511 scmd->scsi_done(scmd);
2512 r = SUCCESS;
2513 goto out;
2514 }
2515
2516 /* for hidden raid components obtain the volume_handle */
2517 handle = 0;
2518 if (sas_device_priv_data->sas_target->flags &
2519 MPT_TARGET_FLAGS_RAID_COMPONENT) {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302520 sas_device = mpt3sas_get_sdev_from_target(ioc,
2521 target_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302522 if (sas_device)
2523 handle = sas_device->volume_handle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302524 } else
2525 handle = sas_device_priv_data->sas_target->handle;
2526
2527 if (!handle) {
2528 scmd->result = DID_RESET << 16;
2529 r = FAILED;
2530 goto out;
2531 }
2532
2533 r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel,
2534 scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04002535 30, TM_MUTEX_ON);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302536
2537 out:
2538 starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
2539 ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302540
2541 if (sas_device)
2542 sas_device_put(sas_device);
2543
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302544 return r;
2545}
2546
2547
2548/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302549 * scsih_host_reset - eh threads main host reset routine
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302550 * @scmd: pointer to scsi command object
2551 *
2552 * Returns SUCCESS if command aborted else FAILED
2553 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05302554int
2555scsih_host_reset(struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302556{
2557 struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
2558 int r, retval;
2559
2560 pr_info(MPT3SAS_FMT "attempting host reset! scmd(%p)\n",
2561 ioc->name, scmd);
2562 scsi_print_command(scmd);
2563
Sreekanth Reddyddb588b2015-01-12 11:38:57 +05302564 if (ioc->is_driver_loading) {
2565 pr_info(MPT3SAS_FMT "Blocking the host reset\n",
2566 ioc->name);
2567 r = FAILED;
2568 goto out;
2569 }
2570
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302571 retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
2572 FORCE_BIG_HAMMER);
2573 r = (retval < 0) ? FAILED : SUCCESS;
Sreekanth Reddyddb588b2015-01-12 11:38:57 +05302574out:
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302575 pr_info(MPT3SAS_FMT "host reset: %s scmd(%p)\n",
2576 ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
2577
2578 return r;
2579}
2580
2581/**
2582 * _scsih_fw_event_add - insert and queue up fw_event
2583 * @ioc: per adapter object
2584 * @fw_event: object describing the event
2585 * Context: This function will acquire ioc->fw_event_lock.
2586 *
2587 * This adds the firmware event object into link list, then queues it up to
2588 * be processed from user context.
2589 *
2590 * Return nothing.
2591 */
2592static void
2593_scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
2594{
2595 unsigned long flags;
2596
2597 if (ioc->firmware_event_thread == NULL)
2598 return;
2599
2600 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2601 INIT_LIST_HEAD(&fw_event->list);
2602 list_add_tail(&fw_event->list, &ioc->fw_event_list);
2603 INIT_WORK(&fw_event->work, _firmware_event_work);
2604 queue_work(ioc->firmware_event_thread, &fw_event->work);
2605 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2606}
2607
2608/**
2609 * _scsih_fw_event_free - delete fw_event
2610 * @ioc: per adapter object
2611 * @fw_event: object describing the event
2612 * Context: This function will acquire ioc->fw_event_lock.
2613 *
2614 * This removes firmware event object from link list, frees associated memory.
2615 *
2616 * Return nothing.
2617 */
2618static void
2619_scsih_fw_event_free(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work
2620 *fw_event)
2621{
2622 unsigned long flags;
2623
2624 spin_lock_irqsave(&ioc->fw_event_lock, flags);
2625 list_del(&fw_event->list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302626 kfree(fw_event);
2627 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
2628}
2629
2630
2631 /**
2632 * mpt3sas_send_trigger_data_event - send event for processing trigger data
2633 * @ioc: per adapter object
2634 * @event_data: trigger event data
2635 *
2636 * Return nothing.
2637 */
2638void
2639mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc,
2640 struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data)
2641{
2642 struct fw_event_work *fw_event;
2643
2644 if (ioc->is_driver_loading)
2645 return;
Joe Lawrence35b62362014-06-25 17:05:34 -04002646 fw_event = kzalloc(sizeof(*fw_event) + sizeof(*event_data),
2647 GFP_ATOMIC);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302648 if (!fw_event)
2649 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302650 fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG;
2651 fw_event->ioc = ioc;
2652 memcpy(fw_event->event_data, event_data, sizeof(*event_data));
2653 _scsih_fw_event_add(ioc, fw_event);
2654}
2655
2656/**
2657 * _scsih_error_recovery_delete_devices - remove devices not responding
2658 * @ioc: per adapter object
2659 *
2660 * Return nothing.
2661 */
2662static void
2663_scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc)
2664{
2665 struct fw_event_work *fw_event;
2666
2667 if (ioc->is_driver_loading)
2668 return;
2669 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2670 if (!fw_event)
2671 return;
2672 fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES;
2673 fw_event->ioc = ioc;
2674 _scsih_fw_event_add(ioc, fw_event);
2675}
2676
2677/**
2678 * mpt3sas_port_enable_complete - port enable completed (fake event)
2679 * @ioc: per adapter object
2680 *
2681 * Return nothing.
2682 */
2683void
2684mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc)
2685{
2686 struct fw_event_work *fw_event;
2687
2688 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
2689 if (!fw_event)
2690 return;
2691 fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE;
2692 fw_event->ioc = ioc;
2693 _scsih_fw_event_add(ioc, fw_event);
2694}
2695
2696/**
2697 * _scsih_fw_event_cleanup_queue - cleanup event queue
2698 * @ioc: per adapter object
2699 *
2700 * Walk the firmware event queue, either killing timers, or waiting
2701 * for outstanding events to complete
2702 *
2703 * Return nothing.
2704 */
2705static void
2706_scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc)
2707{
2708 struct fw_event_work *fw_event, *next;
2709
2710 if (list_empty(&ioc->fw_event_list) ||
2711 !ioc->firmware_event_thread || in_interrupt())
2712 return;
2713
2714 list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05302715 if (cancel_delayed_work_sync(&fw_event->delayed_work)) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302716 _scsih_fw_event_free(ioc, fw_event);
2717 continue;
2718 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302719 }
2720}
2721
2722/**
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302723 * _scsih_internal_device_block - block the sdev device
2724 * @sdev: per device object
2725 * @sas_device_priv_data : per device driver private data
2726 *
2727 * make sure device is blocked without error, if not
2728 * print an error
2729 */
2730static void
2731_scsih_internal_device_block(struct scsi_device *sdev,
2732 struct MPT3SAS_DEVICE *sas_device_priv_data)
2733{
2734 int r = 0;
2735
2736 sdev_printk(KERN_INFO, sdev, "device_block, handle(0x%04x)\n",
2737 sas_device_priv_data->sas_target->handle);
2738 sas_device_priv_data->block = 1;
2739
2740 r = scsi_internal_device_block(sdev);
2741 if (r == -EINVAL)
2742 sdev_printk(KERN_WARNING, sdev,
2743 "device_block failed with return(%d) for handle(0x%04x)\n",
2744 sas_device_priv_data->sas_target->handle, r);
2745}
2746
2747/**
2748 * _scsih_internal_device_unblock - unblock the sdev device
2749 * @sdev: per device object
2750 * @sas_device_priv_data : per device driver private data
2751 * make sure device is unblocked without error, if not retry
2752 * by blocking and then unblocking
2753 */
2754
2755static void
2756_scsih_internal_device_unblock(struct scsi_device *sdev,
2757 struct MPT3SAS_DEVICE *sas_device_priv_data)
2758{
2759 int r = 0;
2760
2761 sdev_printk(KERN_WARNING, sdev, "device_unblock and setting to running, "
2762 "handle(0x%04x)\n", sas_device_priv_data->sas_target->handle);
2763 sas_device_priv_data->block = 0;
2764 r = scsi_internal_device_unblock(sdev, SDEV_RUNNING);
2765 if (r == -EINVAL) {
2766 /* The device has been set to SDEV_RUNNING by SD layer during
2767 * device addition but the request queue is still stopped by
2768 * our earlier block call. We need to perform a block again
2769 * to get the device to SDEV_BLOCK and then to SDEV_RUNNING */
2770
2771 sdev_printk(KERN_WARNING, sdev,
2772 "device_unblock failed with return(%d) for handle(0x%04x) "
2773 "performing a block followed by an unblock\n",
2774 sas_device_priv_data->sas_target->handle, r);
2775 sas_device_priv_data->block = 1;
2776 r = scsi_internal_device_block(sdev);
2777 if (r)
2778 sdev_printk(KERN_WARNING, sdev, "retried device_block "
2779 "failed with return(%d) for handle(0x%04x)\n",
2780 sas_device_priv_data->sas_target->handle, r);
2781
2782 sas_device_priv_data->block = 0;
2783 r = scsi_internal_device_unblock(sdev, SDEV_RUNNING);
2784 if (r)
2785 sdev_printk(KERN_WARNING, sdev, "retried device_unblock"
2786 " failed with return(%d) for handle(0x%04x)\n",
2787 sas_device_priv_data->sas_target->handle, r);
2788 }
2789}
2790
2791/**
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302792 * _scsih_ublock_io_all_device - unblock every device
2793 * @ioc: per adapter object
2794 *
2795 * change the device state from block to running
2796 */
2797static void
2798_scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc)
2799{
2800 struct MPT3SAS_DEVICE *sas_device_priv_data;
2801 struct scsi_device *sdev;
2802
2803 shost_for_each_device(sdev, ioc->shost) {
2804 sas_device_priv_data = sdev->hostdata;
2805 if (!sas_device_priv_data)
2806 continue;
2807 if (!sas_device_priv_data->block)
2808 continue;
2809
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302810 dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
2811 "device_running, handle(0x%04x)\n",
2812 sas_device_priv_data->sas_target->handle));
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302813 _scsih_internal_device_unblock(sdev, sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302814 }
2815}
2816
2817
2818/**
2819 * _scsih_ublock_io_device - prepare device to be deleted
2820 * @ioc: per adapter object
2821 * @sas_addr: sas address
2822 *
2823 * unblock then put device in offline state
2824 */
2825static void
2826_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
2827{
2828 struct MPT3SAS_DEVICE *sas_device_priv_data;
2829 struct scsi_device *sdev;
2830
2831 shost_for_each_device(sdev, ioc->shost) {
2832 sas_device_priv_data = sdev->hostdata;
2833 if (!sas_device_priv_data)
2834 continue;
2835 if (sas_device_priv_data->sas_target->sas_address
2836 != sas_address)
2837 continue;
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302838 if (sas_device_priv_data->block)
2839 _scsih_internal_device_unblock(sdev,
2840 sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302841 }
2842}
2843
2844/**
2845 * _scsih_block_io_all_device - set the device state to SDEV_BLOCK
2846 * @ioc: per adapter object
2847 * @handle: device handle
2848 *
2849 * During device pull we need to appropiately set the sdev state.
2850 */
2851static void
2852_scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc)
2853{
2854 struct MPT3SAS_DEVICE *sas_device_priv_data;
2855 struct scsi_device *sdev;
2856
2857 shost_for_each_device(sdev, ioc->shost) {
2858 sas_device_priv_data = sdev->hostdata;
2859 if (!sas_device_priv_data)
2860 continue;
2861 if (sas_device_priv_data->block)
2862 continue;
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302863 _scsih_internal_device_block(sdev, sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302864 }
2865}
2866
2867/**
2868 * _scsih_block_io_device - set the device state to SDEV_BLOCK
2869 * @ioc: per adapter object
2870 * @handle: device handle
2871 *
2872 * During device pull we need to appropiately set the sdev state.
2873 */
2874static void
2875_scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2876{
2877 struct MPT3SAS_DEVICE *sas_device_priv_data;
2878 struct scsi_device *sdev;
Sreekanth Reddye4bc7f52015-06-30 12:24:49 +05302879 struct _sas_device *sas_device;
2880
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302881 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddye4bc7f52015-06-30 12:24:49 +05302882 if (!sas_device)
2883 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302884
2885 shost_for_each_device(sdev, ioc->shost) {
2886 sas_device_priv_data = sdev->hostdata;
2887 if (!sas_device_priv_data)
2888 continue;
2889 if (sas_device_priv_data->sas_target->handle != handle)
2890 continue;
2891 if (sas_device_priv_data->block)
2892 continue;
Sreekanth Reddye4bc7f52015-06-30 12:24:49 +05302893 if (sas_device->pend_sas_rphy_add)
2894 continue;
Sreekanth Reddydf838f92015-06-30 12:25:05 +05302895 _scsih_internal_device_block(sdev, sas_device_priv_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302896 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302897
2898 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302899}
2900
2901/**
2902 * _scsih_block_io_to_children_attached_to_ex
2903 * @ioc: per adapter object
2904 * @sas_expander: the sas_device object
2905 *
2906 * This routine set sdev state to SDEV_BLOCK for all devices
2907 * attached to this expander. This function called when expander is
2908 * pulled.
2909 */
2910static void
2911_scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc,
2912 struct _sas_node *sas_expander)
2913{
2914 struct _sas_port *mpt3sas_port;
2915 struct _sas_device *sas_device;
2916 struct _sas_node *expander_sibling;
2917 unsigned long flags;
2918
2919 if (!sas_expander)
2920 return;
2921
2922 list_for_each_entry(mpt3sas_port,
2923 &sas_expander->sas_port_list, port_list) {
2924 if (mpt3sas_port->remote_identify.device_type ==
2925 SAS_END_DEVICE) {
2926 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302927 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
2928 mpt3sas_port->remote_identify.sas_address);
2929 if (sas_device) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302930 set_bit(sas_device->handle,
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05302931 ioc->blocking_handles);
2932 sas_device_put(sas_device);
2933 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302934 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
2935 }
2936 }
2937
2938 list_for_each_entry(mpt3sas_port,
2939 &sas_expander->sas_port_list, port_list) {
2940
2941 if (mpt3sas_port->remote_identify.device_type ==
2942 SAS_EDGE_EXPANDER_DEVICE ||
2943 mpt3sas_port->remote_identify.device_type ==
2944 SAS_FANOUT_EXPANDER_DEVICE) {
2945 expander_sibling =
2946 mpt3sas_scsih_expander_find_by_sas_address(
2947 ioc, mpt3sas_port->remote_identify.sas_address);
2948 _scsih_block_io_to_children_attached_to_ex(ioc,
2949 expander_sibling);
2950 }
2951 }
2952}
2953
2954/**
2955 * _scsih_block_io_to_children_attached_directly
2956 * @ioc: per adapter object
2957 * @event_data: topology change event data
2958 *
2959 * This routine set sdev state to SDEV_BLOCK for all devices
2960 * direct attached during device pull.
2961 */
2962static void
2963_scsih_block_io_to_children_attached_directly(struct MPT3SAS_ADAPTER *ioc,
2964 Mpi2EventDataSasTopologyChangeList_t *event_data)
2965{
2966 int i;
2967 u16 handle;
2968 u16 reason_code;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302969
2970 for (i = 0; i < event_data->NumEntries; i++) {
2971 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
2972 if (!handle)
2973 continue;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05302974 reason_code = event_data->PHY[i].PhyStatus &
2975 MPI2_EVENT_SAS_TOPO_RC_MASK;
2976 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
2977 _scsih_block_io_device(ioc, handle);
2978 }
2979}
2980
2981/**
2982 * _scsih_tm_tr_send - send task management request
2983 * @ioc: per adapter object
2984 * @handle: device handle
2985 * Context: interrupt time.
2986 *
2987 * This code is to initiate the device removal handshake protocol
2988 * with controller firmware. This function will issue target reset
2989 * using high priority request queue. It will send a sas iounit
2990 * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
2991 *
2992 * This is designed to send muliple task management request at the same
2993 * time to the fifo. If the fifo is full, we will append the request,
2994 * and process it in a future completion.
2995 */
2996static void
2997_scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
2998{
2999 Mpi2SCSITaskManagementRequest_t *mpi_request;
3000 u16 smid;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303001 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303002 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
3003 u64 sas_address = 0;
3004 unsigned long flags;
3005 struct _tr_list *delayed_tr;
3006 u32 ioc_state;
3007
3008 if (ioc->remove_host) {
3009 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3010 "%s: host has been removed: handle(0x%04x)\n",
3011 __func__, ioc->name, handle));
3012 return;
3013 } else if (ioc->pci_error_recovery) {
3014 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3015 "%s: host in pci error recovery: handle(0x%04x)\n",
3016 __func__, ioc->name,
3017 handle));
3018 return;
3019 }
3020 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3021 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3022 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3023 "%s: host is not operational: handle(0x%04x)\n",
3024 __func__, ioc->name,
3025 handle));
3026 return;
3027 }
3028
3029 /* if PD, then return */
3030 if (test_bit(handle, ioc->pd_handles))
3031 return;
3032
3033 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303034 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303035 if (sas_device && sas_device->starget &&
3036 sas_device->starget->hostdata) {
3037 sas_target_priv_data = sas_device->starget->hostdata;
3038 sas_target_priv_data->deleted = 1;
3039 sas_address = sas_device->sas_address;
3040 }
3041 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
3042
3043 if (sas_target_priv_data) {
3044 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3045 "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n",
3046 ioc->name, handle,
3047 (unsigned long long)sas_address));
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05303048 if (sas_device->enclosure_handle != 0)
3049 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3050 "setting delete flag:enclosure logical id(0x%016llx),"
3051 " slot(%d)\n", ioc->name, (unsigned long long)
3052 sas_device->enclosure_logical_id,
3053 sas_device->slot));
3054 if (sas_device->connector_name)
3055 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3056 "setting delete flag: enclosure level(0x%04x),"
3057 " connector name( %s)\n", ioc->name,
3058 sas_device->enclosure_level,
3059 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303060 _scsih_ublock_io_device(ioc, sas_address);
3061 sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
3062 }
3063
3064 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx);
3065 if (!smid) {
3066 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3067 if (!delayed_tr)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303068 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303069 INIT_LIST_HEAD(&delayed_tr->list);
3070 delayed_tr->handle = handle;
3071 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3072 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3073 "DELAYED:tr:handle(0x%04x), (open)\n",
3074 ioc->name, handle));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303075 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303076 }
3077
3078 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3079 "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3080 ioc->name, handle, smid,
3081 ioc->tm_tr_cb_idx));
3082 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3083 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3084 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3085 mpi_request->DevHandle = cpu_to_le16(handle);
3086 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
3087 mpt3sas_base_put_smid_hi_priority(ioc, smid);
3088 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05303089
3090out:
3091 if (sas_device)
3092 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303093}
3094
3095/**
3096 * _scsih_tm_tr_complete -
3097 * @ioc: per adapter object
3098 * @smid: system request message index
3099 * @msix_index: MSIX table index supplied by the OS
3100 * @reply: reply message frame(lower 32bit addr)
3101 * Context: interrupt time.
3102 *
3103 * This is the target reset completion routine.
3104 * This code is part of the code to initiate the device removal
3105 * handshake protocol with controller firmware.
3106 * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE)
3107 *
3108 * Return 1 meaning mf should be freed from _base_interrupt
3109 * 0 means the mf is freed from this function.
3110 */
3111static u8
3112_scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
3113 u32 reply)
3114{
3115 u16 handle;
3116 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
3117 Mpi2SCSITaskManagementReply_t *mpi_reply =
3118 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3119 Mpi2SasIoUnitControlRequest_t *mpi_request;
3120 u16 smid_sas_ctrl;
3121 u32 ioc_state;
3122
3123 if (ioc->remove_host) {
3124 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3125 "%s: host has been removed\n", __func__, ioc->name));
3126 return 1;
3127 } else if (ioc->pci_error_recovery) {
3128 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3129 "%s: host in pci error recovery\n", __func__,
3130 ioc->name));
3131 return 1;
3132 }
3133 ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
3134 if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
3135 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3136 "%s: host is not operational\n", __func__, ioc->name));
3137 return 1;
3138 }
3139 if (unlikely(!mpi_reply)) {
3140 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3141 ioc->name, __FILE__, __LINE__, __func__);
3142 return 1;
3143 }
3144 mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
3145 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3146 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3147 dewtprintk(ioc, pr_err(MPT3SAS_FMT
3148 "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
3149 ioc->name, handle,
3150 le16_to_cpu(mpi_reply->DevHandle), smid));
3151 return 0;
3152 }
3153
3154 mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT);
3155 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3156 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3157 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3158 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3159 le32_to_cpu(mpi_reply->IOCLogInfo),
3160 le32_to_cpu(mpi_reply->TerminationCount)));
3161
3162 smid_sas_ctrl = mpt3sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx);
3163 if (!smid_sas_ctrl) {
3164 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
3165 ioc->name, __func__);
3166 return 1;
3167 }
3168
3169 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3170 "sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3171 ioc->name, handle, smid_sas_ctrl,
3172 ioc->tm_sas_control_cb_idx));
3173 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid_sas_ctrl);
3174 memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
3175 mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
3176 mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
3177 mpi_request->DevHandle = mpi_request_tm->DevHandle;
3178 mpt3sas_base_put_smid_default(ioc, smid_sas_ctrl);
3179
3180 return _scsih_check_for_pending_tm(ioc, smid);
3181}
3182
3183
3184/**
3185 * _scsih_sas_control_complete - completion routine
3186 * @ioc: per adapter object
3187 * @smid: system request message index
3188 * @msix_index: MSIX table index supplied by the OS
3189 * @reply: reply message frame(lower 32bit addr)
3190 * Context: interrupt time.
3191 *
3192 * This is the sas iounit control completion routine.
3193 * This code is part of the code to initiate the device removal
3194 * handshake protocol with controller firmware.
3195 *
3196 * Return 1 meaning mf should be freed from _base_interrupt
3197 * 0 means the mf is freed from this function.
3198 */
3199static u8
3200_scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
3201 u8 msix_index, u32 reply)
3202{
3203 Mpi2SasIoUnitControlReply_t *mpi_reply =
3204 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3205
3206 if (likely(mpi_reply)) {
3207 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3208 "sc_complete:handle(0x%04x), (open) "
3209 "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
3210 ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid,
3211 le16_to_cpu(mpi_reply->IOCStatus),
3212 le32_to_cpu(mpi_reply->IOCLogInfo)));
3213 } else {
3214 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3215 ioc->name, __FILE__, __LINE__, __func__);
3216 }
3217 return 1;
3218}
3219
3220/**
3221 * _scsih_tm_tr_volume_send - send target reset request for volumes
3222 * @ioc: per adapter object
3223 * @handle: device handle
3224 * Context: interrupt time.
3225 *
3226 * This is designed to send muliple task management request at the same
3227 * time to the fifo. If the fifo is full, we will append the request,
3228 * and process it in a future completion.
3229 */
3230static void
3231_scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3232{
3233 Mpi2SCSITaskManagementRequest_t *mpi_request;
3234 u16 smid;
3235 struct _tr_list *delayed_tr;
3236
3237 if (ioc->shost_recovery || ioc->remove_host ||
3238 ioc->pci_error_recovery) {
3239 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3240 "%s: host reset in progress!\n",
3241 __func__, ioc->name));
3242 return;
3243 }
3244
3245 smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx);
3246 if (!smid) {
3247 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3248 if (!delayed_tr)
3249 return;
3250 INIT_LIST_HEAD(&delayed_tr->list);
3251 delayed_tr->handle = handle;
3252 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list);
3253 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3254 "DELAYED:tr:handle(0x%04x), (open)\n",
3255 ioc->name, handle));
3256 return;
3257 }
3258
3259 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3260 "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
3261 ioc->name, handle, smid,
3262 ioc->tm_tr_volume_cb_idx));
3263 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3264 memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
3265 mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
3266 mpi_request->DevHandle = cpu_to_le16(handle);
3267 mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
3268 mpt3sas_base_put_smid_hi_priority(ioc, smid);
3269}
3270
3271/**
3272 * _scsih_tm_volume_tr_complete - target reset completion
3273 * @ioc: per adapter object
3274 * @smid: system request message index
3275 * @msix_index: MSIX table index supplied by the OS
3276 * @reply: reply message frame(lower 32bit addr)
3277 * Context: interrupt time.
3278 *
3279 * Return 1 meaning mf should be freed from _base_interrupt
3280 * 0 means the mf is freed from this function.
3281 */
3282static u8
3283_scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
3284 u8 msix_index, u32 reply)
3285{
3286 u16 handle;
3287 Mpi2SCSITaskManagementRequest_t *mpi_request_tm;
3288 Mpi2SCSITaskManagementReply_t *mpi_reply =
3289 mpt3sas_base_get_reply_virt_addr(ioc, reply);
3290
3291 if (ioc->shost_recovery || ioc->remove_host ||
3292 ioc->pci_error_recovery) {
3293 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3294 "%s: host reset in progress!\n",
3295 __func__, ioc->name));
3296 return 1;
3297 }
3298 if (unlikely(!mpi_reply)) {
3299 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
3300 ioc->name, __FILE__, __LINE__, __func__);
3301 return 1;
3302 }
3303
3304 mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid);
3305 handle = le16_to_cpu(mpi_request_tm->DevHandle);
3306 if (handle != le16_to_cpu(mpi_reply->DevHandle)) {
3307 dewtprintk(ioc, pr_err(MPT3SAS_FMT
3308 "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n",
3309 ioc->name, handle,
3310 le16_to_cpu(mpi_reply->DevHandle), smid));
3311 return 0;
3312 }
3313
3314 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3315 "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), "
3316 "loginfo(0x%08x), completed(%d)\n", ioc->name,
3317 handle, smid, le16_to_cpu(mpi_reply->IOCStatus),
3318 le32_to_cpu(mpi_reply->IOCLogInfo),
3319 le32_to_cpu(mpi_reply->TerminationCount)));
3320
3321 return _scsih_check_for_pending_tm(ioc, smid);
3322}
3323
3324
3325/**
3326 * _scsih_check_for_pending_tm - check for pending task management
3327 * @ioc: per adapter object
3328 * @smid: system request message index
3329 *
3330 * This will check delayed target reset list, and feed the
3331 * next reqeust.
3332 *
3333 * Return 1 meaning mf should be freed from _base_interrupt
3334 * 0 means the mf is freed from this function.
3335 */
3336static u8
3337_scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid)
3338{
3339 struct _tr_list *delayed_tr;
3340
3341 if (!list_empty(&ioc->delayed_tr_volume_list)) {
3342 delayed_tr = list_entry(ioc->delayed_tr_volume_list.next,
3343 struct _tr_list, list);
3344 mpt3sas_base_free_smid(ioc, smid);
3345 _scsih_tm_tr_volume_send(ioc, delayed_tr->handle);
3346 list_del(&delayed_tr->list);
3347 kfree(delayed_tr);
3348 return 0;
3349 }
3350
3351 if (!list_empty(&ioc->delayed_tr_list)) {
3352 delayed_tr = list_entry(ioc->delayed_tr_list.next,
3353 struct _tr_list, list);
3354 mpt3sas_base_free_smid(ioc, smid);
3355 _scsih_tm_tr_send(ioc, delayed_tr->handle);
3356 list_del(&delayed_tr->list);
3357 kfree(delayed_tr);
3358 return 0;
3359 }
3360
3361 return 1;
3362}
3363
3364/**
3365 * _scsih_check_topo_delete_events - sanity check on topo events
3366 * @ioc: per adapter object
3367 * @event_data: the event data payload
3368 *
3369 * This routine added to better handle cable breaker.
3370 *
3371 * This handles the case where driver receives multiple expander
3372 * add and delete events in a single shot. When there is a delete event
3373 * the routine will void any pending add events waiting in the event queue.
3374 *
3375 * Return nothing.
3376 */
3377static void
3378_scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc,
3379 Mpi2EventDataSasTopologyChangeList_t *event_data)
3380{
3381 struct fw_event_work *fw_event;
3382 Mpi2EventDataSasTopologyChangeList_t *local_event_data;
3383 u16 expander_handle;
3384 struct _sas_node *sas_expander;
3385 unsigned long flags;
3386 int i, reason_code;
3387 u16 handle;
3388
3389 for (i = 0 ; i < event_data->NumEntries; i++) {
3390 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
3391 if (!handle)
3392 continue;
3393 reason_code = event_data->PHY[i].PhyStatus &
3394 MPI2_EVENT_SAS_TOPO_RC_MASK;
3395 if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)
3396 _scsih_tm_tr_send(ioc, handle);
3397 }
3398
3399 expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
3400 if (expander_handle < ioc->sas_hba.num_phys) {
3401 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3402 return;
3403 }
3404 if (event_data->ExpStatus ==
3405 MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) {
3406 /* put expander attached devices into blocking state */
3407 spin_lock_irqsave(&ioc->sas_node_lock, flags);
3408 sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
3409 expander_handle);
3410 _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
3411 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
3412 do {
3413 handle = find_first_bit(ioc->blocking_handles,
3414 ioc->facts.MaxDevHandle);
3415 if (handle < ioc->facts.MaxDevHandle)
3416 _scsih_block_io_device(ioc, handle);
3417 } while (test_and_clear_bit(handle, ioc->blocking_handles));
3418 } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
3419 _scsih_block_io_to_children_attached_directly(ioc, event_data);
3420
3421 if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
3422 return;
3423
3424 /* mark ignore flag for pending events */
3425 spin_lock_irqsave(&ioc->fw_event_lock, flags);
3426 list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
3427 if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
3428 fw_event->ignore)
3429 continue;
Joe Lawrence35b62362014-06-25 17:05:34 -04003430 local_event_data = (Mpi2EventDataSasTopologyChangeList_t *)
3431 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303432 if (local_event_data->ExpStatus ==
3433 MPI2_EVENT_SAS_TOPO_ES_ADDED ||
3434 local_event_data->ExpStatus ==
3435 MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
3436 if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
3437 expander_handle) {
3438 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3439 "setting ignoring flag\n", ioc->name));
3440 fw_event->ignore = 1;
3441 }
3442 }
3443 }
3444 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
3445}
3446
3447/**
3448 * _scsih_set_volume_delete_flag - setting volume delete flag
3449 * @ioc: per adapter object
3450 * @handle: device handle
3451 *
3452 * This returns nothing.
3453 */
3454static void
3455_scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
3456{
3457 struct _raid_device *raid_device;
3458 struct MPT3SAS_TARGET *sas_target_priv_data;
3459 unsigned long flags;
3460
3461 spin_lock_irqsave(&ioc->raid_device_lock, flags);
3462 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
3463 if (raid_device && raid_device->starget &&
3464 raid_device->starget->hostdata) {
3465 sas_target_priv_data =
3466 raid_device->starget->hostdata;
3467 sas_target_priv_data->deleted = 1;
3468 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3469 "setting delete flag: handle(0x%04x), "
3470 "wwid(0x%016llx)\n", ioc->name, handle,
3471 (unsigned long long) raid_device->wwid));
3472 }
3473 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
3474}
3475
3476/**
3477 * _scsih_set_volume_handle_for_tr - set handle for target reset to volume
3478 * @handle: input handle
3479 * @a: handle for volume a
3480 * @b: handle for volume b
3481 *
3482 * IR firmware only supports two raid volumes. The purpose of this
3483 * routine is to set the volume handle in either a or b. When the given
3484 * input handle is non-zero, or when a and b have not been set before.
3485 */
3486static void
3487_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b)
3488{
3489 if (!handle || handle == *a || handle == *b)
3490 return;
3491 if (!*a)
3492 *a = handle;
3493 else if (!*b)
3494 *b = handle;
3495}
3496
3497/**
3498 * _scsih_check_ir_config_unhide_events - check for UNHIDE events
3499 * @ioc: per adapter object
3500 * @event_data: the event data payload
3501 * Context: interrupt time.
3502 *
3503 * This routine will send target reset to volume, followed by target
3504 * resets to the PDs. This is called when a PD has been removed, or
3505 * volume has been deleted or removed. When the target reset is sent
3506 * to volume, the PD target resets need to be queued to start upon
3507 * completion of the volume target reset.
3508 *
3509 * Return nothing.
3510 */
3511static void
3512_scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc,
3513 Mpi2EventDataIrConfigChangeList_t *event_data)
3514{
3515 Mpi2EventIrConfigElement_t *element;
3516 int i;
3517 u16 handle, volume_handle, a, b;
3518 struct _tr_list *delayed_tr;
3519
3520 a = 0;
3521 b = 0;
3522
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303523 if (ioc->is_warpdrive)
3524 return;
3525
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303526 /* Volume Resets for Deleted or Removed */
3527 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3528 for (i = 0; i < event_data->NumElements; i++, element++) {
3529 if (le32_to_cpu(event_data->Flags) &
3530 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3531 continue;
3532 if (element->ReasonCode ==
3533 MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED ||
3534 element->ReasonCode ==
3535 MPI2_EVENT_IR_CHANGE_RC_REMOVED) {
3536 volume_handle = le16_to_cpu(element->VolDevHandle);
3537 _scsih_set_volume_delete_flag(ioc, volume_handle);
3538 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3539 }
3540 }
3541
3542 /* Volume Resets for UNHIDE events */
3543 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3544 for (i = 0; i < event_data->NumElements; i++, element++) {
3545 if (le32_to_cpu(event_data->Flags) &
3546 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
3547 continue;
3548 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) {
3549 volume_handle = le16_to_cpu(element->VolDevHandle);
3550 _scsih_set_volume_handle_for_tr(volume_handle, &a, &b);
3551 }
3552 }
3553
3554 if (a)
3555 _scsih_tm_tr_volume_send(ioc, a);
3556 if (b)
3557 _scsih_tm_tr_volume_send(ioc, b);
3558
3559 /* PD target resets */
3560 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
3561 for (i = 0; i < event_data->NumElements; i++, element++) {
3562 if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE)
3563 continue;
3564 handle = le16_to_cpu(element->PhysDiskDevHandle);
3565 volume_handle = le16_to_cpu(element->VolDevHandle);
3566 clear_bit(handle, ioc->pd_handles);
3567 if (!volume_handle)
3568 _scsih_tm_tr_send(ioc, handle);
3569 else if (volume_handle == a || volume_handle == b) {
3570 delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC);
3571 BUG_ON(!delayed_tr);
3572 INIT_LIST_HEAD(&delayed_tr->list);
3573 delayed_tr->handle = handle;
3574 list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list);
3575 dewtprintk(ioc, pr_info(MPT3SAS_FMT
3576 "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name,
3577 handle));
3578 } else
3579 _scsih_tm_tr_send(ioc, handle);
3580 }
3581}
3582
3583
3584/**
3585 * _scsih_check_volume_delete_events - set delete flag for volumes
3586 * @ioc: per adapter object
3587 * @event_data: the event data payload
3588 * Context: interrupt time.
3589 *
3590 * This will handle the case when the cable connected to entire volume is
3591 * pulled. We will take care of setting the deleted flag so normal IO will
3592 * not be sent.
3593 *
3594 * Return nothing.
3595 */
3596static void
3597_scsih_check_volume_delete_events(struct MPT3SAS_ADAPTER *ioc,
3598 Mpi2EventDataIrVolume_t *event_data)
3599{
3600 u32 state;
3601
3602 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
3603 return;
3604 state = le32_to_cpu(event_data->NewValue);
3605 if (state == MPI2_RAID_VOL_STATE_MISSING || state ==
3606 MPI2_RAID_VOL_STATE_FAILED)
3607 _scsih_set_volume_delete_flag(ioc,
3608 le16_to_cpu(event_data->VolDevHandle));
3609}
3610
3611/**
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05303612 * _scsih_temp_threshold_events - display temperature threshold exceeded events
3613 * @ioc: per adapter object
3614 * @event_data: the temp threshold event data
3615 * Context: interrupt time.
3616 *
3617 * Return nothing.
3618 */
3619static void
3620_scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc,
3621 Mpi2EventDataTemperature_t *event_data)
3622{
3623 if (ioc->temp_sensors_count >= event_data->SensorNum) {
3624 pr_err(MPT3SAS_FMT "Temperature Threshold flags %s%s%s%s"
3625 " exceeded for Sensor: %d !!!\n", ioc->name,
3626 ((le16_to_cpu(event_data->Status) & 0x1) == 1) ? "0 " : " ",
3627 ((le16_to_cpu(event_data->Status) & 0x2) == 2) ? "1 " : " ",
3628 ((le16_to_cpu(event_data->Status) & 0x4) == 4) ? "2 " : " ",
3629 ((le16_to_cpu(event_data->Status) & 0x8) == 8) ? "3 " : " ",
3630 event_data->SensorNum);
3631 pr_err(MPT3SAS_FMT "Current Temp In Celsius: %d\n",
3632 ioc->name, event_data->CurrentTemperature);
3633 }
3634}
3635
3636/**
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303637 * _scsih_flush_running_cmds - completing outstanding commands.
3638 * @ioc: per adapter object
3639 *
3640 * The flushing out of all pending scmd commands following host reset,
3641 * where all IO is dropped to the floor.
3642 *
3643 * Return nothing.
3644 */
3645static void
3646_scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
3647{
3648 struct scsi_cmnd *scmd;
3649 u16 smid;
3650 u16 count = 0;
3651
3652 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
3653 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
3654 if (!scmd)
3655 continue;
3656 count++;
3657 mpt3sas_base_free_smid(ioc, smid);
3658 scsi_dma_unmap(scmd);
3659 if (ioc->pci_error_recovery)
3660 scmd->result = DID_NO_CONNECT << 16;
3661 else
3662 scmd->result = DID_RESET << 16;
3663 scmd->scsi_done(scmd);
3664 }
3665 dtmprintk(ioc, pr_info(MPT3SAS_FMT "completing %d cmds\n",
3666 ioc->name, count));
3667}
3668
3669/**
3670 * _scsih_setup_eedp - setup MPI request for EEDP transfer
3671 * @ioc: per adapter object
3672 * @scmd: pointer to scsi command object
3673 * @mpi_request: pointer to the SCSI_IO reqest message frame
3674 *
3675 * Supporting protection 1 and 3.
3676 *
3677 * Returns nothing
3678 */
3679static void
3680_scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
3681 Mpi2SCSIIORequest_t *mpi_request)
3682{
3683 u16 eedp_flags;
3684 unsigned char prot_op = scsi_get_prot_op(scmd);
3685 unsigned char prot_type = scsi_get_prot_type(scmd);
3686 Mpi25SCSIIORequest_t *mpi_request_3v =
3687 (Mpi25SCSIIORequest_t *)mpi_request;
3688
3689 if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL)
3690 return;
3691
3692 if (prot_op == SCSI_PROT_READ_STRIP)
3693 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP;
3694 else if (prot_op == SCSI_PROT_WRITE_INSERT)
3695 eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP;
3696 else
3697 return;
3698
3699 switch (prot_type) {
3700 case SCSI_PROT_DIF_TYPE1:
3701 case SCSI_PROT_DIF_TYPE2:
3702
3703 /*
3704 * enable ref/guard checking
3705 * auto increment ref tag
3706 */
3707 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG |
3708 MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG |
3709 MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
3710 mpi_request->CDB.EEDP32.PrimaryReferenceTag =
3711 cpu_to_be32(scsi_get_lba(scmd));
3712 break;
3713
3714 case SCSI_PROT_DIF_TYPE3:
3715
3716 /*
3717 * enable guard checking
3718 */
3719 eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD;
3720
3721 break;
3722 }
3723
3724 mpi_request_3v->EEDPBlockSize =
3725 cpu_to_le16(scmd->device->sector_size);
3726 mpi_request->EEDPFlags = cpu_to_le16(eedp_flags);
3727}
3728
3729/**
3730 * _scsih_eedp_error_handling - return sense code for EEDP errors
3731 * @scmd: pointer to scsi command object
3732 * @ioc_status: ioc status
3733 *
3734 * Returns nothing
3735 */
3736static void
3737_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
3738{
3739 u8 ascq;
3740
3741 switch (ioc_status) {
3742 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
3743 ascq = 0x01;
3744 break;
3745 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
3746 ascq = 0x02;
3747 break;
3748 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
3749 ascq = 0x03;
3750 break;
3751 default:
3752 ascq = 0x00;
3753 break;
3754 }
3755 scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10,
3756 ascq);
3757 scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) |
3758 SAM_STAT_CHECK_CONDITION;
3759}
3760
3761
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303762
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303763/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05303764 * scsih_qcmd - main scsi request entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303765 * @scmd: pointer to scsi command object
3766 * @done: function pointer to be invoked on completion
3767 *
3768 * The callback index is set inside `ioc->scsi_io_cb_idx`.
3769 *
3770 * Returns 0 on success. If there's a failure, return either:
3771 * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
3772 * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
3773 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05303774int
3775scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303776{
Matthew Wilcoxd8bfbd82014-03-27 16:40:31 -04003777 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303778 struct MPT3SAS_DEVICE *sas_device_priv_data;
3779 struct MPT3SAS_TARGET *sas_target_priv_data;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303780#ifdef SCSI_MPT2SAS
3781 struct _raid_device *raid_device;
3782#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303783 Mpi2SCSIIORequest_t *mpi_request;
3784 u32 mpi_control;
3785 u16 smid;
3786 u16 handle;
3787
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303788 if (ioc->logging_level & MPT_DEBUG_SCSI)
3789 scsi_print_command(scmd);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303790
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303791 sas_device_priv_data = scmd->device->hostdata;
3792 if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
3793 scmd->result = DID_NO_CONNECT << 16;
3794 scmd->scsi_done(scmd);
3795 return 0;
3796 }
3797
3798 if (ioc->pci_error_recovery || ioc->remove_host) {
3799 scmd->result = DID_NO_CONNECT << 16;
3800 scmd->scsi_done(scmd);
3801 return 0;
3802 }
3803
3804 sas_target_priv_data = sas_device_priv_data->sas_target;
3805
3806 /* invalid device handle */
3807 handle = sas_target_priv_data->handle;
3808 if (handle == MPT3SAS_INVALID_DEVICE_HANDLE) {
3809 scmd->result = DID_NO_CONNECT << 16;
3810 scmd->scsi_done(scmd);
3811 return 0;
3812 }
3813
3814
3815 /* host recovery or link resets sent via IOCTLs */
3816 if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress)
3817 return SCSI_MLQUEUE_HOST_BUSY;
3818
3819 /* device has been deleted */
3820 else if (sas_target_priv_data->deleted) {
3821 scmd->result = DID_NO_CONNECT << 16;
3822 scmd->scsi_done(scmd);
3823 return 0;
3824 /* device busy with task managment */
3825 } else if (sas_target_priv_data->tm_busy ||
3826 sas_device_priv_data->block)
3827 return SCSI_MLQUEUE_DEVICE_BUSY;
3828
3829 if (scmd->sc_data_direction == DMA_FROM_DEVICE)
3830 mpi_control = MPI2_SCSIIO_CONTROL_READ;
3831 else if (scmd->sc_data_direction == DMA_TO_DEVICE)
3832 mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
3833 else
3834 mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
3835
3836 /* set tags */
Christoph Hellwig609aa222014-10-30 11:54:58 +01003837 mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303838
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303839 /* Make sure Device is not raid volume.
3840 * We do not expose raid functionality to upper layer for warpdrive.
3841 */
3842 if (!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev)
3843 && (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303844 scmd->cmd_len != 32)
3845 mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
3846
3847 smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
3848 if (!smid) {
3849 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
3850 ioc->name, __func__);
3851 goto out;
3852 }
3853 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
3854 memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
3855 _scsih_setup_eedp(ioc, scmd, mpi_request);
3856
3857 if (scmd->cmd_len == 32)
3858 mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT;
3859 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
3860 if (sas_device_priv_data->sas_target->flags &
3861 MPT_TARGET_FLAGS_RAID_COMPONENT)
3862 mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
3863 else
3864 mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
3865 mpi_request->DevHandle = cpu_to_le16(handle);
3866 mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
3867 mpi_request->Control = cpu_to_le32(mpi_control);
3868 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
3869 mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
3870 mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
3871 mpi_request->SenseBufferLowAddress =
3872 mpt3sas_base_get_sense_buffer_dma(ioc, smid);
3873 mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
3874 int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
3875 mpi_request->LUN);
3876 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
3877
3878 if (mpi_request->DataLength) {
3879 if (ioc->build_sg_scmd(ioc, scmd, smid)) {
3880 mpt3sas_base_free_smid(ioc, smid);
3881 goto out;
3882 }
3883 } else
3884 ioc->build_zero_len_sge(ioc, &mpi_request->SGL);
3885
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303886#ifdef SCSI_MPT2SAS
3887 raid_device = sas_target_priv_data->raid_device;
3888 if (raid_device && raid_device->direct_io_enabled)
3889 _scsih_setup_direct_io(ioc, scmd, raid_device, mpi_request,
3890 smid);
3891#endif
3892
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303893 if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) {
Sreekanth Reddy45506042015-11-11 17:30:25 +05303894#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303895 if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
3896 mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len |
3897 MPI25_SCSIIO_IOFLAGS_FAST_PATH);
3898 mpt3sas_base_put_smid_fast_path(ioc, smid, handle);
3899 } else
Sreekanth Reddy45506042015-11-11 17:30:25 +05303900#endif
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303901 mpt3sas_base_put_smid_scsi_io(ioc, smid,
3902 le16_to_cpu(mpi_request->DevHandle));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303903 } else
3904 mpt3sas_base_put_smid_default(ioc, smid);
3905 return 0;
3906
3907 out:
3908 return SCSI_MLQUEUE_HOST_BUSY;
3909}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303910
3911/**
3912 * _scsih_normalize_sense - normalize descriptor and fixed format sense data
3913 * @sense_buffer: sense data returned by target
3914 * @data: normalized skey/asc/ascq
3915 *
3916 * Return nothing.
3917 */
3918static void
3919_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
3920{
3921 if ((sense_buffer[0] & 0x7F) >= 0x72) {
3922 /* descriptor format */
3923 data->skey = sense_buffer[1] & 0x0F;
3924 data->asc = sense_buffer[2];
3925 data->ascq = sense_buffer[3];
3926 } else {
3927 /* fixed format */
3928 data->skey = sense_buffer[2] & 0x0F;
3929 data->asc = sense_buffer[12];
3930 data->ascq = sense_buffer[13];
3931 }
3932}
3933
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303934/**
3935 * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
3936 * @ioc: per adapter object
3937 * @scmd: pointer to scsi command object
3938 * @mpi_reply: reply mf payload returned from firmware
3939 *
3940 * scsi_status - SCSI Status code returned from target device
3941 * scsi_state - state info associated with SCSI_IO determined by ioc
3942 * ioc_status - ioc supplied status info
3943 *
3944 * Return nothing.
3945 */
3946static void
3947_scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
3948 Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
3949{
3950 u32 response_info;
3951 u8 *response_bytes;
3952 u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
3953 MPI2_IOCSTATUS_MASK;
3954 u8 scsi_state = mpi_reply->SCSIState;
3955 u8 scsi_status = mpi_reply->SCSIStatus;
3956 char *desc_ioc_state = NULL;
3957 char *desc_scsi_status = NULL;
3958 char *desc_scsi_state = ioc->tmp_string;
3959 u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
3960 struct _sas_device *sas_device = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303961 struct scsi_target *starget = scmd->device->sdev_target;
3962 struct MPT3SAS_TARGET *priv_target = starget->hostdata;
3963 char *device_str = NULL;
3964
3965 if (!priv_target)
3966 return;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05303967 if (ioc->hide_ir_msg)
3968 device_str = "WarpDrive";
3969 else
3970 device_str = "volume";
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05303971
3972 if (log_info == 0x31170000)
3973 return;
3974
3975 switch (ioc_status) {
3976 case MPI2_IOCSTATUS_SUCCESS:
3977 desc_ioc_state = "success";
3978 break;
3979 case MPI2_IOCSTATUS_INVALID_FUNCTION:
3980 desc_ioc_state = "invalid function";
3981 break;
3982 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
3983 desc_ioc_state = "scsi recovered error";
3984 break;
3985 case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
3986 desc_ioc_state = "scsi invalid dev handle";
3987 break;
3988 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
3989 desc_ioc_state = "scsi device not there";
3990 break;
3991 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
3992 desc_ioc_state = "scsi data overrun";
3993 break;
3994 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
3995 desc_ioc_state = "scsi data underrun";
3996 break;
3997 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
3998 desc_ioc_state = "scsi io data error";
3999 break;
4000 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4001 desc_ioc_state = "scsi protocol error";
4002 break;
4003 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4004 desc_ioc_state = "scsi task terminated";
4005 break;
4006 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4007 desc_ioc_state = "scsi residual mismatch";
4008 break;
4009 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4010 desc_ioc_state = "scsi task mgmt failed";
4011 break;
4012 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4013 desc_ioc_state = "scsi ioc terminated";
4014 break;
4015 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4016 desc_ioc_state = "scsi ext terminated";
4017 break;
4018 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4019 desc_ioc_state = "eedp guard error";
4020 break;
4021 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4022 desc_ioc_state = "eedp ref tag error";
4023 break;
4024 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4025 desc_ioc_state = "eedp app tag error";
4026 break;
4027 default:
4028 desc_ioc_state = "unknown";
4029 break;
4030 }
4031
4032 switch (scsi_status) {
4033 case MPI2_SCSI_STATUS_GOOD:
4034 desc_scsi_status = "good";
4035 break;
4036 case MPI2_SCSI_STATUS_CHECK_CONDITION:
4037 desc_scsi_status = "check condition";
4038 break;
4039 case MPI2_SCSI_STATUS_CONDITION_MET:
4040 desc_scsi_status = "condition met";
4041 break;
4042 case MPI2_SCSI_STATUS_BUSY:
4043 desc_scsi_status = "busy";
4044 break;
4045 case MPI2_SCSI_STATUS_INTERMEDIATE:
4046 desc_scsi_status = "intermediate";
4047 break;
4048 case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
4049 desc_scsi_status = "intermediate condmet";
4050 break;
4051 case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
4052 desc_scsi_status = "reservation conflict";
4053 break;
4054 case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
4055 desc_scsi_status = "command terminated";
4056 break;
4057 case MPI2_SCSI_STATUS_TASK_SET_FULL:
4058 desc_scsi_status = "task set full";
4059 break;
4060 case MPI2_SCSI_STATUS_ACA_ACTIVE:
4061 desc_scsi_status = "aca active";
4062 break;
4063 case MPI2_SCSI_STATUS_TASK_ABORTED:
4064 desc_scsi_status = "task aborted";
4065 break;
4066 default:
4067 desc_scsi_status = "unknown";
4068 break;
4069 }
4070
4071 desc_scsi_state[0] = '\0';
4072 if (!scsi_state)
4073 desc_scsi_state = " ";
4074 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4075 strcat(desc_scsi_state, "response info ");
4076 if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4077 strcat(desc_scsi_state, "state terminated ");
4078 if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
4079 strcat(desc_scsi_state, "no status ");
4080 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
4081 strcat(desc_scsi_state, "autosense failed ");
4082 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
4083 strcat(desc_scsi_state, "autosense valid ");
4084
4085 scsi_print_command(scmd);
4086
4087 if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
4088 pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
4089 device_str, (unsigned long long)priv_target->sas_address);
4090 } else {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304091 sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304092 if (sas_device) {
4093 pr_warn(MPT3SAS_FMT
4094 "\tsas_address(0x%016llx), phy(%d)\n",
4095 ioc->name, (unsigned long long)
4096 sas_device->sas_address, sas_device->phy);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304097 if (sas_device->enclosure_handle != 0)
4098 pr_warn(MPT3SAS_FMT
4099 "\tenclosure_logical_id(0x%016llx),"
4100 "slot(%d)\n", ioc->name,
4101 (unsigned long long)
4102 sas_device->enclosure_logical_id,
4103 sas_device->slot);
4104 if (sas_device->connector_name[0])
4105 pr_warn(MPT3SAS_FMT
4106 "\tenclosure level(0x%04x),"
4107 " connector name( %s)\n", ioc->name,
4108 sas_device->enclosure_level,
4109 sas_device->connector_name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304110
4111 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304112 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304113 }
4114
4115 pr_warn(MPT3SAS_FMT
4116 "\thandle(0x%04x), ioc_status(%s)(0x%04x), smid(%d)\n",
4117 ioc->name, le16_to_cpu(mpi_reply->DevHandle),
4118 desc_ioc_state, ioc_status, smid);
4119 pr_warn(MPT3SAS_FMT
4120 "\trequest_len(%d), underflow(%d), resid(%d)\n",
4121 ioc->name, scsi_bufflen(scmd), scmd->underflow,
4122 scsi_get_resid(scmd));
4123 pr_warn(MPT3SAS_FMT
4124 "\ttag(%d), transfer_count(%d), sc->result(0x%08x)\n",
4125 ioc->name, le16_to_cpu(mpi_reply->TaskTag),
4126 le32_to_cpu(mpi_reply->TransferCount), scmd->result);
4127 pr_warn(MPT3SAS_FMT
4128 "\tscsi_status(%s)(0x%02x), scsi_state(%s)(0x%02x)\n",
4129 ioc->name, desc_scsi_status,
4130 scsi_status, desc_scsi_state, scsi_state);
4131
4132 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4133 struct sense_info data;
4134 _scsih_normalize_sense(scmd->sense_buffer, &data);
4135 pr_warn(MPT3SAS_FMT
4136 "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n",
4137 ioc->name, data.skey,
4138 data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
4139 }
4140
4141 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
4142 response_info = le32_to_cpu(mpi_reply->ResponseInfo);
4143 response_bytes = (u8 *)&response_info;
4144 _scsih_response_code(ioc, response_bytes[0]);
4145 }
4146}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304147
4148/**
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304149 * _scsih_turn_on_pfa_led - illuminate PFA LED
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304150 * @ioc: per adapter object
4151 * @handle: device handle
4152 * Context: process
4153 *
4154 * Return nothing.
4155 */
4156static void
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304157_scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304158{
4159 Mpi2SepReply_t mpi_reply;
4160 Mpi2SepRequest_t mpi_request;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304161 struct _sas_device *sas_device;
4162
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304163 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304164 if (!sas_device)
4165 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304166
4167 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
4168 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
4169 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
4170 mpi_request.SlotStatus =
4171 cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
4172 mpi_request.DevHandle = cpu_to_le16(handle);
4173 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
4174 if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
4175 &mpi_request)) != 0) {
4176 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
4177 __FILE__, __LINE__, __func__);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304178 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304179 }
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304180 sas_device->pfa_led_on = 1;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304181
4182 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
4183 dewtprintk(ioc, pr_info(MPT3SAS_FMT
4184 "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
4185 ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
4186 le32_to_cpu(mpi_reply.IOCLogInfo)));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304187 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304188 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304189out:
4190 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304191}
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304192
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304193/**
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304194 * _scsih_turn_off_pfa_led - turn off Fault LED
4195 * @ioc: per adapter object
4196 * @sas_device: sas device whose PFA LED has to turned off
4197 * Context: process
4198 *
4199 * Return nothing.
4200 */
4201static void
4202_scsih_turn_off_pfa_led(struct MPT3SAS_ADAPTER *ioc,
4203 struct _sas_device *sas_device)
4204{
4205 Mpi2SepReply_t mpi_reply;
4206 Mpi2SepRequest_t mpi_request;
4207
4208 memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
4209 mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
4210 mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
4211 mpi_request.SlotStatus = 0;
4212 mpi_request.Slot = cpu_to_le16(sas_device->slot);
4213 mpi_request.DevHandle = 0;
4214 mpi_request.EnclosureHandle = cpu_to_le16(sas_device->enclosure_handle);
4215 mpi_request.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS;
4216 if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
4217 &mpi_request)) != 0) {
4218 printk(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name,
4219 __FILE__, __LINE__, __func__);
4220 return;
4221 }
4222
4223 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
4224 dewtprintk(ioc, printk(MPT3SAS_FMT
4225 "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n",
4226 ioc->name, le16_to_cpu(mpi_reply.IOCStatus),
4227 le32_to_cpu(mpi_reply.IOCLogInfo)));
4228 return;
4229 }
4230}
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304231
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304232/**
4233 * _scsih_send_event_to_turn_on_pfa_led - fire delayed event
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304234 * @ioc: per adapter object
4235 * @handle: device handle
4236 * Context: interrupt.
4237 *
4238 * Return nothing.
4239 */
4240static void
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304241_scsih_send_event_to_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304242{
4243 struct fw_event_work *fw_event;
4244
4245 fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
4246 if (!fw_event)
4247 return;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304248 fw_event->event = MPT3SAS_TURN_ON_PFA_LED;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304249 fw_event->device_handle = handle;
4250 fw_event->ioc = ioc;
4251 _scsih_fw_event_add(ioc, fw_event);
4252}
4253
4254/**
4255 * _scsih_smart_predicted_fault - process smart errors
4256 * @ioc: per adapter object
4257 * @handle: device handle
4258 * Context: interrupt.
4259 *
4260 * Return nothing.
4261 */
4262static void
4263_scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle)
4264{
4265 struct scsi_target *starget;
4266 struct MPT3SAS_TARGET *sas_target_priv_data;
4267 Mpi2EventNotificationReply_t *event_reply;
4268 Mpi2EventDataSasDeviceStatusChange_t *event_data;
4269 struct _sas_device *sas_device;
4270 ssize_t sz;
4271 unsigned long flags;
4272
4273 /* only handle non-raid devices */
4274 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304275 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
4276 if (!sas_device)
4277 goto out_unlock;
4278
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304279 starget = sas_device->starget;
4280 sas_target_priv_data = starget->hostdata;
4281
4282 if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304283 ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)))
4284 goto out_unlock;
4285
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304286 if (sas_device->enclosure_handle != 0)
4287 starget_printk(KERN_INFO, starget, "predicted fault, "
4288 "enclosure logical id(0x%016llx), slot(%d)\n",
4289 (unsigned long long)sas_device->enclosure_logical_id,
4290 sas_device->slot);
4291 if (sas_device->connector_name[0] != '\0')
4292 starget_printk(KERN_WARNING, starget, "predicted fault, "
4293 "enclosure level(0x%04x), connector name( %s)\n",
4294 sas_device->enclosure_level,
4295 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304296 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4297
4298 if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05304299 _scsih_send_event_to_turn_on_pfa_led(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304300
4301 /* insert into event log */
4302 sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
4303 sizeof(Mpi2EventDataSasDeviceStatusChange_t);
4304 event_reply = kzalloc(sz, GFP_KERNEL);
4305 if (!event_reply) {
4306 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4307 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304308 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304309 }
4310
4311 event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
4312 event_reply->Event =
4313 cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
4314 event_reply->MsgLength = sz/4;
4315 event_reply->EventDataLength =
4316 cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
4317 event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
4318 event_reply->EventData;
4319 event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
4320 event_data->ASC = 0x5D;
4321 event_data->DevHandle = cpu_to_le16(handle);
4322 event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
4323 mpt3sas_ctl_add_to_event_log(ioc, event_reply);
4324 kfree(event_reply);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05304325out:
4326 if (sas_device)
4327 sas_device_put(sas_device);
4328 return;
4329
4330out_unlock:
4331 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
4332 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304333}
4334
4335/**
4336 * _scsih_io_done - scsi request callback
4337 * @ioc: per adapter object
4338 * @smid: system request message index
4339 * @msix_index: MSIX table index supplied by the OS
4340 * @reply: reply message frame(lower 32bit addr)
4341 *
4342 * Callback handler when using _scsih_qcmd.
4343 *
4344 * Return 1 meaning mf should be freed from _base_interrupt
4345 * 0 means the mf is freed from this function.
4346 */
4347static u8
4348_scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4349{
4350 Mpi2SCSIIORequest_t *mpi_request;
4351 Mpi2SCSIIOReply_t *mpi_reply;
4352 struct scsi_cmnd *scmd;
4353 u16 ioc_status;
4354 u32 xfer_cnt;
4355 u8 scsi_state;
4356 u8 scsi_status;
4357 u32 log_info;
4358 struct MPT3SAS_DEVICE *sas_device_priv_data;
4359 u32 response_code = 0;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304360#ifdef SCSI_MPT2SAS
4361 unsigned long flags;
4362#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304363
4364 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
4365 scmd = _scsih_scsi_lookup_get_clear(ioc, smid);
4366 if (scmd == NULL)
4367 return 1;
4368
4369 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
4370
4371 if (mpi_reply == NULL) {
4372 scmd->result = DID_OK << 16;
4373 goto out;
4374 }
4375
4376 sas_device_priv_data = scmd->device->hostdata;
4377 if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
4378 sas_device_priv_data->sas_target->deleted) {
4379 scmd->result = DID_NO_CONNECT << 16;
4380 goto out;
4381 }
4382 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
4383
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304384#ifdef SCSI_MPT2SAS
4385 /*
4386 * WARPDRIVE: If direct_io is set then it is directIO,
4387 * the failed direct I/O should be redirected to volume
4388 */
4389 if (_scsih_scsi_direct_io_get(ioc, smid) &&
4390 ((ioc_status & MPI2_IOCSTATUS_MASK)
4391 != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) {
4392 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
4393 ioc->scsi_lookup[smid - 1].scmd = scmd;
4394 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
4395 _scsih_scsi_direct_io_set(ioc, smid, 0);
4396 memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
4397 mpi_request->DevHandle =
4398 cpu_to_le16(sas_device_priv_data->sas_target->handle);
4399 mpt3sas_base_put_smid_scsi_io(ioc, smid,
4400 sas_device_priv_data->sas_target->handle);
4401 return 0;
4402 }
4403#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304404 /* turning off TLR */
4405 scsi_state = mpi_reply->SCSIState;
4406 if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
4407 response_code =
4408 le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
4409 if (!sas_device_priv_data->tlr_snoop_check) {
4410 sas_device_priv_data->tlr_snoop_check++;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05304411 if (!ioc->is_warpdrive &&
4412 !scsih_is_raid(&scmd->device->sdev_gendev) &&
4413 (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) &&
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304414 response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME)
4415 sas_device_priv_data->flags &=
4416 ~MPT_DEVICE_TLR_ON;
4417 }
4418
4419 xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
4420 scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
4421 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
4422 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
4423 else
4424 log_info = 0;
4425 ioc_status &= MPI2_IOCSTATUS_MASK;
4426 scsi_status = mpi_reply->SCSIStatus;
4427
4428 if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
4429 (scsi_status == MPI2_SCSI_STATUS_BUSY ||
4430 scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
4431 scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
4432 ioc_status = MPI2_IOCSTATUS_SUCCESS;
4433 }
4434
4435 if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
4436 struct sense_info data;
4437 const void *sense_data = mpt3sas_base_get_sense_buffer(ioc,
4438 smid);
4439 u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
4440 le32_to_cpu(mpi_reply->SenseCount));
4441 memcpy(scmd->sense_buffer, sense_data, sz);
4442 _scsih_normalize_sense(scmd->sense_buffer, &data);
4443 /* failure prediction threshold exceeded */
4444 if (data.asc == 0x5D)
4445 _scsih_smart_predicted_fault(ioc,
4446 le16_to_cpu(mpi_reply->DevHandle));
4447 mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304448
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304449 if (!(ioc->logging_level & MPT_DEBUG_REPLY) &&
4450 ((scmd->sense_buffer[2] == UNIT_ATTENTION) ||
4451 (scmd->sense_buffer[2] == MEDIUM_ERROR) ||
4452 (scmd->sense_buffer[2] == HARDWARE_ERROR)))
4453 _scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05304454 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304455 switch (ioc_status) {
4456 case MPI2_IOCSTATUS_BUSY:
4457 case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
4458 scmd->result = SAM_STAT_BUSY;
4459 break;
4460
4461 case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4462 scmd->result = DID_NO_CONNECT << 16;
4463 break;
4464
4465 case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
4466 if (sas_device_priv_data->block) {
4467 scmd->result = DID_TRANSPORT_DISRUPTED << 16;
4468 goto out;
4469 }
4470 if (log_info == 0x31110630) {
4471 if (scmd->retries > 2) {
4472 scmd->result = DID_NO_CONNECT << 16;
4473 scsi_device_set_state(scmd->device,
4474 SDEV_OFFLINE);
4475 } else {
4476 scmd->result = DID_SOFT_ERROR << 16;
4477 scmd->device->expecting_cc_ua = 1;
4478 }
4479 break;
Sreekanth Reddy3898f082015-06-30 12:25:00 +05304480 } else if (log_info == VIRTUAL_IO_FAILED_RETRY) {
4481 scmd->result = DID_RESET << 16;
4482 break;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304483 }
4484 scmd->result = DID_SOFT_ERROR << 16;
4485 break;
4486 case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
4487 case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
4488 scmd->result = DID_RESET << 16;
4489 break;
4490
4491 case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
4492 if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
4493 scmd->result = DID_SOFT_ERROR << 16;
4494 else
4495 scmd->result = (DID_OK << 16) | scsi_status;
4496 break;
4497
4498 case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
4499 scmd->result = (DID_OK << 16) | scsi_status;
4500
4501 if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
4502 break;
4503
4504 if (xfer_cnt < scmd->underflow) {
4505 if (scsi_status == SAM_STAT_BUSY)
4506 scmd->result = SAM_STAT_BUSY;
4507 else
4508 scmd->result = DID_SOFT_ERROR << 16;
4509 } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4510 MPI2_SCSI_STATE_NO_SCSI_STATUS))
4511 scmd->result = DID_SOFT_ERROR << 16;
4512 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4513 scmd->result = DID_RESET << 16;
4514 else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
4515 mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
4516 mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
4517 scmd->result = (DRIVER_SENSE << 24) |
4518 SAM_STAT_CHECK_CONDITION;
4519 scmd->sense_buffer[0] = 0x70;
4520 scmd->sense_buffer[2] = ILLEGAL_REQUEST;
4521 scmd->sense_buffer[12] = 0x20;
4522 scmd->sense_buffer[13] = 0;
4523 }
4524 break;
4525
4526 case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
4527 scsi_set_resid(scmd, 0);
4528 case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
4529 case MPI2_IOCSTATUS_SUCCESS:
4530 scmd->result = (DID_OK << 16) | scsi_status;
4531 if (response_code ==
4532 MPI2_SCSITASKMGMT_RSP_INVALID_FRAME ||
4533 (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
4534 MPI2_SCSI_STATE_NO_SCSI_STATUS)))
4535 scmd->result = DID_SOFT_ERROR << 16;
4536 else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
4537 scmd->result = DID_RESET << 16;
4538 break;
4539
4540 case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
4541 case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
4542 case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
4543 _scsih_eedp_error_handling(scmd, ioc_status);
4544 break;
4545
4546 case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
4547 case MPI2_IOCSTATUS_INVALID_FUNCTION:
4548 case MPI2_IOCSTATUS_INVALID_SGL:
4549 case MPI2_IOCSTATUS_INTERNAL_ERROR:
4550 case MPI2_IOCSTATUS_INVALID_FIELD:
4551 case MPI2_IOCSTATUS_INVALID_STATE:
4552 case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
4553 case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
4554 default:
4555 scmd->result = DID_SOFT_ERROR << 16;
4556 break;
4557
4558 }
4559
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304560 if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
4561 _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05304562
4563 out:
4564
4565 scsi_dma_unmap(scmd);
4566
4567 scmd->scsi_done(scmd);
4568 return 1;
4569}
4570
4571/**
4572 * _scsih_sas_host_refresh - refreshing sas host object contents
4573 * @ioc: per adapter object
4574 * Context: user
4575 *
4576 * During port enable, fw will send topology events for every device. Its
4577 * possible that the handles may change from the previous setting, so this
4578 * code keeping handles updating if changed.
4579 *
4580 * Return nothing.
4581 */
4582static void
4583_scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc)
4584{
4585 u16 sz;
4586 u16 ioc_status;
4587 int i;
4588 Mpi2ConfigReply_t mpi_reply;
4589 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4590 u16 attached_handle;
4591 u8 link_rate;
4592
4593 dtmprintk(ioc, pr_info(MPT3SAS_FMT
4594 "updating handles for sas_host(0x%016llx)\n",
4595 ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
4596
4597 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
4598 * sizeof(Mpi2SasIOUnit0PhyData_t));
4599 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4600 if (!sas_iounit_pg0) {
4601 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4602 ioc->name, __FILE__, __LINE__, __func__);
4603 return;
4604 }
4605
4606 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4607 sas_iounit_pg0, sz)) != 0)
4608 goto out;
4609 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
4610 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
4611 goto out;
4612 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
4613 link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4;
4614 if (i == 0)
4615 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4616 PhyData[0].ControllerDevHandle);
4617 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4618 attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i].
4619 AttachedDevHandle);
4620 if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
4621 link_rate = MPI2_SAS_NEG_LINK_RATE_1_5;
4622 mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address,
4623 attached_handle, i, link_rate);
4624 }
4625 out:
4626 kfree(sas_iounit_pg0);
4627}
4628
4629/**
4630 * _scsih_sas_host_add - create sas host object
4631 * @ioc: per adapter object
4632 *
4633 * Creating host side data object, stored in ioc->sas_hba
4634 *
4635 * Return nothing.
4636 */
4637static void
4638_scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc)
4639{
4640 int i;
4641 Mpi2ConfigReply_t mpi_reply;
4642 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
4643 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
4644 Mpi2SasPhyPage0_t phy_pg0;
4645 Mpi2SasDevicePage0_t sas_device_pg0;
4646 Mpi2SasEnclosurePage0_t enclosure_pg0;
4647 u16 ioc_status;
4648 u16 sz;
4649 u8 device_missing_delay;
4650
4651 mpt3sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
4652 if (!ioc->sas_hba.num_phys) {
4653 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4654 ioc->name, __FILE__, __LINE__, __func__);
4655 return;
4656 }
4657
4658 /* sas_iounit page 0 */
4659 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
4660 sizeof(Mpi2SasIOUnit0PhyData_t));
4661 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
4662 if (!sas_iounit_pg0) {
4663 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4664 ioc->name, __FILE__, __LINE__, __func__);
4665 return;
4666 }
4667 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
4668 sas_iounit_pg0, sz))) {
4669 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4670 ioc->name, __FILE__, __LINE__, __func__);
4671 goto out;
4672 }
4673 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4674 MPI2_IOCSTATUS_MASK;
4675 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4676 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4677 ioc->name, __FILE__, __LINE__, __func__);
4678 goto out;
4679 }
4680
4681 /* sas_iounit page 1 */
4682 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
4683 sizeof(Mpi2SasIOUnit1PhyData_t));
4684 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
4685 if (!sas_iounit_pg1) {
4686 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4687 ioc->name, __FILE__, __LINE__, __func__);
4688 goto out;
4689 }
4690 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
4691 sas_iounit_pg1, sz))) {
4692 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4693 ioc->name, __FILE__, __LINE__, __func__);
4694 goto out;
4695 }
4696 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4697 MPI2_IOCSTATUS_MASK;
4698 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4699 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4700 ioc->name, __FILE__, __LINE__, __func__);
4701 goto out;
4702 }
4703
4704 ioc->io_missing_delay =
4705 sas_iounit_pg1->IODeviceMissingDelay;
4706 device_missing_delay =
4707 sas_iounit_pg1->ReportDeviceMissingDelay;
4708 if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
4709 ioc->device_missing_delay = (device_missing_delay &
4710 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
4711 else
4712 ioc->device_missing_delay = device_missing_delay &
4713 MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
4714
4715 ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
4716 ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
4717 sizeof(struct _sas_phy), GFP_KERNEL);
4718 if (!ioc->sas_hba.phy) {
4719 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4720 ioc->name, __FILE__, __LINE__, __func__);
4721 goto out;
4722 }
4723 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
4724 if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
4725 i))) {
4726 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4727 ioc->name, __FILE__, __LINE__, __func__);
4728 goto out;
4729 }
4730 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4731 MPI2_IOCSTATUS_MASK;
4732 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4733 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4734 ioc->name, __FILE__, __LINE__, __func__);
4735 goto out;
4736 }
4737
4738 if (i == 0)
4739 ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0->
4740 PhyData[0].ControllerDevHandle);
4741 ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle;
4742 ioc->sas_hba.phy[i].phy_id = i;
4743 mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
4744 phy_pg0, ioc->sas_hba.parent_dev);
4745 }
4746 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
4747 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) {
4748 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4749 ioc->name, __FILE__, __LINE__, __func__);
4750 goto out;
4751 }
4752 ioc->sas_hba.enclosure_handle =
4753 le16_to_cpu(sas_device_pg0.EnclosureHandle);
4754 ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
4755 pr_info(MPT3SAS_FMT
4756 "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n",
4757 ioc->name, ioc->sas_hba.handle,
4758 (unsigned long long) ioc->sas_hba.sas_address,
4759 ioc->sas_hba.num_phys) ;
4760
4761 if (ioc->sas_hba.enclosure_handle) {
4762 if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
4763 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4764 ioc->sas_hba.enclosure_handle)))
4765 ioc->sas_hba.enclosure_logical_id =
4766 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4767 }
4768
4769 out:
4770 kfree(sas_iounit_pg1);
4771 kfree(sas_iounit_pg0);
4772}
4773
4774/**
4775 * _scsih_expander_add - creating expander object
4776 * @ioc: per adapter object
4777 * @handle: expander handle
4778 *
4779 * Creating expander object, stored in ioc->sas_expander_list.
4780 *
4781 * Return 0 for success, else error.
4782 */
4783static int
4784_scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
4785{
4786 struct _sas_node *sas_expander;
4787 Mpi2ConfigReply_t mpi_reply;
4788 Mpi2ExpanderPage0_t expander_pg0;
4789 Mpi2ExpanderPage1_t expander_pg1;
4790 Mpi2SasEnclosurePage0_t enclosure_pg0;
4791 u32 ioc_status;
4792 u16 parent_handle;
4793 u64 sas_address, sas_address_parent = 0;
4794 int i;
4795 unsigned long flags;
4796 struct _sas_port *mpt3sas_port = NULL;
4797
4798 int rc = 0;
4799
4800 if (!handle)
4801 return -1;
4802
4803 if (ioc->shost_recovery || ioc->pci_error_recovery)
4804 return -1;
4805
4806 if ((mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
4807 MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
4808 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4809 ioc->name, __FILE__, __LINE__, __func__);
4810 return -1;
4811 }
4812
4813 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
4814 MPI2_IOCSTATUS_MASK;
4815 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
4816 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4817 ioc->name, __FILE__, __LINE__, __func__);
4818 return -1;
4819 }
4820
4821 /* handle out of order topology events */
4822 parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
4823 if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent)
4824 != 0) {
4825 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4826 ioc->name, __FILE__, __LINE__, __func__);
4827 return -1;
4828 }
4829 if (sas_address_parent != ioc->sas_hba.sas_address) {
4830 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4831 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
4832 sas_address_parent);
4833 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4834 if (!sas_expander) {
4835 rc = _scsih_expander_add(ioc, parent_handle);
4836 if (rc != 0)
4837 return rc;
4838 }
4839 }
4840
4841 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4842 sas_address = le64_to_cpu(expander_pg0.SASAddress);
4843 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
4844 sas_address);
4845 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4846
4847 if (sas_expander)
4848 return 0;
4849
4850 sas_expander = kzalloc(sizeof(struct _sas_node),
4851 GFP_KERNEL);
4852 if (!sas_expander) {
4853 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4854 ioc->name, __FILE__, __LINE__, __func__);
4855 return -1;
4856 }
4857
4858 sas_expander->handle = handle;
4859 sas_expander->num_phys = expander_pg0.NumPhys;
4860 sas_expander->sas_address_parent = sas_address_parent;
4861 sas_expander->sas_address = sas_address;
4862
4863 pr_info(MPT3SAS_FMT "expander_add: handle(0x%04x)," \
4864 " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
4865 handle, parent_handle, (unsigned long long)
4866 sas_expander->sas_address, sas_expander->num_phys);
4867
4868 if (!sas_expander->num_phys)
4869 goto out_fail;
4870 sas_expander->phy = kcalloc(sas_expander->num_phys,
4871 sizeof(struct _sas_phy), GFP_KERNEL);
4872 if (!sas_expander->phy) {
4873 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4874 ioc->name, __FILE__, __LINE__, __func__);
4875 rc = -1;
4876 goto out_fail;
4877 }
4878
4879 INIT_LIST_HEAD(&sas_expander->sas_port_list);
4880 mpt3sas_port = mpt3sas_transport_port_add(ioc, handle,
4881 sas_address_parent);
4882 if (!mpt3sas_port) {
4883 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4884 ioc->name, __FILE__, __LINE__, __func__);
4885 rc = -1;
4886 goto out_fail;
4887 }
4888 sas_expander->parent_dev = &mpt3sas_port->rphy->dev;
4889
4890 for (i = 0 ; i < sas_expander->num_phys ; i++) {
4891 if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
4892 &expander_pg1, i, handle))) {
4893 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4894 ioc->name, __FILE__, __LINE__, __func__);
4895 rc = -1;
4896 goto out_fail;
4897 }
4898 sas_expander->phy[i].handle = handle;
4899 sas_expander->phy[i].phy_id = i;
4900
4901 if ((mpt3sas_transport_add_expander_phy(ioc,
4902 &sas_expander->phy[i], expander_pg1,
4903 sas_expander->parent_dev))) {
4904 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
4905 ioc->name, __FILE__, __LINE__, __func__);
4906 rc = -1;
4907 goto out_fail;
4908 }
4909 }
4910
4911 if (sas_expander->enclosure_handle) {
4912 if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
4913 &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
4914 sas_expander->enclosure_handle)))
4915 sas_expander->enclosure_logical_id =
4916 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
4917 }
4918
4919 _scsih_expander_node_add(ioc, sas_expander);
4920 return 0;
4921
4922 out_fail:
4923
4924 if (mpt3sas_port)
4925 mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
4926 sas_address_parent);
4927 kfree(sas_expander);
4928 return rc;
4929}
4930
4931/**
4932 * mpt3sas_expander_remove - removing expander object
4933 * @ioc: per adapter object
4934 * @sas_address: expander sas_address
4935 *
4936 * Return nothing.
4937 */
4938void
4939mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address)
4940{
4941 struct _sas_node *sas_expander;
4942 unsigned long flags;
4943
4944 if (ioc->shost_recovery)
4945 return;
4946
4947 spin_lock_irqsave(&ioc->sas_node_lock, flags);
4948 sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc,
4949 sas_address);
4950 if (sas_expander)
4951 list_del(&sas_expander->list);
4952 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
4953 if (sas_expander)
4954 _scsih_expander_node_remove(ioc, sas_expander);
4955}
4956
4957/**
4958 * _scsih_done - internal SCSI_IO callback handler.
4959 * @ioc: per adapter object
4960 * @smid: system request message index
4961 * @msix_index: MSIX table index supplied by the OS
4962 * @reply: reply message frame(lower 32bit addr)
4963 *
4964 * Callback handler when sending internal generated SCSI_IO.
4965 * The callback index passed is `ioc->scsih_cb_idx`
4966 *
4967 * Return 1 meaning mf should be freed from _base_interrupt
4968 * 0 means the mf is freed from this function.
4969 */
4970static u8
4971_scsih_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply)
4972{
4973 MPI2DefaultReply_t *mpi_reply;
4974
4975 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
4976 if (ioc->scsih_cmds.status == MPT3_CMD_NOT_USED)
4977 return 1;
4978 if (ioc->scsih_cmds.smid != smid)
4979 return 1;
4980 ioc->scsih_cmds.status |= MPT3_CMD_COMPLETE;
4981 if (mpi_reply) {
4982 memcpy(ioc->scsih_cmds.reply, mpi_reply,
4983 mpi_reply->MsgLength*4);
4984 ioc->scsih_cmds.status |= MPT3_CMD_REPLY_VALID;
4985 }
4986 ioc->scsih_cmds.status &= ~MPT3_CMD_PENDING;
4987 complete(&ioc->scsih_cmds.done);
4988 return 1;
4989}
4990
4991
4992
4993
4994#define MPT3_MAX_LUNS (255)
4995
4996
4997/**
4998 * _scsih_check_access_status - check access flags
4999 * @ioc: per adapter object
5000 * @sas_address: sas address
5001 * @handle: sas device handle
5002 * @access_flags: errors returned during discovery of the device
5003 *
5004 * Return 0 for success, else failure
5005 */
5006static u8
5007_scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
5008 u16 handle, u8 access_status)
5009{
5010 u8 rc = 1;
5011 char *desc = NULL;
5012
5013 switch (access_status) {
5014 case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS:
5015 case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION:
5016 rc = 0;
5017 break;
5018 case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED:
5019 desc = "sata capability failed";
5020 break;
5021 case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT:
5022 desc = "sata affiliation conflict";
5023 break;
5024 case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE:
5025 desc = "route not addressable";
5026 break;
5027 case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE:
5028 desc = "smp error not addressable";
5029 break;
5030 case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED:
5031 desc = "device blocked";
5032 break;
5033 case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED:
5034 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN:
5035 case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT:
5036 case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG:
5037 case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION:
5038 case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER:
5039 case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN:
5040 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN:
5041 case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN:
5042 case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION:
5043 case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE:
5044 case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX:
5045 desc = "sata initialization failed";
5046 break;
5047 default:
5048 desc = "unknown";
5049 break;
5050 }
5051
5052 if (!rc)
5053 return 0;
5054
5055 pr_err(MPT3SAS_FMT
5056 "discovery errors(%s): sas_address(0x%016llx), handle(0x%04x)\n",
5057 ioc->name, desc, (unsigned long long)sas_address, handle);
5058 return rc;
5059}
5060
5061/**
5062 * _scsih_check_device - checking device responsiveness
5063 * @ioc: per adapter object
5064 * @parent_sas_address: sas address of parent expander or sas host
5065 * @handle: attached device handle
5066 * @phy_numberv: phy number
5067 * @link_rate: new link rate
5068 *
5069 * Returns nothing.
5070 */
5071static void
5072_scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
5073 u64 parent_sas_address, u16 handle, u8 phy_number, u8 link_rate)
5074{
5075 Mpi2ConfigReply_t mpi_reply;
5076 Mpi2SasDevicePage0_t sas_device_pg0;
5077 struct _sas_device *sas_device;
5078 u32 ioc_status;
5079 unsigned long flags;
5080 u64 sas_address;
5081 struct scsi_target *starget;
5082 struct MPT3SAS_TARGET *sas_target_priv_data;
5083 u32 device_info;
5084
5085
5086 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5087 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)))
5088 return;
5089
5090 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
5091 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
5092 return;
5093
5094 /* wide port handling ~ we need only handle device once for the phy that
5095 * is matched in sas device page zero
5096 */
5097 if (phy_number != sas_device_pg0.PhyNum)
5098 return;
5099
5100 /* check if this is end device */
5101 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5102 if (!(_scsih_is_end_device(device_info)))
5103 return;
5104
5105 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5106 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305107 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305108 sas_address);
5109
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305110 if (!sas_device)
5111 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305112
5113 if (unlikely(sas_device->handle != handle)) {
5114 starget = sas_device->starget;
5115 sas_target_priv_data = starget->hostdata;
5116 starget_printk(KERN_INFO, starget,
5117 "handle changed from(0x%04x) to (0x%04x)!!!\n",
5118 sas_device->handle, handle);
5119 sas_target_priv_data->handle = handle;
5120 sas_device->handle = handle;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305121 if (sas_device_pg0.Flags &
5122 MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
5123 sas_device->enclosure_level =
5124 le16_to_cpu(sas_device_pg0.EnclosureLevel);
5125 memcpy(&sas_device->connector_name[0],
5126 &sas_device_pg0.ConnectorName[0], 4);
5127 } else {
5128 sas_device->enclosure_level = 0;
5129 sas_device->connector_name[0] = '\0';
5130 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305131 }
5132
5133 /* check if device is present */
5134 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5135 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5136 pr_err(MPT3SAS_FMT
5137 "device is not present handle(0x%04x), flags!!!\n",
5138 ioc->name, handle);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305139 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305140 }
5141
5142 /* check if there were any issues with discovery */
5143 if (_scsih_check_access_status(ioc, sas_address, handle,
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305144 sas_device_pg0.AccessStatus))
5145 goto out_unlock;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305146
5147 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5148 _scsih_ublock_io_device(ioc, sas_address);
5149
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305150 if (sas_device)
5151 sas_device_put(sas_device);
5152 return;
5153
5154out_unlock:
5155 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
5156 if (sas_device)
5157 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305158}
5159
5160/**
5161 * _scsih_add_device - creating sas device object
5162 * @ioc: per adapter object
5163 * @handle: sas device handle
5164 * @phy_num: phy number end device attached to
5165 * @is_pd: is this hidden raid component
5166 *
5167 * Creating end device object, stored in ioc->sas_device_list.
5168 *
5169 * Returns 0 for success, non-zero for failure.
5170 */
5171static int
5172_scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
5173 u8 is_pd)
5174{
5175 Mpi2ConfigReply_t mpi_reply;
5176 Mpi2SasDevicePage0_t sas_device_pg0;
5177 Mpi2SasEnclosurePage0_t enclosure_pg0;
5178 struct _sas_device *sas_device;
5179 u32 ioc_status;
5180 u64 sas_address;
5181 u32 device_info;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305182
5183 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
5184 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
5185 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5186 ioc->name, __FILE__, __LINE__, __func__);
5187 return -1;
5188 }
5189
5190 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
5191 MPI2_IOCSTATUS_MASK;
5192 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5193 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5194 ioc->name, __FILE__, __LINE__, __func__);
5195 return -1;
5196 }
5197
5198 /* check if this is end device */
5199 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
5200 if (!(_scsih_is_end_device(device_info)))
5201 return -1;
5202 sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
5203
5204 /* check if device is present */
5205 if (!(le16_to_cpu(sas_device_pg0.Flags) &
5206 MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
5207 pr_err(MPT3SAS_FMT "device is not present handle(0x04%x)!!!\n",
5208 ioc->name, handle);
5209 return -1;
5210 }
5211
5212 /* check if there were any issues with discovery */
5213 if (_scsih_check_access_status(ioc, sas_address, handle,
5214 sas_device_pg0.AccessStatus))
5215 return -1;
5216
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305217 sas_device = mpt3sas_get_sdev_by_addr(ioc,
5218 sas_address);
5219 if (sas_device) {
5220 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305221 return -1;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305222 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305223
5224 sas_device = kzalloc(sizeof(struct _sas_device),
5225 GFP_KERNEL);
5226 if (!sas_device) {
5227 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5228 ioc->name, __FILE__, __LINE__, __func__);
5229 return 0;
5230 }
5231
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305232 kref_init(&sas_device->refcount);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305233 sas_device->handle = handle;
5234 if (_scsih_get_sas_address(ioc,
5235 le16_to_cpu(sas_device_pg0.ParentDevHandle),
5236 &sas_device->sas_address_parent) != 0)
5237 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
5238 ioc->name, __FILE__, __LINE__, __func__);
5239 sas_device->enclosure_handle =
5240 le16_to_cpu(sas_device_pg0.EnclosureHandle);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305241 if (sas_device->enclosure_handle != 0)
5242 sas_device->slot =
5243 le16_to_cpu(sas_device_pg0.Slot);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305244 sas_device->device_info = device_info;
5245 sas_device->sas_address = sas_address;
5246 sas_device->phy = sas_device_pg0.PhyNum;
Sreekanth Reddy45506042015-11-11 17:30:25 +05305247#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305248 sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) &
5249 MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0;
Sreekanth Reddy45506042015-11-11 17:30:25 +05305250#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305251
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305252 if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
5253 sas_device->enclosure_level =
5254 le16_to_cpu(sas_device_pg0.EnclosureLevel);
5255 memcpy(&sas_device->connector_name[0],
5256 &sas_device_pg0.ConnectorName[0], 4);
5257 } else {
5258 sas_device->enclosure_level = 0;
5259 sas_device->connector_name[0] = '\0';
5260 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305261 /* get enclosure_logical_id */
5262 if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0(
5263 ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
5264 sas_device->enclosure_handle)))
5265 sas_device->enclosure_logical_id =
5266 le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
5267
5268 /* get device name */
5269 sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
5270
5271 if (ioc->wait_for_discovery_to_complete)
5272 _scsih_sas_device_init_add(ioc, sas_device);
5273 else
5274 _scsih_sas_device_add(ioc, sas_device);
5275
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305276 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305277 return 0;
5278}
5279
5280/**
5281 * _scsih_remove_device - removing sas device object
5282 * @ioc: per adapter object
5283 * @sas_device_delete: the sas_device object
5284 *
5285 * Return nothing.
5286 */
5287static void
5288_scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
5289 struct _sas_device *sas_device)
5290{
5291 struct MPT3SAS_TARGET *sas_target_priv_data;
5292
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05305293 if ((ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) &&
5294 (sas_device->pfa_led_on)) {
5295 _scsih_turn_off_pfa_led(ioc, sas_device);
5296 sas_device->pfa_led_on = 0;
5297 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305298 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5299 "%s: enter: handle(0x%04x), sas_addr(0x%016llx)\n",
5300 ioc->name, __func__,
5301 sas_device->handle, (unsigned long long)
5302 sas_device->sas_address));
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305303 if (sas_device->enclosure_handle != 0)
5304 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5305 "%s: enter: enclosure logical id(0x%016llx), slot(%d)\n",
5306 ioc->name, __func__,
5307 (unsigned long long)sas_device->enclosure_logical_id,
5308 sas_device->slot));
5309 if (sas_device->connector_name[0] != '\0')
5310 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5311 "%s: enter: enclosure level(0x%04x), connector name( %s)\n",
5312 ioc->name, __func__,
5313 sas_device->enclosure_level,
5314 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305315
5316 if (sas_device->starget && sas_device->starget->hostdata) {
5317 sas_target_priv_data = sas_device->starget->hostdata;
5318 sas_target_priv_data->deleted = 1;
5319 _scsih_ublock_io_device(ioc, sas_device->sas_address);
5320 sas_target_priv_data->handle =
5321 MPT3SAS_INVALID_DEVICE_HANDLE;
5322 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05305323
5324 if (!ioc->hide_drives)
5325 mpt3sas_transport_port_remove(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305326 sas_device->sas_address,
5327 sas_device->sas_address_parent);
5328
5329 pr_info(MPT3SAS_FMT
5330 "removing handle(0x%04x), sas_addr(0x%016llx)\n",
5331 ioc->name, sas_device->handle,
5332 (unsigned long long) sas_device->sas_address);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305333 if (sas_device->enclosure_handle != 0)
5334 pr_info(MPT3SAS_FMT
5335 "removing : enclosure logical id(0x%016llx), slot(%d)\n",
5336 ioc->name,
5337 (unsigned long long)sas_device->enclosure_logical_id,
5338 sas_device->slot);
5339 if (sas_device->connector_name[0] != '\0')
5340 pr_info(MPT3SAS_FMT
5341 "removing enclosure level(0x%04x), connector name( %s)\n",
5342 ioc->name, sas_device->enclosure_level,
5343 sas_device->connector_name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305344
5345 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5346 "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n",
5347 ioc->name, __func__,
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05305348 sas_device->handle, (unsigned long long)
5349 sas_device->sas_address));
5350 if (sas_device->enclosure_handle != 0)
5351 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5352 "%s: exit: enclosure logical id(0x%016llx), slot(%d)\n",
5353 ioc->name, __func__,
5354 (unsigned long long)sas_device->enclosure_logical_id,
5355 sas_device->slot));
5356 if (sas_device->connector_name[0] != '\0')
5357 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5358 "%s: exit: enclosure level(0x%04x), connector name(%s)\n",
5359 ioc->name, __func__, sas_device->enclosure_level,
5360 sas_device->connector_name));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305361}
5362
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305363/**
5364 * _scsih_sas_topology_change_event_debug - debug for topology event
5365 * @ioc: per adapter object
5366 * @event_data: event data payload
5367 * Context: user.
5368 */
5369static void
5370_scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5371 Mpi2EventDataSasTopologyChangeList_t *event_data)
5372{
5373 int i;
5374 u16 handle;
5375 u16 reason_code;
5376 u8 phy_number;
5377 char *status_str = NULL;
5378 u8 link_rate, prev_link_rate;
5379
5380 switch (event_data->ExpStatus) {
5381 case MPI2_EVENT_SAS_TOPO_ES_ADDED:
5382 status_str = "add";
5383 break;
5384 case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
5385 status_str = "remove";
5386 break;
5387 case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
5388 case 0:
5389 status_str = "responding";
5390 break;
5391 case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
5392 status_str = "remove delay";
5393 break;
5394 default:
5395 status_str = "unknown status";
5396 break;
5397 }
5398 pr_info(MPT3SAS_FMT "sas topology change: (%s)\n",
5399 ioc->name, status_str);
5400 pr_info("\thandle(0x%04x), enclosure_handle(0x%04x) " \
5401 "start_phy(%02d), count(%d)\n",
5402 le16_to_cpu(event_data->ExpanderDevHandle),
5403 le16_to_cpu(event_data->EnclosureHandle),
5404 event_data->StartPhyNum, event_data->NumEntries);
5405 for (i = 0; i < event_data->NumEntries; i++) {
5406 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5407 if (!handle)
5408 continue;
5409 phy_number = event_data->StartPhyNum + i;
5410 reason_code = event_data->PHY[i].PhyStatus &
5411 MPI2_EVENT_SAS_TOPO_RC_MASK;
5412 switch (reason_code) {
5413 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
5414 status_str = "target add";
5415 break;
5416 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
5417 status_str = "target remove";
5418 break;
5419 case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
5420 status_str = "delay target remove";
5421 break;
5422 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
5423 status_str = "link rate change";
5424 break;
5425 case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
5426 status_str = "target responding";
5427 break;
5428 default:
5429 status_str = "unknown";
5430 break;
5431 }
5432 link_rate = event_data->PHY[i].LinkRate >> 4;
5433 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
5434 pr_info("\tphy(%02d), attached_handle(0x%04x): %s:" \
5435 " link rate: new(0x%02x), old(0x%02x)\n", phy_number,
5436 handle, status_str, link_rate, prev_link_rate);
5437
5438 }
5439}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305440
5441/**
5442 * _scsih_sas_topology_change_event - handle topology changes
5443 * @ioc: per adapter object
5444 * @fw_event: The fw_event_work object
5445 * Context: user.
5446 *
5447 */
5448static int
5449_scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
5450 struct fw_event_work *fw_event)
5451{
5452 int i;
5453 u16 parent_handle, handle;
5454 u16 reason_code;
5455 u8 phy_number, max_phys;
5456 struct _sas_node *sas_expander;
5457 u64 sas_address;
5458 unsigned long flags;
5459 u8 link_rate, prev_link_rate;
Joe Lawrence35b62362014-06-25 17:05:34 -04005460 Mpi2EventDataSasTopologyChangeList_t *event_data =
5461 (Mpi2EventDataSasTopologyChangeList_t *)
5462 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305463
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305464 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5465 _scsih_sas_topology_change_event_debug(ioc, event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305466
5467 if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery)
5468 return 0;
5469
5470 if (!ioc->sas_hba.num_phys)
5471 _scsih_sas_host_add(ioc);
5472 else
5473 _scsih_sas_host_refresh(ioc);
5474
5475 if (fw_event->ignore) {
5476 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5477 "ignoring expander event\n", ioc->name));
5478 return 0;
5479 }
5480
5481 parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
5482
5483 /* handle expander add */
5484 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
5485 if (_scsih_expander_add(ioc, parent_handle) != 0)
5486 return 0;
5487
5488 spin_lock_irqsave(&ioc->sas_node_lock, flags);
5489 sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc,
5490 parent_handle);
5491 if (sas_expander) {
5492 sas_address = sas_expander->sas_address;
5493 max_phys = sas_expander->num_phys;
5494 } else if (parent_handle < ioc->sas_hba.num_phys) {
5495 sas_address = ioc->sas_hba.sas_address;
5496 max_phys = ioc->sas_hba.num_phys;
5497 } else {
5498 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5499 return 0;
5500 }
5501 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
5502
5503 /* handle siblings events */
5504 for (i = 0; i < event_data->NumEntries; i++) {
5505 if (fw_event->ignore) {
5506 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5507 "ignoring expander event\n", ioc->name));
5508 return 0;
5509 }
5510 if (ioc->remove_host || ioc->pci_error_recovery)
5511 return 0;
5512 phy_number = event_data->StartPhyNum + i;
5513 if (phy_number >= max_phys)
5514 continue;
5515 reason_code = event_data->PHY[i].PhyStatus &
5516 MPI2_EVENT_SAS_TOPO_RC_MASK;
5517 if ((event_data->PHY[i].PhyStatus &
5518 MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code !=
5519 MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING))
5520 continue;
5521 handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
5522 if (!handle)
5523 continue;
5524 link_rate = event_data->PHY[i].LinkRate >> 4;
5525 prev_link_rate = event_data->PHY[i].LinkRate & 0xF;
5526 switch (reason_code) {
5527 case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
5528
5529 if (ioc->shost_recovery)
5530 break;
5531
5532 if (link_rate == prev_link_rate)
5533 break;
5534
5535 mpt3sas_transport_update_links(ioc, sas_address,
5536 handle, phy_number, link_rate);
5537
5538 if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5)
5539 break;
5540
5541 _scsih_check_device(ioc, sas_address, handle,
5542 phy_number, link_rate);
5543
5544
5545 case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
5546
5547 if (ioc->shost_recovery)
5548 break;
5549
5550 mpt3sas_transport_update_links(ioc, sas_address,
5551 handle, phy_number, link_rate);
5552
5553 _scsih_add_device(ioc, handle, phy_number, 0);
5554
5555 break;
5556 case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
5557
5558 _scsih_device_remove_by_handle(ioc, handle);
5559 break;
5560 }
5561 }
5562
5563 /* handle expander removal */
5564 if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING &&
5565 sas_expander)
5566 mpt3sas_expander_remove(ioc, sas_address);
5567
5568 return 0;
5569}
5570
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305571/**
5572 * _scsih_sas_device_status_change_event_debug - debug for device event
5573 * @event_data: event data payload
5574 * Context: user.
5575 *
5576 * Return nothing.
5577 */
5578static void
5579_scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5580 Mpi2EventDataSasDeviceStatusChange_t *event_data)
5581{
5582 char *reason_str = NULL;
5583
5584 switch (event_data->ReasonCode) {
5585 case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
5586 reason_str = "smart data";
5587 break;
5588 case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
5589 reason_str = "unsupported device discovered";
5590 break;
5591 case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
5592 reason_str = "internal device reset";
5593 break;
5594 case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
5595 reason_str = "internal task abort";
5596 break;
5597 case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
5598 reason_str = "internal task abort set";
5599 break;
5600 case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
5601 reason_str = "internal clear task set";
5602 break;
5603 case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
5604 reason_str = "internal query task";
5605 break;
5606 case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
5607 reason_str = "sata init failure";
5608 break;
5609 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
5610 reason_str = "internal device reset complete";
5611 break;
5612 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
5613 reason_str = "internal task abort complete";
5614 break;
5615 case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
5616 reason_str = "internal async notification";
5617 break;
5618 case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY:
5619 reason_str = "expander reduced functionality";
5620 break;
5621 case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY:
5622 reason_str = "expander reduced functionality complete";
5623 break;
5624 default:
5625 reason_str = "unknown reason";
5626 break;
5627 }
5628 pr_info(MPT3SAS_FMT "device status change: (%s)\n"
5629 "\thandle(0x%04x), sas address(0x%016llx), tag(%d)",
5630 ioc->name, reason_str, le16_to_cpu(event_data->DevHandle),
5631 (unsigned long long)le64_to_cpu(event_data->SASAddress),
5632 le16_to_cpu(event_data->TaskTag));
5633 if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
5634 pr_info(MPT3SAS_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
5635 event_data->ASC, event_data->ASCQ);
5636 pr_info("\n");
5637}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305638
5639/**
5640 * _scsih_sas_device_status_change_event - handle device status change
5641 * @ioc: per adapter object
5642 * @fw_event: The fw_event_work object
5643 * Context: user.
5644 *
5645 * Return nothing.
5646 */
5647static void
5648_scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc,
5649 struct fw_event_work *fw_event)
5650{
5651 struct MPT3SAS_TARGET *target_priv_data;
5652 struct _sas_device *sas_device;
5653 u64 sas_address;
5654 unsigned long flags;
5655 Mpi2EventDataSasDeviceStatusChange_t *event_data =
Joe Lawrence35b62362014-06-25 17:05:34 -04005656 (Mpi2EventDataSasDeviceStatusChange_t *)
5657 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305658
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305659 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5660 _scsih_sas_device_status_change_event_debug(ioc,
5661 event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305662
5663 /* In MPI Revision K (0xC), the internal device reset complete was
5664 * implemented, so avoid setting tm_busy flag for older firmware.
5665 */
5666 if ((ioc->facts.HeaderVersion >> 8) < 0xC)
5667 return;
5668
5669 if (event_data->ReasonCode !=
5670 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
5671 event_data->ReasonCode !=
5672 MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET)
5673 return;
5674
5675 spin_lock_irqsave(&ioc->sas_device_lock, flags);
5676 sas_address = le64_to_cpu(event_data->SASAddress);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305677 sas_device = __mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305678 sas_address);
5679
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305680 if (!sas_device || !sas_device->starget)
5681 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305682
5683 target_priv_data = sas_device->starget->hostdata;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305684 if (!target_priv_data)
5685 goto out;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305686
5687 if (event_data->ReasonCode ==
5688 MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET)
5689 target_priv_data->tm_busy = 1;
5690 else
5691 target_priv_data->tm_busy = 0;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305692
5693out:
5694 if (sas_device)
5695 sas_device_put(sas_device);
5696
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305697 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05305698
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305699}
5700
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305701/**
5702 * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure
5703 * event
5704 * @ioc: per adapter object
5705 * @event_data: event data payload
5706 * Context: user.
5707 *
5708 * Return nothing.
5709 */
5710static void
5711_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
5712 Mpi2EventDataSasEnclDevStatusChange_t *event_data)
5713{
5714 char *reason_str = NULL;
5715
5716 switch (event_data->ReasonCode) {
5717 case MPI2_EVENT_SAS_ENCL_RC_ADDED:
5718 reason_str = "enclosure add";
5719 break;
5720 case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
5721 reason_str = "enclosure remove";
5722 break;
5723 default:
5724 reason_str = "unknown reason";
5725 break;
5726 }
5727
5728 pr_info(MPT3SAS_FMT "enclosure status change: (%s)\n"
5729 "\thandle(0x%04x), enclosure logical id(0x%016llx)"
5730 " number slots(%d)\n", ioc->name, reason_str,
5731 le16_to_cpu(event_data->EnclosureHandle),
5732 (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
5733 le16_to_cpu(event_data->StartSlot));
5734}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305735
5736/**
5737 * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
5738 * @ioc: per adapter object
5739 * @fw_event: The fw_event_work object
5740 * Context: user.
5741 *
5742 * Return nothing.
5743 */
5744static void
5745_scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
5746 struct fw_event_work *fw_event)
5747{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305748 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
5749 _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
Joe Lawrence35b62362014-06-25 17:05:34 -04005750 (Mpi2EventDataSasEnclDevStatusChange_t *)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305751 fw_event->event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305752}
5753
5754/**
5755 * _scsih_sas_broadcast_primitive_event - handle broadcast events
5756 * @ioc: per adapter object
5757 * @fw_event: The fw_event_work object
5758 * Context: user.
5759 *
5760 * Return nothing.
5761 */
5762static void
5763_scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
5764 struct fw_event_work *fw_event)
5765{
5766 struct scsi_cmnd *scmd;
5767 struct scsi_device *sdev;
5768 u16 smid, handle;
5769 u32 lun;
5770 struct MPT3SAS_DEVICE *sas_device_priv_data;
5771 u32 termination_count;
5772 u32 query_count;
5773 Mpi2SCSITaskManagementReply_t *mpi_reply;
Joe Lawrence35b62362014-06-25 17:05:34 -04005774 Mpi2EventDataSasBroadcastPrimitive_t *event_data =
5775 (Mpi2EventDataSasBroadcastPrimitive_t *)
5776 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305777 u16 ioc_status;
5778 unsigned long flags;
5779 int r;
5780 u8 max_retries = 0;
5781 u8 task_abort_retries;
5782
5783 mutex_lock(&ioc->tm_cmds.mutex);
5784 pr_info(MPT3SAS_FMT
5785 "%s: enter: phy number(%d), width(%d)\n",
5786 ioc->name, __func__, event_data->PhyNum,
5787 event_data->PortWidth);
5788
5789 _scsih_block_io_all_device(ioc);
5790
5791 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5792 mpi_reply = ioc->tm_cmds.reply;
5793 broadcast_aen_retry:
5794
5795 /* sanity checks for retrying this loop */
5796 if (max_retries++ == 5) {
5797 dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: giving up\n",
5798 ioc->name, __func__));
5799 goto out;
5800 } else if (max_retries > 1)
5801 dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: %d retry\n",
5802 ioc->name, __func__, max_retries - 1));
5803
5804 termination_count = 0;
5805 query_count = 0;
5806 for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
5807 if (ioc->shost_recovery)
5808 goto out;
5809 scmd = _scsih_scsi_lookup_get(ioc, smid);
5810 if (!scmd)
5811 continue;
5812 sdev = scmd->device;
5813 sas_device_priv_data = sdev->hostdata;
5814 if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
5815 continue;
5816 /* skip hidden raid components */
5817 if (sas_device_priv_data->sas_target->flags &
5818 MPT_TARGET_FLAGS_RAID_COMPONENT)
5819 continue;
5820 /* skip volumes */
5821 if (sas_device_priv_data->sas_target->flags &
5822 MPT_TARGET_FLAGS_VOLUME)
5823 continue;
5824
5825 handle = sas_device_priv_data->sas_target->handle;
5826 lun = sas_device_priv_data->lun;
5827 query_count++;
5828
5829 if (ioc->shost_recovery)
5830 goto out;
5831
5832 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5833 r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04005834 MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305835 TM_MUTEX_OFF);
5836 if (r == FAILED) {
5837 sdev_printk(KERN_WARNING, sdev,
5838 "mpt3sas_scsih_issue_tm: FAILED when sending "
5839 "QUERY_TASK: scmd(%p)\n", scmd);
5840 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5841 goto broadcast_aen_retry;
5842 }
5843 ioc_status = le16_to_cpu(mpi_reply->IOCStatus)
5844 & MPI2_IOCSTATUS_MASK;
5845 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
5846 sdev_printk(KERN_WARNING, sdev,
5847 "query task: FAILED with IOCSTATUS(0x%04x), scmd(%p)\n",
5848 ioc_status, scmd);
5849 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5850 goto broadcast_aen_retry;
5851 }
5852
5853 /* see if IO is still owned by IOC and target */
5854 if (mpi_reply->ResponseCode ==
5855 MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
5856 mpi_reply->ResponseCode ==
5857 MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) {
5858 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5859 continue;
5860 }
5861 task_abort_retries = 0;
5862 tm_retry:
5863 if (task_abort_retries++ == 60) {
5864 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5865 "%s: ABORT_TASK: giving up\n", ioc->name,
5866 __func__));
5867 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5868 goto broadcast_aen_retry;
5869 }
5870
5871 if (ioc->shost_recovery)
5872 goto out_no_lock;
5873
5874 r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id,
5875 sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30,
Matthew Wilcoxc62e46d2014-03-27 16:40:30 -04005876 TM_MUTEX_OFF);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305877 if (r == FAILED) {
5878 sdev_printk(KERN_WARNING, sdev,
5879 "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : "
5880 "scmd(%p)\n", scmd);
5881 goto tm_retry;
5882 }
5883
5884 if (task_abort_retries > 1)
5885 sdev_printk(KERN_WARNING, sdev,
5886 "mpt3sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):"
5887 " scmd(%p)\n",
5888 task_abort_retries - 1, scmd);
5889
5890 termination_count += le32_to_cpu(mpi_reply->TerminationCount);
5891 spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
5892 }
5893
5894 if (ioc->broadcast_aen_pending) {
5895 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5896 "%s: loop back due to pending AEN\n",
5897 ioc->name, __func__));
5898 ioc->broadcast_aen_pending = 0;
5899 goto broadcast_aen_retry;
5900 }
5901
5902 out:
5903 spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
5904 out_no_lock:
5905
5906 dewtprintk(ioc, pr_info(MPT3SAS_FMT
5907 "%s - exit, query_count = %d termination_count = %d\n",
5908 ioc->name, __func__, query_count, termination_count));
5909
5910 ioc->broadcast_aen_busy = 0;
5911 if (!ioc->shost_recovery)
5912 _scsih_ublock_io_all_device(ioc);
5913 mutex_unlock(&ioc->tm_cmds.mutex);
5914}
5915
5916/**
5917 * _scsih_sas_discovery_event - handle discovery events
5918 * @ioc: per adapter object
5919 * @fw_event: The fw_event_work object
5920 * Context: user.
5921 *
5922 * Return nothing.
5923 */
5924static void
5925_scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
5926 struct fw_event_work *fw_event)
5927{
Joe Lawrence35b62362014-06-25 17:05:34 -04005928 Mpi2EventDataSasDiscovery_t *event_data =
5929 (Mpi2EventDataSasDiscovery_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305930
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305931 if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
5932 pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name,
5933 (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
5934 "start" : "stop");
Sreekanth Reddyaf009412015-11-11 17:30:23 +05305935 if (event_data->DiscoveryStatus)
5936 pr_info("discovery_status(0x%08x)",
5937 le32_to_cpu(event_data->DiscoveryStatus));
5938 pr_info("\n");
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305939 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305940
5941 if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
5942 !ioc->sas_hba.num_phys) {
5943 if (disable_discovery > 0 && ioc->shost_recovery) {
5944 /* Wait for the reset to complete */
5945 while (ioc->shost_recovery)
5946 ssleep(1);
5947 }
5948 _scsih_sas_host_add(ioc);
5949 }
5950}
5951
Sreekanth Reddy45506042015-11-11 17:30:25 +05305952#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305953/**
5954 * _scsih_ir_fastpath - turn on fastpath for IR physdisk
5955 * @ioc: per adapter object
5956 * @handle: device handle for physical disk
5957 * @phys_disk_num: physical disk number
5958 *
5959 * Return 0 for success, else failure.
5960 */
5961static int
5962_scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num)
5963{
5964 Mpi2RaidActionRequest_t *mpi_request;
5965 Mpi2RaidActionReply_t *mpi_reply;
5966 u16 smid;
5967 u8 issue_reset = 0;
5968 int rc = 0;
5969 u16 ioc_status;
5970 u32 log_info;
5971
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05305972 mutex_lock(&ioc->scsih_cmds.mutex);
5973
5974 if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
5975 pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
5976 ioc->name, __func__);
5977 rc = -EAGAIN;
5978 goto out;
5979 }
5980 ioc->scsih_cmds.status = MPT3_CMD_PENDING;
5981
5982 smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
5983 if (!smid) {
5984 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
5985 ioc->name, __func__);
5986 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
5987 rc = -EAGAIN;
5988 goto out;
5989 }
5990
5991 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
5992 ioc->scsih_cmds.smid = smid;
5993 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
5994
5995 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
5996 mpi_request->Action = MPI2_RAID_ACTION_PHYSDISK_HIDDEN;
5997 mpi_request->PhysDiskNum = phys_disk_num;
5998
5999 dewtprintk(ioc, pr_info(MPT3SAS_FMT "IR RAID_ACTION: turning fast "\
6000 "path on for handle(0x%04x), phys_disk_num (0x%02x)\n", ioc->name,
6001 handle, phys_disk_num));
6002
6003 init_completion(&ioc->scsih_cmds.done);
6004 mpt3sas_base_put_smid_default(ioc, smid);
6005 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
6006
6007 if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
6008 pr_err(MPT3SAS_FMT "%s: timeout\n",
6009 ioc->name, __func__);
6010 if (!(ioc->scsih_cmds.status & MPT3_CMD_RESET))
6011 issue_reset = 1;
6012 rc = -EFAULT;
6013 goto out;
6014 }
6015
6016 if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
6017
6018 mpi_reply = ioc->scsih_cmds.reply;
6019 ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
6020 if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
6021 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
6022 else
6023 log_info = 0;
6024 ioc_status &= MPI2_IOCSTATUS_MASK;
6025 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6026 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6027 "IR RAID_ACTION: failed: ioc_status(0x%04x), "
6028 "loginfo(0x%08x)!!!\n", ioc->name, ioc_status,
6029 log_info));
6030 rc = -EFAULT;
6031 } else
6032 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6033 "IR RAID_ACTION: completed successfully\n",
6034 ioc->name));
6035 }
6036
6037 out:
6038 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
6039 mutex_unlock(&ioc->scsih_cmds.mutex);
6040
6041 if (issue_reset)
6042 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
6043 FORCE_BIG_HAMMER);
6044 return rc;
6045}
Sreekanth Reddy45506042015-11-11 17:30:25 +05306046/* End of not defined SCSI_MPT2SAS */
6047#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306048
6049/**
6050 * _scsih_reprobe_lun - reprobing lun
6051 * @sdev: scsi device struct
6052 * @no_uld_attach: sdev->no_uld_attach flag setting
6053 *
6054 **/
6055static void
6056_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
6057{
6058 int rc;
6059 sdev->no_uld_attach = no_uld_attach ? 1 : 0;
6060 sdev_printk(KERN_INFO, sdev, "%s raid component\n",
6061 sdev->no_uld_attach ? "hidding" : "exposing");
6062 rc = scsi_device_reprobe(sdev);
6063}
6064
6065/**
6066 * _scsih_sas_volume_add - add new volume
6067 * @ioc: per adapter object
6068 * @element: IR config element data
6069 * Context: user.
6070 *
6071 * Return nothing.
6072 */
6073static void
6074_scsih_sas_volume_add(struct MPT3SAS_ADAPTER *ioc,
6075 Mpi2EventIrConfigElement_t *element)
6076{
6077 struct _raid_device *raid_device;
6078 unsigned long flags;
6079 u64 wwid;
6080 u16 handle = le16_to_cpu(element->VolDevHandle);
6081 int rc;
6082
6083 mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
6084 if (!wwid) {
6085 pr_err(MPT3SAS_FMT
6086 "failure at %s:%d/%s()!\n", ioc->name,
6087 __FILE__, __LINE__, __func__);
6088 return;
6089 }
6090
6091 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6092 raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
6093 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6094
6095 if (raid_device)
6096 return;
6097
6098 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6099 if (!raid_device) {
6100 pr_err(MPT3SAS_FMT
6101 "failure at %s:%d/%s()!\n", ioc->name,
6102 __FILE__, __LINE__, __func__);
6103 return;
6104 }
6105
6106 raid_device->id = ioc->sas_id++;
6107 raid_device->channel = RAID_CHANNEL;
6108 raid_device->handle = handle;
6109 raid_device->wwid = wwid;
6110 _scsih_raid_device_add(ioc, raid_device);
6111 if (!ioc->wait_for_discovery_to_complete) {
6112 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6113 raid_device->id, 0);
6114 if (rc)
6115 _scsih_raid_device_remove(ioc, raid_device);
6116 } else {
6117 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6118 _scsih_determine_boot_device(ioc, raid_device, 1);
6119 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6120 }
6121}
6122
6123/**
6124 * _scsih_sas_volume_delete - delete volume
6125 * @ioc: per adapter object
6126 * @handle: volume device handle
6127 * Context: user.
6128 *
6129 * Return nothing.
6130 */
6131static void
6132_scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle)
6133{
6134 struct _raid_device *raid_device;
6135 unsigned long flags;
6136 struct MPT3SAS_TARGET *sas_target_priv_data;
6137 struct scsi_target *starget = NULL;
6138
6139 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6140 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6141 if (raid_device) {
6142 if (raid_device->starget) {
6143 starget = raid_device->starget;
6144 sas_target_priv_data = starget->hostdata;
6145 sas_target_priv_data->deleted = 1;
6146 }
6147 pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
6148 ioc->name, raid_device->handle,
6149 (unsigned long long) raid_device->wwid);
6150 list_del(&raid_device->list);
6151 kfree(raid_device);
6152 }
6153 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6154 if (starget)
6155 scsi_remove_target(&starget->dev);
6156}
6157
6158/**
6159 * _scsih_sas_pd_expose - expose pd component to /dev/sdX
6160 * @ioc: per adapter object
6161 * @element: IR config element data
6162 * Context: user.
6163 *
6164 * Return nothing.
6165 */
6166static void
6167_scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc,
6168 Mpi2EventIrConfigElement_t *element)
6169{
6170 struct _sas_device *sas_device;
6171 struct scsi_target *starget = NULL;
6172 struct MPT3SAS_TARGET *sas_target_priv_data;
6173 unsigned long flags;
6174 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6175
6176 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306177 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306178 if (sas_device) {
6179 sas_device->volume_handle = 0;
6180 sas_device->volume_wwid = 0;
6181 clear_bit(handle, ioc->pd_handles);
6182 if (sas_device->starget && sas_device->starget->hostdata) {
6183 starget = sas_device->starget;
6184 sas_target_priv_data = starget->hostdata;
6185 sas_target_priv_data->flags &=
6186 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
6187 }
6188 }
6189 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6190 if (!sas_device)
6191 return;
6192
6193 /* exposing raid component */
6194 if (starget)
6195 starget_for_each_device(starget, NULL, _scsih_reprobe_lun);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306196
6197 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306198}
6199
6200/**
6201 * _scsih_sas_pd_hide - hide pd component from /dev/sdX
6202 * @ioc: per adapter object
6203 * @element: IR config element data
6204 * Context: user.
6205 *
6206 * Return nothing.
6207 */
6208static void
6209_scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc,
6210 Mpi2EventIrConfigElement_t *element)
6211{
6212 struct _sas_device *sas_device;
6213 struct scsi_target *starget = NULL;
6214 struct MPT3SAS_TARGET *sas_target_priv_data;
6215 unsigned long flags;
6216 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6217 u16 volume_handle = 0;
6218 u64 volume_wwid = 0;
6219
6220 mpt3sas_config_get_volume_handle(ioc, handle, &volume_handle);
6221 if (volume_handle)
6222 mpt3sas_config_get_volume_wwid(ioc, volume_handle,
6223 &volume_wwid);
6224
6225 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306226 sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306227 if (sas_device) {
6228 set_bit(handle, ioc->pd_handles);
6229 if (sas_device->starget && sas_device->starget->hostdata) {
6230 starget = sas_device->starget;
6231 sas_target_priv_data = starget->hostdata;
6232 sas_target_priv_data->flags |=
6233 MPT_TARGET_FLAGS_RAID_COMPONENT;
6234 sas_device->volume_handle = volume_handle;
6235 sas_device->volume_wwid = volume_wwid;
6236 }
6237 }
6238 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6239 if (!sas_device)
6240 return;
6241
Sreekanth Reddy45506042015-11-11 17:30:25 +05306242#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306243 /* hiding raid component */
6244 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
Sreekanth Reddy45506042015-11-11 17:30:25 +05306245#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306246 if (starget)
6247 starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306248
6249 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306250}
6251
6252/**
6253 * _scsih_sas_pd_delete - delete pd component
6254 * @ioc: per adapter object
6255 * @element: IR config element data
6256 * Context: user.
6257 *
6258 * Return nothing.
6259 */
6260static void
6261_scsih_sas_pd_delete(struct MPT3SAS_ADAPTER *ioc,
6262 Mpi2EventIrConfigElement_t *element)
6263{
6264 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6265
6266 _scsih_device_remove_by_handle(ioc, handle);
6267}
6268
6269/**
6270 * _scsih_sas_pd_add - remove pd component
6271 * @ioc: per adapter object
6272 * @element: IR config element data
6273 * Context: user.
6274 *
6275 * Return nothing.
6276 */
6277static void
6278_scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc,
6279 Mpi2EventIrConfigElement_t *element)
6280{
6281 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306282 u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
6283 Mpi2ConfigReply_t mpi_reply;
6284 Mpi2SasDevicePage0_t sas_device_pg0;
6285 u32 ioc_status;
6286 u64 sas_address;
6287 u16 parent_handle;
6288
6289 set_bit(handle, ioc->pd_handles);
6290
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306291 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306292 if (sas_device) {
Sreekanth Reddy45506042015-11-11 17:30:25 +05306293#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306294 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
Sreekanth Reddy45506042015-11-11 17:30:25 +05306295#endif
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306296 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306297 return;
6298 }
6299
6300 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
6301 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
6302 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6303 ioc->name, __FILE__, __LINE__, __func__);
6304 return;
6305 }
6306
6307 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6308 MPI2_IOCSTATUS_MASK;
6309 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6310 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6311 ioc->name, __FILE__, __LINE__, __func__);
6312 return;
6313 }
6314
6315 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6316 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6317 mpt3sas_transport_update_links(ioc, sas_address, handle,
6318 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
6319
Sreekanth Reddy45506042015-11-11 17:30:25 +05306320#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306321 _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum);
Sreekanth Reddy45506042015-11-11 17:30:25 +05306322#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306323 _scsih_add_device(ioc, handle, 0, 1);
6324}
6325
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306326/**
6327 * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
6328 * @ioc: per adapter object
6329 * @event_data: event data payload
6330 * Context: user.
6331 *
6332 * Return nothing.
6333 */
6334static void
6335_scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
6336 Mpi2EventDataIrConfigChangeList_t *event_data)
6337{
6338 Mpi2EventIrConfigElement_t *element;
6339 u8 element_type;
6340 int i;
6341 char *reason_str = NULL, *element_str = NULL;
6342
6343 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6344
6345 pr_info(MPT3SAS_FMT "raid config change: (%s), elements(%d)\n",
6346 ioc->name, (le32_to_cpu(event_data->Flags) &
6347 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
6348 "foreign" : "native", event_data->NumElements);
6349 for (i = 0; i < event_data->NumElements; i++, element++) {
6350 switch (element->ReasonCode) {
6351 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6352 reason_str = "add";
6353 break;
6354 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6355 reason_str = "remove";
6356 break;
6357 case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
6358 reason_str = "no change";
6359 break;
6360 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
6361 reason_str = "hide";
6362 break;
6363 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
6364 reason_str = "unhide";
6365 break;
6366 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6367 reason_str = "volume_created";
6368 break;
6369 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6370 reason_str = "volume_deleted";
6371 break;
6372 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
6373 reason_str = "pd_created";
6374 break;
6375 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
6376 reason_str = "pd_deleted";
6377 break;
6378 default:
6379 reason_str = "unknown reason";
6380 break;
6381 }
6382 element_type = le16_to_cpu(element->ElementFlags) &
6383 MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
6384 switch (element_type) {
6385 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
6386 element_str = "volume";
6387 break;
6388 case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
6389 element_str = "phys disk";
6390 break;
6391 case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
6392 element_str = "hot spare";
6393 break;
6394 default:
6395 element_str = "unknown element";
6396 break;
6397 }
6398 pr_info("\t(%s:%s), vol handle(0x%04x), " \
6399 "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
6400 reason_str, le16_to_cpu(element->VolDevHandle),
6401 le16_to_cpu(element->PhysDiskDevHandle),
6402 element->PhysDiskNum);
6403 }
6404}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306405
6406/**
6407 * _scsih_sas_ir_config_change_event - handle ir configuration change events
6408 * @ioc: per adapter object
6409 * @fw_event: The fw_event_work object
6410 * Context: user.
6411 *
6412 * Return nothing.
6413 */
6414static void
6415_scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc,
6416 struct fw_event_work *fw_event)
6417{
6418 Mpi2EventIrConfigElement_t *element;
6419 int i;
6420 u8 foreign_config;
Joe Lawrence35b62362014-06-25 17:05:34 -04006421 Mpi2EventDataIrConfigChangeList_t *event_data =
6422 (Mpi2EventDataIrConfigChangeList_t *)
6423 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306424
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306425 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
6426 (!ioc->hide_ir_msg))
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306427 _scsih_sas_ir_config_change_event_debug(ioc, event_data);
6428
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306429 foreign_config = (le32_to_cpu(event_data->Flags) &
6430 MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0;
6431
6432 element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
6433 if (ioc->shost_recovery) {
Sreekanth Reddy45506042015-11-11 17:30:25 +05306434#ifndef SCSI_MPT2SAS
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306435 for (i = 0; i < event_data->NumElements; i++, element++) {
6436 if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE)
6437 _scsih_ir_fastpath(ioc,
6438 le16_to_cpu(element->PhysDiskDevHandle),
6439 element->PhysDiskNum);
6440 }
Sreekanth Reddy45506042015-11-11 17:30:25 +05306441#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306442 return;
6443 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306444
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306445 for (i = 0; i < event_data->NumElements; i++, element++) {
6446
6447 switch (element->ReasonCode) {
6448 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
6449 case MPI2_EVENT_IR_CHANGE_RC_ADDED:
6450 if (!foreign_config)
6451 _scsih_sas_volume_add(ioc, element);
6452 break;
6453 case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
6454 case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
6455 if (!foreign_config)
6456 _scsih_sas_volume_delete(ioc,
6457 le16_to_cpu(element->VolDevHandle));
6458 break;
6459 case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306460 if (!ioc->is_warpdrive)
6461 _scsih_sas_pd_hide(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306462 break;
6463 case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306464 if (!ioc->is_warpdrive)
6465 _scsih_sas_pd_expose(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306466 break;
6467 case MPI2_EVENT_IR_CHANGE_RC_HIDE:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306468 if (!ioc->is_warpdrive)
6469 _scsih_sas_pd_add(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306470 break;
6471 case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306472 if (!ioc->is_warpdrive)
6473 _scsih_sas_pd_delete(ioc, element);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306474 break;
6475 }
6476 }
6477}
6478
6479/**
6480 * _scsih_sas_ir_volume_event - IR volume event
6481 * @ioc: per adapter object
6482 * @fw_event: The fw_event_work object
6483 * Context: user.
6484 *
6485 * Return nothing.
6486 */
6487static void
6488_scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc,
6489 struct fw_event_work *fw_event)
6490{
6491 u64 wwid;
6492 unsigned long flags;
6493 struct _raid_device *raid_device;
6494 u16 handle;
6495 u32 state;
6496 int rc;
Joe Lawrence35b62362014-06-25 17:05:34 -04006497 Mpi2EventDataIrVolume_t *event_data =
6498 (Mpi2EventDataIrVolume_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306499
6500 if (ioc->shost_recovery)
6501 return;
6502
6503 if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
6504 return;
6505
6506 handle = le16_to_cpu(event_data->VolDevHandle);
6507 state = le32_to_cpu(event_data->NewValue);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306508 if (!ioc->hide_ir_msg)
6509 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6510 "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
6511 ioc->name, __func__, handle,
6512 le32_to_cpu(event_data->PreviousValue), state));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306513 switch (state) {
6514 case MPI2_RAID_VOL_STATE_MISSING:
6515 case MPI2_RAID_VOL_STATE_FAILED:
6516 _scsih_sas_volume_delete(ioc, handle);
6517 break;
6518
6519 case MPI2_RAID_VOL_STATE_ONLINE:
6520 case MPI2_RAID_VOL_STATE_DEGRADED:
6521 case MPI2_RAID_VOL_STATE_OPTIMAL:
6522
6523 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6524 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6525 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6526
6527 if (raid_device)
6528 break;
6529
6530 mpt3sas_config_get_volume_wwid(ioc, handle, &wwid);
6531 if (!wwid) {
6532 pr_err(MPT3SAS_FMT
6533 "failure at %s:%d/%s()!\n", ioc->name,
6534 __FILE__, __LINE__, __func__);
6535 break;
6536 }
6537
6538 raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
6539 if (!raid_device) {
6540 pr_err(MPT3SAS_FMT
6541 "failure at %s:%d/%s()!\n", ioc->name,
6542 __FILE__, __LINE__, __func__);
6543 break;
6544 }
6545
6546 raid_device->id = ioc->sas_id++;
6547 raid_device->channel = RAID_CHANNEL;
6548 raid_device->handle = handle;
6549 raid_device->wwid = wwid;
6550 _scsih_raid_device_add(ioc, raid_device);
6551 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
6552 raid_device->id, 0);
6553 if (rc)
6554 _scsih_raid_device_remove(ioc, raid_device);
6555 break;
6556
6557 case MPI2_RAID_VOL_STATE_INITIALIZING:
6558 default:
6559 break;
6560 }
6561}
6562
6563/**
6564 * _scsih_sas_ir_physical_disk_event - PD event
6565 * @ioc: per adapter object
6566 * @fw_event: The fw_event_work object
6567 * Context: user.
6568 *
6569 * Return nothing.
6570 */
6571static void
6572_scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc,
6573 struct fw_event_work *fw_event)
6574{
6575 u16 handle, parent_handle;
6576 u32 state;
6577 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306578 Mpi2ConfigReply_t mpi_reply;
6579 Mpi2SasDevicePage0_t sas_device_pg0;
6580 u32 ioc_status;
Joe Lawrence35b62362014-06-25 17:05:34 -04006581 Mpi2EventDataIrPhysicalDisk_t *event_data =
6582 (Mpi2EventDataIrPhysicalDisk_t *) fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306583 u64 sas_address;
6584
6585 if (ioc->shost_recovery)
6586 return;
6587
6588 if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
6589 return;
6590
6591 handle = le16_to_cpu(event_data->PhysDiskDevHandle);
6592 state = le32_to_cpu(event_data->NewValue);
6593
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306594 if (!ioc->hide_ir_msg)
6595 dewtprintk(ioc, pr_info(MPT3SAS_FMT
6596 "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n",
6597 ioc->name, __func__, handle,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306598 le32_to_cpu(event_data->PreviousValue), state));
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306599
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306600 switch (state) {
6601 case MPI2_RAID_PD_STATE_ONLINE:
6602 case MPI2_RAID_PD_STATE_DEGRADED:
6603 case MPI2_RAID_PD_STATE_REBUILDING:
6604 case MPI2_RAID_PD_STATE_OPTIMAL:
6605 case MPI2_RAID_PD_STATE_HOT_SPARE:
6606
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306607 if (!ioc->is_warpdrive)
6608 set_bit(handle, ioc->pd_handles);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306609
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306610 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
6611 if (sas_device) {
6612 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306613 return;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05306614 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306615
6616 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6617 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
6618 handle))) {
6619 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6620 ioc->name, __FILE__, __LINE__, __func__);
6621 return;
6622 }
6623
6624 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6625 MPI2_IOCSTATUS_MASK;
6626 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
6627 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
6628 ioc->name, __FILE__, __LINE__, __func__);
6629 return;
6630 }
6631
6632 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
6633 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address))
6634 mpt3sas_transport_update_links(ioc, sas_address, handle,
6635 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
6636
6637 _scsih_add_device(ioc, handle, 0, 1);
6638
6639 break;
6640
6641 case MPI2_RAID_PD_STATE_OFFLINE:
6642 case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
6643 case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
6644 default:
6645 break;
6646 }
6647}
6648
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306649/**
6650 * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
6651 * @ioc: per adapter object
6652 * @event_data: event data payload
6653 * Context: user.
6654 *
6655 * Return nothing.
6656 */
6657static void
6658_scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc,
6659 Mpi2EventDataIrOperationStatus_t *event_data)
6660{
6661 char *reason_str = NULL;
6662
6663 switch (event_data->RAIDOperation) {
6664 case MPI2_EVENT_IR_RAIDOP_RESYNC:
6665 reason_str = "resync";
6666 break;
6667 case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
6668 reason_str = "online capacity expansion";
6669 break;
6670 case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
6671 reason_str = "consistency check";
6672 break;
6673 case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT:
6674 reason_str = "background init";
6675 break;
6676 case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT:
6677 reason_str = "make data consistent";
6678 break;
6679 }
6680
6681 if (!reason_str)
6682 return;
6683
6684 pr_info(MPT3SAS_FMT "raid operational status: (%s)" \
6685 "\thandle(0x%04x), percent complete(%d)\n",
6686 ioc->name, reason_str,
6687 le16_to_cpu(event_data->VolDevHandle),
6688 event_data->PercentComplete);
6689}
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306690
6691/**
6692 * _scsih_sas_ir_operation_status_event - handle RAID operation events
6693 * @ioc: per adapter object
6694 * @fw_event: The fw_event_work object
6695 * Context: user.
6696 *
6697 * Return nothing.
6698 */
6699static void
6700_scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc,
6701 struct fw_event_work *fw_event)
6702{
Joe Lawrence35b62362014-06-25 17:05:34 -04006703 Mpi2EventDataIrOperationStatus_t *event_data =
6704 (Mpi2EventDataIrOperationStatus_t *)
6705 fw_event->event_data;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306706 static struct _raid_device *raid_device;
6707 unsigned long flags;
6708 u16 handle;
6709
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306710 if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) &&
6711 (!ioc->hide_ir_msg))
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306712 _scsih_sas_ir_operation_status_event_debug(ioc,
6713 event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306714
6715 /* code added for raid transport support */
6716 if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) {
6717
6718 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6719 handle = le16_to_cpu(event_data->VolDevHandle);
6720 raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
6721 if (raid_device)
6722 raid_device->percent_complete =
6723 event_data->PercentComplete;
6724 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6725 }
6726}
6727
6728/**
6729 * _scsih_prep_device_scan - initialize parameters prior to device scan
6730 * @ioc: per adapter object
6731 *
6732 * Set the deleted flag prior to device scan. If the device is found during
6733 * the scan, then we clear the deleted flag.
6734 */
6735static void
6736_scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc)
6737{
6738 struct MPT3SAS_DEVICE *sas_device_priv_data;
6739 struct scsi_device *sdev;
6740
6741 shost_for_each_device(sdev, ioc->shost) {
6742 sas_device_priv_data = sdev->hostdata;
6743 if (sas_device_priv_data && sas_device_priv_data->sas_target)
6744 sas_device_priv_data->sas_target->deleted = 1;
6745 }
6746}
6747
6748/**
6749 * _scsih_mark_responding_sas_device - mark a sas_devices as responding
6750 * @ioc: per adapter object
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306751 * @sas_device_pg0: SAS Device page 0
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306752 *
6753 * After host reset, find out whether devices are still responding.
6754 * Used in _scsih_remove_unresponsive_sas_devices.
6755 *
6756 * Return nothing.
6757 */
6758static void
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306759_scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc,
6760Mpi2SasDevicePage0_t *sas_device_pg0)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306761{
6762 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
6763 struct scsi_target *starget;
6764 struct _sas_device *sas_device;
6765 unsigned long flags;
6766
6767 spin_lock_irqsave(&ioc->sas_device_lock, flags);
6768 list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306769 if ((sas_device->sas_address == sas_device_pg0->SASAddress) &&
6770 (sas_device->slot == sas_device_pg0->Slot)) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306771 sas_device->responding = 1;
6772 starget = sas_device->starget;
6773 if (starget && starget->hostdata) {
6774 sas_target_priv_data = starget->hostdata;
6775 sas_target_priv_data->tm_busy = 0;
6776 sas_target_priv_data->deleted = 0;
6777 } else
6778 sas_target_priv_data = NULL;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306779 if (starget) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306780 starget_printk(KERN_INFO, starget,
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306781 "handle(0x%04x), sas_addr(0x%016llx)\n",
6782 sas_device_pg0->DevHandle,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306783 (unsigned long long)
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306784 sas_device->sas_address);
6785
6786 if (sas_device->enclosure_handle != 0)
6787 starget_printk(KERN_INFO, starget,
6788 "enclosure logical id(0x%016llx),"
6789 " slot(%d)\n",
6790 (unsigned long long)
6791 sas_device->enclosure_logical_id,
6792 sas_device->slot);
6793 }
6794 if (sas_device_pg0->Flags &
6795 MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
6796 sas_device->enclosure_level =
6797 le16_to_cpu(sas_device_pg0->EnclosureLevel);
6798 memcpy(&sas_device->connector_name[0],
6799 &sas_device_pg0->ConnectorName[0], 4);
6800 } else {
6801 sas_device->enclosure_level = 0;
6802 sas_device->connector_name[0] = '\0';
6803 }
6804
6805 if (sas_device->handle == sas_device_pg0->DevHandle)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306806 goto out;
6807 pr_info("\thandle changed from(0x%04x)!!!\n",
6808 sas_device->handle);
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306809 sas_device->handle = sas_device_pg0->DevHandle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306810 if (sas_target_priv_data)
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306811 sas_target_priv_data->handle =
6812 sas_device_pg0->DevHandle;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306813 goto out;
6814 }
6815 }
6816 out:
6817 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
6818}
6819
6820/**
6821 * _scsih_search_responding_sas_devices -
6822 * @ioc: per adapter object
6823 *
6824 * After host reset, find out whether devices are still responding.
6825 * If not remove.
6826 *
6827 * Return nothing.
6828 */
6829static void
6830_scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
6831{
6832 Mpi2SasDevicePage0_t sas_device_pg0;
6833 Mpi2ConfigReply_t mpi_reply;
6834 u16 ioc_status;
6835 u16 handle;
6836 u32 device_info;
6837
6838 pr_info(MPT3SAS_FMT "search for end-devices: start\n", ioc->name);
6839
6840 if (list_empty(&ioc->sas_device_list))
6841 goto out;
6842
6843 handle = 0xFFFF;
6844 while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
6845 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
6846 handle))) {
6847 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6848 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05306849 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306850 break;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306851 handle = sas_device_pg0.DevHandle =
6852 le16_to_cpu(sas_device_pg0.DevHandle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306853 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
6854 if (!(_scsih_is_end_device(device_info)))
6855 continue;
Sreekanth Reddye6d45e32015-06-30 12:24:52 +05306856 sas_device_pg0.SASAddress =
6857 le64_to_cpu(sas_device_pg0.SASAddress);
6858 sas_device_pg0.Slot = le16_to_cpu(sas_device_pg0.Slot);
6859 _scsih_mark_responding_sas_device(ioc, &sas_device_pg0);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306860 }
6861
6862 out:
6863 pr_info(MPT3SAS_FMT "search for end-devices: complete\n",
6864 ioc->name);
6865}
6866
6867/**
6868 * _scsih_mark_responding_raid_device - mark a raid_device as responding
6869 * @ioc: per adapter object
6870 * @wwid: world wide identifier for raid volume
6871 * @handle: device handle
6872 *
6873 * After host reset, find out whether devices are still responding.
6874 * Used in _scsih_remove_unresponsive_raid_devices.
6875 *
6876 * Return nothing.
6877 */
6878static void
6879_scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid,
6880 u16 handle)
6881{
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306882 struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306883 struct scsi_target *starget;
6884 struct _raid_device *raid_device;
6885 unsigned long flags;
6886
6887 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6888 list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
6889 if (raid_device->wwid == wwid && raid_device->starget) {
6890 starget = raid_device->starget;
6891 if (starget && starget->hostdata) {
6892 sas_target_priv_data = starget->hostdata;
6893 sas_target_priv_data->deleted = 0;
6894 } else
6895 sas_target_priv_data = NULL;
6896 raid_device->responding = 1;
6897 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6898 starget_printk(KERN_INFO, raid_device->starget,
6899 "handle(0x%04x), wwid(0x%016llx)\n", handle,
6900 (unsigned long long)raid_device->wwid);
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306901
6902#ifdef SCSI_MPT2SAS
6903 /*
6904 * WARPDRIVE: The handles of the PDs might have changed
6905 * across the host reset so re-initialize the
6906 * required data for Direct IO
6907 */
6908 _scsih_init_warpdrive_properties(ioc, raid_device);
6909#endif
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306910 spin_lock_irqsave(&ioc->raid_device_lock, flags);
6911 if (raid_device->handle == handle) {
6912 spin_unlock_irqrestore(&ioc->raid_device_lock,
6913 flags);
6914 return;
6915 }
6916 pr_info("\thandle changed from(0x%04x)!!!\n",
6917 raid_device->handle);
6918 raid_device->handle = handle;
6919 if (sas_target_priv_data)
6920 sas_target_priv_data->handle = handle;
6921 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6922 return;
6923 }
6924 }
6925 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
6926}
6927
6928/**
6929 * _scsih_search_responding_raid_devices -
6930 * @ioc: per adapter object
6931 *
6932 * After host reset, find out whether devices are still responding.
6933 * If not remove.
6934 *
6935 * Return nothing.
6936 */
6937static void
6938_scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc)
6939{
6940 Mpi2RaidVolPage1_t volume_pg1;
6941 Mpi2RaidVolPage0_t volume_pg0;
6942 Mpi2RaidPhysDiskPage0_t pd_pg0;
6943 Mpi2ConfigReply_t mpi_reply;
6944 u16 ioc_status;
6945 u16 handle;
6946 u8 phys_disk_num;
6947
6948 if (!ioc->ir_firmware)
6949 return;
6950
6951 pr_info(MPT3SAS_FMT "search for raid volumes: start\n",
6952 ioc->name);
6953
6954 if (list_empty(&ioc->raid_device_list))
6955 goto out;
6956
6957 handle = 0xFFFF;
6958 while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
6959 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
6960 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6961 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05306962 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306963 break;
6964 handle = le16_to_cpu(volume_pg1.DevHandle);
6965
6966 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
6967 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
6968 sizeof(Mpi2RaidVolPage0_t)))
6969 continue;
6970
6971 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
6972 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
6973 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED)
6974 _scsih_mark_responding_raid_device(ioc,
6975 le64_to_cpu(volume_pg1.WWID), handle);
6976 }
6977
6978 /* refresh the pd_handles */
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306979 if (!ioc->is_warpdrive) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306980 phys_disk_num = 0xFF;
6981 memset(ioc->pd_handles, 0, ioc->pd_handles_sz);
6982 while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
6983 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
6984 phys_disk_num))) {
6985 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
6986 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05306987 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306988 break;
6989 phys_disk_num = pd_pg0.PhysDiskNum;
6990 handle = le16_to_cpu(pd_pg0.DevHandle);
6991 set_bit(handle, ioc->pd_handles);
6992 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05306993 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05306994 out:
6995 pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n",
6996 ioc->name);
6997}
6998
6999/**
7000 * _scsih_mark_responding_expander - mark a expander as responding
7001 * @ioc: per adapter object
7002 * @sas_address: sas address
7003 * @handle:
7004 *
7005 * After host reset, find out whether devices are still responding.
7006 * Used in _scsih_remove_unresponsive_expanders.
7007 *
7008 * Return nothing.
7009 */
7010static void
7011_scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
7012 u16 handle)
7013{
7014 struct _sas_node *sas_expander;
7015 unsigned long flags;
7016 int i;
7017
7018 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7019 list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
7020 if (sas_expander->sas_address != sas_address)
7021 continue;
7022 sas_expander->responding = 1;
7023 if (sas_expander->handle == handle)
7024 goto out;
7025 pr_info("\texpander(0x%016llx): handle changed" \
7026 " from(0x%04x) to (0x%04x)!!!\n",
7027 (unsigned long long)sas_expander->sas_address,
7028 sas_expander->handle, handle);
7029 sas_expander->handle = handle;
7030 for (i = 0 ; i < sas_expander->num_phys ; i++)
7031 sas_expander->phy[i].handle = handle;
7032 goto out;
7033 }
7034 out:
7035 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7036}
7037
7038/**
7039 * _scsih_search_responding_expanders -
7040 * @ioc: per adapter object
7041 *
7042 * After host reset, find out whether devices are still responding.
7043 * If not remove.
7044 *
7045 * Return nothing.
7046 */
7047static void
7048_scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc)
7049{
7050 Mpi2ExpanderPage0_t expander_pg0;
7051 Mpi2ConfigReply_t mpi_reply;
7052 u16 ioc_status;
7053 u64 sas_address;
7054 u16 handle;
7055
7056 pr_info(MPT3SAS_FMT "search for expanders: start\n", ioc->name);
7057
7058 if (list_empty(&ioc->sas_expander_list))
7059 goto out;
7060
7061 handle = 0xFFFF;
7062 while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
7063 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
7064
7065 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7066 MPI2_IOCSTATUS_MASK;
Sreekanth Reddy14be49a2013-06-29 03:53:02 +05307067 if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307068 break;
7069
7070 handle = le16_to_cpu(expander_pg0.DevHandle);
7071 sas_address = le64_to_cpu(expander_pg0.SASAddress);
7072 pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n",
7073 handle,
7074 (unsigned long long)sas_address);
7075 _scsih_mark_responding_expander(ioc, sas_address, handle);
7076 }
7077
7078 out:
7079 pr_info(MPT3SAS_FMT "search for expanders: complete\n", ioc->name);
7080}
7081
7082/**
7083 * _scsih_remove_unresponding_sas_devices - removing unresponding devices
7084 * @ioc: per adapter object
7085 *
7086 * Return nothing.
7087 */
7088static void
7089_scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
7090{
7091 struct _sas_device *sas_device, *sas_device_next;
7092 struct _sas_node *sas_expander, *sas_expander_next;
7093 struct _raid_device *raid_device, *raid_device_next;
7094 struct list_head tmp_list;
7095 unsigned long flags;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307096 LIST_HEAD(head);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307097
7098 pr_info(MPT3SAS_FMT "removing unresponding devices: start\n",
7099 ioc->name);
7100
7101 /* removing unresponding end devices */
7102 pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n",
7103 ioc->name);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307104 /*
7105 * Iterate, pulling off devices marked as non-responding. We become the
7106 * owner for the reference the list had on any object we prune.
7107 */
7108 spin_lock_irqsave(&ioc->sas_device_lock, flags);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307109 list_for_each_entry_safe(sas_device, sas_device_next,
7110 &ioc->sas_device_list, list) {
7111 if (!sas_device->responding)
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307112 list_move_tail(&sas_device->list, &head);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307113 else
7114 sas_device->responding = 0;
7115 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307116 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
7117
7118 /*
7119 * Now, uninitialize and remove the unresponding devices we pruned.
7120 */
7121 list_for_each_entry_safe(sas_device, sas_device_next, &head, list) {
7122 _scsih_remove_device(ioc, sas_device);
7123 list_del_init(&sas_device->list);
7124 sas_device_put(sas_device);
7125 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307126
7127 /* removing unresponding volumes */
7128 if (ioc->ir_firmware) {
7129 pr_info(MPT3SAS_FMT "removing unresponding devices: volumes\n",
7130 ioc->name);
7131 list_for_each_entry_safe(raid_device, raid_device_next,
7132 &ioc->raid_device_list, list) {
7133 if (!raid_device->responding)
7134 _scsih_sas_volume_delete(ioc,
7135 raid_device->handle);
7136 else
7137 raid_device->responding = 0;
7138 }
7139 }
7140
7141 /* removing unresponding expanders */
7142 pr_info(MPT3SAS_FMT "removing unresponding devices: expanders\n",
7143 ioc->name);
7144 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7145 INIT_LIST_HEAD(&tmp_list);
7146 list_for_each_entry_safe(sas_expander, sas_expander_next,
7147 &ioc->sas_expander_list, list) {
7148 if (!sas_expander->responding)
7149 list_move_tail(&sas_expander->list, &tmp_list);
7150 else
7151 sas_expander->responding = 0;
7152 }
7153 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7154 list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list,
7155 list) {
7156 list_del(&sas_expander->list);
7157 _scsih_expander_node_remove(ioc, sas_expander);
7158 }
7159
7160 pr_info(MPT3SAS_FMT "removing unresponding devices: complete\n",
7161 ioc->name);
7162
7163 /* unblock devices */
7164 _scsih_ublock_io_all_device(ioc);
7165}
7166
7167static void
7168_scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc,
7169 struct _sas_node *sas_expander, u16 handle)
7170{
7171 Mpi2ExpanderPage1_t expander_pg1;
7172 Mpi2ConfigReply_t mpi_reply;
7173 int i;
7174
7175 for (i = 0 ; i < sas_expander->num_phys ; i++) {
7176 if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply,
7177 &expander_pg1, i, handle))) {
7178 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7179 ioc->name, __FILE__, __LINE__, __func__);
7180 return;
7181 }
7182
7183 mpt3sas_transport_update_links(ioc, sas_expander->sas_address,
7184 le16_to_cpu(expander_pg1.AttachedDevHandle), i,
7185 expander_pg1.NegotiatedLinkRate >> 4);
7186 }
7187}
7188
7189/**
7190 * _scsih_scan_for_devices_after_reset - scan for devices after host reset
7191 * @ioc: per adapter object
7192 *
7193 * Return nothing.
7194 */
7195static void
7196_scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc)
7197{
7198 Mpi2ExpanderPage0_t expander_pg0;
7199 Mpi2SasDevicePage0_t sas_device_pg0;
7200 Mpi2RaidVolPage1_t volume_pg1;
7201 Mpi2RaidVolPage0_t volume_pg0;
7202 Mpi2RaidPhysDiskPage0_t pd_pg0;
7203 Mpi2EventIrConfigElement_t element;
7204 Mpi2ConfigReply_t mpi_reply;
7205 u8 phys_disk_num;
7206 u16 ioc_status;
7207 u16 handle, parent_handle;
7208 u64 sas_address;
7209 struct _sas_device *sas_device;
7210 struct _sas_node *expander_device;
7211 static struct _raid_device *raid_device;
7212 u8 retry_count;
7213 unsigned long flags;
7214
7215 pr_info(MPT3SAS_FMT "scan devices: start\n", ioc->name);
7216
7217 _scsih_sas_host_refresh(ioc);
7218
7219 pr_info(MPT3SAS_FMT "\tscan devices: expanders start\n", ioc->name);
7220
7221 /* expanders */
7222 handle = 0xFFFF;
7223 while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
7224 MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
7225 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7226 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307227 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7228 pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \
7229 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7230 ioc->name, ioc_status,
7231 le32_to_cpu(mpi_reply.IOCLogInfo));
7232 break;
7233 }
7234 handle = le16_to_cpu(expander_pg0.DevHandle);
7235 spin_lock_irqsave(&ioc->sas_node_lock, flags);
7236 expander_device = mpt3sas_scsih_expander_find_by_sas_address(
7237 ioc, le64_to_cpu(expander_pg0.SASAddress));
7238 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
7239 if (expander_device)
7240 _scsih_refresh_expander_links(ioc, expander_device,
7241 handle);
7242 else {
7243 pr_info(MPT3SAS_FMT "\tBEFORE adding expander: " \
7244 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7245 handle, (unsigned long long)
7246 le64_to_cpu(expander_pg0.SASAddress));
7247 _scsih_expander_add(ioc, handle);
7248 pr_info(MPT3SAS_FMT "\tAFTER adding expander: " \
7249 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7250 handle, (unsigned long long)
7251 le64_to_cpu(expander_pg0.SASAddress));
7252 }
7253 }
7254
7255 pr_info(MPT3SAS_FMT "\tscan devices: expanders complete\n",
7256 ioc->name);
7257
7258 if (!ioc->ir_firmware)
7259 goto skip_to_sas;
7260
7261 pr_info(MPT3SAS_FMT "\tscan devices: phys disk start\n", ioc->name);
7262
7263 /* phys disk */
7264 phys_disk_num = 0xFF;
7265 while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
7266 &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM,
7267 phys_disk_num))) {
7268 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7269 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307270 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7271 pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\
7272 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7273 ioc->name, ioc_status,
7274 le32_to_cpu(mpi_reply.IOCLogInfo));
7275 break;
7276 }
7277 phys_disk_num = pd_pg0.PhysDiskNum;
7278 handle = le16_to_cpu(pd_pg0.DevHandle);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307279 sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
7280 if (sas_device) {
7281 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307282 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307283 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307284 if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7285 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
7286 handle) != 0)
7287 continue;
7288 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7289 MPI2_IOCSTATUS_MASK;
7290 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7291 pr_info(MPT3SAS_FMT "\tbreak from phys disk scan " \
7292 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7293 ioc->name, ioc_status,
7294 le32_to_cpu(mpi_reply.IOCLogInfo));
7295 break;
7296 }
7297 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7298 if (!_scsih_get_sas_address(ioc, parent_handle,
7299 &sas_address)) {
7300 pr_info(MPT3SAS_FMT "\tBEFORE adding phys disk: " \
7301 " handle (0x%04x), sas_addr(0x%016llx)\n",
7302 ioc->name, handle, (unsigned long long)
7303 le64_to_cpu(sas_device_pg0.SASAddress));
7304 mpt3sas_transport_update_links(ioc, sas_address,
7305 handle, sas_device_pg0.PhyNum,
7306 MPI2_SAS_NEG_LINK_RATE_1_5);
7307 set_bit(handle, ioc->pd_handles);
7308 retry_count = 0;
7309 /* This will retry adding the end device.
7310 * _scsih_add_device() will decide on retries and
7311 * return "1" when it should be retried
7312 */
7313 while (_scsih_add_device(ioc, handle, retry_count++,
7314 1)) {
7315 ssleep(1);
7316 }
7317 pr_info(MPT3SAS_FMT "\tAFTER adding phys disk: " \
7318 " handle (0x%04x), sas_addr(0x%016llx)\n",
7319 ioc->name, handle, (unsigned long long)
7320 le64_to_cpu(sas_device_pg0.SASAddress));
7321 }
7322 }
7323
7324 pr_info(MPT3SAS_FMT "\tscan devices: phys disk complete\n",
7325 ioc->name);
7326
7327 pr_info(MPT3SAS_FMT "\tscan devices: volumes start\n", ioc->name);
7328
7329 /* volumes */
7330 handle = 0xFFFF;
7331 while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
7332 &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
7333 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7334 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307335 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7336 pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
7337 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7338 ioc->name, ioc_status,
7339 le32_to_cpu(mpi_reply.IOCLogInfo));
7340 break;
7341 }
7342 handle = le16_to_cpu(volume_pg1.DevHandle);
7343 spin_lock_irqsave(&ioc->raid_device_lock, flags);
7344 raid_device = _scsih_raid_device_find_by_wwid(ioc,
7345 le64_to_cpu(volume_pg1.WWID));
7346 spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
7347 if (raid_device)
7348 continue;
7349 if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply,
7350 &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
7351 sizeof(Mpi2RaidVolPage0_t)))
7352 continue;
7353 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7354 MPI2_IOCSTATUS_MASK;
7355 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7356 pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \
7357 "ioc_status(0x%04x), loginfo(0x%08x)\n",
7358 ioc->name, ioc_status,
7359 le32_to_cpu(mpi_reply.IOCLogInfo));
7360 break;
7361 }
7362 if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
7363 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
7364 volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
7365 memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
7366 element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
7367 element.VolDevHandle = volume_pg1.DevHandle;
7368 pr_info(MPT3SAS_FMT
7369 "\tBEFORE adding volume: handle (0x%04x)\n",
7370 ioc->name, volume_pg1.DevHandle);
7371 _scsih_sas_volume_add(ioc, &element);
7372 pr_info(MPT3SAS_FMT
7373 "\tAFTER adding volume: handle (0x%04x)\n",
7374 ioc->name, volume_pg1.DevHandle);
7375 }
7376 }
7377
7378 pr_info(MPT3SAS_FMT "\tscan devices: volumes complete\n",
7379 ioc->name);
7380
7381 skip_to_sas:
7382
7383 pr_info(MPT3SAS_FMT "\tscan devices: end devices start\n",
7384 ioc->name);
7385
7386 /* sas devices */
7387 handle = 0xFFFF;
7388 while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply,
7389 &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
7390 handle))) {
7391 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
7392 MPI2_IOCSTATUS_MASK;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307393 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
7394 pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\
7395 " ioc_status(0x%04x), loginfo(0x%08x)\n",
7396 ioc->name, ioc_status,
7397 le32_to_cpu(mpi_reply.IOCLogInfo));
7398 break;
7399 }
7400 handle = le16_to_cpu(sas_device_pg0.DevHandle);
7401 if (!(_scsih_is_end_device(
7402 le32_to_cpu(sas_device_pg0.DeviceInfo))))
7403 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307404 sas_device = mpt3sas_get_sdev_by_addr(ioc,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307405 le64_to_cpu(sas_device_pg0.SASAddress));
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307406 if (sas_device) {
7407 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307408 continue;
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05307409 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307410 parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
7411 if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
7412 pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \
7413 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7414 handle, (unsigned long long)
7415 le64_to_cpu(sas_device_pg0.SASAddress));
7416 mpt3sas_transport_update_links(ioc, sas_address, handle,
7417 sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
7418 retry_count = 0;
7419 /* This will retry adding the end device.
7420 * _scsih_add_device() will decide on retries and
7421 * return "1" when it should be retried
7422 */
7423 while (_scsih_add_device(ioc, handle, retry_count++,
7424 0)) {
7425 ssleep(1);
7426 }
7427 pr_info(MPT3SAS_FMT "\tAFTER adding end device: " \
7428 "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name,
7429 handle, (unsigned long long)
7430 le64_to_cpu(sas_device_pg0.SASAddress));
7431 }
7432 }
7433 pr_info(MPT3SAS_FMT "\tscan devices: end devices complete\n",
7434 ioc->name);
7435
7436 pr_info(MPT3SAS_FMT "scan devices: complete\n", ioc->name);
7437}
7438/**
7439 * mpt3sas_scsih_reset_handler - reset callback handler (for scsih)
7440 * @ioc: per adapter object
7441 * @reset_phase: phase
7442 *
7443 * The handler for doing any required cleanup or initialization.
7444 *
7445 * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET,
7446 * MPT3_IOC_DONE_RESET
7447 *
7448 * Return nothing.
7449 */
7450void
7451mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
7452{
7453 switch (reset_phase) {
7454 case MPT3_IOC_PRE_RESET:
7455 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7456 "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__));
7457 break;
7458 case MPT3_IOC_AFTER_RESET:
7459 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7460 "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__));
7461 if (ioc->scsih_cmds.status & MPT3_CMD_PENDING) {
7462 ioc->scsih_cmds.status |= MPT3_CMD_RESET;
7463 mpt3sas_base_free_smid(ioc, ioc->scsih_cmds.smid);
7464 complete(&ioc->scsih_cmds.done);
7465 }
7466 if (ioc->tm_cmds.status & MPT3_CMD_PENDING) {
7467 ioc->tm_cmds.status |= MPT3_CMD_RESET;
7468 mpt3sas_base_free_smid(ioc, ioc->tm_cmds.smid);
7469 complete(&ioc->tm_cmds.done);
7470 }
7471
7472 _scsih_fw_event_cleanup_queue(ioc);
7473 _scsih_flush_running_cmds(ioc);
7474 break;
7475 case MPT3_IOC_DONE_RESET:
7476 dtmprintk(ioc, pr_info(MPT3SAS_FMT
7477 "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__));
7478 if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
7479 !ioc->sas_hba.num_phys)) {
7480 _scsih_prep_device_scan(ioc);
7481 _scsih_search_responding_sas_devices(ioc);
7482 _scsih_search_responding_raid_devices(ioc);
7483 _scsih_search_responding_expanders(ioc);
7484 _scsih_error_recovery_delete_devices(ioc);
7485 }
7486 break;
7487 }
7488}
7489
7490/**
7491 * _mpt3sas_fw_work - delayed task for processing firmware events
7492 * @ioc: per adapter object
7493 * @fw_event: The fw_event_work object
7494 * Context: user.
7495 *
7496 * Return nothing.
7497 */
7498static void
7499_mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
7500{
7501 /* the queue is being flushed so ignore this event */
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05307502 if (ioc->remove_host ||
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307503 ioc->pci_error_recovery) {
7504 _scsih_fw_event_free(ioc, fw_event);
7505 return;
7506 }
7507
7508 switch (fw_event->event) {
7509 case MPT3SAS_PROCESS_TRIGGER_DIAG:
Joe Lawrence35b62362014-06-25 17:05:34 -04007510 mpt3sas_process_trigger_data(ioc,
7511 (struct SL_WH_TRIGGERS_EVENT_DATA_T *)
7512 fw_event->event_data);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307513 break;
7514 case MPT3SAS_REMOVE_UNRESPONDING_DEVICES:
7515 while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery)
7516 ssleep(1);
7517 _scsih_remove_unresponding_sas_devices(ioc);
7518 _scsih_scan_for_devices_after_reset(ioc);
7519 break;
7520 case MPT3SAS_PORT_ENABLE_COMPLETE:
7521 ioc->start_scan = 0;
7522 if (missing_delay[0] != -1 && missing_delay[1] != -1)
7523 mpt3sas_base_update_missing_delay(ioc, missing_delay[0],
7524 missing_delay[1]);
7525 dewtprintk(ioc, pr_info(MPT3SAS_FMT
7526 "port enable: complete from worker thread\n",
7527 ioc->name));
7528 break;
Sreekanth Reddy0f624c32014-09-12 15:35:26 +05307529 case MPT3SAS_TURN_ON_PFA_LED:
7530 _scsih_turn_on_pfa_led(ioc, fw_event->device_handle);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307531 break;
7532 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7533 _scsih_sas_topology_change_event(ioc, fw_event);
7534 break;
7535 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7536 _scsih_sas_device_status_change_event(ioc, fw_event);
7537 break;
7538 case MPI2_EVENT_SAS_DISCOVERY:
7539 _scsih_sas_discovery_event(ioc, fw_event);
7540 break;
7541 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7542 _scsih_sas_broadcast_primitive_event(ioc, fw_event);
7543 break;
7544 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7545 _scsih_sas_enclosure_dev_status_change_event(ioc,
7546 fw_event);
7547 break;
7548 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7549 _scsih_sas_ir_config_change_event(ioc, fw_event);
7550 break;
7551 case MPI2_EVENT_IR_VOLUME:
7552 _scsih_sas_ir_volume_event(ioc, fw_event);
7553 break;
7554 case MPI2_EVENT_IR_PHYSICAL_DISK:
7555 _scsih_sas_ir_physical_disk_event(ioc, fw_event);
7556 break;
7557 case MPI2_EVENT_IR_OPERATION_STATUS:
7558 _scsih_sas_ir_operation_status_event(ioc, fw_event);
7559 break;
7560 }
7561 _scsih_fw_event_free(ioc, fw_event);
7562}
7563
7564/**
7565 * _firmware_event_work
7566 * @ioc: per adapter object
7567 * @work: The fw_event_work object
7568 * Context: user.
7569 *
7570 * wrappers for the work thread handling firmware events
7571 *
7572 * Return nothing.
7573 */
7574
7575static void
7576_firmware_event_work(struct work_struct *work)
7577{
7578 struct fw_event_work *fw_event = container_of(work,
7579 struct fw_event_work, work);
7580
7581 _mpt3sas_fw_work(fw_event->ioc, fw_event);
7582}
7583
7584/**
7585 * mpt3sas_scsih_event_callback - firmware event handler (called at ISR time)
7586 * @ioc: per adapter object
7587 * @msix_index: MSIX table index supplied by the OS
7588 * @reply: reply message frame(lower 32bit addr)
7589 * Context: interrupt.
7590 *
7591 * This function merely adds a new work task into ioc->firmware_event_thread.
7592 * The tasks are worked from _firmware_event_work in user context.
7593 *
7594 * Return 1 meaning mf should be freed from _base_interrupt
7595 * 0 means the mf is freed from this function.
7596 */
7597u8
7598mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
7599 u32 reply)
7600{
7601 struct fw_event_work *fw_event;
7602 Mpi2EventNotificationReply_t *mpi_reply;
7603 u16 event;
7604 u16 sz;
7605
7606 /* events turned off due to host reset or driver unloading */
7607 if (ioc->remove_host || ioc->pci_error_recovery)
7608 return 1;
7609
7610 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
7611
7612 if (unlikely(!mpi_reply)) {
7613 pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n",
7614 ioc->name, __FILE__, __LINE__, __func__);
7615 return 1;
7616 }
7617
7618 event = le16_to_cpu(mpi_reply->Event);
7619
7620 if (event != MPI2_EVENT_LOG_ENTRY_ADDED)
7621 mpt3sas_trigger_event(ioc, event, 0);
7622
7623 switch (event) {
7624 /* handle these */
7625 case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
7626 {
7627 Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
7628 (Mpi2EventDataSasBroadcastPrimitive_t *)
7629 mpi_reply->EventData;
7630
7631 if (baen_data->Primitive !=
7632 MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
7633 return 1;
7634
7635 if (ioc->broadcast_aen_busy) {
7636 ioc->broadcast_aen_pending++;
7637 return 1;
7638 } else
7639 ioc->broadcast_aen_busy = 1;
7640 break;
7641 }
7642
7643 case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
7644 _scsih_check_topo_delete_events(ioc,
7645 (Mpi2EventDataSasTopologyChangeList_t *)
7646 mpi_reply->EventData);
7647 break;
7648 case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
7649 _scsih_check_ir_config_unhide_events(ioc,
7650 (Mpi2EventDataIrConfigChangeList_t *)
7651 mpi_reply->EventData);
7652 break;
7653 case MPI2_EVENT_IR_VOLUME:
7654 _scsih_check_volume_delete_events(ioc,
7655 (Mpi2EventDataIrVolume_t *)
7656 mpi_reply->EventData);
7657 break;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307658 case MPI2_EVENT_LOG_ENTRY_ADDED:
7659 {
7660 Mpi2EventDataLogEntryAdded_t *log_entry;
7661 u32 *log_code;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307662
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307663 if (!ioc->is_warpdrive)
7664 break;
7665
7666 log_entry = (Mpi2EventDataLogEntryAdded_t *)
7667 mpi_reply->EventData;
7668 log_code = (u32 *)log_entry->LogData;
7669
7670 if (le16_to_cpu(log_entry->LogEntryQualifier)
7671 != MPT2_WARPDRIVE_LOGENTRY)
7672 break;
7673
7674 switch (le32_to_cpu(*log_code)) {
7675 case MPT2_WARPDRIVE_LC_SSDT:
7676 pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
7677 "IO Throttling has occurred in the WarpDrive "
7678 "subsystem. Check WarpDrive documentation for "
7679 "additional details.\n", ioc->name);
7680 break;
7681 case MPT2_WARPDRIVE_LC_SSDLW:
7682 pr_warn(MPT3SAS_FMT "WarpDrive Warning: "
7683 "Program/Erase Cycles for the WarpDrive subsystem "
7684 "in degraded range. Check WarpDrive documentation "
7685 "for additional details.\n", ioc->name);
7686 break;
7687 case MPT2_WARPDRIVE_LC_SSDLF:
7688 pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
7689 "There are no Program/Erase Cycles for the "
7690 "WarpDrive subsystem. The storage device will be "
7691 "in read-only mode. Check WarpDrive documentation "
7692 "for additional details.\n", ioc->name);
7693 break;
7694 case MPT2_WARPDRIVE_LC_BRMF:
7695 pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: "
7696 "The Backup Rail Monitor has failed on the "
7697 "WarpDrive subsystem. Check WarpDrive "
7698 "documentation for additional details.\n",
7699 ioc->name);
7700 break;
7701 }
7702
7703 break;
7704 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307705 case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
7706 case MPI2_EVENT_IR_OPERATION_STATUS:
7707 case MPI2_EVENT_SAS_DISCOVERY:
7708 case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
7709 case MPI2_EVENT_IR_PHYSICAL_DISK:
7710 break;
7711
Sreekanth Reddy2d8ce8c2015-01-12 11:38:56 +05307712 case MPI2_EVENT_TEMP_THRESHOLD:
7713 _scsih_temp_threshold_events(ioc,
7714 (Mpi2EventDataTemperature_t *)
7715 mpi_reply->EventData);
7716 break;
7717
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307718 default: /* ignore the rest */
7719 return 1;
7720 }
7721
Joe Lawrence35b62362014-06-25 17:05:34 -04007722 sz = le16_to_cpu(mpi_reply->EventDataLength) * 4;
7723 fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307724 if (!fw_event) {
7725 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
7726 ioc->name, __FILE__, __LINE__, __func__);
7727 return 1;
7728 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307729
7730 memcpy(fw_event->event_data, mpi_reply->EventData, sz);
7731 fw_event->ioc = ioc;
7732 fw_event->VF_ID = mpi_reply->VF_ID;
7733 fw_event->VP_ID = mpi_reply->VP_ID;
7734 fw_event->event = event;
7735 _scsih_fw_event_add(ioc, fw_event);
7736 return 1;
7737}
7738
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307739/**
7740 * _scsih_expander_node_remove - removing expander device from list.
7741 * @ioc: per adapter object
7742 * @sas_expander: the sas_device object
7743 * Context: Calling function should acquire ioc->sas_node_lock.
7744 *
7745 * Removing object and freeing associated memory from the
7746 * ioc->sas_expander_list.
7747 *
7748 * Return nothing.
7749 */
7750static void
7751_scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc,
7752 struct _sas_node *sas_expander)
7753{
7754 struct _sas_port *mpt3sas_port, *next;
7755
7756 /* remove sibling ports attached to this expander */
7757 list_for_each_entry_safe(mpt3sas_port, next,
7758 &sas_expander->sas_port_list, port_list) {
7759 if (ioc->shost_recovery)
7760 return;
7761 if (mpt3sas_port->remote_identify.device_type ==
7762 SAS_END_DEVICE)
7763 mpt3sas_device_remove_by_sas_address(ioc,
7764 mpt3sas_port->remote_identify.sas_address);
7765 else if (mpt3sas_port->remote_identify.device_type ==
7766 SAS_EDGE_EXPANDER_DEVICE ||
7767 mpt3sas_port->remote_identify.device_type ==
7768 SAS_FANOUT_EXPANDER_DEVICE)
7769 mpt3sas_expander_remove(ioc,
7770 mpt3sas_port->remote_identify.sas_address);
7771 }
7772
7773 mpt3sas_transport_port_remove(ioc, sas_expander->sas_address,
7774 sas_expander->sas_address_parent);
7775
7776 pr_info(MPT3SAS_FMT
7777 "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n",
7778 ioc->name,
7779 sas_expander->handle, (unsigned long long)
7780 sas_expander->sas_address);
7781
7782 kfree(sas_expander->phy);
7783 kfree(sas_expander);
7784}
7785
7786/**
7787 * _scsih_ir_shutdown - IR shutdown notification
7788 * @ioc: per adapter object
7789 *
7790 * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that
7791 * the host system is shutting down.
7792 *
7793 * Return nothing.
7794 */
7795static void
7796_scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
7797{
7798 Mpi2RaidActionRequest_t *mpi_request;
7799 Mpi2RaidActionReply_t *mpi_reply;
7800 u16 smid;
7801
7802 /* is IR firmware build loaded ? */
7803 if (!ioc->ir_firmware)
7804 return;
7805
7806 /* are there any volumes ? */
7807 if (list_empty(&ioc->raid_device_list))
7808 return;
7809
7810 mutex_lock(&ioc->scsih_cmds.mutex);
7811
7812 if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) {
7813 pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n",
7814 ioc->name, __func__);
7815 goto out;
7816 }
7817 ioc->scsih_cmds.status = MPT3_CMD_PENDING;
7818
7819 smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx);
7820 if (!smid) {
7821 pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
7822 ioc->name, __func__);
7823 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
7824 goto out;
7825 }
7826
7827 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
7828 ioc->scsih_cmds.smid = smid;
7829 memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t));
7830
7831 mpi_request->Function = MPI2_FUNCTION_RAID_ACTION;
7832 mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED;
7833
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307834 if (!ioc->hide_ir_msg)
7835 pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307836 init_completion(&ioc->scsih_cmds.done);
7837 mpt3sas_base_put_smid_default(ioc, smid);
7838 wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ);
7839
7840 if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) {
7841 pr_err(MPT3SAS_FMT "%s: timeout\n",
7842 ioc->name, __func__);
7843 goto out;
7844 }
7845
7846 if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) {
7847 mpi_reply = ioc->scsih_cmds.reply;
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05307848 if (!ioc->hide_ir_msg)
7849 pr_info(MPT3SAS_FMT "IR shutdown "
7850 "(complete): ioc_status(0x%04x), loginfo(0x%08x)\n",
7851 ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
7852 le32_to_cpu(mpi_reply->IOCLogInfo));
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307853 }
7854
7855 out:
7856 ioc->scsih_cmds.status = MPT3_CMD_NOT_USED;
7857 mutex_unlock(&ioc->scsih_cmds.mutex);
7858}
7859
7860/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05307861 * scsih_remove - detach and remove add host
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307862 * @pdev: PCI device struct
7863 *
7864 * Routine called when unloading the driver.
7865 * Return nothing.
7866 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05307867void scsih_remove(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307868{
7869 struct Scsi_Host *shost = pci_get_drvdata(pdev);
7870 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
7871 struct _sas_port *mpt3sas_port, *next_port;
7872 struct _raid_device *raid_device, *next;
7873 struct MPT3SAS_TARGET *sas_target_priv_data;
7874 struct workqueue_struct *wq;
7875 unsigned long flags;
7876
7877 ioc->remove_host = 1;
7878 _scsih_fw_event_cleanup_queue(ioc);
7879
7880 spin_lock_irqsave(&ioc->fw_event_lock, flags);
7881 wq = ioc->firmware_event_thread;
7882 ioc->firmware_event_thread = NULL;
7883 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
7884 if (wq)
7885 destroy_workqueue(wq);
7886
7887 /* release all the volumes */
7888 _scsih_ir_shutdown(ioc);
7889 list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list,
7890 list) {
7891 if (raid_device->starget) {
7892 sas_target_priv_data =
7893 raid_device->starget->hostdata;
7894 sas_target_priv_data->deleted = 1;
7895 scsi_remove_target(&raid_device->starget->dev);
7896 }
7897 pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n",
7898 ioc->name, raid_device->handle,
7899 (unsigned long long) raid_device->wwid);
7900 _scsih_raid_device_remove(ioc, raid_device);
7901 }
7902
7903 /* free ports attached to the sas_host */
7904 list_for_each_entry_safe(mpt3sas_port, next_port,
7905 &ioc->sas_hba.sas_port_list, port_list) {
7906 if (mpt3sas_port->remote_identify.device_type ==
7907 SAS_END_DEVICE)
7908 mpt3sas_device_remove_by_sas_address(ioc,
7909 mpt3sas_port->remote_identify.sas_address);
7910 else if (mpt3sas_port->remote_identify.device_type ==
7911 SAS_EDGE_EXPANDER_DEVICE ||
7912 mpt3sas_port->remote_identify.device_type ==
7913 SAS_FANOUT_EXPANDER_DEVICE)
7914 mpt3sas_expander_remove(ioc,
7915 mpt3sas_port->remote_identify.sas_address);
7916 }
7917
7918 /* free phys attached to the sas_host */
7919 if (ioc->sas_hba.num_phys) {
7920 kfree(ioc->sas_hba.phy);
7921 ioc->sas_hba.phy = NULL;
7922 ioc->sas_hba.num_phys = 0;
7923 }
7924
7925 sas_remove_host(shost);
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05307926 scsi_remove_host(shost);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307927 mpt3sas_base_detach(ioc);
7928 list_del(&ioc->list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307929 scsi_host_put(shost);
7930}
7931
7932/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05307933 * scsih_shutdown - routine call during system shutdown
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05307934 * @pdev: PCI device struct
7935 *
7936 * Return nothing.
7937 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05307938void
7939scsih_shutdown(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 workqueue_struct *wq;
7944 unsigned long flags;
7945
7946 ioc->remove_host = 1;
7947 _scsih_fw_event_cleanup_queue(ioc);
7948
7949 spin_lock_irqsave(&ioc->fw_event_lock, flags);
7950 wq = ioc->firmware_event_thread;
7951 ioc->firmware_event_thread = NULL;
7952 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
7953 if (wq)
7954 destroy_workqueue(wq);
7955
7956 _scsih_ir_shutdown(ioc);
7957 mpt3sas_base_detach(ioc);
7958}
7959
7960
7961/**
7962 * _scsih_probe_boot_devices - reports 1st device
7963 * @ioc: per adapter object
7964 *
7965 * If specified in bios page 2, this routine reports the 1st
7966 * device scsi-ml or sas transport for persistent boot device
7967 * purposes. Please refer to function _scsih_determine_boot_device()
7968 */
7969static void
7970_scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc)
7971{
7972 u8 is_raid;
7973 void *device;
7974 struct _sas_device *sas_device;
7975 struct _raid_device *raid_device;
7976 u16 handle;
7977 u64 sas_address_parent;
7978 u64 sas_address;
7979 unsigned long flags;
7980 int rc;
7981
7982 /* no Bios, return immediately */
7983 if (!ioc->bios_pg3.BiosVersion)
7984 return;
7985
7986 device = NULL;
7987 is_raid = 0;
7988 if (ioc->req_boot_device.device) {
7989 device = ioc->req_boot_device.device;
7990 is_raid = ioc->req_boot_device.is_raid;
7991 } else if (ioc->req_alt_boot_device.device) {
7992 device = ioc->req_alt_boot_device.device;
7993 is_raid = ioc->req_alt_boot_device.is_raid;
7994 } else if (ioc->current_boot_device.device) {
7995 device = ioc->current_boot_device.device;
7996 is_raid = ioc->current_boot_device.is_raid;
7997 }
7998
7999 if (!device)
8000 return;
8001
8002 if (is_raid) {
8003 raid_device = device;
8004 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
8005 raid_device->id, 0);
8006 if (rc)
8007 _scsih_raid_device_remove(ioc, raid_device);
8008 } else {
8009 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8010 sas_device = device;
8011 handle = sas_device->handle;
8012 sas_address_parent = sas_device->sas_address_parent;
8013 sas_address = sas_device->sas_address;
8014 list_move_tail(&sas_device->list, &ioc->sas_device_list);
8015 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8016
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308017 if (ioc->hide_drives)
8018 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308019 if (!mpt3sas_transport_port_add(ioc, handle,
8020 sas_address_parent)) {
8021 _scsih_sas_device_remove(ioc, sas_device);
8022 } else if (!sas_device->starget) {
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308023 if (!ioc->is_driver_loading) {
8024 mpt3sas_transport_port_remove(ioc,
8025 sas_address,
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308026 sas_address_parent);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308027 _scsih_sas_device_remove(ioc, sas_device);
8028 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308029 }
8030 }
8031}
8032
8033/**
8034 * _scsih_probe_raid - reporting raid volumes to scsi-ml
8035 * @ioc: per adapter object
8036 *
8037 * Called during initial loading of the driver.
8038 */
8039static void
8040_scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc)
8041{
8042 struct _raid_device *raid_device, *raid_next;
8043 int rc;
8044
8045 list_for_each_entry_safe(raid_device, raid_next,
8046 &ioc->raid_device_list, list) {
8047 if (raid_device->starget)
8048 continue;
8049 rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
8050 raid_device->id, 0);
8051 if (rc)
8052 _scsih_raid_device_remove(ioc, raid_device);
8053 }
8054}
8055
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308056static struct _sas_device *get_next_sas_device(struct MPT3SAS_ADAPTER *ioc)
8057{
8058 struct _sas_device *sas_device = NULL;
8059 unsigned long flags;
8060
8061 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8062 if (!list_empty(&ioc->sas_device_init_list)) {
8063 sas_device = list_first_entry(&ioc->sas_device_init_list,
8064 struct _sas_device, list);
8065 sas_device_get(sas_device);
8066 }
8067 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8068
8069 return sas_device;
8070}
8071
8072static void sas_device_make_active(struct MPT3SAS_ADAPTER *ioc,
8073 struct _sas_device *sas_device)
8074{
8075 unsigned long flags;
8076
8077 spin_lock_irqsave(&ioc->sas_device_lock, flags);
8078
8079 /*
8080 * Since we dropped the lock during the call to port_add(), we need to
8081 * be careful here that somebody else didn't move or delete this item
8082 * while we were busy with other things.
8083 *
8084 * If it was on the list, we need a put() for the reference the list
8085 * had. Either way, we need a get() for the destination list.
8086 */
8087 if (!list_empty(&sas_device->list)) {
8088 list_del_init(&sas_device->list);
8089 sas_device_put(sas_device);
8090 }
8091
8092 sas_device_get(sas_device);
8093 list_add_tail(&sas_device->list, &ioc->sas_device_list);
8094
8095 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
8096}
8097
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308098/**
8099 * _scsih_probe_sas - reporting sas devices to sas transport
8100 * @ioc: per adapter object
8101 *
8102 * Called during initial loading of the driver.
8103 */
8104static void
8105_scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc)
8106{
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308107 struct _sas_device *sas_device;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308108
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308109 if (ioc->hide_drives)
8110 return;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308111
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308112 while ((sas_device = get_next_sas_device(ioc))) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308113 if (!mpt3sas_transport_port_add(ioc, sas_device->handle,
8114 sas_device->sas_address_parent)) {
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308115 _scsih_sas_device_remove(ioc, sas_device);
8116 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308117 continue;
8118 } else if (!sas_device->starget) {
8119 /*
8120 * When asyn scanning is enabled, its not possible to
8121 * remove devices while scanning is turned on due to an
8122 * oops in scsi_sysfs_add_sdev()->add_device()->
8123 * sysfs_addrm_start()
8124 */
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308125 if (!ioc->is_driver_loading) {
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308126 mpt3sas_transport_port_remove(ioc,
8127 sas_device->sas_address,
8128 sas_device->sas_address_parent);
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308129 _scsih_sas_device_remove(ioc, sas_device);
8130 sas_device_put(sas_device);
Sreekanth Reddyf5edbe72013-06-29 03:54:51 +05308131 continue;
8132 }
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308133 }
Sreekanth Reddyd1cb5e42015-11-11 17:30:30 +05308134 sas_device_make_active(ioc, sas_device);
8135 sas_device_put(sas_device);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308136 }
8137}
8138
8139/**
8140 * _scsih_probe_devices - probing for devices
8141 * @ioc: per adapter object
8142 *
8143 * Called during initial loading of the driver.
8144 */
8145static void
8146_scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc)
8147{
8148 u16 volume_mapping_flags;
8149
8150 if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
8151 return; /* return when IOC doesn't support initiator mode */
8152
8153 _scsih_probe_boot_devices(ioc);
8154
8155 if (ioc->ir_firmware) {
8156 volume_mapping_flags =
8157 le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
8158 MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
8159 if (volume_mapping_flags ==
8160 MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) {
8161 _scsih_probe_raid(ioc);
8162 _scsih_probe_sas(ioc);
8163 } else {
8164 _scsih_probe_sas(ioc);
8165 _scsih_probe_raid(ioc);
8166 }
8167 } else
8168 _scsih_probe_sas(ioc);
8169}
8170
8171/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308172 * scsih_scan_start - scsi lld callback for .scan_start
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308173 * @shost: SCSI host pointer
8174 *
8175 * The shost has the ability to discover targets on its own instead
8176 * of scanning the entire bus. In our implemention, we will kick off
8177 * firmware discovery.
8178 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308179void
8180scsih_scan_start(struct Scsi_Host *shost)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308181{
8182 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8183 int rc;
8184 if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
8185 mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable);
8186
8187 if (disable_discovery > 0)
8188 return;
8189
8190 ioc->start_scan = 1;
8191 rc = mpt3sas_port_enable(ioc);
8192
8193 if (rc != 0)
8194 pr_info(MPT3SAS_FMT "port enable: FAILED\n", ioc->name);
8195}
8196
8197/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308198 * scsih_scan_finished - scsi lld callback for .scan_finished
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308199 * @shost: SCSI host pointer
8200 * @time: elapsed time of the scan in jiffies
8201 *
8202 * This function will be called periodicallyn until it returns 1 with the
8203 * scsi_host and the elapsed time of the scan in jiffies. In our implemention,
8204 * we wait for firmware discovery to complete, then return 1.
8205 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308206int
8207scsih_scan_finished(struct Scsi_Host *shost, unsigned long time)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308208{
8209 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8210
8211 if (disable_discovery > 0) {
8212 ioc->is_driver_loading = 0;
8213 ioc->wait_for_discovery_to_complete = 0;
8214 return 1;
8215 }
8216
8217 if (time >= (300 * HZ)) {
8218 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
8219 pr_info(MPT3SAS_FMT
8220 "port enable: FAILED with timeout (timeout=300s)\n",
8221 ioc->name);
8222 ioc->is_driver_loading = 0;
8223 return 1;
8224 }
8225
8226 if (ioc->start_scan)
8227 return 0;
8228
8229 if (ioc->start_scan_failed) {
8230 pr_info(MPT3SAS_FMT
8231 "port enable: FAILED with (ioc_status=0x%08x)\n",
8232 ioc->name, ioc->start_scan_failed);
8233 ioc->is_driver_loading = 0;
8234 ioc->wait_for_discovery_to_complete = 0;
8235 ioc->remove_host = 1;
8236 return 1;
8237 }
8238
8239 pr_info(MPT3SAS_FMT "port enable: SUCCESS\n", ioc->name);
8240 ioc->base_cmds.status = MPT3_CMD_NOT_USED;
8241
8242 if (ioc->wait_for_discovery_to_complete) {
8243 ioc->wait_for_discovery_to_complete = 0;
8244 _scsih_probe_devices(ioc);
8245 }
8246 mpt3sas_base_start_watchdog(ioc);
8247 ioc->is_driver_loading = 0;
8248 return 1;
8249}
8250
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308251void
8252_scsih_determine_hba_mpi_version(struct MPT3SAS_ADAPTER *ioc) {
8253
8254 switch (ioc->pdev->device) {
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308255 case MPI2_MFGPAGE_DEVID_SSS6200:
8256 ioc->is_warpdrive = 1;
8257 ioc->hide_ir_msg = 1;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308258 case MPI2_MFGPAGE_DEVID_SAS2004:
8259 case MPI2_MFGPAGE_DEVID_SAS2008:
8260 case MPI2_MFGPAGE_DEVID_SAS2108_1:
8261 case MPI2_MFGPAGE_DEVID_SAS2108_2:
8262 case MPI2_MFGPAGE_DEVID_SAS2108_3:
8263 case MPI2_MFGPAGE_DEVID_SAS2116_1:
8264 case MPI2_MFGPAGE_DEVID_SAS2116_2:
8265 case MPI2_MFGPAGE_DEVID_SAS2208_1:
8266 case MPI2_MFGPAGE_DEVID_SAS2208_2:
8267 case MPI2_MFGPAGE_DEVID_SAS2208_3:
8268 case MPI2_MFGPAGE_DEVID_SAS2208_4:
8269 case MPI2_MFGPAGE_DEVID_SAS2208_5:
8270 case MPI2_MFGPAGE_DEVID_SAS2208_6:
8271 case MPI2_MFGPAGE_DEVID_SAS2308_1:
8272 case MPI2_MFGPAGE_DEVID_SAS2308_2:
8273 case MPI2_MFGPAGE_DEVID_SAS2308_3:
8274 ioc->hba_mpi_version_belonged = MPI2_VERSION;
8275 break;
8276 case MPI25_MFGPAGE_DEVID_SAS3004:
8277 case MPI25_MFGPAGE_DEVID_SAS3008:
8278 case MPI25_MFGPAGE_DEVID_SAS3108_1:
8279 case MPI25_MFGPAGE_DEVID_SAS3108_2:
8280 case MPI25_MFGPAGE_DEVID_SAS3108_5:
8281 case MPI25_MFGPAGE_DEVID_SAS3108_6:
8282 ioc->hba_mpi_version_belonged = MPI25_VERSION;
Sreekanth Reddy42081172015-11-11 17:30:26 +05308283
8284 /* Check whether the controller revision is C0 or above.
8285 * only C0 and above revision controllers support 96 MSI-X
8286 * vectors.
8287 */
8288 if (ioc->pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION)
8289 ioc->msix96_vector = 1;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308290 break;
8291 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308292
8293 if ((ioc->pdev->device != MPI2_MFGPAGE_DEVID_SSS6200) &&
8294 (ioc->hba_mpi_version_belonged == MPI2_VERSION))
8295 ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308296}
8297
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308298/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308299 * scsih_probe - attach and add scsi host
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308300 * @pdev: PCI device struct
8301 * @id: pci device id
8302 *
8303 * Returns 0 success, anything else error.
8304 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308305int
Sreekanth Reddy7497392a2015-11-11 17:30:19 +05308306scsih_probe(struct pci_dev *pdev, struct Scsi_Host *shost)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308307{
8308 struct MPT3SAS_ADAPTER *ioc;
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308309 int rv;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308310
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308311 /* init local params */
8312 ioc = shost_priv(shost);
8313 memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER));
8314 INIT_LIST_HEAD(&ioc->list);
8315 list_add_tail(&ioc->list, &mpt3sas_ioc_list);
8316 ioc->shost = shost;
8317 ioc->id = mpt_ids++;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308318 ioc->pdev = pdev;
8319 ioc->scsi_io_cb_idx = scsi_io_cb_idx;
8320 ioc->tm_cb_idx = tm_cb_idx;
8321 ioc->ctl_cb_idx = ctl_cb_idx;
8322 ioc->base_cb_idx = base_cb_idx;
8323 ioc->port_enable_cb_idx = port_enable_cb_idx;
8324 ioc->transport_cb_idx = transport_cb_idx;
8325 ioc->scsih_cb_idx = scsih_cb_idx;
8326 ioc->config_cb_idx = config_cb_idx;
8327 ioc->tm_tr_cb_idx = tm_tr_cb_idx;
8328 ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx;
8329 ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx;
8330 ioc->logging_level = logging_level;
8331 ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds;
8332 /* misc semaphores and spin locks */
8333 mutex_init(&ioc->reset_in_progress_mutex);
8334 spin_lock_init(&ioc->ioc_reset_in_progress_lock);
8335 spin_lock_init(&ioc->scsi_lookup_lock);
8336 spin_lock_init(&ioc->sas_device_lock);
8337 spin_lock_init(&ioc->sas_node_lock);
8338 spin_lock_init(&ioc->fw_event_lock);
8339 spin_lock_init(&ioc->raid_device_lock);
8340 spin_lock_init(&ioc->diag_trigger_lock);
8341
8342 INIT_LIST_HEAD(&ioc->sas_device_list);
8343 INIT_LIST_HEAD(&ioc->sas_device_init_list);
8344 INIT_LIST_HEAD(&ioc->sas_expander_list);
8345 INIT_LIST_HEAD(&ioc->fw_event_list);
8346 INIT_LIST_HEAD(&ioc->raid_device_list);
8347 INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
8348 INIT_LIST_HEAD(&ioc->delayed_tr_list);
8349 INIT_LIST_HEAD(&ioc->delayed_tr_volume_list);
Joe Lawrencecf9bd21a2013-08-08 16:45:39 -04008350 INIT_LIST_HEAD(&ioc->reply_queue_list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308351
Sreekanth Reddyd357e842015-11-11 17:30:22 +05308352 _scsih_determine_hba_mpi_version(ioc);
8353 sprintf(ioc->name, "%s_cm%d", driver_name, ioc->id);
8354
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308355 /* init shost parameters */
8356 shost->max_cmd_len = 32;
8357 shost->max_lun = max_lun;
8358 shost->transportt = mpt3sas_transport_template;
8359 shost->unique_id = ioc->id;
8360
8361 if (max_sectors != 0xFFFF) {
8362 if (max_sectors < 64) {
8363 shost->max_sectors = 64;
8364 pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
8365 "for max_sectors, range is 64 to 32767. Assigning "
8366 "value of 64.\n", ioc->name, max_sectors);
8367 } else if (max_sectors > 32767) {
8368 shost->max_sectors = 32767;
8369 pr_warn(MPT3SAS_FMT "Invalid value %d passed " \
8370 "for max_sectors, range is 64 to 32767. Assigning "
8371 "default value of 32767.\n", ioc->name,
8372 max_sectors);
8373 } else {
8374 shost->max_sectors = max_sectors & 0xFFFE;
8375 pr_info(MPT3SAS_FMT
8376 "The max_sectors value is set to %d\n",
8377 ioc->name, shost->max_sectors);
8378 }
8379 }
8380
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308381 /* register EEDP capabilities with SCSI layer */
8382 if (prot_mask > 0)
8383 scsi_host_set_prot(shost, prot_mask);
8384 else
8385 scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION
8386 | SHOST_DIF_TYPE2_PROTECTION
8387 | SHOST_DIF_TYPE3_PROTECTION);
8388
8389 scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
8390
8391 /* event thread */
8392 snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
8393 "fw_event%d", ioc->id);
Sreekanth Reddybdff7852015-06-30 12:25:03 +05308394 ioc->firmware_event_thread = alloc_ordered_workqueue(
8395 ioc->firmware_event_name, WQ_MEM_RECLAIM);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308396 if (!ioc->firmware_event_thread) {
8397 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8398 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308399 rv = -ENODEV;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308400 goto out_thread_fail;
8401 }
8402
8403 ioc->is_driver_loading = 1;
8404 if ((mpt3sas_base_attach(ioc))) {
8405 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8406 ioc->name, __FILE__, __LINE__, __func__);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308407 rv = -ENODEV;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308408 goto out_attach_fail;
8409 }
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308410
8411#ifdef SCSI_MPT2SAS
8412 if (ioc->is_warpdrive) {
8413 if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS)
8414 ioc->hide_drives = 0;
8415 else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS)
8416 ioc->hide_drives = 1;
8417 else {
8418 if (_scsih_get_num_volumes(ioc))
8419 ioc->hide_drives = 1;
8420 else
8421 ioc->hide_drives = 0;
8422 }
8423 } else
8424 ioc->hide_drives = 0;
8425#endif
8426
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308427 rv = scsi_add_host(shost, &pdev->dev);
8428 if (rv) {
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308429 pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
8430 ioc->name, __FILE__, __LINE__, __func__);
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308431 goto out_add_shost_fail;
8432 }
8433
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308434 scsi_scan_host(shost);
8435 return 0;
Reddy, Sreekanth4dc06fd2014-07-14 12:01:35 +05308436out_add_shost_fail:
8437 mpt3sas_base_detach(ioc);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308438 out_attach_fail:
8439 destroy_workqueue(ioc->firmware_event_thread);
8440 out_thread_fail:
8441 list_del(&ioc->list);
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308442 scsi_host_put(shost);
Sreekanth Reddyb65f1d42014-09-12 15:35:33 +05308443 return rv;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308444}
8445
8446#ifdef CONFIG_PM
8447/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308448 * scsih_suspend - power management suspend main entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308449 * @pdev: PCI device struct
8450 * @state: PM state change to (usually PCI_D3)
8451 *
8452 * Returns 0 success, anything else error.
8453 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308454int
8455scsih_suspend(struct pci_dev *pdev, pm_message_t state)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308456{
8457 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8458 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8459 pci_power_t device_state;
8460
8461 mpt3sas_base_stop_watchdog(ioc);
8462 flush_scheduled_work();
8463 scsi_block_requests(shost);
8464 device_state = pci_choose_state(pdev, state);
8465 pr_info(MPT3SAS_FMT
8466 "pdev=0x%p, slot=%s, entering operating state [D%d]\n",
8467 ioc->name, pdev, pci_name(pdev), device_state);
8468
8469 pci_save_state(pdev);
8470 mpt3sas_base_free_resources(ioc);
8471 pci_set_power_state(pdev, device_state);
8472 return 0;
8473}
8474
8475/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308476 * scsih_resume - power management resume main entry point
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308477 * @pdev: PCI device struct
8478 *
8479 * Returns 0 success, anything else error.
8480 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308481int
8482scsih_resume(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308483{
8484 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8485 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8486 pci_power_t device_state = pdev->current_state;
8487 int r;
8488
8489 pr_info(MPT3SAS_FMT
8490 "pdev=0x%p, slot=%s, previous operating state [D%d]\n",
8491 ioc->name, pdev, pci_name(pdev), device_state);
8492
8493 pci_set_power_state(pdev, PCI_D0);
8494 pci_enable_wake(pdev, PCI_D0, 0);
8495 pci_restore_state(pdev);
8496 ioc->pdev = pdev;
8497 r = mpt3sas_base_map_resources(ioc);
8498 if (r)
8499 return r;
8500
8501 mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
8502 scsi_unblock_requests(shost);
8503 mpt3sas_base_start_watchdog(ioc);
8504 return 0;
8505}
8506#endif /* CONFIG_PM */
8507
8508/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308509 * scsih_pci_error_detected - Called when a PCI error is detected.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308510 * @pdev: PCI device struct
8511 * @state: PCI channel state
8512 *
8513 * Description: Called when a PCI error is detected.
8514 *
8515 * Return value:
8516 * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
8517 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308518pci_ers_result_t
8519scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308520{
8521 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8522 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8523
8524 pr_info(MPT3SAS_FMT "PCI error: detected callback, state(%d)!!\n",
8525 ioc->name, state);
8526
8527 switch (state) {
8528 case pci_channel_io_normal:
8529 return PCI_ERS_RESULT_CAN_RECOVER;
8530 case pci_channel_io_frozen:
8531 /* Fatal error, prepare for slot reset */
8532 ioc->pci_error_recovery = 1;
8533 scsi_block_requests(ioc->shost);
8534 mpt3sas_base_stop_watchdog(ioc);
8535 mpt3sas_base_free_resources(ioc);
8536 return PCI_ERS_RESULT_NEED_RESET;
8537 case pci_channel_io_perm_failure:
8538 /* Permanent error, prepare for device removal */
8539 ioc->pci_error_recovery = 1;
8540 mpt3sas_base_stop_watchdog(ioc);
8541 _scsih_flush_running_cmds(ioc);
8542 return PCI_ERS_RESULT_DISCONNECT;
8543 }
8544 return PCI_ERS_RESULT_NEED_RESET;
8545}
8546
8547/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308548 * scsih_pci_slot_reset - Called when PCI slot has been reset.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308549 * @pdev: PCI device struct
8550 *
8551 * Description: This routine is called by the pci error recovery
8552 * code after the PCI slot has been reset, just before we
8553 * should resume normal operations.
8554 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308555pci_ers_result_t
8556scsih_pci_slot_reset(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308557{
8558 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8559 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8560 int rc;
8561
8562 pr_info(MPT3SAS_FMT "PCI error: slot reset callback!!\n",
8563 ioc->name);
8564
8565 ioc->pci_error_recovery = 0;
8566 ioc->pdev = pdev;
8567 pci_restore_state(pdev);
8568 rc = mpt3sas_base_map_resources(ioc);
8569 if (rc)
8570 return PCI_ERS_RESULT_DISCONNECT;
8571
8572 rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP,
8573 FORCE_BIG_HAMMER);
8574
8575 pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name,
8576 (rc == 0) ? "success" : "failed");
8577
8578 if (!rc)
8579 return PCI_ERS_RESULT_RECOVERED;
8580 else
8581 return PCI_ERS_RESULT_DISCONNECT;
8582}
8583
8584/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308585 * scsih_pci_resume() - resume normal ops after PCI reset
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308586 * @pdev: pointer to PCI device
8587 *
8588 * Called when the error recovery driver tells us that its
8589 * OK to resume normal operation. Use completion to allow
8590 * halted scsi ops to resume.
8591 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308592void
8593scsih_pci_resume(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308594{
8595 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8596 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8597
8598 pr_info(MPT3SAS_FMT "PCI error: resume callback!!\n", ioc->name);
8599
8600 pci_cleanup_aer_uncorrect_error_status(pdev);
8601 mpt3sas_base_start_watchdog(ioc);
8602 scsi_unblock_requests(ioc->shost);
8603}
8604
8605/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308606 * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308607 * @pdev: pointer to PCI device
8608 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308609pci_ers_result_t
8610scsih_pci_mmio_enabled(struct pci_dev *pdev)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308611{
8612 struct Scsi_Host *shost = pci_get_drvdata(pdev);
8613 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
8614
8615 pr_info(MPT3SAS_FMT "PCI error: mmio enabled callback!!\n",
8616 ioc->name);
8617
8618 /* TODO - dump whatever for debugging purposes */
8619
8620 /* Request a slot reset. */
8621 return PCI_ERS_RESULT_NEED_RESET;
8622}
8623
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308624/**
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308625 * scsih_init - main entry point for this driver.
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308626 *
8627 * Returns 0 success, anything else error.
8628 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308629int
8630scsih_init(void)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308631{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308632 mpt_ids = 0;
8633
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308634 mpt3sas_base_initialize_callback_handler();
8635
8636 /* queuecommand callback hander */
8637 scsi_io_cb_idx = mpt3sas_base_register_callback_handler(_scsih_io_done);
8638
8639 /* task managment callback handler */
8640 tm_cb_idx = mpt3sas_base_register_callback_handler(_scsih_tm_done);
8641
8642 /* base internal commands callback handler */
8643 base_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_base_done);
8644 port_enable_cb_idx = mpt3sas_base_register_callback_handler(
8645 mpt3sas_port_enable_done);
8646
8647 /* transport internal commands callback handler */
8648 transport_cb_idx = mpt3sas_base_register_callback_handler(
8649 mpt3sas_transport_done);
8650
8651 /* scsih internal commands callback handler */
8652 scsih_cb_idx = mpt3sas_base_register_callback_handler(_scsih_done);
8653
8654 /* configuration page API internal commands callback handler */
8655 config_cb_idx = mpt3sas_base_register_callback_handler(
8656 mpt3sas_config_done);
8657
8658 /* ctl module callback handler */
8659 ctl_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_ctl_done);
8660
8661 tm_tr_cb_idx = mpt3sas_base_register_callback_handler(
8662 _scsih_tm_tr_complete);
8663
8664 tm_tr_volume_cb_idx = mpt3sas_base_register_callback_handler(
8665 _scsih_tm_volume_tr_complete);
8666
8667 tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler(
8668 _scsih_sas_control_complete);
8669
Sreekanth Reddy7497392a2015-11-11 17:30:19 +05308670 return 0;
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308671}
8672
8673/**
Sreekanth Reddy7497392a2015-11-11 17:30:19 +05308674 * scsih_exit - exit point for this driver (when it is a module).
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308675 *
8676 * Returns 0 success, anything else error.
8677 */
Sreekanth Reddy8a7e4c22015-11-11 17:30:18 +05308678void
8679scsih_exit(void)
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308680{
Sreekanth Reddyf92363d2012-11-30 07:44:21 +05308681
8682 mpt3sas_base_release_callback_handler(scsi_io_cb_idx);
8683 mpt3sas_base_release_callback_handler(tm_cb_idx);
8684 mpt3sas_base_release_callback_handler(base_cb_idx);
8685 mpt3sas_base_release_callback_handler(port_enable_cb_idx);
8686 mpt3sas_base_release_callback_handler(transport_cb_idx);
8687 mpt3sas_base_release_callback_handler(scsih_cb_idx);
8688 mpt3sas_base_release_callback_handler(config_cb_idx);
8689 mpt3sas_base_release_callback_handler(ctl_cb_idx);
8690
8691 mpt3sas_base_release_callback_handler(tm_tr_cb_idx);
8692 mpt3sas_base_release_callback_handler(tm_tr_volume_cb_idx);
8693 mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx);
8694
8695/* raid transport support */
8696 raid_class_release(mpt3sas_raid_template);
8697 sas_release_transport(mpt3sas_transport_template);
8698}
Sreekanth Reddy7786ab62015-11-11 17:30:28 +05308699
8700#ifdef SCSI_MPT2SAS
8701#include "../mpt2sas/mpt2sas_warpdrive.c"
8702#endif